]> git.proxmox.com Git - qemu.git/blobdiff - hw/pc.c
Add v{add, sub}{s, u}{b, h, w}s instructions
[qemu.git] / hw / pc.c
diff --git a/hw/pc.c b/hw/pc.c
index 167d628fca58afb5091cb744de62a6e71183caaf..64c08a434275728f0e2910857d1dc55ae8b304d8 100644 (file)
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -33,6 +33,9 @@
 #include "boards.h"
 #include "console.h"
 #include "fw_cfg.h"
+#include "virtio-blk.h"
+#include "virtio-balloon.h"
+#include "hpet_emul.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -438,30 +441,45 @@ static void bochs_bios_init(void)
 
 /* 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));
+
+    p = rom;
+    /* Make sure we have an option rom signature */
+    *p++ = 0x55;
+    *p++ = 0xaa;
 
-    memset(bootsect, 0, sizeof(bootsect));
+    /* ROM size in sectors*/
+    *p++ = 1;
 
-    /* Copy the MSDOS partition table if possible */
-    bdrv_read(drives_table[hda].bdrv, 0, bootsect, 1);
+    /* Hook int19 */
 
-    /* Make sure we have a partition signature */
-    bootsect[510] = 0x55;
-    bootsect[511] = 0xaa;
+    *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 +509,13 @@ static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
     *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 +532,8 @@ static long get_file_size(FILE *f)
     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 +683,7 @@ static void load_linux(const char *kernel_filename,
     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 +887,15 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
         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 +925,6 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
 
     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];
@@ -947,6 +978,9 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
     }
     pit = pit_init(0x40, i8259[0]);
     pcspk_init(pit);
+    if (!no_hpet) {
+        hpet_init(i8259);
+    }
     if (pci_enabled) {
         pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
     }
@@ -1064,6 +1098,21 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
            }
         }
     }
+
+    /* Add virtio block devices */
+    if (pci_enabled) {
+        int index;
+        int unit_id = 0;
+
+        while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
+            virtio_blk_init(pci_bus, drives_table[index].bdrv);
+            unit_id++;
+        }
+    }
+
+    /* Add virtio balloon device */
+    if (pci_enabled)
+        virtio_balloon_init(pci_bus);
 }
 
 static void pc_init_pci(ram_addr_t ram_size, int vga_ram_size,
@@ -1090,6 +1139,14 @@ static void pc_init_isa(ram_addr_t ram_size, int vga_ram_size,
              initrd_filename, 0, cpu_model);
 }
 
+/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
+   BIOS will read it and start S3 resume at POST Entry */
+void cmos_set_s3_resume(void)
+{
+    if (rtc_state)
+        rtc_set_memory(rtc_state, 0xF, 0xFE);
+}
+
 QEMUMachine pc_machine = {
     .name = "pc",
     .desc = "Standard PC",