Unlocking ram in handle_post() is tricky and only needed under qemu. Separate out that logic from the coreboot/xen paths by invoking handle_elf_post separately. This simplifies both the qemu and non-qemu code paths.
Also, organize all the "pre-init" functions into one section of the file.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/post.c | 152 +++++++++++++++++++++++++++++++++----------------------- src/romlayout.S | 2 +- 2 files changed, 90 insertions(+), 64 deletions(-)
diff --git a/src/post.c b/src/post.c index 33b51b7..56df90c 100644 --- a/src/post.c +++ b/src/post.c @@ -1,24 +1,23 @@ // 32bit code to Power On Self Test (POST) a machine. // -// Copyright (C) 2008-2010 Kevin O'Connor kevin@koconnor.net +// Copyright (C) 2008-2013 Kevin O'Connor kevin@koconnor.net // Copyright (C) 2002 MandrakeSoft S.A. // // This file may be distributed under the terms of the GNU LGPLv3 license.
-#include "ioport.h" // PORT_* #include "config.h" // CONFIG_* #include "cmos.h" // CMOS_* #include "util.h" // memset #include "biosvar.h" // struct bios_data_area_s -#include "disk.h" // floppy_drive_setup +#include "disk.h" // floppy_setup #include "ata.h" // ata_setup #include "ahci.h" // ahci_setup #include "memmap.h" // add_e820 #include "pic.h" // pic_setup #include "bregs.h" // struct bregs -#include "boot.h" // IPL +#include "boot.h" // boot_init #include "usb.h" // usb_setup -#include "paravirt.h" // qemu_cfg_port_probe +#include "paravirt.h" // qemu_cfg_preinit #include "xen.h" // xen_preinit #include "ps2port.h" // ps2port_setup #include "virtio-blk.h" // virtio_blk_setup @@ -29,30 +28,10 @@
/**************************************************************** - * BIOS init + * BIOS initialization and hardware setup ****************************************************************/
static void -ramsize_preinit(void) -{ - dprintf(3, "Find memory size\n"); - if (CONFIG_COREBOOT) - coreboot_preinit(); - else if (usingXen()) - xen_ramsize_preinit(); - else - qemu_ramsize_preinit(); - - // Don't declare any memory between 0xa0000 and 0x100000 - add_e820(BUILD_LOWRAM_END, BUILD_BIOS_ADDR-BUILD_LOWRAM_END, E820_HOLE); - - // Mark known areas as reserved. - add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED); - - dprintf(1, "Ram Size=0x%08x (0x%016llx high)\n", RamSize, RamSizeOver4G); -} - -static void ivt_init(void) { dprintf(3, "init ivt\n"); @@ -244,24 +223,30 @@ maininit(void) make_bios_readonly(); }
-// Begin the boot process by invoking an int0x19 in 16bit mode. + +/**************************************************************** + * Early initialization (preinit) and code relocation + ****************************************************************/ + static void -startBoot(void) +ramsize_preinit(void) { - // Clear low-memory allocations (required by PMM spec). - memset((void*)BUILD_STACK_ADDR, 0, BUILD_EBDA_MINIMUM - BUILD_STACK_ADDR); + dprintf(3, "Find memory size\n"); + if (CONFIG_COREBOOT) + coreboot_preinit(); + else if (usingXen()) + xen_ramsize_preinit(); + else + qemu_ramsize_preinit();
- dprintf(3, "Jump to int19\n"); - struct bregs br; - memset(&br, 0, sizeof(br)); - br.flags = F_IF; - call16_int(0x19, &br); -} + // Don't declare any memory between 0xa0000 and 0x100000 + add_e820(BUILD_LOWRAM_END, BUILD_BIOS_ADDR-BUILD_LOWRAM_END, E820_HOLE);
+ // Mark known areas as reserved. + add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED);
-/**************************************************************** - * POST entry and code relocation - ****************************************************************/ + dprintf(1, "Ram Size=0x%08x (0x%016llx high)\n", RamSize, RamSizeOver4G); +}
// Update given relocs for the code at 'dest' with a given 'delta' static void @@ -272,7 +257,7 @@ updateRelocs(void *dest, u32 *rstart, u32 *rend, u32 delta) *((u32*)(dest + *reloc)) += delta; }
-// Relocate init code and then call maininit() at new address. +// Relocate init code. static void reloc_preinit(void) { @@ -311,11 +296,22 @@ reloc_preinit(void) barrier(); }
-// Setup for code relocation and then call reloc_init +// Setup for code relocation and then relocate. void VISIBLE32INIT -doreloc(void) +preinit(void) { + // Set reboot flags. HaveRunPost = 1; + outb_cmos(0, CMOS_RESET_CODE); + + // Enable CPU caching + setcr0(getcr0() & ~(CR0_CD|CR0_NW)); + + // Make sure legacy DMA isn't running. + dma_preinit(); + + // Check if we are running under Xen. + xen_preinit();
// Detect ram and setup internal malloc. qemu_cfg_preinit(); @@ -326,32 +322,31 @@ doreloc(void) reloc_preinit(); }
-// 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) -{ - debug_serial_preinit(); - dprintf(1, "Start bios (version %s)\n", VERSION); - - // Enable CPU caching - setcr0(getcr0() & ~(CR0_CD|CR0_NW)); - - // Clear CMOS reboot flag. - outb_cmos(0, CMOS_RESET_CODE);
- // Make sure legacy DMA isn't running. - dma_preinit(); +/**************************************************************** + * POST entry + ****************************************************************/
- // Check if we are running under Xen. - xen_preinit(); +// As the last part of POST, invoke int19 to start boot phase. +static void +startBoot(void) +{ + // Clear low-memory allocations (required by PMM spec). + memset((void*)BUILD_STACK_ADDR, 0, BUILD_EBDA_MINIMUM - BUILD_STACK_ADDR);
- // Allow writes to modify bios area (0xf0000) - make_bios_writable(); + dprintf(3, "Jump to int19\n"); + struct bregs br; + memset(&br, 0, sizeof(br)); + br.flags = F_IF; + call16_int(0x19, &br); +}
+// Power On Self Test (POST) - the main BIOS initialization phase. +static void +post(void) +{ // Do pre-relocation setup and then relocate initialization code. - doreloc(); + preinit();
// Run main code maininit(); @@ -359,3 +354,34 @@ handle_post(void) // Invoke int 19 to start boot process. startBoot(); } + +// Startup debug output and display software version. +static void +debug_splash(void) +{ + debug_serial_preinit(); + dprintf(1, "Start bios (version %s)\n", VERSION); +} + +// Entry point for Power On Self Test (POST) when running under +// xen/coreboot. +void VISIBLE32FLAT +handle_elf_post(void) +{ + debug_splash(); + post(); +} + +// Entry point for Power On Self Test (POST) when running under +// qemu/kvm/bochs. Under qemu the memory at 0xc0000-0xfffff may be +// read-only, so unlock the ram as the first step of booting. +void VISIBLE32FLAT +handle_post(void) +{ + debug_splash(); + + // Allow writes to modify bios area (0xf0000) + make_bios_writable(); + + post(); +} diff --git a/src/romlayout.S b/src/romlayout.S index 8125277..a8e00b6 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -380,7 +380,7 @@ entry_elf: movw %ax, %gs movw %ax, %ss movl $BUILD_STACK_ADDR, %esp - ljmpl $SEG32_MODE32_CS, $_cfunc32flat_handle_post + ljmpl $SEG32_MODE32_CS, $_cfunc32flat_handle_elf_post
.code16gcc