Andrew D. Ball
2006-Aug-11 22:07 UTC
[Xen-devel] [PATCH] [4/5] SMBIOS -- generate SMBIOS tables
Add code to generate SMBIOS tables to hvmloader. Signed-off-by: Andrew D. Ball <aball@us.ibm.com> diff -r 1d817bfc5ed9 tools/firmware/hvmloader/Makefile --- a/tools/firmware/hvmloader/Makefile Fri Aug 11 14:22:54 2006 +0100 +++ b/tools/firmware/hvmloader/Makefile Fri Aug 11 14:55:18 2006 -0400 @@ -31,7 +31,7 @@ DEFINES =-DDEBUG DEFINES =-DDEBUG XENINC =-I$(XEN_ROOT)/tools/libxc -OBJECTS = hvmloader.o acpi_madt.o +OBJECTS = hvmloader.o acpi_madt.o smbios.o # Disable PIE/SSP if GCC supports them. They can break us. CFLAGS += $(call test-gcc-flag,$(CC),-nopie) @@ -42,7 +42,7 @@ CFLAGS += $(DEFINES) -I. $(XENINC) -fno CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR) -SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c +SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c smbios.c OBJS = $(patsubst %.c,%.o,$(SRCS)) .PHONY: all diff -r 1d817bfc5ed9 tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Fri Aug 11 14:22:54 2006 +0100 +++ b/tools/firmware/hvmloader/hvmloader.c Fri Aug 11 16:18:16 2006 -0400 @@ -25,6 +25,8 @@ #include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ #include "hypercall.h" #include "util.h" +#include "smbios.h" +#include "e820.h" #include <xen/version.h> #include <xen/hvm/params.h> @@ -116,15 +118,6 @@ check_amd(void) } static void -cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) -{ - __asm__ __volatile__( - "cpuid" - : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) - : "0" (idx) ); -} - -static void wrmsr(uint32_t idx, uint64_t v) { __asm__ __volatile__( @@ -209,6 +202,9 @@ main(void) } } + puts("Writing SMBIOS tables ...\n"); + hvm_write_smbios_tables(); + if (check_amd()) { /* AMD implies this is SVM */ puts("SVM go ...\n"); diff -r 1d817bfc5ed9 tools/firmware/hvmloader/smbios.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/firmware/hvmloader/smbios.c Fri Aug 11 17:23:20 2006 -0400 @@ -0,0 +1,616 @@ +/* + * smbios.c - Generate 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 <aball@us.ibm.com> + */ + +#include <stdint.h> +#include <xen/version.h> +#include "smbios.h" +#include "smbios_types.h" +#include "util.h" +#include "e820.h" +#include "hypercall.h" + +/* write SMBIOS tables starting at ''start'', without writing more + than ''max_size'' bytes. + + Return the number of bytes written +*/ +static 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); + +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); + +static void +get_cpu_manufacturer(char *buf, int len) +{ + char id[12]; + uint32_t eax = 0; + + cpuid(0, &eax, (uint32_t *)&id[0], (uint32_t *)&id[8], (uint32_t *)&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; +} + +static 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); +} + +/* This tries to figure out how much pseudo-physical memory (in MB) + is allocated to the current domU. + + It iterates through the e820 table, adding up the ''usable'' and + ''reserved'' entries and rounding up to the nearest MB. + + The e820map is not at e820 in hvmloader, so this uses the + E820_MAP_* constants from e820.h to pick it up where libxenguest + left it. + */ +static uint64_t +get_memsize(void) +{ + struct e820entry *map = NULL; + uint8_t num_entries = 0; + uint64_t memsize = 0; + uint8_t i; + + map = (struct e820entry *) (E820_MAP_PAGE + E820_MAP_OFFSET); + num_entries = *((uint8_t *) (E820_MAP_PAGE + E820_MAP_NR_OFFSET)); + + /* walk through e820map, ignoring any entries that aren''t marked + as usable or reserved. */ + + for (i = 0; i < num_entries; i++) { + if (map->type == E820_RAM || map->type == E820_RESERVED) + memsize += map->size; + map++; + } + + /* Round up to the nearest MB. The user specifies domU + pseudo-physical memory in megabytes, so not doing this + could easily lead to reporting one less MB than the user + specified. */ + if (memsize & ((1<<20)-1)) + memsize = (memsize >> 20) + 1; + else + memsize = (memsize >> 20); + + return memsize; +} + +void +hvm_write_smbios_tables(void) +{ + uint8_t uuid[16]; /* ** This will break if xen_domain_handle_t is + not uint8_t[16]. ** */ + uint16_t xen_major_version, xen_minor_version; + uint32_t xen_version; + char xen_extra_version[XEN_EXTRAVERSION_LEN]; + /* guess conservatively on buffer length for Xen version string */ + char xen_version_str[80]; + /* temporary variables used to build up Xen version string */ + char *p = NULL; /* points to next point of insertion */ + unsigned len = 0; /* length of string already composed */ + char *tmp = NULL; /* holds result of itoa() */ + unsigned tmp_len; /* length of next string to add */ + + hypercall_xen_version(XENVER_guest_handle, uuid); + + /* xen_version major and minor */ + xen_version = hypercall_xen_version(XENVER_version, NULL); + xen_major_version = (uint16_t) (xen_version >> 16); + xen_minor_version = (uint16_t) xen_version; + + hypercall_xen_version(XENVER_extraversion, xen_extra_version); + + /* build up human-readable Xen version string */ + p = xen_version_str; + len = 0; + + itoa(tmp, xen_major_version); + tmp_len = strlen(tmp); + len += tmp_len; + if (len >= sizeof(xen_version_str)) + goto error_out; + strcpy(p, tmp); + p += tmp_len; + + len++; + if (len >= sizeof(xen_version_str)) + goto error_out; + *p = ''.''; + p++; + + itoa(tmp, xen_minor_version); + tmp_len = strlen(tmp); + len += tmp_len; + if (len >= sizeof(xen_version_str)) + goto error_out; + strcpy(p, tmp); + p += tmp_len; + + tmp_len = strlen(xen_extra_version); + len += tmp_len; + if (len >= sizeof(xen_version_str)) + goto error_out; + strcpy(p, xen_extra_version); + p += tmp_len; + + xen_version_str[sizeof(xen_version_str)-1] = ''\0''; + + write_smbios_tables((void *) SMBIOS_PHYSICAL_ADDRESS, + SMBIOS_SIZE_LIMIT, get_vcpu_nr(), get_memsize(), + uuid, xen_version_str, + xen_major_version, xen_minor_version); + return; + + error_out: + puts("Could not write SMBIOS tables, error in hvmloader.c:" + "hvm_write_smbios_tables()\n"); +} + + +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[80]; + 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) + itoa(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; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 1d817bfc5ed9 tools/firmware/hvmloader/smbios.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/firmware/hvmloader/smbios.h Fri Aug 11 16:19:30 2006 -0400 @@ -0,0 +1,48 @@ +/* + * 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 <aball@us.ibm.com> + */ + +#ifndef SMBIOS_H +#define SMBIOS_H + +#include <stdint.h> +#include <stdlib.h> + +/* These constants must agree with the ACPI e820 memory map as defined + in tools/libxc/xc_hvm_build.c and the address the ROMBIOS pulls the + SMBIOS entry point from in the smbios_init subroutine. + */ +#define SMBIOS_PHYSICAL_ADDRESS 0x9f000 +#define SMBIOS_SIZE_LIMIT 0x800 + +void hvm_write_smbios_tables(void); + +#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 1d817bfc5ed9 tools/firmware/hvmloader/smbios_types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/firmware/hvmloader/smbios_types.h Fri Aug 11 14:55:18 2006 -0400 @@ -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 <aball@us.ibm.com> + * + * See the SMBIOS 2.4 spec for more detail: + * http://www.dmtf.org/standards/smbios/ + */ + +#ifndef SMBIOS_TYPES_H +#define SMBIOS_TYPES_H + +#include <stdint.h> + +/* 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: + */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel