Commit 4fc9af53d88c0a2a810704a06cb39a7182982e4e
1 parent
6223246a
Use an option rom instead of boot sector for -kernel
Generate an option rom instead of using a hijacked boot sector for kernel booting. This just requires adding a small option ROM header and a few more instructions to the boot sector to take over the int19 vector and run our boot code. A disk is no longer needed when using -kernel on x86. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5650 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
50 additions
and
58 deletions
block.c
| @@ -527,14 +527,6 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num, | @@ -527,14 +527,6 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num, | ||
| 527 | if (!drv) | 527 | if (!drv) |
| 528 | return -ENOMEDIUM; | 528 | return -ENOMEDIUM; |
| 529 | 529 | ||
| 530 | - if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { | ||
| 531 | - memcpy(buf, bs->boot_sector_data, 512); | ||
| 532 | - sector_num++; | ||
| 533 | - nb_sectors--; | ||
| 534 | - buf += 512; | ||
| 535 | - if (nb_sectors == 0) | ||
| 536 | - return 0; | ||
| 537 | - } | ||
| 538 | if (drv->bdrv_pread) { | 530 | if (drv->bdrv_pread) { |
| 539 | int ret, len; | 531 | int ret, len; |
| 540 | len = nb_sectors * 512; | 532 | len = nb_sectors * 512; |
| @@ -567,9 +559,6 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num, | @@ -567,9 +559,6 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num, | ||
| 567 | return -ENOMEDIUM; | 559 | return -ENOMEDIUM; |
| 568 | if (bs->read_only) | 560 | if (bs->read_only) |
| 569 | return -EACCES; | 561 | return -EACCES; |
| 570 | - if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { | ||
| 571 | - memcpy(bs->boot_sector_data, buf, 512); | ||
| 572 | - } | ||
| 573 | if (drv->bdrv_pwrite) { | 562 | if (drv->bdrv_pwrite) { |
| 574 | int ret, len; | 563 | int ret, len; |
| 575 | len = nb_sectors * 512; | 564 | len = nb_sectors * 512; |
| @@ -750,16 +739,6 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr) | @@ -750,16 +739,6 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr) | ||
| 750 | *nb_sectors_ptr = length; | 739 | *nb_sectors_ptr = length; |
| 751 | } | 740 | } |
| 752 | 741 | ||
| 753 | -/* force a given boot sector. */ | ||
| 754 | -void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size) | ||
| 755 | -{ | ||
| 756 | - bs->boot_sector_enabled = 1; | ||
| 757 | - if (size > 512) | ||
| 758 | - size = 512; | ||
| 759 | - memcpy(bs->boot_sector_data, data, size); | ||
| 760 | - memset(bs->boot_sector_data + size, 0, 512 - size); | ||
| 761 | -} | ||
| 762 | - | ||
| 763 | void bdrv_set_geometry_hint(BlockDriverState *bs, | 742 | void bdrv_set_geometry_hint(BlockDriverState *bs, |
| 764 | int cyls, int heads, int secs) | 743 | int cyls, int heads, int secs) |
| 765 | { | 744 | { |
| @@ -1155,14 +1134,6 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, | @@ -1155,14 +1134,6 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num, | ||
| 1155 | if (!drv) | 1134 | if (!drv) |
| 1156 | return NULL; | 1135 | return NULL; |
| 1157 | 1136 | ||
| 1158 | - /* XXX: we assume that nb_sectors == 0 is suppored by the async read */ | ||
| 1159 | - if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { | ||
| 1160 | - memcpy(buf, bs->boot_sector_data, 512); | ||
| 1161 | - sector_num++; | ||
| 1162 | - nb_sectors--; | ||
| 1163 | - buf += 512; | ||
| 1164 | - } | ||
| 1165 | - | ||
| 1166 | ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque); | 1137 | ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque); |
| 1167 | 1138 | ||
| 1168 | if (ret) { | 1139 | if (ret) { |
| @@ -1185,9 +1156,6 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, | @@ -1185,9 +1156,6 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num, | ||
| 1185 | return NULL; | 1156 | return NULL; |
| 1186 | if (bs->read_only) | 1157 | if (bs->read_only) |
| 1187 | return NULL; | 1158 | return NULL; |
| 1188 | - if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { | ||
| 1189 | - memcpy(bs->boot_sector_data, buf, 512); | ||
| 1190 | - } | ||
| 1191 | 1159 | ||
| 1192 | ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque); | 1160 | ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque); |
| 1193 | 1161 |
block.h
| @@ -79,7 +79,6 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset); | @@ -79,7 +79,6 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset); | ||
| 79 | int64_t bdrv_getlength(BlockDriverState *bs); | 79 | int64_t bdrv_getlength(BlockDriverState *bs); |
| 80 | void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); | 80 | void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); |
| 81 | int bdrv_commit(BlockDriverState *bs); | 81 | int bdrv_commit(BlockDriverState *bs); |
| 82 | -void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size); | ||
| 83 | /* async block I/O */ | 82 | /* async block I/O */ |
| 84 | typedef struct BlockDriverAIOCB BlockDriverAIOCB; | 83 | typedef struct BlockDriverAIOCB BlockDriverAIOCB; |
| 85 | typedef void BlockDriverCompletionFunc(void *opaque, int ret); | 84 | typedef void BlockDriverCompletionFunc(void *opaque, int ret); |
block_int.h
| @@ -104,9 +104,6 @@ struct BlockDriverState { | @@ -104,9 +104,6 @@ struct BlockDriverState { | ||
| 104 | BlockDriver *drv; /* NULL means no media */ | 104 | BlockDriver *drv; /* NULL means no media */ |
| 105 | void *opaque; | 105 | void *opaque; |
| 106 | 106 | ||
| 107 | - int boot_sector_enabled; | ||
| 108 | - uint8_t boot_sector_data[512]; | ||
| 109 | - | ||
| 110 | char filename[1024]; | 107 | char filename[1024]; |
| 111 | char backing_file[1024]; /* if non zero, the image is a diff of | 108 | char backing_file[1024]; /* if non zero, the image is a diff of |
| 112 | this file image */ | 109 | this file image */ |
hw/pc.c
| @@ -438,30 +438,45 @@ static void bochs_bios_init(void) | @@ -438,30 +438,45 @@ static void bochs_bios_init(void) | ||
| 438 | 438 | ||
| 439 | /* Generate an initial boot sector which sets state and jump to | 439 | /* Generate an initial boot sector which sets state and jump to |
| 440 | a specified vector */ | 440 | a specified vector */ |
| 441 | -static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip) | 441 | +static void generate_bootsect(uint8_t *option_rom, |
| 442 | + uint32_t gpr[8], uint16_t segs[6], uint16_t ip) | ||
| 442 | { | 443 | { |
| 443 | - uint8_t bootsect[512], *p; | 444 | + uint8_t rom[512], *p, *reloc; |
| 445 | + uint8_t sum; | ||
| 444 | int i; | 446 | int i; |
| 445 | - int hda; | ||
| 446 | 447 | ||
| 447 | - hda = drive_get_index(IF_IDE, 0, 0); | ||
| 448 | - if (hda == -1) { | ||
| 449 | - fprintf(stderr, "A disk image must be given for 'hda' when booting " | ||
| 450 | - "a Linux kernel\n(if you really don't want it, use /dev/zero)\n"); | ||
| 451 | - exit(1); | ||
| 452 | - } | 448 | + memset(rom, 0, sizeof(rom)); |
| 449 | + | ||
| 450 | + p = rom; | ||
| 451 | + /* Make sure we have an option rom signature */ | ||
| 452 | + *p++ = 0x55; | ||
| 453 | + *p++ = 0xaa; | ||
| 453 | 454 | ||
| 454 | - memset(bootsect, 0, sizeof(bootsect)); | 455 | + /* ROM size in sectors*/ |
| 456 | + *p++ = 1; | ||
| 455 | 457 | ||
| 456 | - /* Copy the MSDOS partition table if possible */ | ||
| 457 | - bdrv_read(drives_table[hda].bdrv, 0, bootsect, 1); | 458 | + /* Hook int19 */ |
| 458 | 459 | ||
| 459 | - /* Make sure we have a partition signature */ | ||
| 460 | - bootsect[510] = 0x55; | ||
| 461 | - bootsect[511] = 0xaa; | 460 | + *p++ = 0x50; /* push ax */ |
| 461 | + *p++ = 0x1e; /* push ds */ | ||
| 462 | + *p++ = 0x31; *p++ = 0xc0; /* xor ax, ax */ | ||
| 463 | + *p++ = 0x8e; *p++ = 0xd8; /* mov ax, ds */ | ||
| 462 | 464 | ||
| 465 | + *p++ = 0xc7; *p++ = 0x06; /* movvw _start,0x64 */ | ||
| 466 | + *p++ = 0x64; *p++ = 0x00; | ||
| 467 | + reloc = p; | ||
| 468 | + *p++ = 0x00; *p++ = 0x00; | ||
| 469 | + | ||
| 470 | + *p++ = 0x8c; *p++ = 0x0e; /* mov cs,0x66 */ | ||
| 471 | + *p++ = 0x66; *p++ = 0x00; | ||
| 472 | + | ||
| 473 | + *p++ = 0x1f; /* pop ds */ | ||
| 474 | + *p++ = 0x58; /* pop ax */ | ||
| 475 | + *p++ = 0xcb; /* lret */ | ||
| 476 | + | ||
| 463 | /* Actual code */ | 477 | /* Actual code */ |
| 464 | - p = bootsect; | 478 | + *reloc = (p - rom); |
| 479 | + | ||
| 465 | *p++ = 0xfa; /* CLI */ | 480 | *p++ = 0xfa; /* CLI */ |
| 466 | *p++ = 0xfc; /* CLD */ | 481 | *p++ = 0xfc; /* CLD */ |
| 467 | 482 | ||
| @@ -491,7 +506,13 @@ static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip) | @@ -491,7 +506,13 @@ static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip) | ||
| 491 | *p++ = segs[1]; /* CS */ | 506 | *p++ = segs[1]; /* CS */ |
| 492 | *p++ = segs[1] >> 8; | 507 | *p++ = segs[1] >> 8; |
| 493 | 508 | ||
| 494 | - bdrv_set_boot_sector(drives_table[hda].bdrv, bootsect, sizeof(bootsect)); | 509 | + /* sign rom */ |
| 510 | + sum = 0; | ||
| 511 | + for (i = 0; i < (sizeof(rom) - 1); i++) | ||
| 512 | + sum += rom[i]; | ||
| 513 | + rom[sizeof(rom) - 1] = -sum; | ||
| 514 | + | ||
| 515 | + memcpy(option_rom, rom, sizeof(rom)); | ||
| 495 | } | 516 | } |
| 496 | 517 | ||
| 497 | static long get_file_size(FILE *f) | 518 | static long get_file_size(FILE *f) |
| @@ -508,7 +529,8 @@ static long get_file_size(FILE *f) | @@ -508,7 +529,8 @@ static long get_file_size(FILE *f) | ||
| 508 | return size; | 529 | return size; |
| 509 | } | 530 | } |
| 510 | 531 | ||
| 511 | -static void load_linux(const char *kernel_filename, | 532 | +static void load_linux(uint8_t *option_rom, |
| 533 | + const char *kernel_filename, | ||
| 512 | const char *initrd_filename, | 534 | const char *initrd_filename, |
| 513 | const char *kernel_cmdline) | 535 | const char *kernel_cmdline) |
| 514 | { | 536 | { |
| @@ -658,7 +680,7 @@ static void load_linux(const char *kernel_filename, | @@ -658,7 +680,7 @@ static void load_linux(const char *kernel_filename, | ||
| 658 | memset(gpr, 0, sizeof gpr); | 680 | memset(gpr, 0, sizeof gpr); |
| 659 | gpr[4] = cmdline_addr-real_addr-16; /* SP (-16 is paranoia) */ | 681 | gpr[4] = cmdline_addr-real_addr-16; /* SP (-16 is paranoia) */ |
| 660 | 682 | ||
| 661 | - generate_bootsect(gpr, seg, 0); | 683 | + generate_bootsect(option_rom, gpr, seg, 0); |
| 662 | } | 684 | } |
| 663 | 685 | ||
| 664 | static void main_cpu_reset(void *opaque) | 686 | static void main_cpu_reset(void *opaque) |
| @@ -862,6 +884,15 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, | @@ -862,6 +884,15 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, | ||
| 862 | int size, offset; | 884 | int size, offset; |
| 863 | 885 | ||
| 864 | offset = 0; | 886 | offset = 0; |
| 887 | + if (linux_boot) { | ||
| 888 | + option_rom_offset = qemu_ram_alloc(TARGET_PAGE_SIZE); | ||
| 889 | + load_linux(phys_ram_base + option_rom_offset, | ||
| 890 | + kernel_filename, initrd_filename, kernel_cmdline); | ||
| 891 | + cpu_register_physical_memory(0xd0000, TARGET_PAGE_SIZE, | ||
| 892 | + option_rom_offset | IO_MEM_ROM); | ||
| 893 | + offset = TARGET_PAGE_SIZE; | ||
| 894 | + } | ||
| 895 | + | ||
| 865 | for (i = 0; i < nb_option_roms; i++) { | 896 | for (i = 0; i < nb_option_roms; i++) { |
| 866 | size = get_image_size(option_rom[i]); | 897 | size = get_image_size(option_rom[i]); |
| 867 | if (size < 0) { | 898 | if (size < 0) { |
| @@ -891,9 +922,6 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, | @@ -891,9 +922,6 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, | ||
| 891 | 922 | ||
| 892 | bochs_bios_init(); | 923 | bochs_bios_init(); |
| 893 | 924 | ||
| 894 | - if (linux_boot) | ||
| 895 | - load_linux(kernel_filename, initrd_filename, kernel_cmdline); | ||
| 896 | - | ||
| 897 | cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1); | 925 | cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1); |
| 898 | i8259 = i8259_init(cpu_irq[0]); | 926 | i8259 = i8259_init(cpu_irq[0]); |
| 899 | ferr_irq = i8259[13]; | 927 | ferr_irq = i8259[13]; |