This patch series enables SeaBIOS to be compiled for multiple platforms (eg, CSM, QEMU, Coreboot) at the same time. This is useful for cases where SeaBIOS is running under coreboot which is running under QEMU, for example.
This series is an RFC - some things are not ideal. For example, if CSM or COREBOOT is enabled then CONFIG_DEBUG_IO is automatically disabled (even if ultimately the image is run directly under QEMU). Also, some features of QEMU wont be available when SeaBIOS is launched from CSM/coreboot, even if it is ultimately running under QEMU.
Kevin O'Connor (5): POST: Consolidate platform preinit() calls. Introduce framework for detecting what platform SeaBIOS is running on. Convert common compile time checks to started/runningOnX() checks. Determine century during init and store in VARLOW mem during runtime. Enable simultaneous multi-platform support in Kconfig.
src/Kconfig | 23 ++++++-------- src/ata.c | 3 +- src/block.c | 3 +- src/blockcmd.c | 2 +- src/boot.c | 10 +++--- src/clock.c | 26 +++++++++------ src/coreboot.c | 17 +++++++--- src/csm.c | 2 ++ src/esp-scsi.c | 3 +- src/floppy.c | 3 +- src/lsi-scsi.c | 3 +- src/mtrr.c | 4 +-- src/optionroms.c | 3 +- src/paravirt.c | 24 ++++++++++---- src/paravirt.h | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/pciinit.c | 4 +-- src/post.c | 53 +++++++++++++++---------------- src/ramdisk.c | 2 +- src/resume.c | 6 +--- src/shadow.c | 12 ++++--- src/smm.c | 10 ++---- src/smp.c | 4 +-- src/virtio-blk.c | 4 +-- src/virtio-scsi.c | 2 +- src/xen.c | 67 +++++++++++++++++++++------------------ src/xen.h | 7 ---- 26 files changed, 253 insertions(+), 139 deletions(-)
Consolidate the X_preinit() calls together so that a single per-platform preinit() call fully handles the pre-relocation phase.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/coreboot.c | 6 ++++++ src/paravirt.c | 10 ++++++++- src/paravirt.h | 2 +- src/post.c | 43 +++++++++++++++++---------------------- src/xen.c | 64 +++++++++++++++++++++++++++++++--------------------------- src/xen.h | 1 - 6 files changed, 69 insertions(+), 57 deletions(-)
diff --git a/src/coreboot.c b/src/coreboot.c index 5d013cf..57c9737 100644 --- a/src/coreboot.c +++ b/src/coreboot.c @@ -125,6 +125,8 @@ const char *CBvendor = "", *CBpart = ""; void coreboot_preinit(void) { + if (!CONFIG_COREBOOT) + return; dprintf(3, "Attempting to find coreboot table\n");
// Find coreboot table. @@ -176,6 +178,9 @@ coreboot_preinit(void) dprintf(1, "Found mainboard %s %s\n", CBvendor, CBpart); }
+ // Setup malloc. + malloc_preinit(); + return;
fail: @@ -184,6 +189,7 @@ fail: RamSize = 16*1024*1024; RamSizeOver4G = 0; add_e820(0, 16*1024*1024, E820_RAM); + malloc_preinit(); return; }
diff --git a/src/paravirt.c b/src/paravirt.c index 9022186..ebab256 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -22,8 +22,13 @@ int qemu_cfg_present;
void -qemu_ramsize_preinit(void) +qemu_preinit(void) { + if (!CONFIG_QEMU) + return; + + qemu_cfg_preinit(); + // On emulators, get memory size from nvram. u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16) | (inb_cmos(CMOS_MEM_EXTMEM2_HIGH) << 24)); @@ -61,6 +66,9 @@ qemu_ramsize_preinit(void) // other page for EPT real mode pagetable add_e820(0xfffbc000, 4*4096, E820_RESERVED); } + + // Setup malloc. + malloc_preinit(); }
void diff --git a/src/paravirt.h b/src/paravirt.h index 4f2d5b8..2448993 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -43,7 +43,7 @@ static inline int kvm_para_available(void)
extern int qemu_cfg_present;
-void qemu_ramsize_preinit(void); +void qemu_preinit(void); void qemu_biostable_setup(void); void qemu_cfg_preinit(void); int qemu_cfg_show_boot_menu(void); diff --git a/src/post.c b/src/post.c index f2fabbb..4ab020c 100644 --- a/src/post.c +++ b/src/post.c @@ -311,27 +311,6 @@ reloc_preinit(void *f, void *arg) func(arg); }
-// Setup for code relocation and then relocate. -void VISIBLE32INIT -dopost(void) -{ - // Check if we are running under Xen. - xen_preinit(); - - // Detect ram and setup internal malloc. - qemu_cfg_preinit(); - if (CONFIG_COREBOOT) - coreboot_preinit(); - else if (usingXen()) - xen_ramsize_preinit(); - else - qemu_ramsize_preinit(); - malloc_preinit(); - - // Relocate initialization code and call maininit(). - reloc_preinit(maininit, NULL); -} - // Startup debug output and display software version. static void debug_splash(void) @@ -346,12 +325,28 @@ void VISIBLE32INIT handle_elf(void) { debug_splash(); - dopost(); + + coreboot_preinit(); + xen_preinit(); + + // Relocate initialization code and call maininit(). + reloc_preinit(maininit, NULL); +} + +// Setup code when launched from qemu/kvm/bochs (after memory unlocked). +void VISIBLE32INIT +qemu_post(void) +{ + qemu_preinit(); + + // Relocate initialization code and call maininit(). + reloc_preinit(maininit, NULL); }
// 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. +// read-only and only the first 128K of code may be present. So +// unlock and copy all of ram as the first step of booting. void VISIBLE32FLAT handle_post(void) { @@ -361,5 +356,5 @@ handle_post(void) make_bios_writable();
// Now that memory is read/writable - start post process. - dopost(); + qemu_post(); } diff --git a/src/xen.c b/src/xen.c index c9759f0..a506b42 100644 --- a/src/xen.c +++ b/src/xen.c @@ -6,7 +6,7 @@
#include "config.h" #include "xen.h" - +#include "paravirt.h" // qemu_cfg_preinit #include "memmap.h" // add_e820 #include "types.h" // ASM32FLAT #include "util.h" // copy_acpi_rsdp @@ -76,8 +76,40 @@ void xen_preinit(void) break; } } - if (!xen_cpuid_base) + if (!xen_cpuid_base) { dprintf(1, "No Xen hypervisor found.\n"); + return; + } + + qemu_cfg_preinit(); + + u64 maxram = 0, maxram_over4G = 0; + struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS; + validate_info(info); + + dprintf(1, "xen: copy e820...\n"); + + struct e820entry *e820 = (struct e820entry *)info->e820; + int i; + for (i = 0; i < info->e820_nr; i++) { + struct e820entry *e = &e820[i]; + if (e->type == E820_ACPI || e->type == E820_RAM) { + u64 end = e->start + e->size; + if (end > 0x100000000ull) { + end -= 0x100000000ull; + if (end > maxram_over4G) + maxram_over4G = end; + } else if (end > maxram) + maxram = end; + } + add_e820(e->start, e->size, e->type); + } + + RamSize = maxram; + RamSizeOver4G = maxram_over4G; + + // Setup malloc. + malloc_preinit(); }
static int hypercall_xen_version( int cmd, void *arg) @@ -121,31 +153,3 @@ void xen_biostable_setup(void) for (i=0; i<info->tables_nr; i++) copy_table(tables[i]); } - -void xen_ramsize_preinit(void) -{ - u64 maxram = 0, maxram_over4G = 0; - int i; - struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS; - struct e820entry *e820 = (struct e820entry *)info->e820; - validate_info(info); - - dprintf(1, "xen: copy e820...\n"); - - for (i = 0; i < info->e820_nr; i++) { - struct e820entry *e = &e820[i]; - if (e->type == E820_ACPI || e->type == E820_RAM) { - u64 end = e->start + e->size; - if (end > 0x100000000ull) { - end -= 0x100000000ull; - if (end > maxram_over4G) - maxram_over4G = end; - } else if (end > maxram) - maxram = end; - } - add_e820(e->start, e->size, e->type); - } - - RamSize = maxram; - RamSizeOver4G = maxram_over4G; -} diff --git a/src/xen.h b/src/xen.h index 9b4178a..2be2453 100644 --- a/src/xen.h +++ b/src/xen.h @@ -7,7 +7,6 @@ extern u32 xen_cpuid_base;
void xen_preinit(void); -void xen_ramsize_preinit(void); void xen_hypercall_setup(void); void xen_biostable_setup(void);
Introduce startedOnQEMU()/startedOnCoreboot()/etc. calls to enable code to determine what platform invoked the initial SeaBIOS startup. Also introduce runningOnQEMU()/etc. calls for cases where SeaBIOS can detect it is running on a platform even though it wasn't directly launched by that platform (eg, Xen may have started SeaBIOS, but Xen may be running under qemu).
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/coreboot.c | 3 ++ src/csm.c | 2 ++ src/paravirt.c | 10 +++++-- src/paravirt.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/xen.c | 1 + 5 files changed, 104 insertions(+), 5 deletions(-)
diff --git a/src/coreboot.c b/src/coreboot.c index 57c9737..40a7e72 100644 --- a/src/coreboot.c +++ b/src/coreboot.c @@ -12,6 +12,7 @@ #include "boot.h" // boot_add_cbfs #include "disk.h" // MAXDESCSIZE #include "config.h" // CONFIG_* +#include "paravirt.h" // PlatformStartedOn
/**************************************************************** @@ -145,6 +146,8 @@ coreboot_preinit(void) if (!cbm) goto fail;
+ PlatformStartedOn = PlatformRunningOn = PF_COREBOOT; + u64 maxram = 0, maxram_over4G = 0; int i, count = MEM_RANGE_COUNT(cbm); for (i=0; i<count; i++) { diff --git a/src/csm.c b/src/csm.c index 169b608..c8069d2 100644 --- a/src/csm.c +++ b/src/csm.c @@ -17,6 +17,7 @@ #include "boot.h" #include "smbios.h" #include "pic.h" +#include "paravirt.h" // PlatformStartedOn
struct rsdp_descriptor VAR32FLATVISIBLE __aligned(16) csm_rsdp;
@@ -74,6 +75,7 @@ handle_csm_0000(struct bregs *regs) dprintf(3, "LoPmmMemory %08x\n", csm_init_table->LowPmmMemory); dprintf(3, "LoPmmMemorySize %08x\n", csm_init_table->LowPmmMemorySizeInBytes);
+ PlatformStartedOn = PlatformRunningOn = PF_CSM; csm_malloc_preinit(csm_init_table->LowPmmMemory, csm_init_table->LowPmmMemorySizeInBytes, csm_init_table->HiPmmMemory, diff --git a/src/paravirt.c b/src/paravirt.c index ebab256..35b7c11 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -19,6 +19,8 @@ #include "mptable.h" // mptable_setup #include "pci.h" // create_pirtable
+int PlatformStartedOn, PlatformRunningOn; + int qemu_cfg_present;
void @@ -27,6 +29,7 @@ qemu_preinit(void) if (!CONFIG_QEMU) return;
+ PlatformStartedOn = PlatformRunningOn = PF_QEMU; qemu_cfg_preinit();
// On emulators, get memory size from nvram. @@ -108,12 +111,13 @@ qemu_cfg_read_entry(void *buf, int e, int len)
void qemu_cfg_preinit(void) { + if (!CONFIG_QEMU) + return; + PlatformRunningOn |= PF_QEMU; + char *sig = "QEMU"; int i;
- if (CONFIG_COREBOOT) - return; - qemu_cfg_present = 1;
qemu_cfg_select(QEMU_CFG_SIGNATURE); diff --git a/src/paravirt.h b/src/paravirt.h index 2448993..3b00697 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -1,8 +1,97 @@ #ifndef __PV_H #define __PV_H
-#include "config.h" // CONFIG_COREBOOT -#include "util.h" +#include "config.h" // CONFIG_* +#include "util.h" // memcpy + + +/**************************************************************** + * Current platform detection + ****************************************************************/ + +#define PF_QEMU (1<<0) +#define PF_COREBOOT (1<<1) +#define PF_XEN (1<<2) +#define PF_CSM (1<<3) + +extern int PlatformStartedOn, PlatformRunningOn; + +static inline int startedOnQEMU(void) +{ + if (!CONFIG_QEMU) + return 0; + if (!CONFIG_COREBOOT && !CONFIG_XEN && !CONFIG_CSM) + return 1; + return PlatformStartedOn == PF_QEMU; +} + +static inline int startedOnCoreboot(void) +{ + if (!CONFIG_COREBOOT) + return 0; + if (!CONFIG_QEMU && !CONFIG_XEN && !CONFIG_CSM) + return 1; + return PlatformStartedOn == PF_COREBOOT; +} + +static inline int startedOnXen(void) +{ + if (!CONFIG_XEN) + return 0; + if (!CONFIG_QEMU && !CONFIG_COREBOOT && !CONFIG_CSM) + return 1; + return PlatformStartedOn == PF_XEN; +} + +static inline int startedOnCSM(void) +{ + if (!CONFIG_CSM) + return 0; + if (!CONFIG_QEMU && !CONFIG_COREBOOT && !CONFIG_XEN) + return 1; + return PlatformStartedOn == PF_CSM; +} + +static inline int runningOnQEMU(void) +{ + if (!CONFIG_QEMU) + return 0; + if (!CONFIG_COREBOOT && !CONFIG_XEN && !CONFIG_CSM) + return 1; + return PlatformRunningOn & PF_QEMU; +} + +static inline int runningOnCoreboot(void) +{ + if (!CONFIG_COREBOOT) + return 0; + if (!CONFIG_QEMU && !CONFIG_XEN && !CONFIG_CSM) + return 1; + return PlatformRunningOn & PF_COREBOOT; +} + +static inline int runningOnXen(void) +{ + if (!CONFIG_XEN) + return 0; + if (!CONFIG_QEMU && !CONFIG_COREBOOT && !CONFIG_CSM) + return 1; + return PlatformRunningOn & PF_XEN; +} + +static inline int runningOnCSM(void) +{ + if (!CONFIG_CSM) + return 0; + if (!CONFIG_QEMU && !CONFIG_COREBOOT && !CONFIG_XEN) + return 1; + return PlatformRunningOn & PF_CSM; +} + + +/**************************************************************** + * KVM/QEMU firmware + ****************************************************************/
/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It * should be used to determine that a VM is running under KVM. diff --git a/src/xen.c b/src/xen.c index a506b42..5122a3c 100644 --- a/src/xen.c +++ b/src/xen.c @@ -81,6 +81,7 @@ void xen_preinit(void) return; }
+ PlatformStartedOn = PlatformRunningOn = PF_XEN; qemu_cfg_preinit();
u64 maxram = 0, maxram_over4G = 0;
Convert CONFIG_COREBOOT, CONFIG_CSM, and usingXen() calls to startedOnX() and runningOnX() calls as appropriate.
This change should not alter the runtime behavior as Kconfig will still enforce compile time constraints. However, this change will make it easier for future Kconfig changes to enable simultaneous multi-platform support.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/ata.c | 3 ++- src/block.c | 3 ++- src/blockcmd.c | 2 +- src/boot.c | 10 +++++----- src/coreboot.c | 8 ++++---- src/floppy.c | 3 ++- src/mtrr.c | 4 ++-- src/optionroms.c | 3 ++- src/paravirt.c | 4 ++-- src/pciinit.c | 4 ++-- src/post.c | 10 +++++++--- src/ramdisk.c | 2 +- src/resume.c | 6 +----- src/shadow.c | 12 ++++++++---- src/smm.c | 10 +++------- src/smp.c | 4 ++-- src/virtio-blk.c | 4 ++-- src/virtio-scsi.c | 2 +- src/xen.c | 2 +- src/xen.h | 6 ------ 20 files changed, 50 insertions(+), 52 deletions(-)
diff --git a/src/ata.c b/src/ata.c index d1d8dff..f1223f0 100644 --- a/src/ata.c +++ b/src/ata.c @@ -19,6 +19,7 @@ #include "disk.h" // struct ata_s #include "ata.h" // ATA_CB_STAT #include "blockcmd.h" // CDB_CMD_READ_10 +#include "paravirt.h" // runningOnQEMU
#define IDE_TIMEOUT 32000 //32 seconds max for IDE ops
@@ -1008,7 +1009,7 @@ static const struct pci_device_id pci_ata_tbl[] = { static void ata_scan(void) { - if (!CONFIG_COREBOOT && !PCIDevices) { + if (runningOnQEMU() && !PCIDevices) { // No PCI devices found - probably a QEMU "-M isapc" machine. // Try using ISA ports for ATA controllers. init_controller(NULL, IRQ_ATA1 diff --git a/src/block.c b/src/block.c index e5f3038..274eae2 100644 --- a/src/block.c +++ b/src/block.c @@ -13,6 +13,7 @@ #include "ahci.h" // process_ahci_op #include "virtio-blk.h" // process_virtio_blk_op #include "blockcmd.h" // cdb_* +#include "paravirt.h" // runningOnQEMU
u8 FloppyCount VAR16VISIBLE; u8 CDCount; @@ -62,7 +63,7 @@ static u8 get_translation(struct drive_s *drive_g) { u8 type = GET_GLOBAL(drive_g->type); - if (! CONFIG_COREBOOT && type == DTYPE_ATA) { + if (runningOnQEMU() && type == DTYPE_ATA) { // Emulators pass in the translation info via nvram. u8 ataid = GET_GLOBAL(drive_g->cntl_id); u8 channel = ataid / 2; diff --git a/src/blockcmd.c b/src/blockcmd.c index e033ba7..71175cc 100644 --- a/src/blockcmd.c +++ b/src/blockcmd.c @@ -165,7 +165,7 @@ scsi_drive_setup(struct drive_s *drive, const char *s, int prio) // but some old USB keys only support a very small subset of SCSI which // does not even include the MODE SENSE command! // - if (! CONFIG_COREBOOT && memcmp(vendor, "QEMU", 5) == 0) { + if (CONFIG_QEMU && memcmp(vendor, "QEMU", 5) == 0) { struct cdbres_mode_sense_geom geomdata; ret = cdb_mode_sense_geom(&dop, &geomdata); if (ret == 0) { diff --git a/src/boot.c b/src/boot.c index 85d5051..6b3e2a8 100644 --- a/src/boot.c +++ b/src/boot.c @@ -121,7 +121,7 @@ build_pci_path(char *buf, int max, const char *devname, struct pci_device *pci)
int bootprio_find_pci_device(struct pci_device *pci) { - if (CONFIG_CSM) + if (startedOnCSM()) return csm_bootprio_pci(pci); if (!CONFIG_BOOTORDER) return -1; @@ -147,7 +147,7 @@ int bootprio_find_scsi_device(struct pci_device *pci, int target, int lun)
int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave) { - if (CONFIG_CSM) + if (startedOnCSM()) return csm_bootprio_ata(pci, chanid, slave); if (!CONFIG_BOOTORDER) return -1; @@ -163,7 +163,7 @@ int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave)
int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid) { - if (CONFIG_CSM) + if (startedOnCSM()) return csm_bootprio_fdc(pci, port, fdid); if (!CONFIG_BOOTORDER) return -1; @@ -250,7 +250,7 @@ boot_init(void) if (! CONFIG_BOOT) return;
- if (!CONFIG_COREBOOT) { + if (runningOnQEMU()) { // On emulators, get boot order from nvram. if (inb_cmos(CMOS_BIOS_BOOTFLAG1) & 1) CheckFloppySig = 0; @@ -609,7 +609,7 @@ boot_cdrom(struct drive_s *drive_g) static void boot_cbfs(struct cbfs_file *file) { - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH) + if (!CONFIG_COREBOOT_FLASH) return; printf("Booting from CBFS...\n"); cbfs_run_payload(file); diff --git a/src/coreboot.c b/src/coreboot.c index 40a7e72..daaec7f 100644 --- a/src/coreboot.c +++ b/src/coreboot.c @@ -303,7 +303,7 @@ struct cbfs_file { static int cbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen) { - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH) + if (!CONFIG_COREBOOT_FLASH) return -1;
u32 size = file->rawsize; @@ -335,7 +335,7 @@ cbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen) void coreboot_cbfs_init(void) { - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH) + if (!CONFIG_COREBOOT_FLASH) return;
struct cbfs_header *hdr = *(void **)CBFS_HEADPTR_ADDR; @@ -401,7 +401,7 @@ struct cbfs_payload { void cbfs_run_payload(struct cbfs_file *file) { - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH || !file) + if (!CONFIG_COREBOOT_FLASH || !file) return; dprintf(1, "Run %s\n", file->filename); struct cbfs_payload *pay = (void*)file + be32_to_cpu(file->offset); @@ -452,7 +452,7 @@ cbfs_run_payload(struct cbfs_file *file) void cbfs_payload_setup(void) { - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH) + if (!CONFIG_COREBOOT_FLASH) return; struct romfile_s *file = NULL; for (;;) { diff --git a/src/floppy.c b/src/floppy.c index e9f8916..14136ed 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -16,6 +16,7 @@ #include "boot.h" // boot_add_floppy #include "pci.h" // pci_to_bdf #include "pci_ids.h" // PCI_CLASS_BRIDGE_ISA +#include "paravirt.h" // runningOnQEMU
#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors #define FLOPPY_DATALEN 0xff // Not used - because size code is 0x02 @@ -125,7 +126,7 @@ floppy_setup(void) return; dprintf(3, "init floppy drives\n");
- if (CONFIG_COREBOOT) { + if (!runningOnQEMU()) { u8 type = romfile_loadint("etc/floppy0", 0); if (type) addFloppy(0, type); diff --git a/src/mtrr.c b/src/mtrr.c index 2cbf234..90ae517 100644 --- a/src/mtrr.c +++ b/src/mtrr.c @@ -6,8 +6,8 @@
#include "util.h" // dprintf #include "config.h" // CONFIG_* -#include "xen.h" // usingXen #include "pci.h" // pcimem_start +#include "paravirt.h" // startedOnQEMU()
#define MSR_MTRRcap 0x000000fe #define MSR_MTRRfix64K_00000 0x00000250 @@ -34,7 +34,7 @@
void mtrr_setup(void) { - if (!CONFIG_MTRR_INIT || CONFIG_COREBOOT || usingXen()) + if (!CONFIG_MTRR_INIT || !startedOnQEMU()) return;
u32 eax, ebx, ecx, edx, cpuid_features; diff --git a/src/optionroms.c b/src/optionroms.c index c9e7d7b..3876823 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -14,6 +14,7 @@ #include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA #include "boot.h" // IPL #include "optionroms.h" // struct rom_header +#include "paravirt.h" // runningOnQEMU
/**************************************************************** @@ -425,7 +426,7 @@ vgarom_setup(void)
// Load some config settings that impact VGA. EnforceChecksum = romfile_loadint("etc/optionroms-checksum", 1); - S3ResumeVga = romfile_loadint("etc/s3-resume-vga-init", !CONFIG_COREBOOT); + S3ResumeVga = romfile_loadint("etc/s3-resume-vga-init", runningOnQEMU()); ScreenAndDebug = romfile_loadint("etc/screen-and-debug", 1);
if (CONFIG_OPTIONROMS_DEPLOYED) { diff --git a/src/paravirt.c b/src/paravirt.c index 35b7c11..c44f2bf 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -7,7 +7,7 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license.
-#include "config.h" // CONFIG_COREBOOT +#include "config.h" // CONFIG_QEMU #include "util.h" // dprintf #include "byteorder.h" // be32_to_cpu #include "ioport.h" // outw @@ -391,7 +391,7 @@ struct QemuCfgFile {
void qemu_romfile_init(void) { - if (CONFIG_COREBOOT || !qemu_cfg_present) + if (!CONFIG_QEMU || !qemu_cfg_present) return;
u32 count; diff --git a/src/pciinit.c b/src/pciinit.c index 34b47b6..f29e444 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -11,8 +11,8 @@ #include "pci_regs.h" // PCI_COMMAND #include "ioport.h" // PORT_ATA1_CMD_BASE #include "config.h" // CONFIG_* -#include "xen.h" // usingXen #include "memmap.h" // add_e820 +#include "paravirt.h" // startedOnQEMU() #include "dev-q35.h"
/* PM Timer ticks per second (HZ) */ @@ -734,7 +734,7 @@ static void pci_bios_map_devices(struct pci_bus *busses) void pci_setup(void) { - if (CONFIG_COREBOOT || usingXen()) { + if (!startedOnQEMU()) { // PCI setup already done by coreboot or Xen - just do probe. pci_probe_devices(); return; diff --git a/src/post.c b/src/post.c index 4ab020c..b84e75a 100644 --- a/src/post.c +++ b/src/post.c @@ -177,11 +177,11 @@ platform_hardware_setup(void) smp_setup();
// Setup external BIOS interface tables - if (CONFIG_COREBOOT) + if (startedOnCoreboot()) coreboot_biostable_setup(); - else if (usingXen()) + else if (startedOnXen()) xen_biostable_setup(); - else + else if (startedOnQEMU()) qemu_biostable_setup(); }
@@ -324,6 +324,8 @@ debug_splash(void) void VISIBLE32INIT handle_elf(void) { + if (!CONFIG_COREBOOT && !CONFIG_XEN) + return; debug_splash();
coreboot_preinit(); @@ -350,6 +352,8 @@ qemu_post(void) void VISIBLE32FLAT handle_post(void) { + if (!CONFIG_QEMU) + return; debug_splash();
// Allow writes to modify bios area (0xf0000) diff --git a/src/ramdisk.c b/src/ramdisk.c index 9249a49..b9da2ad 100644 --- a/src/ramdisk.c +++ b/src/ramdisk.c @@ -88,7 +88,7 @@ ramdisk_copy(struct disk_op_s *op, int iswrite) int process_ramdisk_op(struct disk_op_s *op) { - if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH || !CONFIG_FLASH_FLOPPY) + if (!CONFIG_FLASH_FLOPPY) return 0;
switch (op->command) { diff --git a/src/resume.c b/src/resume.c index ffc84fc..adc3594 100644 --- a/src/resume.c +++ b/src/resume.c @@ -130,11 +130,7 @@ tryReboot(void) dprintf(1, "Attempting a hard reboot\n");
// Setup for reset on qemu. - if (! CONFIG_COREBOOT) { - qemu_prep_reset(); - if (HaveRunPost) - apm_shutdown(); - } + qemu_prep_reset();
// Try keyboard controller reboot. i8042_reboot(); diff --git a/src/shadow.c b/src/shadow.c index a2195da..00d6c7f 100644 --- a/src/shadow.c +++ b/src/shadow.c @@ -10,8 +10,8 @@ #include "config.h" // CONFIG_* #include "pci_ids.h" // PCI_VENDOR_ID_INTEL #include "pci_regs.h" // PCI_VENDOR_ID -#include "xen.h" // usingXen #include "dev-q35.h" // PCI_VENDOR_ID_INTEL +#include "paravirt.h" // startedOnQEMU
// On the emulators, the bios at 0xf0000 is also at 0xffff0000 #define BIOS_SRC_OFFSET 0xfff00000 @@ -119,7 +119,7 @@ static const struct pci_device_id dram_controller_make_readonly_tbl[] = { void make_bios_writable(void) { - if (CONFIG_COREBOOT || usingXen()) + if (!CONFIG_QEMU) return;
dprintf(3, "enabling shadow ram\n"); @@ -148,7 +148,7 @@ make_bios_writable(void) void make_bios_readonly(void) { - if (CONFIG_COREBOOT || usingXen()) + if (!startedOnQEMU()) return;
dprintf(3, "locking shadow ram\n"); @@ -161,7 +161,7 @@ make_bios_readonly(void) void qemu_prep_reset(void) { - if (CONFIG_COREBOOT) + if (!startedOnQEMU()) return; // QEMU doesn't map 0xc0000-0xfffff back to the original rom on a // reset, so do that manually before invoking a hard reset. @@ -169,4 +169,8 @@ qemu_prep_reset(void) extern u8 code32flat_start[], code32flat_end[]; memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET , code32flat_end - code32flat_start); + + if (HaveRunPost) + // Memcpy failed to reset memory - try to shutdown machine. + apm_shutdown(); } diff --git a/src/smm.c b/src/smm.c index c69f0fd..95caf26 100644 --- a/src/smm.c +++ b/src/smm.c @@ -10,8 +10,8 @@ #include "config.h" // CONFIG_* #include "ioport.h" // outb #include "pci_ids.h" // PCI_VENDOR_ID_INTEL -#include "xen.h" // usingXen #include "dev-q35.h" +#include "paravirt.h" // startedOnQEMU
ASM32FLAT( ".global smm_relocation_start\n" @@ -184,13 +184,9 @@ static const struct pci_device_id smm_init_tbl[] = { void smm_setup(void) { - if (CONFIG_COREBOOT) - // SMM only supported on emulators. + if (!CONFIG_USE_SMM || !startedOnQEMU()) + // SMM only supported on QEMU style emulators. return; - if (!CONFIG_USE_SMM) - return; - if (usingXen()) - return;
dprintf(3, "init smm\n"); pci_find_init_device(smm_init_tbl, NULL); diff --git a/src/smp.c b/src/smp.c index 18bb05f..f1dba5f 100644 --- a/src/smp.c +++ b/src/smp.c @@ -113,7 +113,7 @@ smp_setup(void) u32 val = readl(APIC_SVR); writel(APIC_SVR, val | APIC_ENABLED);
- if (! CONFIG_COREBOOT) { + if (runningOnQEMU()) { /* Set LINT0 as Ext_INT, level triggered */ writel(APIC_LINT0, 0x8700);
@@ -128,7 +128,7 @@ smp_setup(void) writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector);
// Wait for other CPUs to process the SIPI. - if (CONFIG_COREBOOT) { + if (!runningOnQEMU()) { msleep(10); } else { u8 cmos_smp_count = inb_cmos(CMOS_BIOS_SMP_COUNT); diff --git a/src/virtio-blk.c b/src/virtio-blk.c index 194deaf..9aa9d07 100644 --- a/src/virtio-blk.c +++ b/src/virtio-blk.c @@ -77,7 +77,7 @@ virtio_blk_op(struct disk_op_s *op, int write) int process_virtio_blk_op(struct disk_op_s *op) { - if (! CONFIG_VIRTIO_BLK || CONFIG_COREBOOT) + if (!CONFIG_VIRTIO_BLK) return 0; switch (op->command) { case CMD_READ: @@ -159,7 +159,7 @@ void virtio_blk_setup(void) { ASSERT32FLAT(); - if (! CONFIG_VIRTIO_BLK || CONFIG_COREBOOT) + if (! CONFIG_VIRTIO_BLK) return;
dprintf(3, "init virtio-blk\n"); diff --git a/src/virtio-scsi.c b/src/virtio-scsi.c index 4bbff8f..879ddfb 100644 --- a/src/virtio-scsi.c +++ b/src/virtio-scsi.c @@ -166,7 +166,7 @@ void virtio_scsi_setup(void) { ASSERT32FLAT(); - if (! CONFIG_VIRTIO_SCSI || CONFIG_COREBOOT) + if (! CONFIG_VIRTIO_SCSI) return;
dprintf(3, "init virtio-scsi\n"); diff --git a/src/xen.c b/src/xen.c index 5122a3c..4d10b96 100644 --- a/src/xen.c +++ b/src/xen.c @@ -125,7 +125,7 @@ void xen_hypercall_setup(void) xen_extraversion_t extraversion; unsigned long i;
- if (!usingXen()) + if (!runningOnXen()) return;
cpuid(xen_cpuid_base + 2, &eax, &ebx, &ecx, &edx); diff --git a/src/xen.h b/src/xen.h index 2be2453..fb52702 100644 --- a/src/xen.h +++ b/src/xen.h @@ -10,12 +10,6 @@ void xen_preinit(void); void xen_hypercall_setup(void); void xen_biostable_setup(void);
-static inline int usingXen(void) { - if (!CONFIG_XEN) - return 0; - return (xen_cpuid_base != 0); -} - extern unsigned long xen_hypercall_page;
#define _hypercall0(type, name) \
Avoid reading/writing to cmos at runtime to get the QEMU century information. Instead, read it at startup and cache the info.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/clock.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/src/clock.c b/src/clock.c index 3edcaf5..39df13b 100644 --- a/src/clock.c +++ b/src/clock.c @@ -13,6 +13,7 @@ #include "bregs.h" // struct bregs #include "biosvar.h" // GET_GLOBAL #include "usb-hid.h" // usb_check_event +#include "paravirt.h" // runningOnQEMU()
// RTC register flags #define RTC_A_UIP 0x80 @@ -281,6 +282,8 @@ bcd2bin(u8 val) return (val & 0xf) + ((val >> 4) * 10); }
+u8 Century VARLOW; + void timer_setup(void) { @@ -297,6 +300,17 @@ timer_setup(void) ticks = ((u64)ticks * PIT_TICK_RATE) / PIT_TICK_INTERVAL; SET_BDA(timer_counter, ticks);
+ // Setup Century storage + if (runningOnQEMU()) { + Century = inb_cmos(CMOS_CENTURY); + } else { + u8 year = inb_cmos(CMOS_RTC_YEAR); + if (year > 0x80) + Century = 0x19; + else + Century = 0x20; + } + enable_hwirq(0, FUNC16(entry_08)); enable_hwirq(8, FUNC16(entry_70)); } @@ -420,14 +434,7 @@ handle_1a04(struct bregs *regs) regs->cl = inb_cmos(CMOS_RTC_YEAR); regs->dh = inb_cmos(CMOS_RTC_MONTH); regs->dl = inb_cmos(CMOS_RTC_DAY_MONTH); - if (CONFIG_COREBOOT) { - if (regs->cl > 0x80) - regs->ch = 0x19; - else - regs->ch = 0x20; - } else { - regs->ch = inb_cmos(CMOS_CENTURY); - } + regs->ch = GET_LOW(Century); regs->al = regs->ch; set_success(regs); } @@ -454,8 +461,7 @@ handle_1a05(struct bregs *regs) outb_cmos(regs->cl, CMOS_RTC_YEAR); outb_cmos(regs->dh, CMOS_RTC_MONTH); outb_cmos(regs->dl, CMOS_RTC_DAY_MONTH); - if (!CONFIG_COREBOOT) - outb_cmos(regs->ch, CMOS_CENTURY); + SET_LOW(Century, regs->ch); // clear halt-clock bit u8 val8 = inb_cmos(CMOS_STATUS_B) & ~RTC_B_SET; outb_cmos(val8, CMOS_STATUS_B);
Allow QEMU, Xen, CSM, and Coreboot to all be enabled (or any subset) at the same time.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/Kconfig | 23 ++++++++++------------- src/esp-scsi.c | 3 ++- src/lsi-scsi.c | 3 ++- 3 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig index 55396c6..5b7b21a 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -4,28 +4,18 @@ mainmenu "SeaBIOS Configuration"
menu "General Features"
-choice - prompt "Build Target" - default QEMU - config COREBOOT + default n bool "Build for coreboot" help Configure as a coreboot payload.
config QEMU + default y bool "Build for QEMU" help Configure as QEMU bios.
- config CSM - bool "Build as Compatibilty Support Module for EFI BIOS" - help - Configure to be used by EFI firmware as Compatibility Support - module (CSM) to provide legacy BIOS services. - -endchoice - config XEN depends on QEMU bool "Build for Xen HVM" @@ -33,6 +23,13 @@ endchoice help Configure to be used by xen hvmloader, for a HVM guest.
+ config CSM + default n + bool "Build as Compatibilty Support Module for EFI BIOS" + help + Configure to be used by EFI firmware as Compatibility Support + module (CSM) to provide legacy BIOS services. + config THREADS bool "Parallelize hardware init" default y @@ -399,7 +396,7 @@ menu "Debugging" Base port for serial - generally 0x3f8, 0x2f8, 0x3e8, or 0x2e8.
config DEBUG_IO - depends on QEMU && DEBUG_LEVEL != 0 + depends on QEMU && !COREBOOT && !CSM && DEBUG_LEVEL != 0 bool "Special IO port debugging" default y help diff --git a/src/esp-scsi.c b/src/esp-scsi.c index 4d1f7d2..f3c3423 100644 --- a/src/esp-scsi.c +++ b/src/esp-scsi.c @@ -19,6 +19,7 @@ #include "boot.h" // bootprio_find_scsi_device #include "blockcmd.h" // scsi_drive_setup #include "disk.h" +#include "paravirt.h" // runningOnQEMU()
#define ESP_TCLO 0x00 #define ESP_TCMID 0x04 @@ -218,7 +219,7 @@ void esp_scsi_setup(void) { ASSERT32FLAT(); - if (!CONFIG_ESP_SCSI) + if (!CONFIG_ESP_SCSI || !runningOnQEMU()) return;
dprintf(3, "init esp\n"); diff --git a/src/lsi-scsi.c b/src/lsi-scsi.c index 76e9d1d..707cb3f 100644 --- a/src/lsi-scsi.c +++ b/src/lsi-scsi.c @@ -19,6 +19,7 @@ #include "boot.h" // bootprio_find_scsi_device #include "blockcmd.h" // scsi_drive_setup #include "disk.h" +#include "paravirt.h" // runningOnQEMU()
#define LSI_REG_DSTAT 0x0c #define LSI_REG_ISTAT0 0x14 @@ -197,7 +198,7 @@ void lsi_scsi_setup(void) { ASSERT32FLAT(); - if (!CONFIG_LSI_SCSI) + if (!CONFIG_LSI_SCSI || !runningOnQEMU()) return;
dprintf(3, "init lsi53c895a\n");
On Fri, 2013-02-08 at 00:06 -0500, Kevin O'Connor wrote:
This patch series enables SeaBIOS to be compiled for multiple platforms (eg, CSM, QEMU, Coreboot) at the same time. This is useful for cases where SeaBIOS is running under coreboot which is running under QEMU, for example.
I think you're conflating two issues there.
Firstly, do you actually want to be able to build a multi-platform binary where a single binary build can be used *either* from Coreboot, as CSM, or directly on native hardware? Is there really a need for such a beast? I'm not sure it would even work for CSM, because it would probably be too big.
For the case of SeaBIOS loaded via Coreboot or CSM when it's *actually* running under Qemu, all you really need to do is separate the "started on Qemu" and "running on Qemu" options.
Also, some features of QEMU wont be available when SeaBIOS is launched from CSM/coreboot, even if it is ultimately running under QEMU.
I consider that a feature. From CSM I want almost *nothing* of the Qemu support. It's supposed to be hardware-agnostic, and I don't want it to magically work on qemu and then fail on real hardware.
I only really want to be allowed to use virtio devices, and also the "real" hardware devices like lsi scsi, which are currently enabled only for QEMU for some reason (is the qemu emulation not compatible with real devices?)
Is there not a similar consideration when you're running under Coreboot?
Hi,
I only really want to be allowed to use virtio devices, and also the "real" hardware devices like lsi scsi, which are currently enabled only for QEMU for some reason (is the qemu emulation not compatible with real devices?)
Pretty close: It isn't tested on real hardware, thats why the restriction to qemu. We had that for other drivers too: ahci started as qemu-supported too, after testing+fixing on real hardware it got enabled for everybody. Given the age of real lsi hardware it is unlikely anybody ever wants to use it on !qemu though ...
cheers, Gerd
Il 08/02/2013 11:37, Gerd Hoffmann ha scritto:
Hi,
I only really want to be allowed to use virtio devices, and also the "real" hardware devices like lsi scsi, which are currently enabled only for QEMU for some reason (is the qemu emulation not compatible with real devices?)
Pretty close: It isn't tested on real hardware, thats why the restriction to qemu. We had that for other drivers too: ahci started as qemu-supported too, after testing+fixing on real hardware it got enabled for everybody. Given the age of real lsi hardware it is unlikely anybody ever wants to use it on !qemu though ...
Also, unlike AHCI the real hardware would likely come with option ROMs...
Paolo
On Fri, Feb 08, 2013 at 09:24:55AM +0000, David Woodhouse wrote:
On Fri, 2013-02-08 at 00:06 -0500, Kevin O'Connor wrote:
This patch series enables SeaBIOS to be compiled for multiple platforms (eg, CSM, QEMU, Coreboot) at the same time. This is useful for cases where SeaBIOS is running under coreboot which is running under QEMU, for example.
I think you're conflating two issues there.
Firstly, do you actually want to be able to build a multi-platform binary where a single binary build can be used *either* from Coreboot, as CSM, or directly on native hardware? Is there really a need for such a beast?
No - I don't see a need for one image to run in multiple places.
I'm not sure it would even work for CSM, because it would probably be too big.
As an aside, is there a way to pass in the "init" sections to ovmf such that they don't prevent option roms from using the space? Also, I briefly tried not padding bios.bin to a power of 2, but ovmf doesn't seem to like that.
For the case of SeaBIOS loaded via Coreboot or CSM when it's *actually* running under Qemu, all you really need to do is separate the "started on Qemu" and "running on Qemu" options.
That's kind of what this patch series attemps - distinguishing between "started on qemu" and "running on qemu".
There's really two separate goals: 1 - Don't attempt to access virtual hardware when running on real machines as that can cause very bad behavior on real hardware. 2 - Minimize the size of the bios image.
The patch series attempts to make Kconfig the sole place to control image size, and runtime the sole place to verify virtual hardware is only accessed on an emulator.
Like you point out, though, it might be simpler to add a kconfig selection to choose between qemu/csm/coreboot and then add another kconfig option to enable support for some qemu hardware when under csm or coreboot. If so, the code should still verify at runtime that it's actually running on QEMU before poking at virtual hardware - otherwise there's a risk of someone building a generic image with QEMU support, running it on real hardware, and having it cause mysterious failures due to random ports being poked.
Also, some features of QEMU wont be available when SeaBIOS is launched from CSM/coreboot, even if it is ultimately running under QEMU.
I consider that a feature. From CSM I want almost *nothing* of the Qemu support. It's supposed to be hardware-agnostic, and I don't want it to magically work on qemu and then fail on real hardware.
Good point. The patch series wouldn't have changed this though.
I only really want to be allowed to use virtio devices, and also the "real" hardware devices like lsi scsi, which are currently enabled only for QEMU for some reason (is the qemu emulation not compatible with real devices?)
Is there not a similar consideration when you're running under Coreboot?
Yes - that's why it doesn't make sense to change the Kconfig settings of the various qemu drivers from "depends on QEMU" to "depends on !COREBOOT" - the CSM is in the same situation as Coreboot. It's fine to access the hardware when under QEMU, but not when running on real hardware, and thus the driver should depend on "QEMU".
-Kevin
On Fri, 2013-02-08 at 18:02 -0500, Kevin O'Connor wrote:
Yes - that's why it doesn't make sense to change the Kconfig settings of the various qemu drivers from "depends on QEMU" to "depends on !COREBOOT" - the CSM is in the same situation as Coreboot. It's fine to access the hardware when under QEMU, but not when running on real hardware, and thus the driver should depend on "QEMU".
I think we should focus on fixing this.
You'll not that COREBOOT vs. QEMU was *already* a choice; switching from 'depends on QEMU' to 'depends on !COREBOOT' was a no-op except for the CSM implications. And yes, for one of those (PMTIMER) I've *already* gone back and removed that bogus dependency completely.
I don't think we need a massive refactoring of the config. Let CONFIG_QEMU mean that the system is actually started natively as the Qemu firmware. If you want to add a separate config option for "may run under Qemu even though it's a CSM or COREBOOT build", then add that separately.
I'm not sure what would depend on that. The virtio drivers don't need to. You just won't find those devices on real hardware. And hell, if someone actually makes real hardware that behaves like a virtio block device, why *shouldn't* it work?
I think the only use case is for enabling the lsi SCSI and whatever the other driver was that was only ever tested on the qemu emulation?
Certainly I think that's true for CSM. In the Coreboot case, is there anything else qemu-specific that you should be doing yourself, rather than letting Coreboot sort it out for you?
Hi,
I'm not sure what would depend on that. The virtio drivers don't need to. You just won't find those devices on real hardware. And hell, if someone actually makes real hardware that behaves like a virtio block device, why *shouldn't* it work?
It's basically two things we have:
(a) Hardware initialization: get config info via fw-cfg, map+init pci devices (src/pciinit.c), create acpi tables, ... (b) Hardware drivers for virtual hardware (virtio-blk, virtio-scsi, lsi, ...).
(a) is done by seabios only when booted directly, otherwise xen / coreboot /ovmf will handle that part.
(b) currently depends on CONFIG_QEMU, but those are useful for other cases too, to also boot from virtio when running on coreboot / csm.
I think the only use case is for enabling the lsi SCSI and whatever the other driver was that was only ever tested on the qemu emulation?
That, and I think also to reduce the number of options.
I guess we should have a choice where you can pick coreboot / qemu / xen / csm (I think xen isn't there today exactly because they want the virtio drivers).
Then add a CONFIG_QEMU_DRIVERS menu where we put all virtual hardware drivers in. So when building for real hardware you'll just say 'n' there and all virtual drivers will be skipped.
cheers, Gerd
On 02/11/13 12:18, Gerd Hoffmann wrote:
Then add a CONFIG_QEMU_DRIVERS menu where we put all virtual hardware drivers in. So when building for real hardware you'll just say 'n' there and all virtual drivers will be skipped.
Ah, just saw your new series adds CONFIG_QEMU_HARDWARE for that, great.
cheers, Gerd
On Mon, 2013-02-11 at 12:26 +0100, Gerd Hoffmann wrote:
On 02/11/13 12:18, Gerd Hoffmann wrote:
Then add a CONFIG_QEMU_DRIVERS menu where we put all virtual
hardware
drivers in. So when building for real hardware you'll just say 'n' there and all virtual drivers will be skipped.
Ah, just saw your new series adds CONFIG_QEMU_HARDWARE for that, great.
And at (http://,) git://git.infradead.org/users/dwmw2/seabios.git I've also made Xen one of the top-level choices, which you also mentioned.
I did post that to the list a few minutes ago but the greylisting on mail.coresystems.de is horribly misconfigured and is delaying mails *even* from mailservers which have been observed to queue and retry within the last few days; so it should *know* it's just a gratuitous delay causing communication problems and mails to "cross in the ether" like this, and won't actually prevent any spam getting through.
On Mon, Feb 11, 2013 at 11:42:41AM +0000, David Woodhouse wrote:
On Mon, 2013-02-11 at 12:26 +0100, Gerd Hoffmann wrote:
On 02/11/13 12:18, Gerd Hoffmann wrote:
Then add a CONFIG_QEMU_DRIVERS menu where we put all virtual
hardware
drivers in. So when building for real hardware you'll just say 'n' there and all virtual drivers will be skipped.
Ah, just saw your new series adds CONFIG_QEMU_HARDWARE for that, great.
And at (http://,) git://git.infradead.org/users/dwmw2/seabios.git I've also made Xen one of the top-level choices, which you also mentioned.
I'm fine with that change, but I'm not sure how to communicate that to the distro maintainers. I wouldn't want them to try and build the next version of xen and find it mysterously failing.
BTW, I did pull a bunch of other patches from your tree into the seabios repo.
-Kevin
On Tue, 2013-02-12 at 21:27 -0500, Kevin O'Connor wrote:
I'm fine with that change, but I'm not sure how to communicate that to the distro maintainers. I wouldn't want them to try and build the next version of xen and find it mysterously failing.
I'm not so worried about that. Xen ships its own seabios-config file and is set up to build SeaBIOS for itself as part of its build process. So distros who patch it to use their own prebuilt SeaBIOS (like Fedora does) should expect to be at least watching for changes to the config file.
However, if the Xen SeaBIOS image also wants some parts of CONFIG_QEMU like the fw_cfg support, then I do start to wonder if it's actually worth making that change anyway. It was a nice cleanup, with a bunch of s/if (CONFIG_QEMU && !runningOnXen())/if (CONFIG_QEMU)/ and s/if (!CONFIG_QEMU || runningOnXen())/if (!CONFIG_QEMU)/
But now we'd have to add *back* some more complex conditions in other places.... but I suppose it would still be a net win. I'll put it together and test it, and we can make a decision. I really do need to get my act together for testing under Xen *anyway* since I should test OVMF+CSM there, so the effort involved in doing so is mostly not wasted.
BTW, I did pull a bunch of other patches from your tree into the seabios repo.
Ta. I don't have a lot left, do I? :)
I've pushed my dregs out....
- e1272ff8 Enable VGA output when settings bochs-specific mode
You're already looking at this one.
- 20bcdbcf Make Xen one of the top-level build target choices
Will test this and post a version for review.
- 4940c334 Clean up Kconfig options for CSM
Merging this would be good.
- d87fd3cc Add UmbStart,UmbEnd fields to EFI_COMPATIBILITY16_TABLE
Still chasing up the spec change...
- 4def181d Reject non-compliant PCI option ROMs with unaligned PCIR structure
We can drop this if you're not keen, but it *is* an option so people could still keep compatibility with broken ROMs, and consistency is good. We'd never have been shipping broken ROMs if we'd done this in the first place...
On Wed, Feb 13, 2013 at 09:50:13AM +0000, David Woodhouse wrote:
However, if the Xen SeaBIOS image also wants some parts of CONFIG_QEMU like the fw_cfg support, then I do start to wonder if it's actually worth making that change anyway. It was a nice cleanup, with a bunch of s/if (CONFIG_QEMU && !runningOnXen())/if (CONFIG_QEMU)/ and s/if (!CONFIG_QEMU || runningOnXen())/if (!CONFIG_QEMU)/
Another way to tackle this might be to just group all the qemu and xen calls into paravirt.c. That retains runningOnXen, but it's not spread around as much. See patch below as an idea.
-Kevin
diff --git a/src/coreboot.c b/src/coreboot.c index c0c6653..0d44834 100644 --- a/src/coreboot.c +++ b/src/coreboot.c @@ -13,6 +13,8 @@ #include "disk.h" // MAXDESCSIZE #include "config.h" // CONFIG_* #include "acpi.h" // find_pmtimer +#include "pci.h" // pci_probe_devices +
/**************************************************************** * Memory map @@ -125,6 +127,9 @@ const char *CBvendor = "", *CBpart = ""; void coreboot_preinit(void) { + if (!CONFIG_COREBOOT) + return; + dprintf(3, "Attempting to find coreboot table\n");
// Find coreboot table. @@ -204,10 +209,14 @@ scan_tables(u32 start, u32 size) }
void -coreboot_biostable_setup(void) +coreboot_platform_setup(void) { + if (!CONFIG_COREBOOT) + return; + pci_probe_devices(); + struct cb_memory *cbm = CBMemTable; - if (! CONFIG_COREBOOT || !cbm) + if (!cbm) return;
dprintf(3, "Relocating coreboot bios tables\n"); diff --git a/src/mtrr.c b/src/mtrr.c index 0575b14..56f85f9 100644 --- a/src/mtrr.c +++ b/src/mtrr.c @@ -6,7 +6,6 @@
#include "util.h" // dprintf #include "config.h" // CONFIG_* -#include "paravirt.h" // runningOnXen #include "pci.h" // pcimem_start
#define MSR_MTRRcap 0x000000fe @@ -34,7 +33,7 @@
void mtrr_setup(void) { - if (!CONFIG_MTRR_INIT || runningOnXen()) + if (!CONFIG_MTRR_INIT) return;
u32 eax, ebx, ecx, edx, cpuid_features; diff --git a/src/paravirt.c b/src/paravirt.c index aa4a421..f76b47f 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -19,6 +19,7 @@ #include "acpi.h" // acpi_setup #include "mptable.h" // mptable_setup #include "pci.h" // create_pirtable +#include "xen.h" // xen_biostable_setup
/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It * should be used to determine that a VM is running under KVM. @@ -45,11 +46,16 @@ static void kvm_preinit(void) }
void -qemu_ramsize_preinit(void) +qemu_preinit(void) { if (!CONFIG_QEMU) return;
+ if (runningOnXen()) { + xen_ramsize_preinit(); + return; + } + PlatformRunningOn = PF_QEMU; kvm_preinit();
@@ -77,8 +83,27 @@ qemu_ramsize_preinit(void) }
void -qemu_biostable_setup(void) +qemu_platform_setup(void) { + if (!CONFIG_QEMU) + return; + + if (runningOnXen()) { + pci_probe_devices(); + xen_hypercall_setup(); + xen_biostable_setup(); + return; + } + + // Initialize pci + pci_setup(); + smm_setup(); + + // Initialize mtrr and smp + mtrr_setup(); + smp_setup(); + + // Create bios tables pirtable_setup(); mptable_setup(); smbios_setup(); diff --git a/src/paravirt.h b/src/paravirt.h index 4438273..96b35ba 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -23,8 +23,8 @@ static inline int runningOnKVM(void) { return CONFIG_QEMU && GET_GLOBAL(PlatformRunningOn) & PF_KVM; }
-void qemu_ramsize_preinit(void); -void qemu_biostable_setup(void); +void qemu_preinit(void); +void qemu_platform_setup(void); void qemu_cfg_init(void);
#endif diff --git a/src/pciinit.c b/src/pciinit.c index 1d34653..d757ab6 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -11,7 +11,6 @@ #include "pci_regs.h" // PCI_COMMAND #include "ioport.h" // PORT_ATA1_CMD_BASE #include "config.h" // CONFIG_* -#include "paravirt.h" // runningOnXen #include "memmap.h" // add_e820 #include "dev-q35.h"
@@ -734,11 +733,8 @@ static void pci_bios_map_devices(struct pci_bus *busses) void pci_setup(void) { - if (!CONFIG_QEMU || runningOnXen()) { - // PCI setup already done by coreboot or Xen - just do probe. - pci_probe_devices(); + if (!CONFIG_QEMU) return; - }
dprintf(3, "pci setup\n");
diff --git a/src/post.c b/src/post.c index 3af3638..f2eded9 100644 --- a/src/post.c +++ b/src/post.c @@ -159,24 +159,9 @@ platform_hardware_setup(void) mathcp_setup(); timer_setup();
- // Initialize pci - pci_setup(); - smm_setup(); - - // Initialize mtrr and smp - mtrr_setup(); - smp_setup(); - - // Setup Xen hypercalls - xen_hypercall_setup(); - - // Setup external BIOS interface tables - if (CONFIG_COREBOOT) - coreboot_biostable_setup(); - else if (runningOnXen()) - xen_biostable_setup(); - else - qemu_biostable_setup(); + // Platform specific setup + qemu_platform_setup(); + coreboot_platform_setup(); }
void @@ -314,12 +299,8 @@ void VISIBLE32INIT dopost(void) { // Detect ram and setup internal malloc. - if (CONFIG_COREBOOT) - coreboot_preinit(); - else if (runningOnXen()) - xen_ramsize_preinit(); - else - qemu_ramsize_preinit(); + qemu_preinit(); + coreboot_preinit(); malloc_preinit();
// Relocate initialization code and call maininit(). diff --git a/src/smm.c b/src/smm.c index 4128296..490a626 100644 --- a/src/smm.c +++ b/src/smm.c @@ -10,7 +10,6 @@ #include "config.h" // CONFIG_* #include "ioport.h" // outb #include "pci_ids.h" // PCI_VENDOR_ID_INTEL -#include "paravirt.h" // runningOnXen #include "dev-q35.h"
ASM32FLAT( @@ -184,7 +183,7 @@ static const struct pci_device_id smm_init_tbl[] = { void smm_setup(void) { - if (!CONFIG_USE_SMM || runningOnXen()) + if (!CONFIG_USE_SMM) return;
dprintf(3, "init smm\n"); diff --git a/src/util.h b/src/util.h index 0659d24..8875d95 100644 --- a/src/util.h +++ b/src/util.h @@ -327,7 +327,7 @@ int apic_id_is_present(u8 apic_id); extern const char *CBvendor, *CBpart; struct cbfs_file; void cbfs_run_payload(struct cbfs_file *file); -void coreboot_biostable_setup(void); +void coreboot_platform_setup(void); void cbfs_payload_setup(void); void coreboot_preinit(void); void coreboot_cbfs_init(void);
On Wed, Feb 13, 2013 at 09:50:13AM +0000, David Woodhouse wrote:
- 4940c334 Clean up Kconfig options for CSM
Merging this would be good.
The "BIOS interfaces" menu allows developers to turn off bios features for testing or to shrink the SeaBIOS binary size. I don't see a gain to limiting what devs can turn off. Turning off CONFIG_BOOT could be useful - an embedded device might want support for running legacy option roms under UEFI but know it will never need to boot in legacy mode. CONFIG_OPTIONROMS doesn't do anything under CSM, but maybe it makes sense to add "if (!CONFIG_OPTIONROMS) return" to the top of handle_csm_0005.
Granted, CONFIG_OPTIONROMS_DEPLOYED isn't terribly useful - it's probably about time all that code was just removed. (Or at least set to depends on QEMU.)
- 4def181d Reject non-compliant PCI option ROMs with unaligned PCIR structure
We can drop this if you're not keen, but it *is* an option so people could still keep compatibility with broken ROMs, and consistency is good. We'd never have been shipping broken ROMs if we'd done this in the first place...
I don't see why one would want to enable an option that will cause the boot to fail mysteriously for some users. It wouldn't be a problem if we thought all roms followed the spec, but we know the current "lgpl vgabios" violates this. How about the following instead:
--- a/src/optionroms.c +++ b/src/optionroms.c @@ -109,6 +109,9 @@ get_pci_rom(struct rom_header *rom) struct pci_data *pd = (void*)((u32)rom + rom->pcioffset); if (pd->signature != PCI_ROM_SIGNATURE) return NULL; + if (rom->pcioffset & 3) + dprintf(1, "WARNING! Found unaligned PCI rom (vd=%04x:%04x)\n" + , pd->vendor, pd->device); return pd; }
-Kevin
On Wed, 2013-02-13 at 20:02 -0500, Kevin O'Connor wrote:
On Wed, Feb 13, 2013 at 09:50:13AM +0000, David Woodhouse wrote:
- 4940c334 Clean up Kconfig options for CSM
Merging this would be good.
The "BIOS interfaces" menu allows developers to turn off bios features for testing or to shrink the SeaBIOS binary size. I don't see a gain to limiting what devs can turn off. Turning off CONFIG_BOOT could be useful - an embedded device might want support for running legacy option roms under UEFI but know it will never need to boot in legacy mode. CONFIG_OPTIONROMS doesn't do anything under CSM, but maybe it makes sense to add "if (!CONFIG_OPTIONROMS) return" to the top of handle_csm_0005.
I'm dubious about the sanity of those who use UEFI and yet also actually care about the size of their firmware. But yes, that makes a certain amount of sense. I'll look at implementing the CONFIG_BOOT part of it at least, and I might as well do the CONFIG_OPTIONROMS bit as you suggest too.
Granted, CONFIG_OPTIONROMS_DEPLOYED isn't terribly useful - it's probably about time all that code was just removed. (Or at least set to depends on QEMU.)
OK.
- if (rom->pcioffset & 3)
dprintf(1, "WARNING! Found unaligned PCI rom (vd=%04x:%04x)\n"
, pd->vendor, pd->device);
Yeah, that works.
Hi,
Granted, CONFIG_OPTIONROMS_DEPLOYED isn't terribly useful - it's probably about time all that code was just removed. (Or at least set to depends on QEMU.)
IMO it can go away. The corresponding code in qemu is gone since 0.12, so you'll break seabios for qemu 0.11 + older (that are those releases which ship with bochs bios ...).
cheers, Gerd
I oppose the name runningOnXen() ! I propose the name running_on_Xen()
On Fri, 2013-02-08 at 18:02 -0500, Kevin O'Connor wrote:
I'm not sure it would even work for CSM, because it would probably be too big.
As an aside, is there a way to pass in the "init" sections to ovmf such that they don't prevent option roms from using the space? Also, I briefly tried not padding bios.bin to a power of 2, but ovmf doesn't seem to like that.
I've already proposed the UmbStart and UmbEnd fields which the CSM can use to mark the memory it needs to be writeable, and I've hard-coded that to 0xe0000-0xf0000 for the SeaBIOS CSM build. That 0xe0000 should actually be datalow_start, shouldn't it?
We could happily declare that OVMF can place option ROMs up to UmbStart (== datalow_start) so when SeaBIOS relocates its own init code, the extra memory (below the memory it uses for its own purposes) can be reclaimed.
In fact I think my OVMF patch for the UmbStart,UmbEnd support already did that, didn't it?
On Fri, Feb 08, 2013 at 11:25:39PM +0000, David Woodhouse wrote:
On Fri, 2013-02-08 at 18:02 -0500, Kevin O'Connor wrote:
I'm not sure it would even work for CSM, because it would probably be too big.
As an aside, is there a way to pass in the "init" sections to ovmf such that they don't prevent option roms from using the space? Also, I briefly tried not padding bios.bin to a power of 2, but ovmf doesn't seem to like that.
I've already proposed the UmbStart and UmbEnd fields which the CSM can use to mark the memory it needs to be writeable, and I've hard-coded that to 0xe0000-0xf0000 for the SeaBIOS CSM build. That 0xe0000 should actually be datalow_start, shouldn't it?
I think you'd want datalow_base. Ideally SeaBIOS would update the setting dynamically.
We could happily declare that OVMF can place option ROMs up to UmbStart (== datalow_start) so when SeaBIOS relocates its own init code, the extra memory (below the memory it uses for its own purposes) can be reclaimed.
In fact I think my OVMF patch for the UmbStart,UmbEnd support already did that, didn't it?
That would work for SeaBIOS. I missed that in your proposal.
-Kevin
On Fri, 2013-02-08 at 18:37 -0500, Kevin O'Connor wrote:
On Fri, Feb 08, 2013 at 11:25:39PM +0000, David Woodhouse wrote:
On Fri, 2013-02-08 at 18:02 -0500, Kevin O'Connor wrote:
I'm not sure it would even work for CSM, because it would probably be too big.
As an aside, is there a way to pass in the "init" sections to ovmf such that they don't prevent option roms from using the space? Also, I briefly tried not padding bios.bin to a power of 2, but ovmf doesn't seem to like that.
I've already proposed the UmbStart and UmbEnd fields which the CSM can use to mark the memory it needs to be writeable, and I've hard-coded that to 0xe0000-0xf0000 for the SeaBIOS CSM build. That 0xe0000 should actually be datalow_start, shouldn't it?
I think you'd want datalow_base. Ideally SeaBIOS would update the setting dynamically.
In my current builds, datalow_base is 0xd2800. datalow_start is 0xe1800, and datalow_end is 0xe2071.
I didn't think we ever really went as low as datalow_base; that's just the segment base, while all the offsets were higher?
If we really need writeable RAM all the way down to datalow_base, then that's a problem; OVMF isn't currently giving us that.
We could happily declare that OVMF can place option ROMs up to UmbStart (== datalow_start) so when SeaBIOS relocates its own init code, the extra memory (below the memory it uses for its own purposes) can be reclaimed.
In fact I think my OVMF patch for the UmbStart,UmbEnd support already did that, didn't it?
That would work for SeaBIOS. I missed that in your proposal.
Note the MaxRomAddr bit: http://sourceforge.net/mailarchive/forum.php?thread_name=50FD7290.9060003%40...