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); | ... | ... |