grml...
[seabios.git] / src / post.c
index f1ab6befaad02377ded1776cae3867d6fa0e4d97..cf7501ebbd67e475c0b2c6fd30f11b7051cd9f5e 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
 #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
 
+
+/****************************************************************
+ * BIOS init
+ ****************************************************************/
+
 static void
 init_ivt(void)
 {
@@ -77,13 +84,16 @@ init_bda(void)
 
     int esize = EBDA_SIZE_START;
     SET_BDA(mem_size_kb, BUILD_LOWRAM_END/1024 - esize);
-    u16 eseg = EBDA_SEGMENT_START;
-    SET_BDA(ebda_seg, eseg);
+    u16 ebda_seg = EBDA_SEGMENT_START;
+    SET_BDA(ebda_seg, ebda_seg);
 
     // Init ebda
     struct extended_bios_data_area_s *ebda = get_ebda_ptr();
     memset(ebda, 0, sizeof(*ebda));
     ebda->size = esize;
+
+    add_e820((u32)MAKE_FLATPTR(ebda_seg, 0), GET_EBDA2(ebda_seg, size) * 1024
+             , E820_RESERVED);
 }
 
 static void
@@ -92,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)
@@ -120,9 +132,6 @@ ram_probe(void)
     add_e820(BUILD_LOWRAM_END, BUILD_BIOS_ADDR-BUILD_LOWRAM_END, E820_HOLE);
 
     // Mark known areas as reserved.
-    u16 ebda_seg = get_ebda_seg();
-    add_e820((u32)MAKE_FLATPTR(ebda_seg, 0), GET_EBDA2(ebda_seg, size) * 1024
-             , E820_RESERVED);
     add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED);
 
     u32 count = qemu_cfg_e820_entries();
@@ -152,6 +161,10 @@ init_bios_tables(void)
         coreboot_copy_biostable();
         return;
     }
+    if (usingXen()) {
+       xen_copy_biostables();
+       return;
+    }
 
     create_pirtable();
 
@@ -173,22 +186,36 @@ 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.
+void VISIBLE32FLAT
+startBoot(void)
+{
+    // Clear low-memory allocations (required by PMM spec).
+    memset((void*)BUILD_STACK_ADDR, 0, BUILD_EBDA_MINIMUM - BUILD_STACK_ADDR);
+
+    dprintf(3, "Jump to int19\n");
+    struct bregs br;
+    memset(&br, 0, sizeof(br));
+    br.flags = F_IF;
+    call16_int(0x19, &br);
+}
+
 // Main setup code.
-void VISIBLE32INIT
-post(void)
+static void
+maininit(void)
 {
-    // Detect and init ram.
+    // Running at new code address - do code relocation fixups
+    malloc_fixupreloc();
+
+    // Setup ivt/bda/ebda
     init_ivt();
     init_bda();
-    memmap_setup();
-    qemu_cfg_port_probe();
-    ram_probe();
-    malloc_setup();
-    thread_setup();
 
     // Init base pc hardware.
     pic_setup();
@@ -196,16 +223,17 @@ post(void)
     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)
@@ -216,13 +244,19 @@ post(void)
 
     // Setup interfaces that option roms may need
     bios32_setup();
+       dprintf(3, "[wurm] pmm_setup\n");
     pmm_setup();
+       dprintf(3, "[wurm] pnp_setup\n");
     pnp_setup();
+       dprintf(3, "[wurm] kbd_setup\n");
     kbd_setup();
+       dprintf(3, "[wurm] mouse_setup\n");
     mouse_setup();
+       dprintf(3, "[wurm] init_bios_tables\n");
     init_bios_tables();
 
     // Run vga option rom
+       dprintf(3, "[wurm] vga_setup\n");
     vga_setup();
 
     // Do hardware initialization (if running synchronously)
@@ -232,76 +266,126 @@ post(void)
     }
 
     // Run option roms
