Commit 46d4767d93bcb2e84869ba6d2344ebff4382be86
1 parent
e35c55fe
better BIOS ATA translation support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1153 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
79 additions
and
24 deletions
block.c
... | ... | @@ -348,6 +348,11 @@ void bdrv_set_type_hint(BlockDriverState *bs, int type) |
348 | 348 | type == BDRV_TYPE_FLOPPY)); |
349 | 349 | } |
350 | 350 | |
351 | +void bdrv_set_translation_hint(BlockDriverState *bs, int translation) | |
352 | +{ | |
353 | + bs->translation = translation; | |
354 | +} | |
355 | + | |
351 | 356 | void bdrv_get_geometry_hint(BlockDriverState *bs, |
352 | 357 | int *pcyls, int *pheads, int *psecs) |
353 | 358 | { |
... | ... | @@ -361,6 +366,11 @@ int bdrv_get_type_hint(BlockDriverState *bs) |
361 | 366 | return bs->type; |
362 | 367 | } |
363 | 368 | |
369 | +int bdrv_get_translation_hint(BlockDriverState *bs) | |
370 | +{ | |
371 | + return bs->translation; | |
372 | +} | |
373 | + | |
364 | 374 | int bdrv_is_removable(BlockDriverState *bs) |
365 | 375 | { |
366 | 376 | return bs->removable; | ... | ... |
block_int.h
... | ... | @@ -68,7 +68,7 @@ struct BlockDriverState { |
68 | 68 | |
69 | 69 | /* NOTE: the following infos are only hints for real hardware |
70 | 70 | drivers. They are not used by the block driver */ |
71 | - int cyls, heads, secs; | |
71 | + int cyls, heads, secs, translation; | |
72 | 72 | int type; |
73 | 73 | char device_name[32]; |
74 | 74 | BlockDriverState *next; | ... | ... |
hw/ide.c
... | ... | @@ -1826,11 +1826,11 @@ struct partition { |
1826 | 1826 | uint32_t nr_sects; /* nr of sectors in partition */ |
1827 | 1827 | } __attribute__((packed)); |
1828 | 1828 | |
1829 | -/* try to guess the IDE geometry from the MSDOS partition table */ | |
1829 | +/* try to guess the IDE physical geometry from the MSDOS partition table */ | |
1830 | 1830 | static void ide_guess_geometry(IDEState *s) |
1831 | 1831 | { |
1832 | 1832 | uint8_t buf[512]; |
1833 | - int ret, i; | |
1833 | + int ret, i, heads, sectors, cylinders; | |
1834 | 1834 | struct partition *p; |
1835 | 1835 | uint32_t nr_sects; |
1836 | 1836 | |
... | ... | @@ -1848,9 +1848,18 @@ static void ide_guess_geometry(IDEState *s) |
1848 | 1848 | if (nr_sects && p->end_head) { |
1849 | 1849 | /* We make the assumption that the partition terminates on |
1850 | 1850 | a cylinder boundary */ |
1851 | - s->heads = p->end_head + 1; | |
1852 | - s->sectors = p->end_sector & 63; | |
1853 | - s->cylinders = s->nb_sectors / (s->heads * s->sectors); | |
1851 | + heads = p->end_head + 1; | |
1852 | + if (heads < 1 || heads > 16) | |
1853 | + continue; | |
1854 | + sectors = p->end_sector & 63; | |
1855 | + if (sectors == 0) | |
1856 | + continue; | |
1857 | + cylinders = s->nb_sectors / (heads * sectors); | |
1858 | + if (cylinders < 1 || cylinders > 16383) | |
1859 | + continue; | |
1860 | + s->heads = heads; | |
1861 | + s->sectors = sectors; | |
1862 | + s->cylinders = cylinders; | |
1854 | 1863 | #if 0 |
1855 | 1864 | printf("guessed partition: CHS=%d %d %d\n", |
1856 | 1865 | s->cylinders, s->heads, s->sectors); |
... | ... | @@ -1885,7 +1894,7 @@ static void ide_init2(IDEState *ide_state, int irq, |
1885 | 1894 | } else { |
1886 | 1895 | ide_guess_geometry(s); |
1887 | 1896 | if (s->cylinders == 0) { |
1888 | - /* if no geometry, use a LBA compatible one */ | |
1897 | + /* if no geometry, use a standard physical disk geometry */ | |
1889 | 1898 | cylinders = nb_sectors / (16 * 63); |
1890 | 1899 | if (cylinders > 16383) |
1891 | 1900 | cylinders = 16383; | ... | ... |
hw/pc.c
... | ... | @@ -217,19 +217,23 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table |
217 | 217 | val = 0; |
218 | 218 | for (i = 0; i < 4; i++) { |
219 | 219 | if (hd_table[i]) { |
220 | - int cylinders, heads, sectors; | |
221 | - uint8_t translation; | |
222 | - /* NOTE: bdrv_get_geometry_hint() returns the geometry | |
223 | - that the hard disk returns. It is always such that: 1 <= | |
224 | - sects <= 63, 1 <= heads <= 16, 1 <= cylinders <= | |
225 | - 16383. The BIOS geometry can be different. */ | |
226 | - bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, §ors); | |
227 | - if (cylinders <= 1024 && heads <= 16 && sectors <= 63) { | |
228 | - /* No translation. */ | |
229 | - translation = 0; | |
220 | + int cylinders, heads, sectors, translation; | |
221 | + /* NOTE: bdrv_get_geometry_hint() returns the physical | |
222 | + geometry. It is always such that: 1 <= sects <= 63, 1 | |
223 | + <= heads <= 16, 1 <= cylinders <= 16383. The BIOS | |
224 | + geometry can be different if a translation is done. */ | |
225 | + translation = bdrv_get_translation_hint(hd_table[i]); | |
226 | + if (translation == BIOS_ATA_TRANSLATION_AUTO) { | |
227 | + bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, §ors); | |
228 | + if (cylinders <= 1024 && heads <= 16 && sectors <= 63) { | |
229 | + /* No translation. */ | |
230 | + translation = 0; | |
231 | + } else { | |
232 | + /* LBA translation. */ | |
233 | + translation = 1; | |
234 | + } | |
230 | 235 | } else { |
231 | - /* LBA translation. */ | |
232 | - translation = 1; | |
236 | + translation--; | |
233 | 237 | } |
234 | 238 | val |= translation << (i * 2); |
235 | 239 | } | ... | ... |
qemu-doc.texi
... | ... | @@ -343,6 +343,12 @@ Change gdb connection port. |
343 | 343 | Do not start CPU at startup (you must type 'c' in the monitor). |
344 | 344 | @item -d |
345 | 345 | Output log in /tmp/qemu.log |
346 | +@item -hdachs c,h,s,[,t] | |
347 | +Force hard disk 0 physical geometry (1 <= @var{c} <= 16383, 1 <= | |
348 | +@var{h} <= 16, 1 <= @var{s} <= 63) and optionally force the BIOS | |
349 | +translation mode (@var{t}=none, lba or auto). Usually QEMU can guess | |
350 | +all thoses parameters. This option is useful for old MS-DOS disk | |
351 | +images. | |
346 | 352 | @item -isa |
347 | 353 | Simulate an ISA-only system (default is PCI system). |
348 | 354 | @item -std-vga | ... | ... |
vl.c
... | ... | @@ -2537,7 +2537,8 @@ void help(void) |
2537 | 2537 | "-s wait gdb connection to port %d\n" |
2538 | 2538 | "-p port change gdb connection port\n" |
2539 | 2539 | "-d item1,... output log to %s (use -d ? for a list of log items)\n" |
2540 | - "-hdachs c,h,s force hard disk 0 geometry (usually qemu can guess it)\n" | |
2540 | + "-hdachs c,h,s[,t] force hard disk 0 physical geometry and the optional BIOS\n" | |
2541 | + " translation (t=none or lba) (usually qemu can guess them)\n" | |
2541 | 2542 | "-L path set the directory for the BIOS and VGA BIOS\n" |
2542 | 2543 | #ifdef USE_CODE_COPY |
2543 | 2544 | "-no-code-copy disable code copy acceleration\n" |
... | ... | @@ -2753,7 +2754,7 @@ int main(int argc, char **argv) |
2753 | 2754 | const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD]; |
2754 | 2755 | const char *kernel_filename, *kernel_cmdline; |
2755 | 2756 | DisplayState *ds = &display_state; |
2756 | - int cyls, heads, secs; | |
2757 | + int cyls, heads, secs, translation; | |
2757 | 2758 | int start_emulation = 1; |
2758 | 2759 | uint8_t macaddr[6]; |
2759 | 2760 | int net_if_type, nb_tun_fds, tun_fds[MAX_NICS]; |
... | ... | @@ -2788,6 +2789,7 @@ int main(int argc, char **argv) |
2788 | 2789 | kernel_cmdline = ""; |
2789 | 2790 | has_cdrom = 1; |
2790 | 2791 | cyls = heads = secs = 0; |
2792 | + translation = BIOS_ATA_TRANSLATION_AUTO; | |
2791 | 2793 | pstrcpy(monitor_device, sizeof(monitor_device), "vc"); |
2792 | 2794 | |
2793 | 2795 | pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc"); |
... | ... | @@ -2857,17 +2859,34 @@ int main(int argc, char **argv) |
2857 | 2859 | const char *p; |
2858 | 2860 | p = optarg; |
2859 | 2861 | cyls = strtol(p, (char **)&p, 0); |
2862 | + if (cyls < 1 || cyls > 16383) | |
2863 | + goto chs_fail; | |
2860 | 2864 | if (*p != ',') |
2861 | 2865 | goto chs_fail; |
2862 | 2866 | p++; |
2863 | 2867 | heads = strtol(p, (char **)&p, 0); |
2868 | + if (heads < 1 || heads > 16) | |
2869 | + goto chs_fail; | |
2864 | 2870 | if (*p != ',') |
2865 | 2871 | goto chs_fail; |
2866 | 2872 | p++; |
2867 | 2873 | secs = strtol(p, (char **)&p, 0); |
2868 | - if (*p != '\0') { | |
2874 | + if (secs < 1 || secs > 63) | |
2875 | + goto chs_fail; | |
2876 | + if (*p == ',') { | |
2877 | + p++; | |
2878 | + if (!strcmp(p, "none")) | |
2879 | + translation = BIOS_ATA_TRANSLATION_NONE; | |
2880 | + else if (!strcmp(p, "lba")) | |
2881 | + translation = BIOS_ATA_TRANSLATION_LBA; | |
2882 | + else if (!strcmp(p, "auto")) | |
2883 | + translation = BIOS_ATA_TRANSLATION_AUTO; | |
2884 | + else | |
2885 | + goto chs_fail; | |
2886 | + } else if (*p != '\0') { | |
2869 | 2887 | chs_fail: |
2870 | - cyls = 0; | |
2888 | + fprintf(stderr, "qemu: invalid physical CHS format\n"); | |
2889 | + exit(1); | |
2871 | 2890 | } |
2872 | 2891 | } |
2873 | 2892 | break; |
... | ... | @@ -3230,8 +3249,10 @@ int main(int argc, char **argv) |
3230 | 3249 | hd_filename[i]); |
3231 | 3250 | exit(1); |
3232 | 3251 | } |
3233 | - if (i == 0 && cyls != 0) | |
3252 | + if (i == 0 && cyls != 0) { | |
3234 | 3253 | bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs); |
3254 | + bdrv_set_translation_hint(bs_table[i], translation); | |
3255 | + } | |
3235 | 3256 | } |
3236 | 3257 | } |
3237 | 3258 | ... | ... |
vl.h
... | ... | @@ -383,13 +383,18 @@ void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size); |
383 | 383 | #define BDRV_TYPE_HD 0 |
384 | 384 | #define BDRV_TYPE_CDROM 1 |
385 | 385 | #define BDRV_TYPE_FLOPPY 2 |
386 | +#define BIOS_ATA_TRANSLATION_AUTO 0 | |
387 | +#define BIOS_ATA_TRANSLATION_NONE 1 | |
388 | +#define BIOS_ATA_TRANSLATION_LBA 2 | |
386 | 389 | |
387 | 390 | void bdrv_set_geometry_hint(BlockDriverState *bs, |
388 | 391 | int cyls, int heads, int secs); |
389 | 392 | void bdrv_set_type_hint(BlockDriverState *bs, int type); |
393 | +void bdrv_set_translation_hint(BlockDriverState *bs, int translation); | |
390 | 394 | void bdrv_get_geometry_hint(BlockDriverState *bs, |
391 | 395 | int *pcyls, int *pheads, int *psecs); |
392 | 396 | int bdrv_get_type_hint(BlockDriverState *bs); |
397 | +int bdrv_get_translation_hint(BlockDriverState *bs); | |
393 | 398 | int bdrv_is_removable(BlockDriverState *bs); |
394 | 399 | int bdrv_is_read_only(BlockDriverState *bs); |
395 | 400 | int bdrv_is_inserted(BlockDriverState *bs); | ... | ... |