Commit 4fc9af53d88c0a2a810704a06cb39a7182982e4e

Authored by aliguori
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
@@ -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
@@ -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 */
@@ -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];