+       dprintf(3, "[wurm] optionrom_setup\n");
     optionrom_setup();
 
     // Run BCVs and show optional boot menu
+       dprintf(3, "[wurm] boot_prep\n");
     boot_prep();
 
     // Finalize data structures before boot
+       dprintf(3, "[wurm] cdemu_setup\n");
     cdemu_setup();
+       dprintf(3, "[wurm] pmm_finalize\n");
     pmm_finalize();
+       dprintf(3, "[wurm] malloc_finalize\n");
     malloc_finalize();
+       dprintf(3, "[wurm] memmap_finalize\n");
     memmap_finalize();
+
+    // Setup bios checksum.
+    BiosChecksum -= checksum((u8*)BUILD_BIOS_ADDR, BUILD_BIOS_SIZE);
+
+    // Write protect bios memory.
+       dprintf(3, "[wurm] make_bios_readonly\n");
+    make_bios_readonly();
+
+    // Invoke int 19 to start boot process.
+       dprintf(3, "[wurm] startBoot\n");
+    startBoot();
 }
 
-static int HaveRunPost;
 
-// Attempt to invoke a hard-reboot.
+/****************************************************************
+ * POST entry and code relocation
+ ****************************************************************/
+
+// Update given relocs for the code at 'dest' with a given 'delta'
 static void
-tryReboot(void)
+updateRelocs(void *dest, u32 *rstart, u32 *rend, u32 delta)
 {
-    dprintf(1, "Attempting a hard reboot\n");
+    u32 *reloc;
+    for (reloc = rstart; reloc < rend; reloc++)
+        *((u32*)(dest + *reloc)) += delta;
+}
 
-    // Setup for reset on qemu.
-    if (! CONFIG_COREBOOT) {
-        qemu_prep_reset();
-        if (HaveRunPost)
-            apm_shutdown();
+// 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();
+}
 
-    // Try keyboard controller reboot.
-    i8042_reboot();
-
-    // Try PCI 0xcf9 reboot
-    pci_reboot();
+// Setup for code relocation and then call reloc_init
+void VISIBLE32INIT
+dopost(void)
+{
+    HaveRunPost = 1;
 
-    // Try triple fault
-    asm volatile("int3");
+    // Detect ram and setup internal malloc.
+    qemu_cfg_port_probe();
+    ram_probe();
+    malloc_setup();
 
-    panic("Could not reboot");
+    // Relocate initialization code and call maininit().
+    reloc_init();
 }
 
-// 32-bit entry point.
+// 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
-_start(void)
+handle_post(void)
 {
-    init_dma();
-
     debug_serial_setup();
     dprintf(1, "Start bios (version %s)\n", VERSION);
 
-    if (HaveRunPost)
-        // This is a soft reboot - invoke a hard reboot.
-        tryReboot();
-
-    // Allow writes to modify bios area (0xf0000)
-    make_bios_writable();
+    // Enable CPU caching
+    setcr0(getcr0() & ~(CR0_CD|CR0_NW));
 
-    HaveRunPost = 1;
+    // Clear CMOS reboot flag.
+    outb_cmos(0, CMOS_RESET_CODE);
 
-    // Perform main setup code.
-    post();
+    // Make sure legacy DMA isn't running.
+    init_dma();
 
-    // Setup bios checksum.
-    BiosChecksum -= checksum((u8*)BUILD_BIOS_ADDR, BUILD_BIOS_SIZE);
+    // Check if we are running under Xen.
+    xen_probe();
 
-    // Write protect bios memory.
-    make_bios_readonly();
+    // Allow writes to modify bios area (0xf0000)
+    make_bios_writable();
 
-    // Invoke int 19 to start boot process.
-    dprintf(3, "Jump to int19\n");
-    struct bregs br;
-    memset(&br, 0, sizeof(br));
-    br.flags = F_IF;
-    call16_int(0x19, &br);
+    // Now that memory is read/writable - start post process.
+    dopost();
 }