vgabios: Unify code to generate the vbe mode list.
[seabios.git] / src / post.c
index 4d9993561d7050b922b4800f39cd093267cbe797..b4ad1fa07b3dde5ec9c7d8870bf18315c116af8f 100644 (file)
@@ -12,6 +12,7 @@
 #include "biosvar.h" // struct bios_data_area_s
 #include "disk.h" // floppy_drive_setup
 #include "ata.h" // ata_setup
+#include "ahci.h" // ahci_setup
 #include "memmap.h" // add_e820
 #include "pic.h" // pic_setup
 #include "pci.h" // create_pirtable
@@ -22,6 +23,7 @@
 #include "usb.h" // usb_setup
 #include "smbios.h" // smbios_init
 #include "paravirt.h" // qemu_cfg_port_probe
+#include "xen.h" // xen_probe_hvm_info
 #include "ps2port.h" // ps2port_setup
 #include "virtio-blk.h" // virtio_blk_setup
 
@@ -100,6 +102,8 @@ ram_probe(void)
     dprintf(3, "Find memory size\n");
     if (CONFIG_COREBOOT) {
         coreboot_setup();
+    } else if (usingXen()) {
+       xen_setup();
     } else {
         // On emulators, get memory size from nvram.
         u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16)
@@ -157,6 +161,10 @@ init_bios_tables(void)
         coreboot_copy_biostable();
         return;
     }
+    if (usingXen()) {
+       xen_copy_biostables();
+       return;
+    }
 
     create_pirtable();
 
@@ -178,12 +186,14 @@ init_hw(void)
 
     floppy_setup();
     ata_setup();
+    ahci_setup();
+    cbfs_payload_setup();
     ramdisk_setup();
     virtio_blk_setup();
 }
 
 // Begin the boot process by invoking an int0x19 in 16bit mode.
-static void
+void VISIBLE32FLAT
 startBoot(void)
 {
     // Clear low-memory allocations (required by PMM spec).
@@ -200,27 +210,30 @@ startBoot(void)
 static void
 maininit(void)
 {
+    // Running at new code address - do code relocation fixups
+    malloc_fixupreloc();
+
     // Setup ivt/bda/ebda
     init_ivt();
     init_bda();
 
     // Init base pc hardware.
-    thread_setup();
     pic_setup();
     timer_setup();
     mathcp_setup();
 
     // Initialize mtrr
-    smp_probe_setup();
     mtrr_setup();
 
     // Initialize pci
     pci_setup();
     smm_init();
 
+    // Setup Xen hypercalls
+    xen_init_hypercalls();
+
     // Initialize internal tables
     boot_setup();
-    drive_setup();
 
     // Start hardware initialization (if optionrom threading)
     if (CONFIG_THREADS && CONFIG_THREAD_OPTIONROMS)
@@ -268,69 +281,97 @@ maininit(void)
     startBoot();
 }
 
-static int HaveRunPost;
 
-// Start of Power On Self Test (POST) - the BIOS initilization phase.
-void VISIBLE32INIT
-post(void)
+/****************************************************************
+ * POST entry and code relocation
+ ****************************************************************/
+
+// Update given relocs for the code at 'dest' with a given 'delta'
+static void
+updateRelocs(void *dest, u32 *rstart, u32 *rend, u32 delta)
 {
-    // Allow writes to modify bios area (0xf0000)
-    make_bios_writable();
+    u32 *reloc;
+    for (reloc = rstart; reloc < rend; reloc++)
+        *((u32*)(dest + *reloc)) += delta;
+}
+
+// Relocate init code and then call maininit() at new address.
+static void
+reloc_init(void)
+{
+    if (!CONFIG_RELOCATE_INIT) {
+        maininit();
+        return;
+    }
+    // Symbols populated by the build.
+    extern u8 code32flat_start[];
+    extern u8 _reloc_min_align[];
+    extern u32 _reloc_abs_start[], _reloc_abs_end[];
+    extern u32 _reloc_rel_start[], _reloc_rel_end[];
+    extern u32 _reloc_init_start[], _reloc_init_end[];
+    extern u8 code32init_start[], code32init_end[];
+
+    // Allocate space for init code.
+    u32 initsize = code32init_end - code32init_start;
+    u32 align = (u32)&_reloc_min_align;
+    void *dest = memalign_tmp(align, initsize);
+    if (!dest)
+        panic("No space for init relocation.\n");
+
+    // Copy code and update relocs (init absolute, init relative, and runtime)
+    dprintf(1, "Relocating init from %p to %p (size %d)\n"
+            , code32init_start, dest, initsize);
+    s32 delta = dest - (void*)code32init_start;
+    memcpy(dest, code32init_start, initsize);
+    updateRelocs(dest, _reloc_abs_start, _reloc_abs_end, delta);
+    updateRelocs(dest, _reloc_rel_start, _reloc_rel_end, -delta);
+    updateRelocs(code32flat_start, _reloc_init_start, _reloc_init_end, delta);
+
+    // Call maininit() in relocated code.
+    void (*func)(void) = (void*)maininit + delta;
+    barrier();
+    func();
+}
 
+// Setup for code relocation and then call reloc_init
+void VISIBLE32INIT
+dopost(void)
+{
     HaveRunPost = 1;
 
     // Detect ram and setup internal malloc.
-    memmap_setup();
     qemu_cfg_port_probe();
     ram_probe();
     malloc_setup();
 
-    maininit();
+    // Relocate initialization code and call maininit().
+    reloc_init();
 }
 
-
-/****************************************************************
- * POST entry point
- ****************************************************************/
-
-// Attempt to invoke a hard-reboot.
-static void
-tryReboot(void)
+// Entry point for Power On Self Test (POST) - the BIOS initilization
+// phase.  This function makes the memory at 0xc0000-0xfffff
+// read/writable and then calls dopost().
+void VISIBLE32FLAT
+handle_post(void)
 {
-    dprintf(1, "Attempting a hard reboot\n");
-
-    // Setup for reset on qemu.
-    if (! CONFIG_COREBOOT) {
-        qemu_prep_reset();
-        if (HaveRunPost)
-            apm_shutdown();
-    }
-
-    // Try keyboard controller reboot.
-    i8042_reboot();
+    debug_serial_setup();
+    dprintf(1, "Start bios (version %s)\n", VERSION);
 
-    // Try PCI 0xcf9 reboot
-    pci_reboot();
+    // Enable CPU caching
+    setcr0(getcr0() & ~(CR0_CD|CR0_NW));
 
-    // Try triple fault
-    asm volatile("int3");
+    // Clear CMOS reboot flag.
+    outb_cmos(0, CMOS_RESET_CODE);
 
-    panic("Could not reboot");
-}
-
-// 32-bit entry point.
-void VISIBLE32FLAT
-_start(void)
-{
+    // Make sure legacy DMA isn't running.
     init_dma();
 
-    debug_serial_setup();
-    dprintf(1, "Start bios (version %s)\n", VERSION);
+    // Check if we are running under Xen.
+    xen_probe();
 
-    if (HaveRunPost)
-        // This is a soft reboot - invoke a hard reboot.
-        tryReboot();
+    // Allow writes to modify bios area (0xf0000)
+    make_bios_writable();
 
-    // Perform main setup code.
-    post();
+    // Now that memory is read/writable - start post process.
+    dopost();
 }