The protocol we use between qemu and seabios already allows any field
to be specified (via smbios_add_field() in qemu). This patch makes
seabios look for qemu specified values for nearly every field we set
in the types 0,1,3,4,16,17,32 smbios tables. No change in current
default values for any fields.
Signed-off-by: Alex Williamson <alex.williamson(a)redhat.com>
---
src/smbios.c | 222 +++++++++++++++++++++++++++++++++++++---------------------
1 files changed, 141 insertions(+), 81 deletions(-)
diff --git a/src/smbios.c b/src/smbios.c
index e19a62d..917428a 100644
--- a/src/smbios.c
+++ b/src/smbios.c
@@ -61,7 +61,7 @@ smbios_entry_point_init(u16 max_structure_size,
p->field = ++str_index; \
} while (0)
-#define load_str_field_or_skip(type, field) \
+#define load_str_field_or_skip(type, field) \
do { \
size = qemu_cfg_smbios_load_field(type, \
offsetof(struct smbios_type_##type, \
@@ -74,6 +74,15 @@ smbios_entry_point_init(u16 max_structure_size,
} \
} while (0)
+#define set_field_with_default(type, field, def) \
+ do { \
+ if (!qemu_cfg_smbios_load_field(type, \
+ offsetof(struct smbios_type_##type, \
+ field), &p->field)) { \
+ p->field = def; \
+ } \
+ } while (0)
+
/* Type 0 -- BIOS Information */
#define RELEASE_DATE_STR "01/01/2007"
static void *
@@ -97,24 +106,26 @@ smbios_init_type_0(void *start)
p->bios_rom_size = 0; /* FIXME */
- memset(p->bios_characteristics, 0, 8);
- p->bios_characteristics[0] = 0x08; /* BIOS characteristics not supported */
- p->bios_characteristics_extension_bytes[0] = 0;
- /* Enable targeted content distribution. Needed for SVVP */
- p->bios_characteristics_extension_bytes[1] = 4;
-
if (!qemu_cfg_smbios_load_field(0, offsetof(struct smbios_type_0,
- system_bios_major_release),
- &p->system_bios_major_release))
- p->system_bios_major_release = 1;
+ 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,
- system_bios_minor_release),
- &p->system_bios_minor_release))
- p->system_bios_minor_release = 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;
+ }
- p->embedded_controller_major_release = 0xff;
- p->embedded_controller_minor_release = 0xff;
+ 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);
*end = 0;
end++;
@@ -140,12 +151,12 @@ smbios_init_type_1(void *start)
load_str_field_or_skip(1, version_str);
load_str_field_or_skip(1, serial_number_str);
- size = qemu_cfg_smbios_load_field(1, offsetof(struct smbios_type_1,
- uuid), &p->uuid);
- if (size == 0)
+ if (!qemu_cfg_smbios_load_field(1, offsetof(struct smbios_type_1,
+ uuid), &p->uuid)) {
memset(p->uuid, 0, 16);
+ }
- p->wake_up_type = 0x06; /* power switch */
+ set_field_with_default(1, wake_up_type, 0x06); /* power switch */
load_str_field_or_skip(1, sku_number_str);
load_str_field_or_skip(1, family_str);
@@ -165,29 +176,39 @@ static void *
smbios_init_type_3(void *start)
{
struct smbios_type_3 *p = (struct smbios_type_3 *)start;
+ char *end = (char *)start + sizeof(struct smbios_type_3);
+ size_t size;
+ int str_index = 0;
p->header.type = 3;
p->header.length = sizeof(struct smbios_type_3);
p->header.handle = 0x300;
- p->manufacturer_str = 1;
- p->type = 0x01; /* other */
- p->version_str = 0;
- p->serial_number_str = 0;
- p->asset_tag_number_str = 0;
- p->boot_up_state = 0x03; /* safe */
- p->power_supply_state = 0x03; /* safe */
- p->thermal_state = 0x03; /* safe */
- p->security_status = 0x02; /* unknown */
- p->oem_defined = 0;
- p->height = 0;
- p->number_of_power_cords = 0;
- p->contained_element_count = 0;
-
- start += sizeof(struct smbios_type_3);
- memcpy((char *)start, CONFIG_APPNAME"\0\0", sizeof(CONFIG_APPNAME) + 1);
-
- return start + sizeof(CONFIG_APPNAME) + 1;
+ load_str_field_with_default(3, manufacturer_str, CONFIG_APPNAME);
+ set_field_with_default(3, type, 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);
+
+ 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, 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);
+
+ *end = 0;
+ end++;
+ if (!str_index) {
+ *end = 0;
+ end++;
+ }
+
+ return end;
}
/* Type 4 -- Processor Information */
@@ -195,42 +216,63 @@ static void *
smbios_init_type_4(void *start, unsigned int cpu_number)
{
struct smbios_type_4 *p = (struct smbios_type_4 *)start;
+ char *end = (char *)start + sizeof(struct smbios_type_4);
+ size_t size;
+ int str_index = 0;
+ char name[1024];
p->header.type = 4;
p->header.length = sizeof(struct smbios_type_4);
p->header.handle = 0x400 + cpu_number;
- p->socket_designation_str = 1;
- p->processor_type = 0x03; /* CPU */
- p->processor_family = 0x01; /* other */
- p->processor_manufacturer_str = 2;
-
- u32 cpuid_signature, ebx, ecx, cpuid_features;
- cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
- p->processor_id[0] = cpuid_signature;
- p->processor_id[1] = cpuid_features;
-
- p->processor_version_str = 0;
- p->voltage = 0;
- p->external_clock = 0;
+ size = qemu_cfg_smbios_load_field(4, offsetof(struct smbios_type_4,
+ socket_designation_str),
+ name);
+ if (size)
+ snprintf(name + size - 1, sizeof(name) - size, "%2x", cpu_number);
+ else
+ snprintf(name, sizeof(name), "CPU%2x", cpu_number);
+
+ memcpy(end, name, strlen(name) + 1);
+ 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 */
+
+ 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)) {
+ u32 cpuid_signature, ebx, ecx, cpuid_features;
+ cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
+ p->processor_id[0] = cpuid_signature;
+ p->processor_id[1] = cpuid_features;
+ }
- p->max_speed = 2000;
- p->current_speed = 2000;
+ load_str_field_or_skip(4, processor_version_str);
+ set_field_with_default(4, voltage, 0);
+ set_field_with_default(4, external_clock, 0);
- p->status = 0x41; /* socket populated, CPU enabled */
- p->processor_upgrade = 0x01; /* other */
+ set_field_with_default(4, max_speed, 2000);
+ set_field_with_default(4, current_speed, 2000);
- p->l1_cache_handle = 0xffff; /* cache information structure not provided */
- p->l2_cache_handle = 0xffff;
- p->l3_cache_handle = 0xffff;
+ set_field_with_default(4, status, 0x41); /* socket populated, CPU enabled */
+ set_field_with_default(4, processor_upgrade, 0x01); /* other */
- start += sizeof(struct smbios_type_4);
+ /* cache information structure not provided */
+ p->l1_cache_handle = 0xffff;
+ p->l2_cache_handle = 0xffff;
+ p->l3_cache_handle = 0xffff;
- snprintf((char*)start, 6, "CPU%2x", cpu_number);
- start += 6;
- memcpy((char *)start, CONFIG_APPNAME"\0\0", sizeof(CONFIG_APPNAME) + 1);
+ *end = 0;
+ end++;
+ if (!str_index) {
+ *end = 0;
+ end++;
+ }
- return start + sizeof(CONFIG_APPNAME) + 1;
+ return end;
}
/* Type 16 -- Physical Memory Array */
@@ -243,9 +285,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;
- p->location = 0x01; /* other */
- p->use = 0x03; /* system memory */
- p->error_correction = 0x06; /* Multi-bit ECC to make Microsoft happy */
+ set_field_with_default(16, location, 0x01); /* other */
+ set_field_with_default(16, use, 0x03); /* system memory */
+ /* Multi-bit ECC to make Microsoft happy */
+ set_field_with_default(16, error_correction, 0x06);
/* 0x80000000 = unknown, accept sizes < 2TB - TODO multiple arrays */
p->maximum_capacity = memory_size_mb < 2 << 20 ?
memory_size_mb << 10 : 0x80000000;
@@ -263,30 +306,47 @@ static void *
smbios_init_type_17(void *start, u32 size_mb, int instance)
{
struct smbios_type_17 *p = (struct smbios_type_17 *)start;
+ char *end = (char *)start + sizeof(struct smbios_type_17);
+ size_t size;
+ int str_index = 0;
+ char name[1024];
p->header.type = 17;
p->header.length = sizeof(struct smbios_type_17);
p->header.handle = 0x1100 + instance;
p->physical_memory_array_handle = 0x1000;
- p->total_width = 64;
- p->data_width = 64;
+ set_field_with_default(17, total_width, 64);
+ set_field_with_default(17, data_width, 64);
/* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */
p->size = size_mb;
- p->form_factor = 0x09; /* DIMM */
+ set_field_with_default(17, form_factor, 0x09); /* DIMM */
p->device_set = 0;
- p->device_locator_str = 1;
- p->bank_locator_str = 0;
- p->memory_type = 0x07; /* RAM */
- p->type_detail = 0;
-
- start += sizeof(struct smbios_type_17);
- memcpy((char *)start, "DIMM 0", 7);
- ((char*)start)[5] += instance;
- start += 7;
- *((u8 *)start) = 0;
-
- return start+1;
+
+ size = qemu_cfg_smbios_load_field(17, offsetof(struct smbios_type_17,
+ device_locator_str),
+ name);
+ if (size)
+ snprintf(name + size - 1, sizeof(name) - size, "%d", instance);
+ else
+ snprintf(name, sizeof(name), "DIMM %d", instance);
+
+ memcpy(end, name, strlen(name) + 1);
+ 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);
+
+ *end = 0;
+ end++;
+ if (!str_index) {
+ *end = 0;
+ end++;
+ }
+
+ return end;
}
/* Type 19 -- Memory Array Mapped Address */
@@ -345,7 +405,7 @@ smbios_init_type_32(void *start)
p->header.length = sizeof(struct smbios_type_32);
p->header.handle = 0x2000;
memset(p->reserved, 0, 6);
- p->boot_status = 0; /* no errors detected */
+ set_field_with_default(32, boot_status, 0); /* no errors detected */
start += sizeof(struct smbios_type_32);
*((u16 *)start) = 0;