[HVM] [Firmware] Write SMBIOS tables in hvmloader if enabled. Signed-off-by: Andrew D. Ball diff -r 5e4bb5e0903f tools/firmware/hvmloader/Makefile --- a/tools/firmware/hvmloader/Makefile Fri Jul 7 18:57:25 2006 +++ b/tools/firmware/hvmloader/Makefile Fri Jul 7 15:04:50 2006 @@ -31,7 +31,7 @@ DEFINES =-DDEBUG XENINC =-I$(XEN_ROOT)/tools/libxc -OBJECTS = hvmloader.o acpi_madt.o util.o +OBJECTS = hvmloader.o acpi_madt.o util.o smbios.o # Disable PIE/SSP if GCC supports them. They can break us. CFLAGS += $(call test-gcc-flag,$(CC),-nopie) @@ -45,9 +45,9 @@ .PHONY: all all: hvmloader -hvmloader: roms.h hvmloader.c acpi_madt.c util.c - $(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c util.c - $(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o util.o +hvmloader: roms.h hvmloader.c acpi_madt.c util.c smbios.c + $(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c util.c smbios.c + $(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o util.o smbios.o $(OBJCOPY) hvmloader.tmp hvmloader rm -f hvmloader.tmp diff -r 5e4bb5e0903f tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Fri Jul 7 18:57:25 2006 +++ b/tools/firmware/hvmloader/hvmloader.c Fri Jul 7 15:04:50 2006 @@ -24,6 +24,7 @@ #include "roms.h" #include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ #include "util.h" +#include "smbios.h" /* memory map */ #define VGABIOS_PHYSICAL_ADDRESS 0x000C0000 @@ -139,8 +140,17 @@ } int +get_smbios_enabled(void) +{ + struct hvm_info_table *t = get_hvm_info_table(); + return t->smbios_enabled != 0; +} + +int main(void) { + struct hvm_info_table *t = NULL; + puts("HVM Loader\n"); puts("Loading ROMBIOS ...\n"); @@ -168,6 +178,21 @@ } } + if (get_smbios_enabled() != 0) { + puts("Loading SMBIOS ...\n"); + t = get_hvm_info_table(); + if (t == NULL) { + puts("Could not get hvm_info_table\n"); + } else { + write_smbios_tables((void *)SMBIOS_PHYSICAL_ADDRESS, + SMBIOS_SIZE_LIMIT, + t->nr_vcpus, t->memsize, t->uuid, + t->xen_version, + t->xen_major_version, + t->xen_minor_version); + } + } + if (check_amd()) { /* AMD implies this is SVM */ puts("SVM go ...\n"); diff -r 5e4bb5e0903f tools/firmware/hvmloader/smbios.c --- /dev/null Fri Jul 7 18:57:25 2006 +++ b/tools/firmware/hvmloader/smbios.c Fri Jul 7 15:04:50 2006 @@ -0,0 +1,538 @@ +/* + * smbios.c - utilities for writing SMBIOS tables for Xen HVM + * domU's. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2006 + * + * Authors: Andrew D. Ball + */ + +#include "smbios.h" +#include "smbios_types.h" +#include "util.h" + +static void +get_cpu_manufacturer(char *buf, int len); +static size_t +smbios_table_size(uint32_t vcpus, const char *xen_version, + const char *processor_manufacturer); +static void * +smbios_entry_point_init(void *start, + uint16_t max_structure_size, + uint16_t structure_table_length, + uint32_t structure_table_address, + uint16_t number_of_structures); +static void * +smbios_type_0_init(void *start, const char *xen_version, + uint32_t xen_major_version, uint32_t xen_minor_version); +static void * +smbios_type_1_init(void *start, const char *xen_version, + uint8_t uuid[16]); +static void * +smbios_type_3_init(void *start); +static void * +smbios_type_4_init(void *start, unsigned int cpu_number, + char *cpu_manufacturer); +static void * +smbios_type_16_init(void *start, uint32_t memory_size_mb); +static void * +smbios_type_17_init(void *start, uint32_t memory_size_mb); +static void * +smbios_type_19_init(void *start, uint32_t memory_size_mb); +static void * +smbios_type_20_init(void *start, uint32_t memory_size_mb); +static void * +smbios_type_32_init(void *start); +void * +smbios_type_127_init(void *start); + +/* from xen/include/asm-x86/processor.h */ + +/* + * Generic CPUID function + * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx + * resulting in stale register contents being returned. + */ +#define cpuid(_op,_eax,_ebx,_ecx,_edx) \ + __asm__("cpuid" \ + : "=a" (*(int *)(_eax)), \ + "=b" (*(int *)(_ebx)), \ + "=c" (*(int *)(_ecx)), \ + "=d" (*(int *)(_edx)) \ + : "0" (_op), "2" (0)) + + +/* adapted from tools/firmware/hvmloader/hvmloader.c */ + +/* Function to convert an unsigned integer to a string to + be able to write "CPU n" for 1 <= n <= 99 for SMBIOS type 4. + + Preconditions: + (1) n must be less than 100. + (2) buf must point to a char [] with at least 3 elements. + */ +static void +uint_to_string(char *buf, unsigned int n); + +static void +get_cpu_manufacturer(char *buf, int len) +{ + char id[12]; + uint32_t eax = 0; + + cpuid(0, eax, &id[0], &id[8], &id[4]); + + if (memcmp(id, "GenuineIntel", 12) == 0) + strncpy(buf, "Intel", len); + else if (memcmp(id, "AuthenticAMD", 12) == 0) + strncpy(buf, "AMD", len); + else + strncpy(buf, "unknown", len); +} + + +/* Calculate the size of the SMBIOS structure table. +*/ +static size_t +smbios_table_size(uint32_t vcpus, const char *xen_version, + const char *processor_manufacturer) +{ + size_t size; + + /* first compute size without strings or terminating 0 bytes */ + size = sizeof(struct smbios_type_0) + sizeof(struct smbios_type_1) + + sizeof(struct smbios_type_3) + sizeof(struct smbios_type_4)*vcpus + + sizeof(struct smbios_type_16) + sizeof(struct smbios_type_17) + + sizeof(struct smbios_type_19) + sizeof(struct smbios_type_20) + + sizeof(struct smbios_type_32) + sizeof(struct smbios_type_127); + + /* 5 structures with no strings, 2 null bytes each */ + size += 10; + + /* Need to include 1 null byte per structure with strings (first + terminating null byte comes from the string terminator of the + last string). */ + size += 4 + vcpus; + + /* type 0: "Xen", xen_version, and release_date */ + size += strlen("Xen") + strlen(xen_version) + 2; + /* type 1: "Xen", xen_version, "HVM domU" */ + size += strlen("Xen") + strlen("HVM domU") + strlen(xen_version) + 3; + /* type 3: "Xen" */ + size += strlen("Xen") + 1; + /* type 4: socket designation ("CPU n"), processor_manufacturer */ + size += vcpus * (strlen("CPU n") + strlen(processor_manufacturer) + 2); + /* Make room for two-digit CPU numbers if necessary -- doesn't handle + vcpus > 99 */ + if (vcpus > 9) + size += vcpus - 9; + /* type 17: device locator string ("DIMM 1") */ + size += strlen("DIMM 1") + 1; + + return size; +} + +size_t +write_smbios_tables(void *start, size_t max_size, + uint32_t vcpus, uint64_t memsize, + uint8_t uuid[16], char *xen_version, + uint32_t xen_major_version, uint32_t xen_minor_version) +{ + unsigned cpu_num; + void *p = start; + char cpu_manufacturer[15]; + size_t structure_table_length; + + get_cpu_manufacturer(cpu_manufacturer, 15); + + + structure_table_length = smbios_table_size(vcpus, xen_version, + cpu_manufacturer); + + if (structure_table_length + sizeof(struct smbios_entry_point) > max_size) + return 0; + + p = smbios_entry_point_init(p, sizeof(struct smbios_type_4), + structure_table_length, + (uint32_t)start + + sizeof(struct smbios_entry_point), + 9 + vcpus); + + p = smbios_type_0_init(p, xen_version, xen_major_version, + xen_minor_version); + p = smbios_type_1_init(p, xen_version, uuid); + p = smbios_type_3_init(p); + for (cpu_num = 1; cpu_num <= vcpus; ++cpu_num) + p = smbios_type_4_init(p, cpu_num, cpu_manufacturer); + p = smbios_type_16_init(p, memsize); + p = smbios_type_17_init(p, memsize); + p = smbios_type_19_init(p, memsize); + p = smbios_type_20_init(p, memsize); + p = smbios_type_32_init(p); + p = smbios_type_127_init(p); + + return (size_t)((char*)p - (char*)start); +} + +static void * +smbios_entry_point_init(void *start, + uint16_t max_structure_size, + uint16_t structure_table_length, + uint32_t structure_table_address, + uint16_t number_of_structures) +{ + uint8_t sum; + int i; + struct smbios_entry_point *ep = (struct smbios_entry_point *)start; + + strncpy(ep->anchor_string, "_SM_", 4); + ep->length = 0x1f; + ep->smbios_major_version = 2; + ep->smbios_minor_version = 4; + ep->max_structure_size = max_structure_size; + ep->entry_point_revision = 0; + memset(ep->formatted_area, 0, 5); + strncpy(ep->intermediate_anchor_string, "_DMI_", 5); + + ep->structure_table_length = structure_table_length; + ep->structure_table_address = structure_table_address; + ep->number_of_structures = number_of_structures; + ep->smbios_bcd_revision = 0x24; + + ep->checksum = 0; + ep->intermediate_checksum = 0; + + sum = 0; + for (i = 0; i < 0x10; ++i) + sum += ((int8_t *)start)[i]; + ep->checksum = -sum; + + sum = 0; + for (i = 0x10; i < ep->length; ++i) + sum += ((int8_t *)start)[i]; + ep->intermediate_checksum = -sum; + + return (char *)start + sizeof(struct smbios_entry_point); +} + +/* Type 0 -- BIOS Information */ +static void * +smbios_type_0_init(void *start, const char *xen_version, + uint32_t xen_major_version, uint32_t xen_minor_version) +{ + struct smbios_type_0 *p = (struct smbios_type_0 *)start; + + p->header.type = 0; + p->header.length = sizeof(struct smbios_type_0); + p->header.handle = 0; + + p->vendor_str = 1; + p->version_str = 2; + p->starting_address_segment = 0xe800; + p->release_date_str = 0; + p->rom_size = 0; + + memset(p->characteristics, 0, 8); + p->characteristics[7] = 0x08; /* BIOS characteristics not supported */ + p->characteristics_extension_bytes[0] = 0; + p->characteristics_extension_bytes[1] = 0; + + p->major_release = (uint8_t) xen_major_version; + p->minor_release = (uint8_t) xen_minor_version; + p->embedded_controller_major = 0xff; + p->embedded_controller_minor = 0xff; + + start += sizeof(struct smbios_type_0); + strcpy((char *)start, "Xen"); + start += strlen("Xen") + 1; + strcpy((char *)start, xen_version); + start += strlen(xen_version) + 1; + + *((uint8_t *)start) = 0; + return start + 1; +} + +/* Type 1 -- System Information */ +static void * +smbios_type_1_init(void *start, const char *xen_version, + uint8_t uuid[16]) +{ + struct smbios_type_1 *p = (struct smbios_type_1 *)start; + p->header.type = 1; + p->header.length = sizeof(struct smbios_type_1); + p->header.handle = 0x100; + + p->manufacturer_str = 1; + p->product_name_str = 2; + p->version_str = 3; + p->serial_number_str = 0; + + memcpy(p->uuid, uuid, 16); + + p->wake_up_type = 0x06; /* power switch */ + p->sku_str = 0; + p->family_str = 0; + + start += sizeof(struct smbios_type_1); + + strcpy((char *)start, "Xen"); + start += strlen("Xen") + 1; + strcpy((char *)start, "HVM domU"); + start += strlen("HVM domU") + 1; + strcpy((char *)start, xen_version); + start += strlen(xen_version) + 1; + *((uint8_t *)start) = 0; + + return start+1; +} + +/* Type 3 -- System Enclosure */ +static void * +smbios_type_3_init(void *start) +{ + struct smbios_type_3 *p = (struct smbios_type_3 *)start; + + 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_str = 0; + p->boot_up_state = 0x03; /* safe */ + p->power_supply_state = 0x03; /* safe */ + p->thermal_state = 0x03; /* safe */ + p->security_status = 0x02; /* unknown */ + + start += sizeof(struct smbios_type_3); + + strcpy((char *)start, "Xen"); + start += strlen("Xen") + 1; + *((uint8_t *)start) = 0; + return start+1; +} + +/* Type 4 -- Processor Information */ +static void * +smbios_type_4_init(void *start, unsigned int cpu_number, char *cpu_manufacturer) +{ + char buf[15]; + struct smbios_type_4 *p = (struct smbios_type_4 *)start; + uint32_t eax, ebx, ecx, edx; + + 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->manufacturer_str = 2; + + cpuid(1, &eax, &ebx, &ecx, &edx); + + p->cpuid[0] = eax; + p->cpuid[1] = edx; + + p->version_str = 0; + p->voltage = 0; + p->external_clock = 0; + + p->max_speed = 0; /* unknown */ + p->current_speed = 0; /* unknown */ + + p->status = 0x41; /* socket populated, CPU enabled */ + p->upgrade = 0x01; /* other */ + + start += sizeof(struct smbios_type_4); + + strncpy(buf, "CPU ", sizeof(buf)); + if ((sizeof(buf) - strlen("CPU ")) >= 3) + uint_to_string(buf + strlen("CPU "), cpu_number); + + strcpy((char *)start, buf); + start += strlen(buf) + 1; + + strcpy((char *)start, cpu_manufacturer); + start += strlen(buf) + 1; + + *((uint8_t *)start) = 0; + return start+1; +} + +/* Type 16 -- Physical Memory Array */ +static void * +smbios_type_16_init(void *start, uint32_t memsize) +{ + struct smbios_type_16 *p = (struct smbios_type_16*)start; + + p->header.type = 16; + p->header.handle = 0x1000; + p->header.length = sizeof(struct smbios_type_16); + + p->location = 0x01; /* other */ + p->use = 0x03; /* system memory */ + p->error_correction = 0x01; /* other */ + p->maximum_capacity = memsize * 1024; + p->memory_error_information_handle = 0xfffe; /* none provided */ + p->number_of_memory_devices = 1; + + start += sizeof(struct smbios_type_16); + *((uint16_t *)start) = 0; + return start + 2; +} + +/* Type 17 -- Memory Device */ +static void * +smbios_type_17_init(void *start, uint32_t memory_size_mb) +{ + struct smbios_type_17 *p = (struct smbios_type_17 *)start; + + p->header.type = 17; + p->header.length = sizeof(struct smbios_type_17); + p->header.handle = 0x1100; + + p->physical_memory_array_handle = 0x1000; + p->total_width = 64; + p->data_width = 64; + /* truncate memory_size_mb to 16 bits and clear most significant + bit [indicates size in MB] */ + p->size = (uint16_t) memory_size_mb & 0x7fff; + p->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); + strcpy((char *)start, "DIMM 1"); + start += strlen("DIMM 1") + 1; + *((uint8_t *)start) = 0; + + return start+1; +} + +/* Type 19 -- Memory Array Mapped Address */ +static void * +smbios_type_19_init(void *start, uint32_t memory_size_mb) +{ + struct smbios_type_19 *p = (struct smbios_type_19 *)start; + + p->header.type = 19; + p->header.length = sizeof(struct smbios_type_19); + p->header.handle = 0x1300; + + p->starting_address = 0; + p->ending_address = (memory_size_mb-1) * 1024; + p->memory_array_handle = 0x1000; + p->partition_width = 1; + + start += sizeof(struct smbios_type_19); + *((uint16_t *)start) = 0; + return start + 2; +} + +/* Type 20 -- Memory Device Mapped Address */ +static void * +smbios_type_20_init(void *start, uint32_t memory_size_mb) +{ + struct smbios_type_20 *p = (struct smbios_type_20 *)start; + + p->header.type = 20; + p->header.length = sizeof(struct smbios_type_20); + p->header.handle = 0x1400; + + p->starting_address = 0; + p->ending_address = (memory_size_mb-1)*1024; + p->memory_device_handle = 0x1100; + p->memory_array_mapped_address_handle = 0x1300; + p->partition_row_position = 1; + p->interleave_position = 0; + p->interleaved_data_depth = 0; + + start += sizeof(struct smbios_type_20); + + *((uint16_t *)start) = 0; + return start+2; +} + +/* Type 32 -- System Boot Information */ +static void * +smbios_type_32_init(void *start) +{ + struct smbios_type_32 *p = (struct smbios_type_32 *)start; + + p->header.type = 32; + p->header.length = sizeof(struct smbios_type_32); + p->header.handle = 0x2000; + memset(p->reserved, 0, 6); + p->boot_status = 0; /* no errors detected */ + + start += sizeof(struct smbios_type_32); + *((uint16_t *)start) = 0; + return start+2; +} + +/* Type 127 -- End of Table */ +void * +smbios_type_127_init(void *start) +{ + struct smbios_type_127 *p = (struct smbios_type_127 *)start; + + p->header.type = 127; + p->header.length = sizeof(struct smbios_type_127); + p->header.handle = 0x7f00; + + start += sizeof(struct smbios_type_127); + *((uint16_t *)start) = 0; + return start + 2; +} + +/* Function to convert an unsigned integer to a string to + be able to write "CPU n" for 1 <= n <= 99 for SMBIOS type 4. + + Preconditions: + (1) n must be less than 100. + (2) buf must point to a char [] with at least 3 elements. + */ +static void +uint_to_string(char *buf, unsigned int n) +{ + if (n >= 100) + return; + + buf[0] = ((char) (n % 10)) + '0'; + if (n >= 10) { + buf[1] = ((char) (n / 10)) + '0'; + buf[2] = '\0'; + } else { + buf[1] = '\0'; + } +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 5e4bb5e0903f tools/firmware/hvmloader/smbios.h --- /dev/null Fri Jul 7 18:57:25 2006 +++ b/tools/firmware/hvmloader/smbios.h Fri Jul 7 15:04:50 2006 @@ -0,0 +1,56 @@ +/* + * smbios.h - interface for Xen HVM SMBIOS generation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2006 + * + * Authors: Andrew D. Ball + */ + +#ifndef SMBIOS_H +#define SMBIOS_H + +#include +#include + +/* These constants must agree with the ACPI e820 memory map as defined + in tools/libxc/xc_hvm_build.c . + */ +#define SMBIOS_PHYSICAL_ADDRESS 0x9f000 +#define SMBIOS_SIZE_LIMIT 0x800 + +/* write SMBIOS tables starting at 'start' and not writing more + than 'max_size' bytes. + + Return the number of bytes written +*/ +size_t +write_smbios_tables(void *start, size_t max_size, + uint32_t vcpus, uint64_t memsize, + uint8_t uuid[16], char *xen_version, + uint32_t xen_major_version, uint32_t xen_minor_version); + +#endif /* SMBIOS_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 5e4bb5e0903f tools/firmware/hvmloader/smbios_types.h --- /dev/null Fri Jul 7 18:57:25 2006 +++ b/tools/firmware/hvmloader/smbios_types.h Fri Jul 7 15:04:50 2006 @@ -0,0 +1,192 @@ +/* + * smbios_types.h - data structure definitions for Xen HVM SMBIOS support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2006 + * + * Authors: Andrew D. Ball + * + * See the SMBIOS 2.4 spec for more detail: + * http://www.dmtf.org/standards/smbios/ + */ + +#ifndef SMBIOS_TYPES_H +#define SMBIOS_TYPES_H + +#include + +/* SMBIOS entry point -- must be written to a 16-bit aligned address + between 0xf0000 and 0xfffff. + */ +struct smbios_entry_point { + char anchor_string[4]; + uint8_t checksum; + uint8_t length; + uint8_t smbios_major_version; + uint8_t smbios_minor_version; + uint16_t max_structure_size; + uint8_t entry_point_revision; + uint8_t formatted_area[5]; + char intermediate_anchor_string[5]; + uint8_t intermediate_checksum; + uint16_t structure_table_length; + uint32_t structure_table_address; + uint16_t number_of_structures; + uint8_t smbios_bcd_revision; +} __attribute__ ((packed)); + +/* This goes at the beginning of every SMBIOS structure. */ +struct smbios_structure_header { + uint8_t type; + uint8_t length; + uint16_t handle; +} __attribute__ ((packed)); + +/* SMBIOS type 0 - BIOS Information */ +struct smbios_type_0 { + struct smbios_structure_header header; + uint8_t vendor_str; + uint8_t version_str; + uint16_t starting_address_segment; + uint8_t release_date_str; + uint8_t rom_size; + uint8_t characteristics[8]; + uint8_t characteristics_extension_bytes[2]; + uint8_t major_release; + uint8_t minor_release; + uint8_t embedded_controller_major; + uint8_t embedded_controller_minor; +} __attribute__ ((packed)); + +/* SMBIOS type 1 - System Information */ +struct smbios_type_1 { + struct smbios_structure_header header; + uint8_t manufacturer_str; + uint8_t product_name_str; + uint8_t version_str; + uint8_t serial_number_str; + uint8_t uuid[16]; + uint8_t wake_up_type; + uint8_t sku_str; + uint8_t family_str; +} __attribute__ ((packed)); + +/* SMBIOS type 3 - System Enclosure */ +struct smbios_type_3 { + struct smbios_structure_header header; + uint8_t manufacturer_str; + uint8_t type; + uint8_t version_str; + uint8_t serial_number_str; + uint8_t asset_tag_str; + uint8_t boot_up_state; + uint8_t power_supply_state; + uint8_t thermal_state; + uint8_t security_status; +} __attribute__ ((packed)); + +/* SMBIOS type 4 - Processor Information */ +struct smbios_type_4 { + struct smbios_structure_header header; + uint8_t socket_designation_str; + uint8_t processor_type; + uint8_t processor_family; + uint8_t manufacturer_str; + uint32_t cpuid[2]; + uint8_t version_str; + uint8_t voltage; + uint16_t external_clock; + uint16_t max_speed; + uint16_t current_speed; + uint8_t status; + uint8_t upgrade; +} __attribute__ ((packed)); + +/* SMBIOS type 16 - Physical Memory Array + * Associated with one type 17 (Memory Device). + */ +struct smbios_type_16 { + struct smbios_structure_header header; + uint8_t location; + uint8_t use; + uint8_t error_correction; + uint32_t maximum_capacity; + uint16_t memory_error_information_handle; + uint16_t number_of_memory_devices; +} __attribute__ ((packed)); + +/* SMBIOS type 17 - Memory Device + * Associated with one type 19 + */ +struct smbios_type_17 { + struct smbios_structure_header header; + uint16_t physical_memory_array_handle; + uint16_t memory_error_information_handle; + uint16_t total_width; + uint16_t data_width; + uint16_t size; + uint8_t form_factor; + uint8_t device_set; + uint8_t device_locator_str; + uint8_t bank_locator_str; + uint8_t memory_type; + uint16_t type_detail; +} __attribute__ ((packed)); + +/* SMBIOS type 19 - Memory Array Mapped Address */ +struct smbios_type_19 { + struct smbios_structure_header header; + uint32_t starting_address; + uint32_t ending_address; + uint16_t memory_array_handle; + uint8_t partition_width; +} __attribute__ ((packed)); + +/* SMBIOS type 20 - Memory Device Mapped Address */ +struct smbios_type_20 { + struct smbios_structure_header header; + uint32_t starting_address; + uint32_t ending_address; + uint16_t memory_device_handle; + uint16_t memory_array_mapped_address_handle; + uint8_t partition_row_position; + uint8_t interleave_position; + uint8_t interleaved_data_depth; +} __attribute__ ((packed)); + +/* SMBIOS type 32 - System Boot Information */ +struct smbios_type_32 { + struct smbios_structure_header header; + uint8_t reserved[6]; + uint8_t boot_status; +} __attribute__ ((packed)); + +/* SMBIOS type 127 -- End-of-table */ +struct smbios_type_127 { + struct smbios_structure_header header; +} __attribute__ ((packed)); + +#endif /* SMBIOS_TYPES_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */