Hello!
These patches adds support for providing SMBIOS "Onboard Devices Extended Information" fields to the guest i386/x86_64 system inside qemu. This could be used in conjunction with biosdevname to provide "consistent network device naming" inside VM.
I will also send corresponding patches to qemu-devel@nongnu.org and linux-poweredge@dell.com (for biosdevname).
Signed-off-by: Ivan Mironov mironov.ivan@gmail.com --- src/fw/paravirt.c | 66 ++++++++++++++++------ src/fw/smbios.c | 160 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 144 insertions(+), 82 deletions(-)
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index b84196a..8059416 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -199,6 +199,7 @@ qemu_cfg_read_entry(void *buf, int e, int len) struct qemu_romfile_s { struct romfile_s file; int select, skip; + void *const_val; };
static int @@ -208,14 +209,18 @@ qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) return -1; struct qemu_romfile_s *qfile; qfile = container_of(file, struct qemu_romfile_s, file); - qemu_cfg_select(qfile->select); - qemu_cfg_skip(qfile->skip); - qemu_cfg_read(dst, file->size); + if (qfile->const_val) { + memcpy(dst, qfile->const_val, file->size); + } else { + qemu_cfg_select(qfile->select); + qemu_cfg_skip(qfile->skip); + qemu_cfg_read(dst, file->size); + } return file->size; }
static void -qemu_romfile_add(char *name, int select, int skip, int size) +qemu_romfile_add(char *name, int select, int skip, int size, void *const_val) { struct qemu_romfile_s *qfile = malloc_tmp(sizeof(*qfile)); if (!qfile) { @@ -227,6 +232,7 @@ qemu_romfile_add(char *name, int select, int skip, int size) qfile->file.size = size; qfile->select = select; qfile->skip = skip; + qfile->const_val = const_val; qfile->file.copy = qemu_cfg_read_file; romfile_add(&qfile->file); } @@ -326,19 +332,19 @@ qemu_cfg_legacy(void) return;
// 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); + qemu_romfile_add("etc/show-boot-menu", QEMU_CFG_BOOT_MENU, 0, 2, NULL); + qemu_romfile_add("etc/irq0-override", QEMU_CFG_IRQ0_OVERRIDE, 0, 1, NULL); + qemu_romfile_add("etc/max-cpus", QEMU_CFG_MAX_CPUS, 0, 2, NULL);
// NUMA data u64 numacount; qemu_cfg_read_entry(&numacount, QEMU_CFG_NUMA, sizeof(numacount)); int max_cpu = romfile_loadint("etc/max-cpus", 0); qemu_romfile_add("etc/numa-cpu-map", QEMU_CFG_NUMA, sizeof(numacount) - , max_cpu*sizeof(u64)); + , max_cpu*sizeof(u64), NULL); qemu_romfile_add("etc/numa-nodes", QEMU_CFG_NUMA , sizeof(numacount) + max_cpu*sizeof(u64) - , numacount*sizeof(u64)); + , numacount*sizeof(u64), NULL);
// ACPI tables char name[128]; @@ -350,7 +356,7 @@ qemu_cfg_legacy(void) 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_romfile_add(name, QEMU_CFG_ACPI_TABLES, offset, len, NULL); qemu_cfg_skip(len); offset += len; } @@ -358,24 +364,50 @@ qemu_cfg_legacy(void) // SMBIOS info qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt)); offset = sizeof(cnt); + u16 fields_sets_cnt[256]; + memset(fields_sets_cnt, 0, sizeof(fields_sets_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)); + if (header.fieldoffset || (header.length - sizeof(header))) { + /* Regular field. */ + snprintf(name, sizeof(name), "smbios/field%d-%d-%d" + , header.tabletype, header.fieldoffset + , (int)fields_sets_cnt[header.tabletype]); + qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES + , offset + sizeof(header) + , header.length - sizeof(header), NULL); + } else { + /* End of current set of fields. */ + fields_sets_cnt[header.tabletype]++; + } } 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); + , offset + 3, header.length - 3, NULL); } qemu_cfg_skip(header.length - sizeof(header)); offset += header.length; } + u16 *fields_set_cnt = malloc_tmp(sizeof(*fields_set_cnt)); + for (i = 0; i < (sizeof(fields_sets_cnt) / sizeof(fields_sets_cnt[0])); + i++) { + if (!fields_set_cnt) { + warn_noalloc(); + return; + } + + *fields_set_cnt = fields_sets_cnt[i]; + if (*fields_set_cnt) { + snprintf(name, sizeof(name), "smbios/fields-set-cnt-%d", i); + qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES, 0 + , sizeof(*fields_set_cnt), fields_set_cnt); + + fields_set_cnt = malloc_tmp(sizeof(*fields_set_cnt)); + } + } }
struct QemuCfgFile { @@ -411,7 +443,7 @@ void qemu_cfg_init(void) struct QemuCfgFile qfile; qemu_cfg_read(&qfile, sizeof(qfile)); qemu_romfile_add(qfile.name, be16_to_cpu(qfile.select) - , 0, be32_to_cpu(qfile.size)); + , 0, be32_to_cpu(qfile.size), NULL); }
qemu_cfg_e820(); diff --git a/src/fw/smbios.c b/src/fw/smbios.c index affb9be..3113d3a 100644 --- a/src/fw/smbios.c +++ b/src/fw/smbios.c @@ -63,10 +63,23 @@ smbios_entry_point_setup(u16 max_structure_size, }
static int -get_field(int type, int offset, void *dest) +get_fields_sets_cnt(int type) { char name[128]; - snprintf(name, sizeof(name), "smbios/field%d-%d", type, offset); + snprintf(name, sizeof(name), "smbios/fields-set-cnt-%d", type); + struct romfile_s *file = romfile_find(name); + if (!file) + return 0; + u16 cnt; + file->copy(file, &cnt, file->size); + return cnt; +} + +static int +get_field(int type, int offset, int index, void *dest) +{ + char name[128]; + snprintf(name, sizeof(name), "smbios/field%d-%d-%d", type, offset, index); struct romfile_s *file = romfile_find(name); if (!file) return 0; @@ -129,10 +142,10 @@ get_external(int type, char **p, unsigned *nr_structs, return 1; }
-#define load_str_field_with_default(type, field, def) \ +#define load_str_field_with_default(type, field, skip_fields, def) \ do { \ size = get_field(type, offsetof(struct smbios_type_##type, \ - field), end); \ + field), skip_fields, end); \ if (size > 0) { \ end += size; \ } else { \ @@ -142,10 +155,10 @@ get_external(int type, char **p, unsigned *nr_structs, p->field = ++str_index; \ } while (0)
-#define load_str_field_or_skip(type, field) \ +#define load_str_field_or_skip(type, field, skip_fields) \ do { \ size = get_field(type, offsetof(struct smbios_type_##type, \ - field), end); \ + field), skip_fields, end); \ if (size > 0) { \ end += size; \ p->field = ++str_index; \ @@ -154,10 +167,10 @@ get_external(int type, char **p, unsigned *nr_structs, } \ } while (0)
-#define set_field_with_default(type, field, def) \ +#define set_field_with_default(type, field, skip_fields, def) \ do { \ if (!get_field(type, offsetof(struct smbios_type_##type, \ - field), &p->field)) { \ + field), skip_fields, &p->field)) {\ p->field = def; \ } \ } while (0) @@ -176,16 +189,16 @@ smbios_init_type_0(void *start) p->header.length = sizeof(struct smbios_type_0); p->header.handle = 0;
- load_str_field_with_default(0, vendor_str, BUILD_APPNAME); - load_str_field_with_default(0, bios_version_str, BUILD_APPNAME); + load_str_field_with_default(0, vendor_str, 0, BUILD_APPNAME); + load_str_field_with_default(0, bios_version_str, 0, BUILD_APPNAME);
p->bios_starting_address_segment = 0xe800;
- load_str_field_with_default(0, bios_release_date_str, RELEASE_DATE_STR); + load_str_field_with_default(0, bios_release_date_str, 0, RELEASE_DATE_STR);
p->bios_rom_size = 0; /* FIXME */
- if (!get_field(0, offsetof(struct smbios_type_0, bios_characteristics), + if (!get_field(0, offsetof(struct smbios_type_0, bios_characteristics), 0, &p->bios_characteristics)) { memset(p->bios_characteristics, 0, 8); /* BIOS characteristics not supported */ @@ -193,17 +206,17 @@ smbios_init_type_0(void *start) }
if (!get_field(0, offsetof(struct smbios_type_0, - bios_characteristics_extension_bytes), + bios_characteristics_extension_bytes), 0, &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; }
- set_field_with_default(0, system_bios_major_release, 1); - set_field_with_default(0, system_bios_minor_release, 0); - set_field_with_default(0, embedded_controller_major_release, 0xff); - set_field_with_default(0, embedded_controller_minor_release, 0xff); + set_field_with_default(0, system_bios_major_release, 0, 1); + set_field_with_default(0, system_bios_minor_release, 0, 0); + set_field_with_default(0, embedded_controller_major_release, 0, 0xff); + set_field_with_default(0, embedded_controller_minor_release, 0, 0xff);
*end = 0; end++; @@ -224,18 +237,18 @@ smbios_init_type_1(void *start) p->header.length = sizeof(struct smbios_type_1); p->header.handle = 0x100;
- load_str_field_with_default(1, manufacturer_str, BUILD_APPNAME); - load_str_field_with_default(1, product_name_str, BUILD_APPNAME); - load_str_field_or_skip(1, version_str); - load_str_field_or_skip(1, serial_number_str); + load_str_field_with_default(1, manufacturer_str, 0, BUILD_APPNAME); + load_str_field_with_default(1, product_name_str, 0, BUILD_APPNAME); + load_str_field_or_skip(1, version_str, 0); + load_str_field_or_skip(1, serial_number_str, 0);
- if (!get_field(1, offsetof(struct smbios_type_1, uuid), &p->uuid)) + if (!get_field(1, offsetof(struct smbios_type_1, uuid), 0, &p->uuid)) memset(p->uuid, 0, 16);
- set_field_with_default(1, wake_up_type, 0x06); /* power switch */ + set_field_with_default(1, wake_up_type, 0, 0x06); /* power switch */
- load_str_field_or_skip(1, sku_number_str); - load_str_field_or_skip(1, family_str); + load_str_field_or_skip(1, sku_number_str, 0); + load_str_field_or_skip(1, family_str, 0);
*end = 0; end++; @@ -260,22 +273,22 @@ smbios_init_type_3(void *start) p->header.length = sizeof(struct smbios_type_3); p->header.handle = 0x300;
- load_str_field_with_default(3, manufacturer_str, BUILD_APPNAME); - set_field_with_default(3, type, 0x01); /* other */ + load_str_field_with_default(3, manufacturer_str, 0, BUILD_APPNAME); + set_field_with_default(3, type, 0, 0x01); /* other */
- load_str_field_or_skip(3, version_str); - load_str_field_or_skip(3, serial_number_str); - load_str_field_or_skip(3, asset_tag_number_str); + load_str_field_or_skip(3, version_str, 0); + load_str_field_or_skip(3, serial_number_str, 0); + load_str_field_or_skip(3, asset_tag_number_str, 0);
- set_field_with_default(3, boot_up_state, 0x03); /* safe */ - set_field_with_default(3, power_supply_state, 0x03); /* safe */ - set_field_with_default(3, thermal_state, 0x03); /* safe */ - set_field_with_default(3, security_status, 0x02); /* unknown */ + set_field_with_default(3, boot_up_state, 0, 0x03); /* safe */ + set_field_with_default(3, power_supply_state, 0, 0x03); /* safe */ + set_field_with_default(3, thermal_state, 0, 0x03); /* safe */ + set_field_with_default(3, security_status, 0, 0x02); /* unknown */
- set_field_with_default(3, oem_defined, 0); - set_field_with_default(3, height, 0); - set_field_with_default(3, number_of_power_cords, 0); - set_field_with_default(3, contained_element_count, 0); + set_field_with_default(3, oem_defined, 0, 0); + set_field_with_default(3, height, 0, 0); + set_field_with_default(3, number_of_power_cords, 0, 0); + set_field_with_default(3, contained_element_count, 0, 0);
*end = 0; end++; @@ -302,7 +315,7 @@ smbios_init_type_4(void *start, unsigned int cpu_number) p->header.handle = 0x400 + cpu_number;
size = get_field(4, offsetof(struct smbios_type_4, socket_designation_str), - name); + 0, name); if (size) snprintf(name + size - 1, sizeof(name) - size, "%2x", cpu_number); else @@ -312,12 +325,13 @@ smbios_init_type_4(void *start, unsigned int cpu_number) end += strlen(name) + 1; p->socket_designation_str = ++str_index;
- set_field_with_default(4, processor_type, 0x03); /* CPU */ - set_field_with_default(4, processor_family, 0x01); /* other */ + set_field_with_default(4, processor_type, 0, 0x03); /* CPU */ + set_field_with_default(4, processor_family, 0, 0x01); /* other */
- load_str_field_with_default(4, processor_manufacturer_str, BUILD_APPNAME); + load_str_field_with_default(4, processor_manufacturer_str, 0 + , BUILD_APPNAME);
- if (!get_field(4, offsetof(struct smbios_type_4, processor_id) + if (!get_field(4, offsetof(struct smbios_type_4, processor_id), 0 , p->processor_id)) { u32 cpuid_signature, ebx, ecx, cpuid_features; cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features); @@ -325,15 +339,16 @@ smbios_init_type_4(void *start, unsigned int cpu_number) p->processor_id[1] = cpuid_features; }
- load_str_field_or_skip(4, processor_version_str); - set_field_with_default(4, voltage, 0); - set_field_with_default(4, external_clock, 0); + load_str_field_or_skip(4, processor_version_str, 0); + set_field_with_default(4, voltage, 0, 0); + set_field_with_default(4, external_clock, 0, 0);
- set_field_with_default(4, max_speed, 2000); - set_field_with_default(4, current_speed, 2000); + set_field_with_default(4, max_speed, 0, 2000); + set_field_with_default(4, current_speed, 0, 2000);
- set_field_with_default(4, status, 0x41); /* socket populated, CPU enabled */ - set_field_with_default(4, processor_upgrade, 0x01); /* other */ + set_field_with_default(4, status, 0 + , 0x41); /* socket populated, CPU enabled */ + set_field_with_default(4, processor_upgrade, 0, 0x01); /* other */
/* cache information structure not provided */ p->l1_cache_handle = 0xffff; @@ -360,10 +375,10 @@ smbios_init_type_16(void *start, u32 memory_size_mb, int nr_mem_devs) p->header.length = sizeof(struct smbios_type_16); p->header.handle = 0x1000;
- set_field_with_default(16, location, 0x01); /* other */ - set_field_with_default(16, use, 0x03); /* system memory */ + set_field_with_default(16, location, 0, 0x01); /* other */ + set_field_with_default(16, use, 0, 0x03); /* system memory */ /* Multi-bit ECC to make Microsoft happy */ - set_field_with_default(16, error_correction, 0x06); + set_field_with_default(16, error_correction, 0, 0x06); /* 0x80000000 = unknown, accept sizes < 2TB - TODO multiple arrays */ p->maximum_capacity = memory_size_mb < 2 << 20 ? memory_size_mb << 10 : 0x80000000; @@ -391,15 +406,15 @@ smbios_init_type_17(void *start, u32 size_mb, int instance) p->header.handle = 0x1100 + instance;
p->physical_memory_array_handle = 0x1000; - set_field_with_default(17, total_width, 64); - set_field_with_default(17, data_width, 64); + set_field_with_default(17, total_width, 0, 64); + set_field_with_default(17, data_width, 0, 64); /* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */ p->size = size_mb; - set_field_with_default(17, form_factor, 0x09); /* DIMM */ + set_field_with_default(17, form_factor, 0, 0x09); /* DIMM */ p->device_set = 0;
size = get_field(17, offsetof(struct smbios_type_17, device_locator_str), - name); + 0, name); if (size) snprintf(name + size - 1, sizeof(name) - size, "%d", instance); else @@ -409,9 +424,9 @@ smbios_init_type_17(void *start, u32 size_mb, int instance) end += strlen(name) + 1; p->device_locator_str = ++str_index;
- load_str_field_or_skip(17, bank_locator_str); - set_field_with_default(17, memory_type, 0x07); /* RAM */ - set_field_with_default(17, type_detail, 0); + load_str_field_or_skip(17, bank_locator_str, 0); + set_field_with_default(17, memory_type, 0, 0x07); /* RAM */ + set_field_with_default(17, type_detail, 0, 0);
*end = 0; end++; @@ -479,7 +494,7 @@ smbios_init_type_32(void *start) p->header.length = sizeof(struct smbios_type_32); p->header.handle = 0x2000; memset(p->reserved, 0, 6); - set_field_with_default(32, boot_status, 0); /* no errors detected */ + set_field_with_default(32, boot_status, 0, 0); /* no errors detected */
start += sizeof(struct smbios_type_32); *((u16 *)start) = 0; @@ -523,14 +538,27 @@ smbios_setup(void) char *q, *p = start; char *end = start + TEMPSMBIOSSIZE - sizeof(struct smbios_type_127);
-#define add_struct(type, args...) \ - do { \ - if (!get_external(type, &p, &nr_structs, &max_struct_size, end)) { \ +#define add_struct_inner(type, args...) \ q = smbios_init_type_##type(args); \ nr_structs++; \ if ((q - p) > max_struct_size) \ max_struct_size = q - p; \ - p = q; \ + p = q; +#define add_struct(type, args...) \ + do { \ + if (!get_external(type, &p, &nr_structs, &max_struct_size, end)) { \ + add_struct_inner(type, args) \ + } \ + } while (0) +#define add_structs(type, with_external, args...) \ + do { \ + if (get_external(type, &p, &nr_structs, &max_struct_size, end) && \ + !with_external) { \ + break; \ + } \ + u16 instance, instances = get_fields_sets_cnt(type); \ + for (instance = 0; instance < instances; instance++) { \ + add_struct_inner(type, instance, args) \ } \ } while (0)
@@ -579,7 +607,9 @@ smbios_setup(void) get_external(i, &p, &nr_structs, &max_struct_size, end); add_struct(127, p);
+#undef add_structs #undef add_struct +#undef add_struct_inner
smbios_entry_point_setup(max_struct_size, p - start, start, nr_structs); free(start);
Signed-off-by: Ivan Mironov mironov.ivan@gmail.com --- src/fw/smbios.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/fw/smbios.c b/src/fw/smbios.c index 3113d3a..a9137b8 100644 --- a/src/fw/smbios.c +++ b/src/fw/smbios.c @@ -42,7 +42,7 @@ smbios_entry_point_setup(u16 max_structure_size, memcpy(ep->anchor_string, "_SM_", 4); ep->length = 0x1f; ep->smbios_major_version = 2; - ep->smbios_minor_version = 4; + ep->smbios_minor_version = 6; ep->max_structure_size = max_structure_size; ep->entry_point_revision = 0; memset(ep->formatted_area, 0, 5); @@ -51,7 +51,7 @@ smbios_entry_point_setup(u16 max_structure_size, ep->structure_table_length = structure_table_length; ep->structure_table_address = (u32)finaltable; ep->number_of_structures = number_of_structures; - ep->smbios_bcd_revision = 0x24; + ep->smbios_bcd_revision = 0x26;
ep->checksum -= checksum(ep, 0x10);
Signed-off-by: Ivan Mironov mironov.ivan@gmail.com --- src/fw/smbios.c | 56 +++++++++++++++++++++++++++++++++++++++++++------------- src/std/smbios.h | 11 +++++++++++ 2 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/src/fw/smbios.c b/src/fw/smbios.c index a9137b8..d4dbc6d 100644 --- a/src/fw/smbios.c +++ b/src/fw/smbios.c @@ -17,6 +17,19 @@
struct smbios_entry_point *SMBiosAddr;
+static int +get_fields_sets_cnt(int type) +{ + char name[128]; + snprintf(name, sizeof(name), "smbios/fields-set-cnt-%d", type); + struct romfile_s *file = romfile_find(name); + if (!file) + return 0; + u16 cnt; + file->copy(file, &cnt, file->size); + return cnt; +} + static void smbios_entry_point_setup(u16 max_structure_size, u16 structure_table_length, @@ -63,19 +76,6 @@ smbios_entry_point_setup(u16 max_structure_size, }
static int -get_fields_sets_cnt(int type) -{ - char name[128]; - snprintf(name, sizeof(name), "smbios/fields-set-cnt-%d", type); - struct romfile_s *file = romfile_find(name); - if (!file) - return 0; - u16 cnt; - file->copy(file, &cnt, file->size); - return cnt; -} - -static int get_field(int type, int offset, int index, void *dest) { char name[128]; @@ -502,6 +502,34 @@ smbios_init_type_32(void *start) return start+2; }
+/* Type 41 -- Onboard Devices Extended Information */ +static void * +smbios_init_type_41(int instance, void *start) +{ + struct smbios_type_41 *p = (struct smbios_type_41 *)start; + char *end = (char *)start + sizeof(struct smbios_type_41); + size_t size; + int str_index = 0; + + p->header.type = 41; + p->header.length = sizeof(struct smbios_type_41); + p->header.handle = 0x3000 + instance; + + load_str_field_with_default(41, reference_designation_str, instance + , "No reference designation string specified"); + set_field_with_default(41, device_type, instance + , (1 << 7) | 0x02) /* enabled unknown device */; + set_field_with_default(41, device_type_instance, instance, 0); /* invalid */ + set_field_with_default(41, segment_group_number, instance, 0); + set_field_with_default(41, bus_number, instance, 0); + set_field_with_default(41, device_function_number, instance, 0); + + *end = 0; + end++; + + return end; +} + /* Type 127 -- End of Table */ static void * smbios_init_type_127(void *start) @@ -602,6 +630,8 @@ smbios_setup(void) }
add_struct(32, p); + add_structs(41, 1, p); + /* Add any remaining provided entries before the end marker */ for (i = 0; i < 256; i++) get_external(i, &p, &nr_structs, &max_struct_size, end); diff --git a/src/std/smbios.h b/src/std/smbios.h index 0513716..02bc1c1 100644 --- a/src/std/smbios.h +++ b/src/std/smbios.h @@ -157,6 +157,17 @@ struct smbios_type_32 { u8 boot_status; } PACKED;
+/* SMBIOS type 41 - Onboard Devices Extended Information */ +struct smbios_type_41 { + struct smbios_structure_header header; + u8 reference_designation_str; + u8 device_type; + u8 device_type_instance; + u16 segment_group_number; + u8 bus_number; + u8 device_function_number; +} PACKED; + /* SMBIOS type 127 -- End-of-table */ struct smbios_type_127 { struct smbios_structure_header header;
On Tue, Nov 19, 2013 at 08:57:16PM +0400, Ivan Mironov wrote:
Hello!
These patches adds support for providing SMBIOS "Onboard Devices Extended Information" fields to the guest i386/x86_64 system inside qemu. This could be used in conjunction with biosdevname to provide "consistent network device naming" inside VM.
I will also send corresponding patches to qemu-devel@nongnu.org and linux-poweredge@dell.com (for biosdevname).
Hi Ivan,
Thanks for looking at this. However, it's my opinion that the smbios mechanism between qemu and seabios needs to be redone. The table passing system (and shared ownership) of smbios is way too complex today. Your patch makes it even more complex. What I think needs to happen is for QEMU to generate the smbios table in entirety and pass it in entirety to seabios.
-Kevin