diff options
Diffstat (limited to 'src/smbios.c')
-rw-r--r-- | src/smbios.c | 222 |
1 files changed, 141 insertions, 81 deletions
diff --git a/src/smbios.c b/src/smbios.c index e19a62d2..8df0f2da 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; |