qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [5650] Use an option rom instead of boot sector for -kernel


From: Anthony Liguori
Subject: [Qemu-devel] [5650] Use an option rom instead of boot sector for -kernel
Date: Sat, 08 Nov 2008 16:27:08 +0000

Revision: 5650
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5650
Author:   aliguori
Date:     2008-11-08 16:27:07 +0000 (Sat, 08 Nov 2008)

Log Message:
-----------
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 <address@hidden>

Modified Paths:
--------------
    trunk/block.c
    trunk/block.h
    trunk/block_int.h
    trunk/hw/pc.c

Modified: trunk/block.c
===================================================================
--- trunk/block.c       2008-11-08 09:10:39 UTC (rev 5649)
+++ trunk/block.c       2008-11-08 16:27:07 UTC (rev 5650)
@@ -527,14 +527,6 @@
     if (!drv)
         return -ENOMEDIUM;
 
-    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
-            memcpy(buf, bs->boot_sector_data, 512);
-        sector_num++;
-        nb_sectors--;
-        buf += 512;
-        if (nb_sectors == 0)
-            return 0;
-    }
     if (drv->bdrv_pread) {
         int ret, len;
         len = nb_sectors * 512;
@@ -567,9 +559,6 @@
         return -ENOMEDIUM;
     if (bs->read_only)
         return -EACCES;
-    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
-        memcpy(bs->boot_sector_data, buf, 512);
-    }
     if (drv->bdrv_pwrite) {
         int ret, len;
         len = nb_sectors * 512;
@@ -750,16 +739,6 @@
     *nb_sectors_ptr = length;
 }
 
-/* force a given boot sector. */
-void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
-{
-    bs->boot_sector_enabled = 1;
-    if (size > 512)
-        size = 512;
-    memcpy(bs->boot_sector_data, data, size);
-    memset(bs->boot_sector_data + size, 0, 512 - size);
-}
-
 void bdrv_set_geometry_hint(BlockDriverState *bs,
                             int cyls, int heads, int secs)
 {
@@ -1155,14 +1134,6 @@
     if (!drv)
         return NULL;
 
-    /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
-    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
-        memcpy(buf, bs->boot_sector_data, 512);
-        sector_num++;
-        nb_sectors--;
-        buf += 512;
-    }
-
     ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
 
     if (ret) {
@@ -1185,9 +1156,6 @@
         return NULL;
     if (bs->read_only)
         return NULL;
-    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
-        memcpy(bs->boot_sector_data, buf, 512);
-    }
 
     ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
 

Modified: trunk/block.h
===================================================================
--- trunk/block.h       2008-11-08 09:10:39 UTC (rev 5649)
+++ trunk/block.h       2008-11-08 16:27:07 UTC (rev 5650)
@@ -79,7 +79,6 @@
 int64_t bdrv_getlength(BlockDriverState *bs);
 void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
 int bdrv_commit(BlockDriverState *bs);
-void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
 /* async block I/O */
 typedef struct BlockDriverAIOCB BlockDriverAIOCB;
 typedef void BlockDriverCompletionFunc(void *opaque, int ret);

Modified: trunk/block_int.h
===================================================================
--- trunk/block_int.h   2008-11-08 09:10:39 UTC (rev 5649)
+++ trunk/block_int.h   2008-11-08 16:27:07 UTC (rev 5650)
@@ -104,9 +104,6 @@
     BlockDriver *drv; /* NULL means no media */
     void *opaque;
 
-    int boot_sector_enabled;
-    uint8_t boot_sector_data[512];
-
     char filename[1024];
     char backing_file[1024]; /* if non zero, the image is a diff of
                                 this file image */

Modified: trunk/hw/pc.c
===================================================================
--- trunk/hw/pc.c       2008-11-08 09:10:39 UTC (rev 5649)
+++ trunk/hw/pc.c       2008-11-08 16:27:07 UTC (rev 5650)
@@ -438,30 +438,45 @@
 
 /* Generate an initial boot sector which sets state and jump to
    a specified vector */
-static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
+static void generate_bootsect(uint8_t *option_rom,
+                              uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
 {
-    uint8_t bootsect[512], *p;
+    uint8_t rom[512], *p, *reloc;
+    uint8_t sum;
     int i;
-    int hda;
 
-    hda = drive_get_index(IF_IDE, 0, 0);
-    if (hda == -1) {
-       fprintf(stderr, "A disk image must be given for 'hda' when booting "
-               "a Linux kernel\n(if you really don't want it, use 
/dev/zero)\n");
-       exit(1);
-    }
+    memset(rom, 0, sizeof(rom));
 
-    memset(bootsect, 0, sizeof(bootsect));
+    p = rom;
+    /* Make sure we have an option rom signature */
+    *p++ = 0x55;
+    *p++ = 0xaa;
 
-    /* Copy the MSDOS partition table if possible */
-    bdrv_read(drives_table[hda].bdrv, 0, bootsect, 1);
+    /* ROM size in sectors*/
+    *p++ = 1;
 
-    /* Make sure we have a partition signature */
-    bootsect[510] = 0x55;
-    bootsect[511] = 0xaa;
+    /* Hook int19 */
 
+    *p++ = 0x50;               /* push ax */
+    *p++ = 0x1e;               /* push ds */
+    *p++ = 0x31; *p++ = 0xc0;  /* xor ax, ax */
+    *p++ = 0x8e; *p++ = 0xd8;  /* mov ax, ds */
+
+    *p++ = 0xc7; *p++ = 0x06;   /* movvw _start,0x64 */
+    *p++ = 0x64; *p++ = 0x00;
+    reloc = p;
+    *p++ = 0x00; *p++ = 0x00;
+
+    *p++ = 0x8c; *p++ = 0x0e;   /* mov cs,0x66 */
+    *p++ = 0x66; *p++ = 0x00;
+
+    *p++ = 0x1f;               /* pop ds */
+    *p++ = 0x58;               /* pop ax */
+    *p++ = 0xcb;               /* lret */
+    
     /* Actual code */
-    p = bootsect;
+    *reloc = (p - rom);
+
     *p++ = 0xfa;               /* CLI */
     *p++ = 0xfc;               /* CLD */
 
@@ -491,7 +506,13 @@
     *p++ = segs[1];            /* CS */
     *p++ = segs[1] >> 8;
 
-    bdrv_set_boot_sector(drives_table[hda].bdrv, bootsect, sizeof(bootsect));
+    /* sign rom */
+    sum = 0;
+    for (i = 0; i < (sizeof(rom) - 1); i++)
+        sum += rom[i];
+    rom[sizeof(rom) - 1] = -sum;
+
+    memcpy(option_rom, rom, sizeof(rom));
 }
 
 static long get_file_size(FILE *f)
@@ -508,7 +529,8 @@
     return size;
 }
 
-static void load_linux(const char *kernel_filename,
+static void load_linux(uint8_t *option_rom,
+                       const char *kernel_filename,
                       const char *initrd_filename,
                       const char *kernel_cmdline)
 {
@@ -658,7 +680,7 @@
     memset(gpr, 0, sizeof gpr);
     gpr[4] = cmdline_addr-real_addr-16;        /* SP (-16 is paranoia) */
 
-    generate_bootsect(gpr, seg, 0);
+    generate_bootsect(option_rom, gpr, seg, 0);
 }
 
 static void main_cpu_reset(void *opaque)
@@ -862,6 +884,15 @@
         int size, offset;
 
         offset = 0;
+        if (linux_boot) {
+            option_rom_offset = qemu_ram_alloc(TARGET_PAGE_SIZE);
+            load_linux(phys_ram_base + option_rom_offset,
+                       kernel_filename, initrd_filename, kernel_cmdline);
+            cpu_register_physical_memory(0xd0000, TARGET_PAGE_SIZE,
+                                         option_rom_offset | IO_MEM_ROM);
+            offset = TARGET_PAGE_SIZE;
+        }
+
         for (i = 0; i < nb_option_roms; i++) {
             size = get_image_size(option_rom[i]);
             if (size < 0) {
@@ -891,9 +922,6 @@
 
     bochs_bios_init();
 
-    if (linux_boot)
-       load_linux(kernel_filename, initrd_filename, kernel_cmdline);
-
     cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
     i8259 = i8259_init(cpu_irq[0]);
     ferr_irq = i8259[13];






reply via email to

[Prev in Thread] Current Thread [Next in Thread]