5 files changed, 754 insertions(+), 2 deletions(-) Makefile.target | 4 hw/pc.c | 47 ++++ smbios.c | 519 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ smbios_types.h | 182 +++++++++++++++++++ sysemu.h | 4
# HG changeset patch # User Ryan Harper <[EMAIL PROTECTED]> # Date 1197058922 21600 # Node ID 37bf559ffcf74bfe62ec038c5818e4cf29b817f5 # Parent 25082b761acbe8b7fa535dedb4a53e02ef74128d export SMBIOS/DMI tables to PC machines. This patch introduces code to generate PC SMBIOS/DMI tables and load them into machine memory. The resultant machine can use standard tools like dmidecode to examine the in-memory generated table. Signed-off-by: Ryan Harper <[EMAIL PROTECTED]> diff -r 25082b761acb -r 37bf559ffcf7 Makefile.target --- a/Makefile.target Wed Dec 05 03:23:38 2007 +0000 +++ b/Makefile.target Fri Dec 07 14:22:02 2007 -0600 @@ -396,7 +396,7 @@ endif endif # must use static linking to avoid leaving stuff in virtual address space -VL_OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o +VL_OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o smbios.o # XXX: suppress QEMU_TOOL tests VL_OBJS+=block-raw.o @@ -535,7 +535,7 @@ ifndef CONFIG_DARWIN ifndef CONFIG_DARWIN ifndef CONFIG_WIN32 ifndef CONFIG_SOLARIS -VL_LIBS+=-lutil +VL_LIBS+=-lutil -luuid endif endif endif diff -r 25082b761acb -r 37bf559ffcf7 hw/pc.c --- a/hw/pc.c Wed Dec 05 03:23:38 2007 +0000 +++ b/hw/pc.c Fri Dec 07 14:22:02 2007 -0600 @@ -44,6 +44,13 @@ #define MAX_IDE_BUS 2 +/* Hole in BIOS space between 0xF0000 and 0xFFF0 for DMI entry point */ +#define SMBIOS_ENTRY 0x000fac00 + +/* ensure SMBIOS tables have enough room to support MAX_CPUS number of + * processor entries */ +#define SMBIOS_EXTRA (5 << 12) + static fdctrl_t *floppy_controller; static RTCState *rtc_state; static PITState *pit; @@ -832,6 +839,46 @@ static void pc_init1(int ram_size, int v } } + { + ram_addr_t smbios_offset, entrypoint_offset, smbios_base; + uint32_t smbios_phys; + int smbios_size; + + /* phys_ram_base + bios_offset implies 0xe0000 in guest ram */ + smbios_base = (ram_addr_t)phys_ram_base + bios_offset; + + /* take a guess at smbios size */ + smbios_size = (SMBIOS_EXTRA-1) & ~4095; + + /* we only have 32k of space between rombios32 and rombios16 */ + if (smbios_size > SMBIOS_MAXIMUM_SIZE) { + fprintf(stderr, "qemu: SMBIOS image size too big (%u), max %u\n", + smbios_size, SMBIOS_MAXIMUM_SIZE); + exit(1); + } + + /* smbios is composed of two regions, an entry point table and + * a second table of all of the data. These regions will live + * at different phyiscal addresses so we need to reserve space + * for two locations + * NB: Entry point is a fixed size (0x1f) + */ + + /* use the hole between end of rombios32 and start of + * rombios16 @ 0xf0000 */ + smbios_phys = 0xf0000 - smbios_size; + smbios_offset = (ram_addr_t)(smbios_phys - 0xe0000); + entrypoint_offset = (ram_addr_t)(SMBIOS_ENTRY - 0xe0000); + + ret = load_smbios_tables((uint8_t *)smbios_base + entrypoint_offset, + (uint8_t *)smbios_base + smbios_offset, + smbios_phys); + if (ret < 0) { + fprintf(stderr, "qemu: could not generate SMBIOS\n"); + exit(1); + } + } + /* map all the bios at the top of memory */ cpu_register_physical_memory((uint32_t)(-bios_size), bios_size, bios_offset | IO_MEM_ROM); diff -r 25082b761acb -r 37bf559ffcf7 smbios.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smbios.c Fri Dec 07 14:22:02 2007 -0600 @@ -0,0 +1,519 @@ +/* + * smbios.c - Generate SMBIOS tables for Xen HVM domU's. + * - Adapted for QEMU/KVM + * + * 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, 2007 + * + * Authors: Andrew D. Ball <[EMAIL PROTECTED]> + * Ryan Harper <[EMAIL PROTECTED]> + */ + +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <uuid/uuid.h> +#include "hw/hw.h" +#include "sysemu.h" +#include "smbios_types.h" +#include "config-host.h" + +CPUState *first_cpu; + +/* Write a two-character hex representation of 'byte' to digits[]. + Pre-condition: sizeof(digits) >= 2 */ +void +byte_to_hex(char *digits, uint8_t byte) +{ + uint8_t nybbel = byte >> 4; + + if ( nybbel > 9 ) + digits[0] = 'a' + nybbel-10; + else + digits[0] = '0' + nybbel; + + nybbel = byte & 0x0f; + if ( nybbel > 9 ) + digits[1] = 'a' + nybbel-10; + else + digits[1] = '0' + nybbel; +} + +/* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID + string. + + Pre-condition: sizeof(dest) >= 37 */ +static void +uuid_to_string(char *dest, uint8_t *uuid) +{ + int i = 0; + char *p = dest; + + for ( i = 0; i < 4; i++ ) + { + byte_to_hex(p, uuid[i]); + p += 2; + } + *p++ = '-'; + for ( i = 4; i < 6; i++ ) + { + byte_to_hex(p, uuid[i]); + p += 2; + } + *p++ = '-'; + for ( i = 6; i < 8; i++ ) + { + byte_to_hex(p, uuid[i]); + p += 2; + } + *p++ = '-'; + for ( i = 8; i < 10; i++ ) + { + byte_to_hex(p, uuid[i]); + p += 2; + } + *p++ = '-'; + for ( i = 10; i < 16; i++ ) + { + byte_to_hex(p, uuid[i]); + p += 2; + } + *p = '\0'; +} + +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; +} + +/* Type 0 -- BIOS Information */ +#define RELEASE_DATE_STR "01/01/2007" +static void * +smbios_type_0_init(void *start, const char *version, + uint32_t major_version, uint32_t 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 = 3; + 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) major_version; + p->minor_release = (uint8_t) minor_version; + p->embedded_controller_major = 0xff; + p->embedded_controller_minor = 0xff; + + /* copy in vendor string */ + start += sizeof(struct smbios_type_0); + strcpy((char *)start, "QEMU"); + + /* copy in version string */ + start += strlen("QEMU") + 1; + strcpy((char *)start, version); + + /* copy in release date string */ + start += strlen(version) + 1; + strcpy((char *)start, RELEASE_DATE_STR); + start += strlen(RELEASE_DATE_STR) +1; + + *((uint8_t *)start) = 0; + return start + 1; +} + +/* Type 1 -- System Information */ +static void * +smbios_type_1_init(void *start, const char *version, + uint8_t uuid[16]) +{ + char uuid_str[37]; + 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 = 4; + + 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, "QEMU"); + start += strlen("QEMU") + 1; + strcpy((char *)start, "QEMU"); + start += strlen("QEMU") + 1; + strcpy((char *)start, version); + start += strlen(version) + 1; + uuid_to_string(uuid_str, uuid); + strcpy((char *)start, uuid_str); + start += strlen(uuid_str) + 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, "QEMU"); + start += strlen("QEMU") + 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; + CPUState *env = first_cpu; + + 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; + + p->cpuid[0] = env->cpuid_version; + p->cpuid[1] = env->cpuid_features; + + 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); + + /* NB: supports up to 255 cpus */ + strncpy(buf, "CPU ", sizeof(buf)); + if ( (sizeof(buf) - strlen("CPU ")) >= 3 ) + snprintf(buf + strlen("CPU "), 4, "%d", cpu_number); + + strcpy((char *)start, buf); + start += strlen(buf) + 1; + + strcpy((char *)start, cpu_manufacturer); + start += strlen(cpu_manufacturer) + 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 */ +static 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; +} + +static void +get_cpu_manufacturer(char *buf, int len) +{ + char id[12]; + CPUState *env = first_cpu; + + /* load id with cpuid(0) call */ + memcpy(id, &(env->cpuid_vendor1), 4); + memcpy(id+4, &(env->cpuid_vendor2), 4); + memcpy(id+8, &(env->cpuid_vendor3), 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); +} + +static int +write_smbios_tables(uint8_t *entry, uint8_t *tables, + uint32_t table_phys_start, + uint32_t vcpus, uint64_t memsize, + uint8_t uuid[16], const char *version, + uint32_t major_version, uint32_t minor_version) +{ + unsigned cpu_num, nr_structs = 0, max_struct_size = 0; + char *p, *q; + char cpu_manufacturer[15]; + + get_cpu_manufacturer(cpu_manufacturer, 15); + + p = tables; + +#define do_struct(fn) do { \ + q = (fn); \ + nr_structs++; \ + if ( (q - p) > max_struct_size ) \ + max_struct_size = q - p; \ + p = q; \ +} while (0) + + do_struct(smbios_type_0_init(p, version, major_version, + minor_version)); + do_struct(smbios_type_1_init(p, version, uuid)); + do_struct(smbios_type_3_init(p)); + for ( cpu_num = 1; cpu_num <= vcpus; cpu_num++ ) + do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer)); + do_struct(smbios_type_16_init(p, memsize)); + do_struct(smbios_type_17_init(p, memsize)); + do_struct(smbios_type_19_init(p, memsize)); + do_struct(smbios_type_20_init(p, memsize)); + do_struct(smbios_type_32_init(p)); + do_struct(smbios_type_127_init(p)); + +#undef do_struct + + smbios_entry_point_init(entry, max_struct_size, + (p - (char *)tables), + table_phys_start, nr_structs); + + return ((char *)p - (char *)tables); +} + +/* entry point */ +int +load_smbios_tables(uint8_t *entry, uint8_t *table, uint32_t phys_table_start) +{ + int len; + uint32_t major_version = 0; + uint32_t minor_version = 9; + uuid_t uuid; + + uuid_generate(uuid); + + len = write_smbios_tables(entry, table, phys_table_start, + smp_cpus, (ram_size >> 20), + uuid, QEMU_VERSION, + major_version, minor_version); + + if (len > SMBIOS_MAXIMUM_SIZE) { + fprintf(stderr, "SMBIOS: Could not write SMBIOS tables\n"); + return -1; + } + + return len; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 25082b761acb -r 37bf559ffcf7 smbios_types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smbios_types.h Fri Dec 07 14:22:02 2007 -0600 @@ -0,0 +1,182 @@ +/* + * 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 <[EMAIL PROTECTED]> + * + * 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 */ diff -r 25082b761acb -r 37bf559ffcf7 sysemu.h --- a/sysemu.h Wed Dec 05 03:23:38 2007 +0000 +++ b/sysemu.h Fri Dec 07 14:22:02 2007 -0600 @@ -116,6 +116,10 @@ extern unsigned int nb_prom_envs; #define BIOS_SIZE (4 * 1024 * 1024) #endif +#define SMBIOS_MAXIMUM_SIZE (32 << 10) +int load_smbios_tables(uint8_t *entry, uint8_t *table, + uint32_t phys_table_start); + typedef enum { IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD } BlockInterfaceType;