Add support for loading roms using the qemu fw_cfg interface, modeled after the existing cbfs support. Use it to look for vgabios (vgaroms/*) and option roms (genroms/*).
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/optionroms.c | 22 ++++++++++++++++++++++ src/paravirt.c | 37 +++++++++++++++++++++++++++++++++++++ src/paravirt.h | 11 +++++++++++ 3 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/src/optionroms.c b/src/optionroms.c index 27465ad..c5de1ad 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -247,6 +247,26 @@ run_cbfs_roms(const char *prefix, int isvga) } }
+static void +run_qemu_roms(const char *prefix, int isvga) +{ + struct QemuCfgFile entry; + int plen = strlen(prefix); + int rc, dlen; + + rc = qemu_cfg_first_file(&entry); + while (rc > 0) { + if (memcmp(prefix, entry.name, plen) == 0) { + dlen = qemu_cfg_read_file(&entry, (void*)RomEnd, max_rom() - RomEnd); + if (dlen > 0) { + dprintf(1, "init qemu rom: %s\n", entry.name); + init_optionrom((void*)RomEnd, 0, isvga); + } + } + rc = qemu_cfg_next_file(&entry); + } +} +
/**************************************************************** * PCI roms @@ -375,6 +395,7 @@ optionrom_setup()
// Find and deploy CBFS roms not associated with a device. run_cbfs_roms("genroms/", 0); + run_qemu_roms("genroms/", 0); }
// All option roms found and deployed - now build BEV/BCV vectors. @@ -434,6 +455,7 @@ vga_setup()
// Find and deploy CBFS vga-style roms not associated with a device. run_cbfs_roms("vgaroms/", 1); + run_qemu_roms("vgaroms/", 1); }
if (RomEnd == BUILD_ROM_START) { diff --git a/src/paravirt.c b/src/paravirt.c index 6f48d2e..7171bac 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -8,6 +8,7 @@ // This file may be distributed under the terms of the GNU LGPLv3 license.
#include "config.h" // CONFIG_COREBOOT +#include "util.h" // ntoh[ls] #include "ioport.h" // outw #include "paravirt.h" // qemu_cfg_port_probe #include "smbios.h" // struct smbios_structure_header @@ -287,3 +288,39 @@ u16 qemu_cfg_get_max_cpus(void)
return cnt; } + +u16 qemu_cfg_first_file(QemuCfgFile *entry) +{ + memset(entry, 0, sizeof(*entry)); + return qemu_cfg_next_file(entry); +} + +u16 qemu_cfg_next_file(QemuCfgFile *entry) +{ + u16 last = ntohs(entry->select); + u32 e,count; + + if (!qemu_cfg_present) + return 0; + + qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count)); + for (e = 0; e < ntohl(count); e++) { + qemu_cfg_read((void*)entry, sizeof(*entry)); + if (ntohs(entry->select) > last) { + return 1; + } + } + return 0; +} + +u32 qemu_cfg_read_file(QemuCfgFile *entry, void *dst, u32 maxlen) +{ + int len = ntohl(entry->size); + + if (!qemu_cfg_present) + return 0; + if (len > maxlen) + return 0; + qemu_cfg_read_entry(dst, ntohs(entry->select), len); + return len; +} diff --git a/src/paravirt.h b/src/paravirt.h index 29a2c04..d33e10d 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -31,6 +31,7 @@ static inline int kvm_para_available(void) #define QEMU_CFG_NUMA 0x0d #define QEMU_CFG_BOOT_MENU 0x0e #define QEMU_CFG_MAX_CPUS 0x0f +#define QEMU_CFG_FILE_DIR 0x19 #define QEMU_CFG_ARCH_LOCAL 0x8000 #define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0) #define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1) @@ -53,4 +54,14 @@ int qemu_cfg_get_numa_nodes(void); void qemu_cfg_get_numa_data(u64 *data, int n); u16 qemu_cfg_get_max_cpus(void);
+typedef struct QemuCfgFile { + u32 size; /* file size */ + u16 select; /* write this to 0x510 to read it */ + u16 reserved; + char name[56]; +} QemuCfgFile; + +u16 qemu_cfg_first_file(QemuCfgFile *entry); +u16 qemu_cfg_next_file(QemuCfgFile *entry); + #endif