#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
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)
coreboot_copy_biostable();
return;
}
+ if (usingXen()) {
+ xen_copy_biostables();
+ return;
+ }
create_pirtable();
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).
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)
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();
}