[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 05/41] vvfat: Do not clobber the user's geometry
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PATCH 05/41] vvfat: Do not clobber the user's geometry |
Date: |
Tue, 17 Jul 2012 18:00:02 +0200 |
From: Markus Armbruster <address@hidden>
vvfat creates a virtual VFAT filesystem with a certain logical
geometry that depends on its options. It sets the "geometry hint" to
this geometry. It is the only block driver to do this.
The geometry hint is about about *physical* geometry, and used only by
certain hard disk device models.
vvfat's hint is normally invisible for device models, because
bdrv_open() puts a raw format on top of vvfat's fat protocol. That
raw format is where drive_init() puts the user's geometry (if any),
and where the device model gets it from.
Nobody complained, because the default physical geometry is the same
as vvfat's logical geometry:
opts LCHS def. PCHS
1024,16,63 same
:32: 1024,16,63 same
:16: 1024,16,63 same
:12: 64,16,63 same
Except when you specify :floppy:
opts LCHS def. PCHS
:floppy: 80, 2,36 5,16,63
:32:floppy: 80, 2,36 5,16,63
:16:floppy: 80, 2,36 5,16,63
:12:floppy: 80, 2,18 2,16,63
Silly thing to do for use with a hard disk.
However, the "raw" format can be suppressed by adding an
redundant-looking "format=vvfat" to "file=fat:FOO". Then, vvfat's
hint clobbers the user's geometry, i.e. -drive options cyls, heads,
secs get silently ignored. Don't do that.
No change without format=vvfat. With it, the user's hard disk
geometry (-drive options cyls, heads, secs) is now obeyed, and the
default hard disk geometry with :floppy: now matches the one without
format=vvfat.
Signed-off-by: Markus Armbruster <address@hidden>
Signed-off-by: Kevin Wolf <address@hidden>
---
block/vvfat.c | 53 +++++++++++++++++++++++++++++------------------------
1 files changed, 29 insertions(+), 24 deletions(-)
diff --git a/block/vvfat.c b/block/vvfat.c
index e2b83a2..7b1dcee 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -359,11 +359,12 @@ typedef struct BDRVVVFATState {
* if the position is outside the specified geometry, fill maximum value for
CHS
* and return 1 to signal overflow.
*/
-static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
+static int sector2CHS(mbr_chs_t *chs, int spos, int cyls, int heads, int secs)
+{
int head,sector;
- sector = spos % (bs->secs); spos/= bs->secs;
- head = spos % (bs->heads); spos/= bs->heads;
- if(spos >= bs->cyls){
+ sector = spos % secs; spos /= secs;
+ head = spos % heads; spos /= heads;
+ if (spos >= cyls) {
/* Overflow,
it happens if 32bit sector positions are used, while CHS is only 24bit.
Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
@@ -378,7 +379,7 @@ static int sector2CHS(BlockDriverState* bs, mbr_chs_t *
chs, int spos){
return 0;
}
-static void init_mbr(BDRVVVFATState* s)
+static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
{
/* TODO: if the files mbr.img and bootsect.img exist, use them */
mbr_t* real_mbr=(mbr_t*)s->first_sectors;
@@ -393,8 +394,10 @@ static void init_mbr(BDRVVVFATState* s)
partition->attributes=0x80; /* bootable */
/* LBA is used when partition is outside the CHS geometry */
- lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
- lba |= sector2CHS(s->bs, &partition->end_CHS, s->bs->total_sectors - 1);
+ lba = sector2CHS(&partition->start_CHS, s->first_sectors_number - 1,
+ cyls, heads, secs);
+ lba |= sector2CHS(&partition->end_CHS, s->bs->total_sectors - 1,
+ cyls, heads, secs);
/*LBA partitions are identified only by start/length_sector_long not by
CHS*/
partition->start_sector_long = cpu_to_le32(s->first_sectors_number - 1);
@@ -831,7 +834,7 @@ static inline off_t cluster2sector(BDRVVVFATState* s,
uint32_t cluster_num)
}
static int init_directories(BDRVVVFATState* s,
- const char* dirname)
+ const char *dirname, int heads, int secs)
{
bootsector_t* bootsector;
mapping_t* mapping;
@@ -958,8 +961,8 @@ static int init_directories(BDRVVVFATState* s,
bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media
descriptor (f8=hd, f0=3.5 fd)*/
s->fat.pointer[0] = bootsector->media_type;
bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
- bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
- bootsector->number_of_heads=cpu_to_le16(s->bs->heads);
+ bootsector->sectors_per_track = cpu_to_le16(secs);
+ bootsector->number_of_heads = cpu_to_le16(heads);
bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
@@ -992,7 +995,7 @@ static void vvfat_rebind(BlockDriverState *bs)
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
{
BDRVVVFATState *s = bs->opaque;
- int i;
+ int i, cyls, heads, secs;
#ifdef DEBUG
vvv = s;
@@ -1034,24 +1037,28 @@ DLOG(if (stderr == NULL) {
/* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
if (!s->fat_type) {
s->fat_type = 12;
- bs->secs = 36;
+ secs = 36;
s->sectors_per_cluster=2;
} else {
- bs->secs=(s->fat_type == 12 ? 18 : 36);
+ secs = s->fat_type == 12 ? 18 : 36;
s->sectors_per_cluster=1;
}
s->first_sectors_number = 1;
- bs->cyls=80; bs->heads=2;
+ cyls = 80;
+ heads = 2;
} else {
/* 32MB or 504MB disk*/
if (!s->fat_type) {
s->fat_type = 16;
}
- bs->cyls=(s->fat_type == 12 ? 64 : 1024);
- bs->heads=16; bs->secs=63;
+ cyls = s->fat_type == 12 ? 64 : 1024;
+ heads = 16;
+ secs = 63;
}
+ fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
+ dirname, cyls, heads, secs);
- s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
+ s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
if (strstr(dirname, ":rw:")) {
if (enable_write_target(s))
@@ -1067,18 +1074,16 @@ DLOG(if (stderr == NULL) {
else
dirname += i+1;
- bs->total_sectors=bs->cyls*bs->heads*bs->secs;
+ bs->total_sectors = cyls * heads * secs;
- if(init_directories(s, dirname))
+ if (init_directories(s, dirname, heads, secs)) {
return -1;
+ }
s->sector_count = s->faked_sectors +
s->sectors_per_cluster*s->cluster_count;
- if(s->first_sectors_number==0x40)
- init_mbr(s);
- else {
- /* MS-DOS does not like to know about CHS (?). */
- bs->heads = bs->cyls = bs->secs = 0;
+ if (s->first_sectors_number == 0x40) {
+ init_mbr(s, cyls, heads, secs);
}
// assert(is_consistent(s));
--
1.7.6.5
- [Qemu-devel] [PULL 00/41] Block patches, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 01/41] sheepdog: always use coroutine-based network functions, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 02/41] sheepdog: do not blindly memset all read buffers, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 03/41] fdc: Move floppy geometry guessing back from block.c, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 09/41] hd-geometry: Unnest conditional in hd_geometry_guess(), Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 07/41] hd-geometry: Move disk geometry guessing back from block.c, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 05/41] vvfat: Do not clobber the user's geometry,
Kevin Wolf <=
- [Qemu-devel] [PATCH 11/41] hd-geometry: Clean up gratuitous goto in hd_geometry_guess(), Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 06/41] qtest: Add hard disk geometry test, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 04/41] vvfat: Fix partition table, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 10/41] hd-geometry: Factor out guess_chs_for_size(), Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 08/41] hd-geometry: Add tracepoints, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 13/41] hd-geometry: Cut out block layer translation middleman, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 15/41] blockdev: Save geometry in DriveInfo, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 16/41] qdev: Introduce block geometry properties, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 14/41] ide pc: Cut out the block layer geometry middleman, Kevin Wolf, 2012/07/17
- [Qemu-devel] [PATCH 29/41] hd-geometry: Compute BIOS CHS translation in one place, Kevin Wolf, 2012/07/17