QEMU has multiple mechanisms for passing configuration information into SeaBIOS: cmos, fw_cfg ports, and fw_cfg "files". The preferred mechanism is the "file" interface which is internally accessed via a "romfile" interface.
It's annoying to have to switch between the different interfaces. So, this patch series converts all the older fw_cfg ports (and some cmos info) to use romfile as well.
I've lightly tested this series. I've also pushed it for testing to: https://github.com/KevinOConnor/seabios/branches/test-fwcfg-20130209
-Kevin
Kevin O'Connor (8): Support skipping content when reading from QEMU fw_cfg romfile entries. Convert fw_cfg ACPI entries into romfile entries. Convert fw_cfg SMBIOS entries into romfile entries. Convert basic integer fw_cfg entries into romfile entries. Convert fw_cfg NUMA entries into a romfile entry. Process fw_cfg e820 entries during the fw_cfg setup stage. Integrate qemu_cfg_preinit() into qemu_romfile_init(). Convert some QEMU cmos config variables to the romfile interface.
src/acpi.c | 50 ++++--- src/ata.c | 1 - src/boot.c | 2 +- src/clock.c | 5 +- src/cmos.h | 12 +- src/coreboot.c | 1 - src/floppy.c | 21 +-- src/mptable.c | 3 +- src/paravirt.c | 429 +++++++++++++++++++-------------------------------------- src/paravirt.h | 18 +-- src/post.c | 3 +- src/romfile.c | 1 + src/smbios.c | 119 +++++++++++----- src/smp.c | 3 +- 14 files changed, 272 insertions(+), 396 deletions(-)
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/coreboot.c | 1 - src/paravirt.c | 42 ++++++++++++++++++++++++++---------------- src/romfile.c | 1 + 3 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/src/coreboot.c b/src/coreboot.c index 5d5e03b..a7556d0 100644 --- a/src/coreboot.c +++ b/src/coreboot.c @@ -352,7 +352,6 @@ coreboot_cbfs_init(void) } memset(file, 0, sizeof(*file)); strtcpy(file->name, cfile->filename, sizeof(file->name)); - dprintf(3, "Found CBFS file: %s\n", file->name); file->size = file->rawsize = be32_to_cpu(cfile->len); file->id = (u32)cfile; file->copy = cbfs_copyfile; diff --git a/src/paravirt.c b/src/paravirt.c index cc64094..0d1fb35 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -133,7 +133,7 @@ qemu_cfg_select(u16 f) }
static void -qemu_cfg_read(u8 *buf, int len) +qemu_cfg_read(void *buf, int len) { insb(PORT_QEMU_CFG_DATA, buf, len); } @@ -416,14 +416,34 @@ u16 qemu_cfg_get_max_cpus(void) return cnt; }
-int qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) +static int +qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) { if (file->size > maxlen) return -1; - qemu_cfg_read_entry(dst, file->id, file->size); + qemu_cfg_select(file->id); + qemu_cfg_skip(file->rawsize); + qemu_cfg_read(dst, file->size); return file->size; }
+static void +qemu_romfile_add(char *name, int select, int skip, int size) +{ + struct romfile_s *file = malloc_tmp(sizeof(*file)); + if (!file) { + warn_noalloc(); + return; + } + memset(file, 0, sizeof(*file)); + strtcpy(file->name, name, sizeof(file->name)); + file->id = select; + file->rawsize = skip; // Use rawsize to indicate skip length. + file->size = size; + file->copy = qemu_cfg_read_file; + romfile_add(file); +} + struct QemuCfgFile { u32 size; /* file size */ u16 select; /* write this to 0x510 to read it */ @@ -442,18 +462,8 @@ void qemu_romfile_init(void) u32 e; for (e = 0; e < count; e++) { struct QemuCfgFile qfile; - qemu_cfg_read((void*)&qfile, sizeof(qfile)); - struct romfile_s *file = malloc_tmp(sizeof(*file)); - if (!file) { - warn_noalloc(); - return; - } - memset(file, 0, sizeof(*file)); - strtcpy(file->name, qfile.name, sizeof(file->name)); - file->size = be32_to_cpu(qfile.size); - file->id = be16_to_cpu(qfile.select); - file->copy = qemu_cfg_read_file; - romfile_add(file); - dprintf(3, "Found fw_cfg file: %s (size=%d)\n", file->name, file->size); + qemu_cfg_read(&qfile, sizeof(qfile)); + qemu_romfile_add(qfile.name, be16_to_cpu(qfile.select) + , 0, be32_to_cpu(qfile.size)); } } diff --git a/src/romfile.c b/src/romfile.c index b732e29..93ee3d6 100644 --- a/src/romfile.c +++ b/src/romfile.c @@ -12,6 +12,7 @@ static struct romfile_s *RomfileRoot; void romfile_add(struct romfile_s *file) { + dprintf(3, "Add romfile: %s (size=%d)\n", file->name, file->size); file->next = RomfileRoot; RomfileRoot = file; }
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/acpi.c | 24 +++++++++++++----------- src/paravirt.c | 52 +++++++++++++++++++++++++--------------------------- src/paravirt.h | 3 --- 3 files changed, 38 insertions(+), 41 deletions(-)
diff --git a/src/acpi.c b/src/acpi.c index c4479d9..5396ae2 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -828,23 +828,25 @@ acpi_setup(void) if (pci->device == PCI_DEVICE_ID_INTEL_ICH9_LPC) ACPI_INIT_TABLE(build_mcfg_q35());
- u16 i, external_tables = qemu_cfg_acpi_additional_tables(); - - for (i = 0; i < external_tables; i++) { - u16 len = qemu_cfg_next_acpi_table_len(); - void *addr = malloc_high(len); - if (!addr) { + struct romfile_s *file = NULL; + for (;;) { + file = romfile_findprefix("acpi/", file); + if (!file) + break; + struct acpi_table_header *table = malloc_high(file->size); + if (!table) { warn_noalloc(); continue; } - struct acpi_table_header *header = - qemu_cfg_next_acpi_table_load(addr, len); - if (header->signature == DSDT_SIGNATURE) { + int ret = file->copy(file, table, file->size); + if (ret <= sizeof(*table)) + continue; + if (table->signature == DSDT_SIGNATURE) { if (fadt) { - fill_dsdt(fadt, addr); + fill_dsdt(fadt, table); } } else { - ACPI_INIT_TABLE(header); + ACPI_INIT_TABLE(table); } if (tbl_idx == MAX_ACPI_TABLES) { warn_noalloc(); diff --git a/src/paravirt.c b/src/paravirt.c index 0d1fb35..f17930f 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -203,33 +203,6 @@ int qemu_cfg_irq0_override(void) return v; }
-u16 qemu_cfg_acpi_additional_tables(void) -{ - u16 cnt; - - if (!qemu_cfg_present) - return 0; - - qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt)); - - return cnt; -} - -u16 qemu_cfg_next_acpi_table_len(void) -{ - u16 len; - - qemu_cfg_read((u8*)&len, sizeof(len)); - - return len; -} - -void* qemu_cfg_next_acpi_table_load(void *addr, u16 len) -{ - qemu_cfg_read(addr, len); - return addr; -} - u16 qemu_cfg_smbios_entries(void) { u16 cnt; @@ -444,6 +417,27 @@ qemu_romfile_add(char *name, int select, int skip, int size) romfile_add(file); }
+// Populate romfile entries for legacy fw_cfg ports (that predate the +// "file" interface). +static void +qemu_cfg_legacy(void) +{ + // ACPI tables + char name[128]; + u16 cnt; + qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt)); + int i, offset = sizeof(cnt); + for (i = 0; i < cnt; i++) { + u16 len; + qemu_cfg_read(&len, sizeof(len)); + offset += sizeof(len); + snprintf(name, sizeof(name), "acpi/table%d", i); + qemu_romfile_add(name, QEMU_CFG_ACPI_TABLES, offset, len); + qemu_cfg_skip(len); + offset += len; + } +} + struct QemuCfgFile { u32 size; /* file size */ u16 select; /* write this to 0x510 to read it */ @@ -456,6 +450,10 @@ void qemu_romfile_init(void) if (!CONFIG_QEMU || !qemu_cfg_present) return;
+ // Populate romfiles for legacy fw_cfg entries + qemu_cfg_legacy(); + + // Load files found in the fw_cfg file directory u32 count; qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count)); count = be32_to_cpu(count); diff --git a/src/paravirt.h b/src/paravirt.h index a3da04d..6836290 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -29,9 +29,6 @@ void qemu_cfg_preinit(void); int qemu_cfg_show_boot_menu(void); void qemu_cfg_get_uuid(u8 *uuid); int qemu_cfg_irq0_override(void); -u16 qemu_cfg_acpi_additional_tables(void); -u16 qemu_cfg_next_acpi_table_len(void); -void *qemu_cfg_next_acpi_table_load(void *addr, u16 len); u16 qemu_cfg_smbios_entries(void); size_t qemu_cfg_smbios_load_field(int type, size_t offset, void *addr); int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs,
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/paravirt.c | 174 +++++++++++---------------------------------------------- src/paravirt.h | 4 -- src/smbios.c | 119 +++++++++++++++++++++++++++++---------- 3 files changed, 121 insertions(+), 176 deletions(-)
diff --git a/src/paravirt.c b/src/paravirt.c index f17930f..e782227 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -12,7 +12,7 @@ #include "byteorder.h" // be32_to_cpu #include "ioport.h" // outw #include "paravirt.h" // qemu_cfg_preinit -#include "smbios.h" // struct smbios_structure_header +#include "smbios.h" // smbios_setup #include "memmap.h" // add_e820 #include "cmos.h" // CMOS_* #include "acpi.h" // acpi_setup @@ -203,18 +203,6 @@ int qemu_cfg_irq0_override(void) return v; }
-u16 qemu_cfg_smbios_entries(void) -{ - u16 cnt; - - if (!qemu_cfg_present) - return 0; - - qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt)); - - return cnt; -} - u32 qemu_cfg_e820_entries(void) { u32 cnt; @@ -232,134 +220,6 @@ void* qemu_cfg_e820_load_next(void *addr) return addr; }
-struct smbios_header { - u16 length; - u8 type; -} PACKED; - -struct smbios_field { - struct smbios_header header; - u8 type; - u16 offset; - u8 data[]; -} PACKED; - -struct smbios_table { - struct smbios_header header; - u8 data[]; -} PACKED; - -#define SMBIOS_FIELD_ENTRY 0 -#define SMBIOS_TABLE_ENTRY 1 - -size_t qemu_cfg_smbios_load_field(int type, size_t offset, void *addr) -{ - int i; - - for (i = qemu_cfg_smbios_entries(); i > 0; i--) { - struct smbios_field field; - - qemu_cfg_read((u8 *)&field, sizeof(struct smbios_header)); - field.header.length -= sizeof(struct smbios_header); - - if (field.header.type != SMBIOS_FIELD_ENTRY) { - qemu_cfg_skip(field.header.length); - continue; - } - - qemu_cfg_read((u8 *)&field.type, - sizeof(field) - sizeof(struct smbios_header)); - field.header.length -= sizeof(field) - sizeof(struct smbios_header); - - if (field.type != type || field.offset != offset) { - qemu_cfg_skip(field.header.length); - continue; - } - - qemu_cfg_read(addr, field.header.length); - return (size_t)field.header.length; - } - return 0; -} - -int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs, - unsigned *max_struct_size, char *end) -{ - static u64 used_bitmap[4] = { 0 }; - char *start = *p; - int i; - - /* Check if we've already reported these tables */ - if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f))) - return 1; - - /* Don't introduce spurious end markers */ - if (type == 127) - return 0; - - for (i = qemu_cfg_smbios_entries(); i > 0; i--) { - struct smbios_table table; - struct smbios_structure_header *header = (void *)*p; - int string; - - qemu_cfg_read((u8 *)&table, sizeof(struct smbios_header)); - table.header.length -= sizeof(struct smbios_header); - - if (table.header.type != SMBIOS_TABLE_ENTRY) { - qemu_cfg_skip(table.header.length); - continue; - } - - if (end - *p < sizeof(struct smbios_structure_header)) { - warn_noalloc(); - break; - } - - qemu_cfg_read((u8 *)*p, sizeof(struct smbios_structure_header)); - table.header.length -= sizeof(struct smbios_structure_header); - - if (header->type != type) { - qemu_cfg_skip(table.header.length); - continue; - } - - *p += sizeof(struct smbios_structure_header); - - /* Entries end with a double NULL char, if there's a string at - * the end (length is greater than formatted length), the string - * terminator provides the first NULL. */ - string = header->length < table.header.length + - sizeof(struct smbios_structure_header); - - /* Read the rest and terminate the entry */ - if (end - *p < table.header.length) { - warn_noalloc(); - *p -= sizeof(struct smbios_structure_header); - continue; - } - qemu_cfg_read((u8 *)*p, table.header.length); - *p += table.header.length; - *((u8*)*p) = 0; - (*p)++; - if (!string) { - *((u8*)*p) = 0; - (*p)++; - } - - (*nr_structs)++; - if (*p - (char *)header > *max_struct_size) - *max_struct_size = *p - (char *)header; - } - - if (start != *p) { - /* Mark that we've reported on this type */ - used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f)); - return 1; - } - - return 0; -} - int qemu_cfg_get_numa_nodes(void) { u64 cnt; @@ -417,6 +277,16 @@ qemu_romfile_add(char *name, int select, int skip, int size) romfile_add(file); }
+#define SMBIOS_FIELD_ENTRY 0 +#define SMBIOS_TABLE_ENTRY 1 + +struct qemu_smbios_header { + u16 length; + u8 headertype; + u8 tabletype; + u16 fieldoffset; +} PACKED; + // Populate romfile entries for legacy fw_cfg ports (that predate the // "file" interface). static void @@ -436,6 +306,28 @@ qemu_cfg_legacy(void) qemu_cfg_skip(len); offset += len; } + + // SMBIOS info + qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt)); + offset = sizeof(cnt); + for (i = 0; i < cnt; i++) { + struct qemu_smbios_header header; + qemu_cfg_read(&header, sizeof(header)); + if (header.headertype == SMBIOS_FIELD_ENTRY) { + snprintf(name, sizeof(name), "smbios/field%d-%d" + , header.tabletype, header.fieldoffset); + qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES + , offset + sizeof(header) + , header.length - sizeof(header)); + } else { + snprintf(name, sizeof(name), "smbios/table%d-%d" + , header.tabletype, i); + qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES + , offset + 3, header.length - 3); + } + qemu_cfg_skip(header.length - sizeof(header)); + offset += header.length; + } }
struct QemuCfgFile { diff --git a/src/paravirt.h b/src/paravirt.h index 6836290..6b99ca9 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -29,10 +29,6 @@ void qemu_cfg_preinit(void); int qemu_cfg_show_boot_menu(void); void qemu_cfg_get_uuid(u8 *uuid); int qemu_cfg_irq0_override(void); -u16 qemu_cfg_smbios_entries(void); -size_t qemu_cfg_smbios_load_field(int type, size_t offset, void *addr); -int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs, - unsigned *max_struct_size, char *end); int qemu_cfg_get_numa_nodes(void); void qemu_cfg_get_numa_data(u64 *data, int n); u16 qemu_cfg_get_max_cpus(void); diff --git a/src/smbios.c b/src/smbios.c index c235564..a9d76f0 100644 --- a/src/smbios.c +++ b/src/smbios.c @@ -6,7 +6,7 @@ // This file may be distributed under the terms of the GNU LGPLv3 license.
#include "util.h" // dprintf -#include "paravirt.h" // qemu_cfg_smbios_load_field +#include "config.h" // CONFIG_* #include "smbios.h" // struct smbios_entry_point
struct smbios_entry_point *SMBiosAddr; @@ -56,11 +56,77 @@ smbios_entry_point_setup(u16 max_structure_size, , ep, finaltable, structure_table_length); }
+static int +get_field(int type, int offset, void *dest) +{ + char name[128]; + snprintf(name, sizeof(name), "smbios/field%d-%d", type, offset); + struct romfile_s *file = romfile_find(name); + if (!file) + return 0; + file->copy(file, dest, file->size); + return file->size; +} + +static int +get_external(int type, char **p, unsigned *nr_structs, + unsigned *max_struct_size, char *end) +{ + static u64 used_bitmap[4] = { 0 }; + char *start = *p; + + /* Check if we've already reported these tables */ + if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f))) + return 1; + + /* Don't introduce spurious end markers */ + if (type == 127) + return 0; + + char prefix[128]; + snprintf(prefix, sizeof(prefix), "smbios/table%d-", type); + struct romfile_s *file = NULL; + for (;;) { + file = romfile_findprefix(prefix, file); + if (!file) + break; + + if (end - *p < file->size) { + warn_noalloc(); + break; + } + + struct smbios_structure_header *header = (void*)*p; + file->copy(file, header, file->size); + *p += file->size; + + /* Entries end with a double NULL char, if there's a string at + * the end (length is greater than formatted length), the string + * terminator provides the first NULL. */ + *((u8*)*p) = 0; + (*p)++; + if (header->length >= file->size) { + *((u8*)*p) = 0; + (*p)++; + } + + (*nr_structs)++; + if (*p - (char*)header > *max_struct_size) + *max_struct_size = *p - (char*)header; + } + + if (start == *p) + return 0; + + /* Mark that we've reported on this type */ + used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f)); + return 1; +} + #define load_str_field_with_default(type, field, def) \ do { \ - size = qemu_cfg_smbios_load_field(type, \ - offsetof(struct smbios_type_##type, \ - field), end); \ + size = get_field(type, offsetof(struct smbios_type_##type, \ + field), end); \ if (size > 0) { \ end += size; \ } else { \ @@ -72,9 +138,8 @@ smbios_entry_point_setup(u16 max_structure_size,
#define load_str_field_or_skip(type, field) \ do { \ - size = qemu_cfg_smbios_load_field(type, \ - offsetof(struct smbios_type_##type, \ - field), end); \ + size = get_field(type, offsetof(struct smbios_type_##type, \ + field), end); \ if (size > 0) { \ end += size; \ p->field = ++str_index; \ @@ -85,9 +150,8 @@ smbios_entry_point_setup(u16 max_structure_size,
#define set_field_with_default(type, field, def) \ do { \ - if (!qemu_cfg_smbios_load_field(type, \ - offsetof(struct smbios_type_##type, \ - field), &p->field)) { \ + if (!get_field(type, offsetof(struct smbios_type_##type, \ + field), &p->field)) { \ p->field = def; \ } \ } while (0) @@ -115,17 +179,16 @@ smbios_init_type_0(void *start)
p->bios_rom_size = 0; /* FIXME */
- if (!qemu_cfg_smbios_load_field(0, offsetof(struct smbios_type_0, - bios_characteristics), - &p->bios_characteristics)) { + if (!get_field(0, offsetof(struct smbios_type_0, bios_characteristics), + &p->bios_characteristics)) { memset(p->bios_characteristics, 0, 8); /* BIOS characteristics not supported */ p->bios_characteristics[0] = 0x08; }
- if (!qemu_cfg_smbios_load_field(0, offsetof(struct smbios_type_0, - bios_characteristics_extension_bytes), - &p->bios_characteristics_extension_bytes)) { + if (!get_field(0, offsetof(struct smbios_type_0, + bios_characteristics_extension_bytes), + &p->bios_characteristics_extension_bytes)) { p->bios_characteristics_extension_bytes[0] = 0; /* Enable targeted content distribution. Needed for SVVP */ p->bios_characteristics_extension_bytes[1] = 4; @@ -160,10 +223,8 @@ smbios_init_type_1(void *start) load_str_field_or_skip(1, version_str); load_str_field_or_skip(1, serial_number_str);
- if (!qemu_cfg_smbios_load_field(1, offsetof(struct smbios_type_1, - uuid), &p->uuid)) { + if (!get_field(1, offsetof(struct smbios_type_1, uuid), &p->uuid)) memset(p->uuid, 0, 16); - }
set_field_with_default(1, wake_up_type, 0x06); /* power switch */
@@ -234,9 +295,8 @@ smbios_init_type_4(void *start, unsigned int cpu_number) p->header.length = sizeof(struct smbios_type_4); p->header.handle = 0x400 + cpu_number;
- size = qemu_cfg_smbios_load_field(4, offsetof(struct smbios_type_4, - socket_designation_str), - name); + size = get_field(4, offsetof(struct smbios_type_4, socket_designation_str), + name); if (size) snprintf(name + size - 1, sizeof(name) - size, "%2x", cpu_number); else @@ -251,8 +311,8 @@ smbios_init_type_4(void *start, unsigned int cpu_number)
load_str_field_with_default(4, processor_manufacturer_str, CONFIG_APPNAME);
- if (!qemu_cfg_smbios_load_field(4, offsetof(struct smbios_type_4, - processor_id), p->processor_id)) { + if (!get_field(4, offsetof(struct smbios_type_4, processor_id) + , p->processor_id)) { u32 cpuid_signature, ebx, ecx, cpuid_features; cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features); p->processor_id[0] = cpuid_signature; @@ -332,9 +392,8 @@ smbios_init_type_17(void *start, u32 size_mb, int instance) set_field_with_default(17, form_factor, 0x09); /* DIMM */ p->device_set = 0;
- size = qemu_cfg_smbios_load_field(17, offsetof(struct smbios_type_17, - device_locator_str), - name); + size = get_field(17, offsetof(struct smbios_type_17, device_locator_str), + name); if (size) snprintf(name + size - 1, sizeof(name) - size, "%d", instance); else @@ -460,8 +519,7 @@ smbios_setup(void)
#define add_struct(type, args...) \ do { \ - if (!qemu_cfg_smbios_load_external(type, &p, &nr_structs, \ - &max_struct_size, end)) { \ + if (!get_external(type, &p, &nr_structs, &max_struct_size, end)) { \ q = smbios_init_type_##type(args); \ nr_structs++; \ if ((q - p) > max_struct_size) \ @@ -512,8 +570,7 @@ smbios_setup(void) add_struct(32, p); /* Add any remaining provided entries before the end marker */ for (i = 0; i < 256; i++) - qemu_cfg_smbios_load_external(i, &p, &nr_structs, &max_struct_size, - end); + get_external(i, &p, &nr_structs, &max_struct_size, end); add_struct(127, p);
#undef add_struct
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/acpi.c | 2 +- src/boot.c | 2 +- src/mptable.c | 3 +-- src/paravirt.c | 48 +++++------------------------------------------- src/paravirt.h | 4 ---- src/smp.c | 3 +-- 6 files changed, 9 insertions(+), 53 deletions(-)
diff --git a/src/acpi.c b/src/acpi.c index 5396ae2..aebf26e 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -372,7 +372,7 @@ build_madt(void) io_apic->interrupt = cpu_to_le32(0);
struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1]; - if (qemu_cfg_irq0_override()) { + if (romfile_loadint("etc/irq0-override", 0)) { memset(intsrcovr, 0, sizeof(*intsrcovr)); intsrcovr->type = APIC_XRUPT_OVERRIDE; intsrcovr->length = sizeof(*intsrcovr); diff --git a/src/boot.c b/src/boot.c index f70e402..ec411b7 100644 --- a/src/boot.c +++ b/src/boot.c @@ -404,7 +404,7 @@ interactive_bootmenu(void) { // XXX - show available drives?
- if (! CONFIG_BOOTMENU || ! qemu_cfg_show_boot_menu()) + if (! CONFIG_BOOTMENU || !romfile_loadint("etc/show-boot-menu", 1)) return;
while (get_keystroke(0) >= 0) diff --git a/src/mptable.c b/src/mptable.c index 2d4e441..fc16096 100644 --- a/src/mptable.c +++ b/src/mptable.c @@ -8,7 +8,6 @@ #include "util.h" // dprintf #include "config.h" // CONFIG_* #include "mptable.h" // MPTABLE_SIGNATURE -#include "paravirt.h" // qemu_cfg_irq0_override #include "pci.h" #include "pci_regs.h"
@@ -143,7 +142,7 @@ mptable_setup(void) intsrc->srcbusirq = i; intsrc->dstapic = ioapic_id; intsrc->dstirq = i; - if (qemu_cfg_irq0_override()) { + if (romfile_loadint("etc/irq0-override", 0)) { /* Destination 2 is covered by irq0->inti2 override (i == 0). Source IRQ 2 is unused */ if (i == 0) diff --git a/src/paravirt.c b/src/paravirt.c index e782227..79b1c56 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -172,37 +172,6 @@ void qemu_cfg_preinit(void) dprintf(4, "qemu_cfg_present=%d\n", qemu_cfg_present); }
-void qemu_cfg_get_uuid(u8 *uuid) -{ - if (!qemu_cfg_present) - return; - - qemu_cfg_read_entry(uuid, QEMU_CFG_UUID, 16); -} - -int qemu_cfg_show_boot_menu(void) -{ - u16 v; - if (!qemu_cfg_present) - return 1; - - qemu_cfg_read_entry(&v, QEMU_CFG_BOOT_MENU, sizeof(v)); - - return v; -} - -int qemu_cfg_irq0_override(void) -{ - u8 v; - - if (!qemu_cfg_present) - return 0; - - qemu_cfg_read_entry(&v, QEMU_CFG_IRQ0_OVERRIDE, sizeof(v)); - - return v; -} - u32 qemu_cfg_e820_entries(void) { u32 cnt; @@ -237,18 +206,6 @@ void qemu_cfg_get_numa_data(u64 *data, int n) qemu_cfg_read((u8*)(data + i), sizeof(u64)); }
-u16 qemu_cfg_get_max_cpus(void) -{ - u16 cnt; - - if (!qemu_cfg_present) - return 0; - - qemu_cfg_read_entry(&cnt, QEMU_CFG_MAX_CPUS, sizeof(cnt)); - - return cnt; -} - static int qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) { @@ -292,6 +249,11 @@ struct qemu_smbios_header { static void qemu_cfg_legacy(void) { + // Misc config items. + qemu_romfile_add("etc/show-boot-menu", QEMU_CFG_BOOT_MENU, 0, 2); + qemu_romfile_add("etc/irq0-override", QEMU_CFG_IRQ0_OVERRIDE, 0, 1); + qemu_romfile_add("etc/max-cpus", QEMU_CFG_MAX_CPUS, 0, 2); + // ACPI tables char name[128]; u16 cnt; diff --git a/src/paravirt.h b/src/paravirt.h index 6b99ca9..e92e236 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -26,12 +26,8 @@ static inline int runningOnKVM(void) { void qemu_ramsize_preinit(void); void qemu_biostable_setup(void); void qemu_cfg_preinit(void); -int qemu_cfg_show_boot_menu(void); -void qemu_cfg_get_uuid(u8 *uuid); -int qemu_cfg_irq0_override(void); int qemu_cfg_get_numa_nodes(void); void qemu_cfg_get_numa_data(u64 *data, int n); -u16 qemu_cfg_get_max_cpus(void); u32 qemu_cfg_e820_entries(void); void* qemu_cfg_e820_load_next(void *addr); void qemu_romfile_init(void); diff --git a/src/smp.c b/src/smp.c index 394dc4b..1590d65 100644 --- a/src/smp.c +++ b/src/smp.c @@ -8,7 +8,6 @@ #include "util.h" // dprintf #include "config.h" // CONFIG_* #include "cmos.h" // CMOS_BIOS_SMP_COUNT -#include "paravirt.h"
#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300) #define APIC_SVR ((u8*)BUILD_APIC_ADDR + 0x0F0) @@ -139,7 +138,7 @@ smp_setup(void) // Restore memory. *(u64*)BUILD_AP_BOOT_ADDR = old;
- MaxCountCPUs = qemu_cfg_get_max_cpus(); + MaxCountCPUs = romfile_loadint("etc/max-cpus", 0); if (!MaxCountCPUs || MaxCountCPUs < CountCPUs) MaxCountCPUs = CountCPUs;
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/acpi.c | 24 +++++++++--------------- src/paravirt.c | 24 +++++++----------------- src/paravirt.h | 2 -- 3 files changed, 16 insertions(+), 34 deletions(-)
diff --git a/src/acpi.c b/src/acpi.c index aebf26e..f7a2e55 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -12,8 +12,8 @@ #include "pci_ids.h" // PCI_VENDOR_ID_INTEL #include "pci_regs.h" // PCI_INTERRUPT_LINE #include "ioport.h" // inl -#include "paravirt.h" // qemu_cfg_irq0_override -#include "dev-q35.h" // qemu_cfg_irq0_override +#include "config.h" // CONFIG_* +#include "dev-q35.h"
/****************************************************/ /* ACPI tables init */ @@ -672,22 +672,16 @@ acpi_build_srat_memory(struct srat_memory_affinity *numamem, static void * build_srat(void) { - int nb_numa_nodes = qemu_cfg_get_numa_nodes(); - - if (nb_numa_nodes == 0) - return NULL; - - u64 *numadata = malloc_tmphigh(sizeof(u64) * (MaxCountCPUs + nb_numa_nodes)); - if (!numadata) { - warn_noalloc(); + int filesize; + u64 *numadata = romfile_loadfile("etc/numa-nodes", &filesize); + if (!numadata) return NULL; - } - - qemu_cfg_get_numa_data(numadata, MaxCountCPUs + nb_numa_nodes); + int max_cpu = romfile_loadint("etc/max-cpus", 0); + int nb_numa_nodes = (filesize / sizeof(u64)) - max_cpu;
struct system_resource_affinity_table *srat; int srat_size = sizeof(*srat) + - sizeof(struct srat_processor_affinity) * MaxCountCPUs + + sizeof(struct srat_processor_affinity) * max_cpu + sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2);
srat = malloc_high(srat_size); @@ -703,7 +697,7 @@ build_srat(void) int i; u64 curnode;
- for (i = 0; i < MaxCountCPUs; ++i) { + for (i = 0; i < max_cpu; ++i) { core->type = SRAT_PROCESSOR; core->length = sizeof(*core); core->local_apic_id = i; diff --git a/src/paravirt.c b/src/paravirt.c index 79b1c56..0c91c8d 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -189,23 +189,6 @@ void* qemu_cfg_e820_load_next(void *addr) return addr; }
-int qemu_cfg_get_numa_nodes(void) -{ - u64 cnt; - - qemu_cfg_read_entry(&cnt, QEMU_CFG_NUMA, sizeof(cnt)); - - return (int)cnt; -} - -void qemu_cfg_get_numa_data(u64 *data, int n) -{ - int i; - - for (i = 0; i < n; i++) - qemu_cfg_read((u8*)(data + i), sizeof(u64)); -} - static int qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) { @@ -254,6 +237,13 @@ qemu_cfg_legacy(void) qemu_romfile_add("etc/irq0-override", QEMU_CFG_IRQ0_OVERRIDE, 0, 1); qemu_romfile_add("etc/max-cpus", QEMU_CFG_MAX_CPUS, 0, 2);
+ // NUMA data + u64 numacount; + qemu_cfg_read_entry(&numacount, QEMU_CFG_NUMA, sizeof(numacount)); + numacount += romfile_loadint("etc/max-cpus", 0); + qemu_romfile_add("etc/numa-nodes", QEMU_CFG_NUMA, sizeof(numacount) + , numacount*sizeof(u64)); + // ACPI tables char name[128]; u16 cnt; diff --git a/src/paravirt.h b/src/paravirt.h index e92e236..527522b 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -26,8 +26,6 @@ static inline int runningOnKVM(void) { void qemu_ramsize_preinit(void); void qemu_biostable_setup(void); void qemu_cfg_preinit(void); -int qemu_cfg_get_numa_nodes(void); -void qemu_cfg_get_numa_data(u64 *data, int n); u32 qemu_cfg_e820_entries(void); void* qemu_cfg_e820_load_next(void *addr); void qemu_romfile_init(void);
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/paravirt.c | 62 ++++++++++++++++++++++------------------------------------ src/paravirt.h | 2 -- 2 files changed, 23 insertions(+), 41 deletions(-)
diff --git a/src/paravirt.c b/src/paravirt.c index 0c91c8d..9b288ac 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -19,12 +19,6 @@ #include "mptable.h" // mptable_setup #include "pci.h" // create_pirtable
-struct e820_reservation { - u64 address; - u64 length; - u32 type; -}; - /* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It * should be used to determine that a VM is running under KVM. */ @@ -79,22 +73,6 @@ qemu_ramsize_preinit(void)
/* reserve 256KB BIOS area at the end of 4 GB */ add_e820(0xfffc0000, 256*1024, E820_RESERVED); - - u32 count = qemu_cfg_e820_entries(); - if (count) { - struct e820_reservation entry; - int i; - - for (i = 0; i < count; i++) { - qemu_cfg_e820_load_next(&entry); - add_e820(entry.address, entry.length, entry.type); - } - } else if (runningOnKVM()) { - // Backwards compatibility - provide hard coded range. - // 4 pages before the bios, 3 pages for vmx tss pages, the - // other page for EPT real mode pagetable - add_e820(0xfffbc000, 4*4096, E820_RESERVED); - } }
void @@ -172,23 +150,6 @@ void qemu_cfg_preinit(void) dprintf(4, "qemu_cfg_present=%d\n", qemu_cfg_present); }
-u32 qemu_cfg_e820_entries(void) -{ - u32 cnt; - - if (!qemu_cfg_present) - return 0; - - qemu_cfg_read_entry(&cnt, QEMU_CFG_E820_TABLE, sizeof(cnt)); - return cnt; -} - -void* qemu_cfg_e820_load_next(void *addr) -{ - qemu_cfg_read(addr, sizeof(struct e820_reservation)); - return addr; -} - static int qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) { @@ -217,6 +178,12 @@ qemu_romfile_add(char *name, int select, int skip, int size) romfile_add(file); }
+struct e820_reservation { + u64 address; + u64 length; + u32 type; +}; + #define SMBIOS_FIELD_ENTRY 0 #define SMBIOS_TABLE_ENTRY 1
@@ -244,6 +211,23 @@ qemu_cfg_legacy(void) qemu_romfile_add("etc/numa-nodes", QEMU_CFG_NUMA, sizeof(numacount) , numacount*sizeof(u64));
+ // e820 data + u32 count32; + qemu_cfg_read_entry(&count32, QEMU_CFG_E820_TABLE, sizeof(count32)); + if (count32) { + struct e820_reservation entry; + int i; + for (i = 0; i < count32; i++) { + qemu_cfg_read(&entry, sizeof(entry)); + add_e820(entry.address, entry.length, entry.type); + } + } else if (runningOnKVM()) { + // Backwards compatibility - provide hard coded range. + // 4 pages before the bios, 3 pages for vmx tss pages, the + // other page for EPT real mode pagetable + add_e820(0xfffbc000, 4*4096, E820_RESERVED); + } + // ACPI tables char name[128]; u16 cnt; diff --git a/src/paravirt.h b/src/paravirt.h index 527522b..1d06e58 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -26,8 +26,6 @@ static inline int runningOnKVM(void) { void qemu_ramsize_preinit(void); void qemu_biostable_setup(void); void qemu_cfg_preinit(void); -u32 qemu_cfg_e820_entries(void); -void* qemu_cfg_e820_load_next(void *addr); void qemu_romfile_init(void);
#endif
Now that only qemu_romfile_init() uses the fw_cfg interface, it only needs to be detected in that function.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/paravirt.c | 38 ++++++++++++++------------------------ src/paravirt.h | 3 +-- src/post.c | 3 +-- 3 files changed, 16 insertions(+), 28 deletions(-)
diff --git a/src/paravirt.c b/src/paravirt.c index 9b288ac..aa4a421 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -1,5 +1,6 @@ // Paravirtualization support. // +// Copyright (C) 2013 Kevin O'Connor kevin@koconnor.net // Copyright (C) 2009 Red Hat Inc. // // Authors: @@ -89,8 +90,8 @@ qemu_biostable_setup(void) * QEMU firmware config (fw_cfg) interface ****************************************************************/
-int qemu_cfg_present; - +// List of QEMU fw_cfg entries. DO NOT ADD MORE. (All new content +// should be passed via the fw_cfg "file" interface.) #define QEMU_CFG_SIGNATURE 0x00 #define QEMU_CFG_ID 0x01 #define QEMU_CFG_UUID 0x02 @@ -130,26 +131,6 @@ qemu_cfg_read_entry(void *buf, int e, int len) qemu_cfg_read(buf, len); }
-void qemu_cfg_preinit(void) -{ - char *sig = "QEMU"; - int i; - - if (!CONFIG_QEMU) - return; - - qemu_cfg_present = 1; - - qemu_cfg_select(QEMU_CFG_SIGNATURE); - - for (i = 0; i < 4; i++) - if (inb(PORT_QEMU_CFG_DATA) != sig[i]) { - qemu_cfg_present = 0; - break; - } - dprintf(4, "qemu_cfg_present=%d\n", qemu_cfg_present); -} - static int qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) { @@ -273,11 +254,20 @@ struct QemuCfgFile { char name[56]; };
-void qemu_romfile_init(void) +void qemu_cfg_init(void) { - if (!CONFIG_QEMU || !qemu_cfg_present) + if (!CONFIG_QEMU) return;
+ // Detect fw_cfg interface. + qemu_cfg_select(QEMU_CFG_SIGNATURE); + char *sig = "QEMU"; + int i; + for (i = 0; i < 4; i++) + if (inb(PORT_QEMU_CFG_DATA) != sig[i]) + return; + dprintf(1, "Found QEMU fw_cfg\n"); + // Populate romfiles for legacy fw_cfg entries qemu_cfg_legacy();
diff --git a/src/paravirt.h b/src/paravirt.h index 1d06e58..4438273 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -25,7 +25,6 @@ static inline int runningOnKVM(void) {
void qemu_ramsize_preinit(void); void qemu_biostable_setup(void); -void qemu_cfg_preinit(void); -void qemu_romfile_init(void); +void qemu_cfg_init(void);
#endif diff --git a/src/post.c b/src/post.c index 2c5e34e..2d5dd4f 100644 --- a/src/post.c +++ b/src/post.c @@ -108,7 +108,7 @@ interface_init(void) malloc_fixupreloc_init();
// Setup romfile items. - qemu_romfile_init(); + qemu_cfg_init(); coreboot_cbfs_init();
// Setup ivt/bda/ebda @@ -316,7 +316,6 @@ void VISIBLE32INIT dopost(void) { // Detect ram and setup internal malloc. - qemu_cfg_preinit(); if (CONFIG_COREBOOT) coreboot_preinit(); else if (runningOnXen())
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/ata.c | 1 - src/clock.c | 5 ++--- src/cmos.h | 12 ++++-------- src/floppy.c | 21 ++++++--------------- src/paravirt.c | 31 +++++++++++++++++++++++++++++++ 5 files changed, 43 insertions(+), 27 deletions(-)
diff --git a/src/ata.c b/src/ata.c index 59ae765..9909fb8 100644 --- a/src/ata.c +++ b/src/ata.c @@ -9,7 +9,6 @@ #include "ioport.h" // inb #include "util.h" // dprintf #include "byteorder.h" // be16_to_cpu -#include "cmos.h" // inb_cmos #include "pic.h" // enable_hwirq #include "biosvar.h" // GET_GLOBAL #include "pci.h" // foreachpci diff --git a/src/clock.c b/src/clock.c index bbcafd7..c84882d 100644 --- a/src/clock.c +++ b/src/clock.c @@ -300,9 +300,8 @@ timer_setup(void) SET_BDA(timer_counter, ticks);
// Setup Century storage - if (CONFIG_QEMU) { - Century = inb_cmos(CMOS_CENTURY); - } else { + Century = romfile_loadint("etc/century", 0); + if (!Century) { // Infer current century from the year. u8 year = inb_cmos(CMOS_RTC_YEAR); if (year > 0x80) diff --git a/src/cmos.h b/src/cmos.h index e4b6462..df1d465 100644 --- a/src/cmos.h +++ b/src/cmos.h @@ -6,6 +6,7 @@ #ifndef __CMOS_H #define __CMOS_H
+// Standard BIOS RTC chip entries #define CMOS_RTC_SECONDS 0x00 #define CMOS_RTC_SECONDS_ALARM 0x01 #define CMOS_RTC_MINUTES 0x02 @@ -21,6 +22,9 @@ #define CMOS_STATUS_C 0x0c #define CMOS_STATUS_D 0x0d #define CMOS_RESET_CODE 0x0f + +// QEMU cmos config fields. DO NOT ADD MORE. (All new content should +// be passed via the fw_cfg "file" interface.) #define CMOS_FLOPPY_DRIVE_TYPE 0x10 #define CMOS_DISK_DATA 0x12 #define CMOS_EQUIPMENT_INFO 0x14 @@ -41,14 +45,6 @@ #define CMOS_MEM_HIGHMEM_HIGH 0x5d #define CMOS_BIOS_SMP_COUNT 0x5f
-// CMOS_FLOPPY_DRIVE_TYPE bitdefs -#define CFD_NO_DRIVE 0 -#define CFD_360KB 1 -#define CFD_12MB 2 -#define CFD_720KB 3 -#define CFD_144MB 4 -#define CFD_288MB 5 - #ifndef __ASSEMBLY__
#include "ioport.h" // inb, outb diff --git a/src/floppy.c b/src/floppy.c index 2887e78..00b57c1 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -10,7 +10,6 @@ #include "config.h" // CONFIG_FLOPPY #include "biosvar.h" // SET_BDA #include "util.h" // dprintf -#include "cmos.h" // inb_cmos #include "pic.h" // eoi_pic1 #include "bregs.h" // struct bregs #include "boot.h" // boot_add_floppy @@ -125,20 +124,12 @@ floppy_setup(void) return; dprintf(3, "init floppy drives\n");
- if (CONFIG_QEMU) { - u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); - if (type & 0xf0) - addFloppy(0, type >> 4); - if (type & 0x0f) - addFloppy(1, type & 0x0f); - } else { - u8 type = romfile_loadint("etc/floppy0", 0); - if (type) - addFloppy(0, type); - type = romfile_loadint("etc/floppy1", 0); - if (type) - addFloppy(1, type); - } + u8 type = romfile_loadint("etc/floppy0", 0); + if (type) + addFloppy(0, type); + type = romfile_loadint("etc/floppy1", 0); + if (type) + addFloppy(1, type);
outb(0x02, PORT_DMA1_MASK_REG);
diff --git a/src/paravirt.c b/src/paravirt.c index aa4a421..0cf5149 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -132,6 +132,31 @@ qemu_cfg_read_entry(void *buf, int e, int len) }
static int +qemu_value_read_file(struct romfile_s *file, void *dst, u32 maxlen) +{ + if (file->size > maxlen) + return -1; + memcpy(dst, &file->rawsize, file->size); + return file->size; +} + +static void +qemu_value_add(char *name, int value) +{ + struct romfile_s *file = malloc_tmp(sizeof(*file)); + if (!file) { + warn_noalloc(); + return; + } + memset(file, 0, sizeof(*file)); + strtcpy(file->name, name, sizeof(file->name)); + file->rawsize = value; // Use rawsize to store the value. + file->size = 4; + file->copy = qemu_value_read_file; + romfile_add(file); +} + +static int qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) { if (file->size > maxlen) @@ -180,6 +205,12 @@ struct qemu_smbios_header { static void qemu_cfg_legacy(void) { + // Misc cmos items. + qemu_value_add("etc/century", inb_cmos(CMOS_CENTURY)); + u8 floppy = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); + qemu_value_add("etc/floppy0", floppy >> 4); + qemu_value_add("etc/floppy1", floppy & 0x0f); + // Misc config items. qemu_romfile_add("etc/show-boot-menu", QEMU_CFG_BOOT_MENU, 0, 2); qemu_romfile_add("etc/irq0-override", QEMU_CFG_IRQ0_OVERRIDE, 0, 1);