ia64/xen-unstable

changeset 11115:0b176f84c3bf

Add code to generate SMBIOS tables to hvmloader.
Signed-off-by: Andrew D. Ball <aball@us.ibm.com>
author kfraser@localhost.localdomain
date Mon Aug 14 17:37:07 2006 +0100 (2006-08-14)
parents 5a454f6e320f
children 7ba73e24c5a5
files tools/firmware/hvmloader/Makefile tools/firmware/hvmloader/hvmloader.c tools/firmware/hvmloader/smbios.c tools/firmware/hvmloader/smbios.h tools/firmware/hvmloader/smbios_types.h
line diff
     1.1 --- a/tools/firmware/hvmloader/Makefile	Mon Aug 14 17:29:11 2006 +0100
     1.2 +++ b/tools/firmware/hvmloader/Makefile	Mon Aug 14 17:37:07 2006 +0100
     1.3 @@ -31,8 +31,6 @@ LOADADDR = 0x100000
     1.4  DEFINES  =-DDEBUG
     1.5  XENINC   =-I$(XEN_ROOT)/tools/libxc
     1.6  
     1.7 -OBJECTS	 = hvmloader.o acpi_madt.o 
     1.8 -
     1.9  # Disable PIE/SSP if GCC supports them. They can break us.
    1.10  CFLAGS  += $(call test-gcc-flag,$(CC),-nopie)
    1.11  CFLAGS  += $(call test-gcc-flag,$(CC),-fno-stack-protector)
    1.12 @@ -42,7 +40,7 @@ OBJCOPY  = objcopy
    1.13  CFLAGS  += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float
    1.14  LDFLAGS  = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR)
    1.15  
    1.16 -SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c
    1.17 +SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c smbios.c
    1.18  OBJS = $(patsubst %.c,%.o,$(SRCS))
    1.19  
    1.20  .PHONY: all
    1.21 @@ -64,5 +62,5 @@ roms.h:	../rombios/BIOS-bochs-latest ../
    1.22  .PHONY: clean
    1.23  clean:
    1.24  	rm -f roms.h acpi.h
    1.25 -	rm -f hvmloader hvmloader.tmp hvmloader.o $(OBJECTS)
    1.26 +	rm -f hvmloader hvmloader.tmp hvmloader.o $(OBJS)
    1.27  
     2.1 --- a/tools/firmware/hvmloader/hvmloader.c	Mon Aug 14 17:29:11 2006 +0100
     2.2 +++ b/tools/firmware/hvmloader/hvmloader.c	Mon Aug 14 17:37:07 2006 +0100
     2.3 @@ -25,6 +25,7 @@
     2.4  #include "../acpi/acpi2_0.h"  /* for ACPI_PHYSICAL_ADDRESS */
     2.5  #include "hypercall.h"
     2.6  #include "util.h"
     2.7 +#include "smbios.h"
     2.8  #include <xen/version.h>
     2.9  #include <xen/hvm/params.h>
    2.10  
    2.11 @@ -200,6 +201,9 @@ main(void)
    2.12  		}
    2.13  	}
    2.14  
    2.15 +	puts("Writing SMBIOS tables ...\n");
    2.16 +	hvm_write_smbios_tables();
    2.17 +
    2.18  	if (check_amd()) {
    2.19  		/* AMD implies this is SVM */
    2.20                  puts("SVM go ...\n");
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/firmware/hvmloader/smbios.c	Mon Aug 14 17:37:07 2006 +0100
     3.3 @@ -0,0 +1,606 @@
     3.4 +/*
     3.5 + * smbios.c - Generate SMBIOS tables for Xen HVM domU's.
     3.6 + *
     3.7 + * This program is free software; you can redistribute it and/or modify
     3.8 + * it under the terms of the GNU General Public License as published by
     3.9 + * the Free Software Foundation; either version 2 of the License, or
    3.10 + * (at your option) any later version.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU General Public License
    3.18 + * along with this program; if not, write to the Free Software
    3.19 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    3.20 + *
    3.21 + * Copyright (C) IBM Corporation, 2006
    3.22 + *
    3.23 + * Authors: Andrew D. Ball <aball@us.ibm.com>
    3.24 + */
    3.25 +
    3.26 +#include <stdint.h>
    3.27 +#include <xen/version.h>
    3.28 +#include <xen/hvm/e820.h>
    3.29 +#include "smbios.h"
    3.30 +#include "smbios_types.h"
    3.31 +#include "util.h"
    3.32 +#include "hypercall.h"
    3.33 +
    3.34 +/* write SMBIOS tables starting at 'start', without writing more
    3.35 +   than 'max_size' bytes.
    3.36 +
    3.37 +   Return the number of bytes written
    3.38 +*/
    3.39 +static size_t
    3.40 +write_smbios_tables(void *start, size_t max_size,
    3.41 +		    uint32_t vcpus, uint64_t memsize,
    3.42 +		    uint8_t uuid[16], char *xen_version,
    3.43 +		    uint32_t xen_major_version, uint32_t xen_minor_version);
    3.44 +
    3.45 +static void
    3.46 +get_cpu_manufacturer(char *buf, int len);
    3.47 +static size_t
    3.48 +smbios_table_size(uint32_t vcpus, const char *xen_version,
    3.49 +		  const char *processor_manufacturer);
    3.50 +static void *
    3.51 +smbios_entry_point_init(void *start,
    3.52 +			uint16_t max_structure_size,
    3.53 +			uint16_t structure_table_length,
    3.54 +			uint32_t structure_table_address,
    3.55 +			uint16_t number_of_structures);
    3.56 +static void *
    3.57 +smbios_type_0_init(void *start, const char *xen_version,
    3.58 +		   uint32_t xen_major_version, uint32_t xen_minor_version);
    3.59 +static void *
    3.60 +smbios_type_1_init(void *start, const char *xen_version, 
    3.61 +		   uint8_t uuid[16]);
    3.62 +static void *
    3.63 +smbios_type_3_init(void *start);
    3.64 +static void *
    3.65 +smbios_type_4_init(void *start, unsigned int cpu_number,
    3.66 +		   char *cpu_manufacturer);
    3.67 +static void *
    3.68 +smbios_type_16_init(void *start, uint32_t memory_size_mb);
    3.69 +static void *
    3.70 +smbios_type_17_init(void *start, uint32_t memory_size_mb);
    3.71 +static void *
    3.72 +smbios_type_19_init(void *start, uint32_t memory_size_mb);
    3.73 +static void *
    3.74 +smbios_type_20_init(void *start, uint32_t memory_size_mb);
    3.75 +static void *
    3.76 +smbios_type_32_init(void *start);
    3.77 +void *
    3.78 +smbios_type_127_init(void *start);
    3.79 +
    3.80 +static void
    3.81 +get_cpu_manufacturer(char *buf, int len)
    3.82 +{
    3.83 +	char id[12];
    3.84 +	uint32_t eax = 0;
    3.85 +
    3.86 +	cpuid(0, &eax, (uint32_t *)&id[0], (uint32_t *)&id[8], (uint32_t *)&id[4]);
    3.87 +
    3.88 +	if (memcmp(id, "GenuineIntel", 12) == 0)
    3.89 +		strncpy(buf, "Intel", len);
    3.90 +	else if (memcmp(id, "AuthenticAMD", 12) == 0)
    3.91 +		strncpy(buf, "AMD", len);
    3.92 +	else
    3.93 +		strncpy(buf, "unknown", len);
    3.94 +}
    3.95 +
    3.96 +
    3.97 +/* Calculate the size of the SMBIOS structure table.
    3.98 +*/
    3.99 +static size_t
   3.100 +smbios_table_size(uint32_t vcpus, const char *xen_version,
   3.101 +		  const char *processor_manufacturer)
   3.102 +{
   3.103 +	size_t size;
   3.104 +
   3.105 +	/* first compute size without strings or terminating 0 bytes */
   3.106 +	size =  sizeof(struct smbios_type_0) + sizeof(struct smbios_type_1) +
   3.107 +		sizeof(struct smbios_type_3) + sizeof(struct smbios_type_4)*vcpus +
   3.108 +		sizeof(struct smbios_type_16) + sizeof(struct smbios_type_17) +
   3.109 +		sizeof(struct smbios_type_19) + sizeof(struct smbios_type_20) +
   3.110 +		sizeof(struct smbios_type_32) + sizeof(struct smbios_type_127);
   3.111 +
   3.112 +	/* 5 structures with no strings, 2 null bytes each */
   3.113 +	size += 10;
   3.114 +
   3.115 +	/* Need to include 1 null byte per structure with strings (first
   3.116 +	   terminating null byte comes from the string terminator of the
   3.117 +	   last string). */
   3.118 +	size += 4 + vcpus;
   3.119 +
   3.120 +	/* type 0: "Xen", xen_version, and release_date */
   3.121 +	size += strlen("Xen") + strlen(xen_version) + 2;
   3.122 +	/* type 1: "Xen", xen_version, "HVM domU" */
   3.123 +	size += strlen("Xen") + strlen("HVM domU") + strlen(xen_version) + 3;
   3.124 +	/* type 3: "Xen" */
   3.125 +	size += strlen("Xen") + 1;
   3.126 +	/* type 4: socket designation ("CPU n"), processor_manufacturer */
   3.127 +	size += vcpus * (strlen("CPU n") + strlen(processor_manufacturer) + 2);
   3.128 +	/* Make room for two-digit CPU numbers if necessary -- doesn't handle
   3.129 +	   vcpus > 99 */
   3.130 +	if (vcpus > 9)
   3.131 +		size += vcpus - 9;
   3.132 +	/* type 17: device locator string ("DIMM 1") */
   3.133 +	size += strlen("DIMM 1") + 1;
   3.134 +
   3.135 +	return size;
   3.136 +}
   3.137 +
   3.138 +static size_t
   3.139 +write_smbios_tables(void *start, size_t max_size,
   3.140 +		    uint32_t vcpus, uint64_t memsize,
   3.141 +		    uint8_t uuid[16], char *xen_version,
   3.142 +		    uint32_t xen_major_version, uint32_t xen_minor_version)
   3.143 +{
   3.144 +	unsigned cpu_num;
   3.145 +	void *p = start;
   3.146 +	char cpu_manufacturer[15];
   3.147 +	size_t structure_table_length;
   3.148 +
   3.149 +	get_cpu_manufacturer(cpu_manufacturer, 15);
   3.150 +
   3.151 +
   3.152 +	structure_table_length = smbios_table_size(vcpus, xen_version,
   3.153 +						   cpu_manufacturer);
   3.154 +
   3.155 +	if (structure_table_length + sizeof(struct smbios_entry_point) > max_size)
   3.156 +		return 0;
   3.157 +
   3.158 +	p = smbios_entry_point_init(p, sizeof(struct smbios_type_4), 
   3.159 +				    structure_table_length,
   3.160 +				    (uint32_t)start + 
   3.161 +				    sizeof(struct smbios_entry_point),
   3.162 +				    9 + vcpus);
   3.163 +
   3.164 +	p = smbios_type_0_init(p, xen_version, xen_major_version,
   3.165 +			       xen_minor_version);
   3.166 +	p = smbios_type_1_init(p, xen_version, uuid);
   3.167 +	p = smbios_type_3_init(p);
   3.168 +	for (cpu_num = 1; cpu_num <= vcpus; ++cpu_num)
   3.169 +		p = smbios_type_4_init(p, cpu_num, cpu_manufacturer);
   3.170 +	p = smbios_type_16_init(p, memsize);
   3.171 +	p = smbios_type_17_init(p, memsize);
   3.172 +	p = smbios_type_19_init(p, memsize);
   3.173 +	p = smbios_type_20_init(p, memsize);
   3.174 +	p = smbios_type_32_init(p);
   3.175 +	p = smbios_type_127_init(p);
   3.176 +
   3.177 +	return (size_t)((char*)p - (char*)start);
   3.178 +}
   3.179 +
   3.180 +/* This tries to figure out how much pseudo-physical memory (in MB)
   3.181 +   is allocated to the current domU.
   3.182 +
   3.183 +   It iterates through the e820 table, adding up the 'usable' and
   3.184 +   'reserved' entries and rounding up to the nearest MB.
   3.185 +
   3.186 +   The e820map is not at e820 in hvmloader, so this uses the
   3.187 +   E820_MAP_* constants from e820.h to pick it up where libxenguest
   3.188 +   left it.
   3.189 + */
   3.190 +static uint64_t
   3.191 +get_memsize(void)
   3.192 +{
   3.193 +	struct e820entry *map = NULL;
   3.194 +	uint8_t num_entries = 0;
   3.195 +	uint64_t memsize = 0;
   3.196 +	uint8_t i;
   3.197 +
   3.198 +	map = (struct e820entry *) (E820_MAP_PAGE + E820_MAP_OFFSET);
   3.199 +	num_entries = *((uint8_t *) (E820_MAP_PAGE + E820_MAP_NR_OFFSET));
   3.200 +
   3.201 +	/* walk through e820map, ignoring any entries that aren't marked
   3.202 +	   as usable or reserved. */
   3.203 +
   3.204 +	for (i = 0; i < num_entries; i++) {
   3.205 +		if (map->type == E820_RAM || map->type == E820_RESERVED)
   3.206 +			memsize += map->size;
   3.207 +		map++;
   3.208 +	}
   3.209 +
   3.210 +	/* Round up to the nearest MB.  The user specifies domU
   3.211 +	   pseudo-physical memory in megabytes, so not doing this
   3.212 +	   could easily lead to reporting one less MB than the user
   3.213 +	   specified. */
   3.214 +	if (memsize & ((1<<20)-1))
   3.215 +		memsize = (memsize >> 20) + 1;
   3.216 +	else
   3.217 +		memsize = (memsize >> 20);
   3.218 +
   3.219 +	return memsize;
   3.220 +}
   3.221 +
   3.222 +void
   3.223 +hvm_write_smbios_tables(void)
   3.224 +{
   3.225 +	uint8_t uuid[16]; /* ** This will break if xen_domain_handle_t is
   3.226 +			     not uint8_t[16]. ** */
   3.227 +	uint16_t xen_major_version, xen_minor_version;
   3.228 +	uint32_t xen_version;
   3.229 +	char xen_extra_version[XEN_EXTRAVERSION_LEN];
   3.230 +	/* guess conservatively on buffer length for Xen version string */
   3.231 +	char xen_version_str[80];
   3.232 +	/* temporary variables used to build up Xen version string */
   3.233 +	char *p = NULL; /* points to next point of insertion */
   3.234 +	unsigned len = 0; /* length of string already composed */
   3.235 +	char *tmp = NULL; /* holds result of itoa() */
   3.236 +	unsigned tmp_len; /* length of next string to add */
   3.237 +
   3.238 +	hypercall_xen_version(XENVER_guest_handle, uuid);
   3.239 +
   3.240 +	/* xen_version major and minor */
   3.241 +	xen_version = hypercall_xen_version(XENVER_version, NULL);
   3.242 +	xen_major_version = (uint16_t) (xen_version >> 16);
   3.243 +	xen_minor_version = (uint16_t) xen_version;
   3.244 +
   3.245 +	hypercall_xen_version(XENVER_extraversion, xen_extra_version);
   3.246 +
   3.247 +	/* build up human-readable Xen version string */
   3.248 +	p = xen_version_str;
   3.249 +	len = 0;
   3.250 +
   3.251 +	itoa(tmp, xen_major_version);
   3.252 +	tmp_len = strlen(tmp);
   3.253 +	len += tmp_len;
   3.254 +	if (len >= sizeof(xen_version_str))
   3.255 +		goto error_out;
   3.256 +	strcpy(p, tmp);
   3.257 +	p += tmp_len;
   3.258 +
   3.259 +	len++;
   3.260 +	if (len >= sizeof(xen_version_str))
   3.261 +		goto error_out;
   3.262 +	*p = '.';
   3.263 +	p++;
   3.264 +
   3.265 +	itoa(tmp, xen_minor_version);
   3.266 +	tmp_len = strlen(tmp);
   3.267 +	len += tmp_len;
   3.268 +	if (len >= sizeof(xen_version_str))
   3.269 +		goto error_out;
   3.270 +	strcpy(p, tmp);
   3.271 +	p += tmp_len;
   3.272 +
   3.273 +	tmp_len = strlen(xen_extra_version);
   3.274 +	len += tmp_len;
   3.275 +	if (len >= sizeof(xen_version_str))
   3.276 +		goto error_out;
   3.277 +	strcpy(p, xen_extra_version);
   3.278 +	p += tmp_len;
   3.279 +
   3.280 +	xen_version_str[sizeof(xen_version_str)-1] = '\0';
   3.281 +
   3.282 +	write_smbios_tables((void *) SMBIOS_PHYSICAL_ADDRESS,
   3.283 +			    SMBIOS_SIZE_LIMIT, get_vcpu_nr(), get_memsize(),
   3.284 +			    uuid, xen_version_str,
   3.285 +			    xen_major_version, xen_minor_version);
   3.286 +	return;
   3.287 +
   3.288 + error_out:
   3.289 +	puts("Could not write SMBIOS tables, error in hvmloader.c:"
   3.290 +	     "hvm_write_smbios_tables()\n");
   3.291 +}
   3.292 +
   3.293 +
   3.294 +static void *
   3.295 +smbios_entry_point_init(void *start,
   3.296 +			uint16_t max_structure_size,
   3.297 +			uint16_t structure_table_length,
   3.298 +			uint32_t structure_table_address,
   3.299 +			uint16_t number_of_structures)
   3.300 +{
   3.301 +	uint8_t sum;
   3.302 +	int i;
   3.303 +	struct smbios_entry_point *ep = (struct smbios_entry_point *)start;
   3.304 +
   3.305 +	strncpy(ep->anchor_string, "_SM_", 4);
   3.306 +	ep->length = 0x1f;
   3.307 +	ep->smbios_major_version = 2;
   3.308 +	ep->smbios_minor_version = 4;
   3.309 +	ep->max_structure_size = max_structure_size;
   3.310 +	ep->entry_point_revision = 0;
   3.311 +	memset(ep->formatted_area, 0, 5);
   3.312 +	strncpy(ep->intermediate_anchor_string, "_DMI_", 5);
   3.313 +    
   3.314 +	ep->structure_table_length = structure_table_length;
   3.315 +	ep->structure_table_address = structure_table_address;
   3.316 +	ep->number_of_structures = number_of_structures;
   3.317 +	ep->smbios_bcd_revision = 0x24;
   3.318 +
   3.319 +	ep->checksum = 0;
   3.320 +	ep->intermediate_checksum = 0;
   3.321 +    
   3.322 +	sum = 0;
   3.323 +	for (i = 0; i < 0x10; ++i)
   3.324 +		sum += ((int8_t *)start)[i];
   3.325 +	ep->checksum = -sum;
   3.326 +
   3.327 +	sum = 0;
   3.328 +	for (i = 0x10; i < ep->length; ++i)
   3.329 +		sum += ((int8_t *)start)[i];
   3.330 +	ep->intermediate_checksum = -sum;
   3.331 +
   3.332 +	return (char *)start + sizeof(struct smbios_entry_point);
   3.333 +}
   3.334 +
   3.335 +/* Type 0 -- BIOS Information */
   3.336 +static void *
   3.337 +smbios_type_0_init(void *start, const char *xen_version,
   3.338 +		   uint32_t xen_major_version, uint32_t xen_minor_version)
   3.339 +{
   3.340 +	struct smbios_type_0 *p = (struct smbios_type_0 *)start;
   3.341 +    
   3.342 +	p->header.type = 0;
   3.343 +	p->header.length = sizeof(struct smbios_type_0);
   3.344 +	p->header.handle = 0;
   3.345 +    
   3.346 +	p->vendor_str = 1;
   3.347 +	p->version_str = 2;
   3.348 +	p->starting_address_segment = 0xe800;
   3.349 +	p->release_date_str = 0;
   3.350 +	p->rom_size = 0;
   3.351 +    
   3.352 +	memset(p->characteristics, 0, 8);
   3.353 +	p->characteristics[7] = 0x08; /* BIOS characteristics not supported */
   3.354 +	p->characteristics_extension_bytes[0] = 0;
   3.355 +	p->characteristics_extension_bytes[1] = 0;
   3.356 +    
   3.357 +	p->major_release = (uint8_t) xen_major_version;
   3.358 +	p->minor_release = (uint8_t) xen_minor_version;
   3.359 +	p->embedded_controller_major = 0xff;
   3.360 +	p->embedded_controller_minor = 0xff;
   3.361 +
   3.362 +	start += sizeof(struct smbios_type_0);
   3.363 +	strcpy((char *)start, "Xen");
   3.364 +	start += strlen("Xen") + 1;
   3.365 +	strcpy((char *)start, xen_version);
   3.366 +	start += strlen(xen_version) + 1;
   3.367 +
   3.368 +	*((uint8_t *)start) = 0;
   3.369 +	return start + 1;
   3.370 +}
   3.371 +
   3.372 +/* Type 1 -- System Information */
   3.373 +static void *
   3.374 +smbios_type_1_init(void *start, const char *xen_version, 
   3.375 +		   uint8_t uuid[16])
   3.376 +{
   3.377 +	struct smbios_type_1 *p = (struct smbios_type_1 *)start;
   3.378 +	p->header.type = 1;
   3.379 +	p->header.length = sizeof(struct smbios_type_1);
   3.380 +	p->header.handle = 0x100;
   3.381 +
   3.382 +	p->manufacturer_str = 1;
   3.383 +	p->product_name_str = 2;
   3.384 +	p->version_str = 3;
   3.385 +	p->serial_number_str = 0;
   3.386 +    
   3.387 +	memcpy(p->uuid, uuid, 16);
   3.388 +
   3.389 +	p->wake_up_type = 0x06; /* power switch */
   3.390 +	p->sku_str = 0;
   3.391 +	p->family_str = 0;
   3.392 +
   3.393 +	start += sizeof(struct smbios_type_1);
   3.394 +    
   3.395 +	strcpy((char *)start, "Xen");
   3.396 +	start += strlen("Xen") + 1;
   3.397 +	strcpy((char *)start, "HVM domU");
   3.398 +	start += strlen("HVM domU") + 1;
   3.399 +	strcpy((char *)start, xen_version);
   3.400 +	start += strlen(xen_version) + 1;
   3.401 +	*((uint8_t *)start) = 0;
   3.402 +    
   3.403 +	return start+1; 
   3.404 +}
   3.405 +
   3.406 +/* Type 3 -- System Enclosure */
   3.407 +static void *
   3.408 +smbios_type_3_init(void *start)
   3.409 +{
   3.410 +	struct smbios_type_3 *p = (struct smbios_type_3 *)start;
   3.411 +    
   3.412 +	p->header.type = 3;
   3.413 +	p->header.length = sizeof(struct smbios_type_3);
   3.414 +	p->header.handle = 0x300;
   3.415 +
   3.416 +	p->manufacturer_str = 1;
   3.417 +	p->type = 0x01; /* other */
   3.418 +	p->version_str = 0;
   3.419 +	p->serial_number_str = 0;
   3.420 +	p->asset_tag_str = 0;
   3.421 +	p->boot_up_state = 0x03; /* safe */
   3.422 +	p->power_supply_state = 0x03; /* safe */
   3.423 +	p->thermal_state = 0x03; /* safe */
   3.424 +	p->security_status = 0x02; /* unknown */
   3.425 +
   3.426 +	start += sizeof(struct smbios_type_3);
   3.427 +    
   3.428 +	strcpy((char *)start, "Xen");
   3.429 +	start += strlen("Xen") + 1;
   3.430 +	*((uint8_t *)start) = 0;
   3.431 +	return start+1;
   3.432 +}
   3.433 +
   3.434 +/* Type 4 -- Processor Information */
   3.435 +static void *
   3.436 +smbios_type_4_init(void *start, unsigned int cpu_number, char *cpu_manufacturer)
   3.437 +{
   3.438 +	char buf[80]; 
   3.439 +	struct smbios_type_4 *p = (struct smbios_type_4 *)start;
   3.440 +	uint32_t eax, ebx, ecx, edx;
   3.441 +
   3.442 +	p->header.type = 4;
   3.443 +	p->header.length = sizeof(struct smbios_type_4);
   3.444 +	p->header.handle = 0x400 + cpu_number;
   3.445 +
   3.446 +	p->socket_designation_str = 1;
   3.447 +	p->processor_type = 0x03; /* CPU */
   3.448 +	p->processor_family = 0x01; /* other */
   3.449 +	p->manufacturer_str = 2;
   3.450 +
   3.451 +	cpuid(1, &eax, &ebx, &ecx, &edx);
   3.452 +
   3.453 +	p->cpuid[0] = eax;
   3.454 +	p->cpuid[1] = edx;
   3.455 +
   3.456 +	p->version_str = 0;
   3.457 +	p->voltage = 0;
   3.458 +	p->external_clock = 0;
   3.459 +
   3.460 +	p->max_speed = 0; /* unknown */
   3.461 +	p->current_speed = 0; /* unknown */
   3.462 +
   3.463 +	p->status = 0x41; /* socket populated, CPU enabled */
   3.464 +	p->upgrade = 0x01; /* other */
   3.465 +
   3.466 +	start += sizeof(struct smbios_type_4);
   3.467 +
   3.468 +	strncpy(buf, "CPU ", sizeof(buf));
   3.469 +	if ((sizeof(buf) - strlen("CPU ")) >= 3)
   3.470 +		itoa(buf + strlen("CPU "), cpu_number);
   3.471 +
   3.472 +	strcpy((char *)start, buf);
   3.473 +	start += strlen(buf) + 1;
   3.474 +
   3.475 +	strcpy((char *)start, cpu_manufacturer);
   3.476 +	start += strlen(buf) + 1;
   3.477 +
   3.478 +	*((uint8_t *)start) = 0;
   3.479 +	return start+1;
   3.480 +}
   3.481 +
   3.482 +/* Type 16 -- Physical Memory Array */
   3.483 +static void *
   3.484 +smbios_type_16_init(void *start, uint32_t memsize)
   3.485 +{
   3.486 +	struct smbios_type_16 *p = (struct smbios_type_16*)start;
   3.487 +
   3.488 +	p->header.type = 16;
   3.489 +	p->header.handle = 0x1000;
   3.490 +	p->header.length = sizeof(struct smbios_type_16);
   3.491 +    
   3.492 +	p->location = 0x01; /* other */
   3.493 +	p->use = 0x03; /* system memory */
   3.494 +	p->error_correction = 0x01; /* other */
   3.495 +	p->maximum_capacity = memsize * 1024;
   3.496 +	p->memory_error_information_handle = 0xfffe; /* none provided */
   3.497 +	p->number_of_memory_devices = 1;
   3.498 +
   3.499 +	start += sizeof(struct smbios_type_16);
   3.500 +	*((uint16_t *)start) = 0;
   3.501 +	return start + 2;
   3.502 +}
   3.503 +
   3.504 +/* Type 17 -- Memory Device */
   3.505 +static void *
   3.506 +smbios_type_17_init(void *start, uint32_t memory_size_mb)
   3.507 +{
   3.508 +	struct smbios_type_17 *p = (struct smbios_type_17 *)start;
   3.509 +    
   3.510 +	p->header.type = 17;
   3.511 +	p->header.length = sizeof(struct smbios_type_17);
   3.512 +	p->header.handle = 0x1100;
   3.513 +
   3.514 +	p->physical_memory_array_handle = 0x1000;
   3.515 +	p->total_width = 64;
   3.516 +	p->data_width = 64;
   3.517 +	/* truncate memory_size_mb to 16 bits and clear most significant
   3.518 +	   bit [indicates size in MB] */
   3.519 +	p->size = (uint16_t) memory_size_mb & 0x7fff;
   3.520 +	p->form_factor = 0x09; /* DIMM */
   3.521 +	p->device_set = 0;
   3.522 +	p->device_locator_str = 1;
   3.523 +	p->bank_locator_str = 0;
   3.524 +	p->memory_type = 0x07; /* RAM */
   3.525 +	p->type_detail = 0;
   3.526 +
   3.527 +	start += sizeof(struct smbios_type_17);
   3.528 +	strcpy((char *)start, "DIMM 1");
   3.529 +	start += strlen("DIMM 1") + 1;
   3.530 +	*((uint8_t *)start) = 0;
   3.531 +
   3.532 +	return start+1;
   3.533 +}
   3.534 +
   3.535 +/* Type 19 -- Memory Array Mapped Address */
   3.536 +static void *
   3.537 +smbios_type_19_init(void *start, uint32_t memory_size_mb)
   3.538 +{
   3.539 +	struct smbios_type_19 *p = (struct smbios_type_19 *)start;
   3.540 +    
   3.541 +	p->header.type = 19;
   3.542 +	p->header.length = sizeof(struct smbios_type_19);
   3.543 +	p->header.handle = 0x1300;
   3.544 +
   3.545 +	p->starting_address = 0;
   3.546 +	p->ending_address = (memory_size_mb-1) * 1024;
   3.547 +	p->memory_array_handle = 0x1000;
   3.548 +	p->partition_width = 1;
   3.549 +
   3.550 +	start += sizeof(struct smbios_type_19);
   3.551 +	*((uint16_t *)start) = 0;
   3.552 +	return start + 2;
   3.553 +}
   3.554 +
   3.555 +/* Type 20 -- Memory Device Mapped Address */
   3.556 +static void *
   3.557 +smbios_type_20_init(void *start, uint32_t memory_size_mb)
   3.558 +{
   3.559 +	struct smbios_type_20 *p = (struct smbios_type_20 *)start;
   3.560 +
   3.561 +	p->header.type = 20;
   3.562 +	p->header.length = sizeof(struct smbios_type_20);
   3.563 +	p->header.handle = 0x1400;
   3.564 +
   3.565 +	p->starting_address = 0;
   3.566 +	p->ending_address = (memory_size_mb-1)*1024;
   3.567 +	p->memory_device_handle = 0x1100;
   3.568 +	p->memory_array_mapped_address_handle = 0x1300;
   3.569 +	p->partition_row_position = 1;
   3.570 +	p->interleave_position = 0;
   3.571 +	p->interleaved_data_depth = 0;
   3.572 +
   3.573 +	start += sizeof(struct smbios_type_20);
   3.574 +
   3.575 +	*((uint16_t *)start) = 0;
   3.576 +	return start+2;
   3.577 +}
   3.578 +
   3.579 +/* Type 32 -- System Boot Information */
   3.580 +static void *
   3.581 +smbios_type_32_init(void *start)
   3.582 +{
   3.583 +	struct smbios_type_32 *p = (struct smbios_type_32 *)start;
   3.584 +
   3.585 +	p->header.type = 32;
   3.586 +	p->header.length = sizeof(struct smbios_type_32);
   3.587 +	p->header.handle = 0x2000;
   3.588 +	memset(p->reserved, 0, 6);
   3.589 +	p->boot_status = 0; /* no errors detected */
   3.590 +    
   3.591 +	start += sizeof(struct smbios_type_32);
   3.592 +	*((uint16_t *)start) = 0;
   3.593 +	return start+2;
   3.594 +}
   3.595 +
   3.596 +/* Type 127 -- End of Table */
   3.597 +void *
   3.598 +smbios_type_127_init(void *start)
   3.599 +{
   3.600 +	struct smbios_type_127 *p = (struct smbios_type_127 *)start;
   3.601 +
   3.602 +	p->header.type = 127;
   3.603 +	p->header.length = sizeof(struct smbios_type_127);
   3.604 +	p->header.handle = 0x7f00;
   3.605 +
   3.606 +	start += sizeof(struct smbios_type_127);
   3.607 +	*((uint16_t *)start) = 0;
   3.608 +	return start + 2;
   3.609 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/firmware/hvmloader/smbios.h	Mon Aug 14 17:37:07 2006 +0100
     4.3 @@ -0,0 +1,38 @@
     4.4 +/*
     4.5 + * smbios.h - interface for Xen HVM SMBIOS generation
     4.6 + *
     4.7 + * This program is free software; you can redistribute it and/or modify
     4.8 + * it under the terms of the GNU General Public License as published by
     4.9 + * the Free Software Foundation; either version 2 of the License, or
    4.10 + * (at your option) any later version.
    4.11 + *
    4.12 + * This program is distributed in the hope that it will be useful,
    4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.15 + * GNU General Public License for more details.
    4.16 + *
    4.17 + * You should have received a copy of the GNU General Public License
    4.18 + * along with this program; if not, write to the Free Software
    4.19 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    4.20 + *
    4.21 + * Copyright (C) IBM Corporation, 2006
    4.22 + *
    4.23 + * Authors: Andrew D. Ball <aball@us.ibm.com>
    4.24 + */
    4.25 +
    4.26 +#ifndef SMBIOS_H
    4.27 +#define SMBIOS_H
    4.28 +
    4.29 +#include <stdint.h>
    4.30 +#include <stdlib.h>
    4.31 +
    4.32 +/* These constants must agree with the ACPI e820 memory map as defined
    4.33 +   in tools/libxc/xc_hvm_build.c and the address the ROMBIOS pulls the
    4.34 +   SMBIOS entry point from in the smbios_init subroutine.
    4.35 + */
    4.36 +#define SMBIOS_PHYSICAL_ADDRESS 0x9f000
    4.37 +#define SMBIOS_SIZE_LIMIT 0x800
    4.38 +
    4.39 +void hvm_write_smbios_tables(void);
    4.40 +
    4.41 +#endif /* SMBIOS_H */
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/firmware/hvmloader/smbios_types.h	Mon Aug 14 17:37:07 2006 +0100
     5.3 @@ -0,0 +1,182 @@
     5.4 +/*
     5.5 + * smbios_types.h - data structure definitions for Xen HVM SMBIOS support
     5.6 + *
     5.7 + * This program is free software; you can redistribute it and/or modify
     5.8 + * it under the terms of the GNU General Public License as published by
     5.9 + * the Free Software Foundation; either version 2 of the License, or
    5.10 + * (at your option) any later version.
    5.11 + *
    5.12 + * This program is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 + * GNU General Public License for more details.
    5.16 + *
    5.17 + * You should have received a copy of the GNU General Public License
    5.18 + * along with this program; if not, write to the Free Software
    5.19 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    5.20 + *
    5.21 + * Copyright (C) IBM Corporation, 2006
    5.22 + *
    5.23 + * Authors: Andrew D. Ball <aball@us.ibm.com>
    5.24 + *
    5.25 + * See the SMBIOS 2.4 spec for more detail:
    5.26 + *   http://www.dmtf.org/standards/smbios/
    5.27 + */
    5.28 +
    5.29 +#ifndef SMBIOS_TYPES_H
    5.30 +#define SMBIOS_TYPES_H
    5.31 +
    5.32 +#include <stdint.h>
    5.33 +
    5.34 +/* SMBIOS entry point -- must be written to a 16-bit aligned address
    5.35 +   between 0xf0000 and 0xfffff. 
    5.36 + */
    5.37 +struct smbios_entry_point {
    5.38 +	char anchor_string[4];
    5.39 +	uint8_t checksum;
    5.40 +	uint8_t length;
    5.41 +	uint8_t smbios_major_version;
    5.42 +	uint8_t smbios_minor_version;
    5.43 +	uint16_t max_structure_size;
    5.44 +	uint8_t entry_point_revision;
    5.45 +	uint8_t formatted_area[5];
    5.46 +	char intermediate_anchor_string[5];
    5.47 +	uint8_t intermediate_checksum;
    5.48 +	uint16_t structure_table_length;
    5.49 +	uint32_t structure_table_address;
    5.50 +	uint16_t number_of_structures;
    5.51 +	uint8_t smbios_bcd_revision;
    5.52 +} __attribute__ ((packed));
    5.53 +
    5.54 +/* This goes at the beginning of every SMBIOS structure. */
    5.55 +struct smbios_structure_header {
    5.56 +	uint8_t type;
    5.57 +	uint8_t length;
    5.58 +	uint16_t handle;
    5.59 +} __attribute__ ((packed));
    5.60 +
    5.61 +/* SMBIOS type 0 - BIOS Information */
    5.62 +struct smbios_type_0 {
    5.63 +	struct smbios_structure_header header;
    5.64 +	uint8_t vendor_str;
    5.65 +	uint8_t version_str;
    5.66 +	uint16_t starting_address_segment;
    5.67 +	uint8_t release_date_str;
    5.68 +	uint8_t rom_size; 
    5.69 +	uint8_t characteristics[8];
    5.70 +	uint8_t characteristics_extension_bytes[2];
    5.71 +	uint8_t major_release;
    5.72 +	uint8_t minor_release;
    5.73 +	uint8_t embedded_controller_major;
    5.74 +	uint8_t embedded_controller_minor;
    5.75 +} __attribute__ ((packed));
    5.76 +
    5.77 +/* SMBIOS type 1 - System Information */
    5.78 +struct smbios_type_1 {
    5.79 +	struct smbios_structure_header header;
    5.80 +	uint8_t manufacturer_str;
    5.81 +	uint8_t product_name_str;
    5.82 +	uint8_t version_str;
    5.83 +	uint8_t serial_number_str;
    5.84 +	uint8_t uuid[16];
    5.85 +	uint8_t wake_up_type;
    5.86 +	uint8_t sku_str;
    5.87 +	uint8_t family_str;
    5.88 +} __attribute__ ((packed));
    5.89 +
    5.90 +/* SMBIOS type 3 - System Enclosure */
    5.91 +struct smbios_type_3 {
    5.92 +	struct smbios_structure_header header;
    5.93 +	uint8_t manufacturer_str;
    5.94 +	uint8_t type;
    5.95 +	uint8_t version_str;
    5.96 +	uint8_t serial_number_str;
    5.97 +	uint8_t asset_tag_str;
    5.98 +	uint8_t boot_up_state;
    5.99 +	uint8_t power_supply_state;
   5.100 +	uint8_t thermal_state;
   5.101 +	uint8_t security_status;
   5.102 +} __attribute__ ((packed));
   5.103 +
   5.104 +/* SMBIOS type 4 - Processor Information */
   5.105 +struct smbios_type_4 {
   5.106 +	struct smbios_structure_header header;
   5.107 +	uint8_t socket_designation_str;
   5.108 +	uint8_t processor_type;
   5.109 +	uint8_t processor_family;
   5.110 +	uint8_t manufacturer_str;
   5.111 +	uint32_t cpuid[2];
   5.112 +	uint8_t version_str;
   5.113 +	uint8_t voltage;
   5.114 +	uint16_t external_clock;
   5.115 +	uint16_t max_speed;
   5.116 +	uint16_t current_speed;
   5.117 +	uint8_t status;
   5.118 +	uint8_t upgrade;
   5.119 +} __attribute__ ((packed));
   5.120 +
   5.121 +/* SMBIOS type 16 - Physical Memory Array
   5.122 + *   Associated with one type 17 (Memory Device).
   5.123 + */
   5.124 +struct smbios_type_16 {
   5.125 +	struct smbios_structure_header header;
   5.126 +	uint8_t location;
   5.127 +	uint8_t use;
   5.128 +	uint8_t error_correction;
   5.129 +	uint32_t maximum_capacity;
   5.130 +	uint16_t memory_error_information_handle;
   5.131 +	uint16_t number_of_memory_devices;
   5.132 +} __attribute__ ((packed));
   5.133 +
   5.134 +/* SMBIOS type 17 - Memory Device 
   5.135 + *   Associated with one type 19
   5.136 + */
   5.137 +struct smbios_type_17 {
   5.138 +	struct smbios_structure_header header;
   5.139 +	uint16_t physical_memory_array_handle;
   5.140 +	uint16_t memory_error_information_handle;
   5.141 +	uint16_t total_width;
   5.142 +	uint16_t data_width;
   5.143 +	uint16_t size;
   5.144 +	uint8_t form_factor;
   5.145 +	uint8_t device_set;
   5.146 +	uint8_t device_locator_str;
   5.147 +	uint8_t bank_locator_str;
   5.148 +	uint8_t memory_type;
   5.149 +	uint16_t type_detail;
   5.150 +} __attribute__ ((packed));
   5.151 +
   5.152 +/* SMBIOS type 19 - Memory Array Mapped Address */
   5.153 +struct smbios_type_19 {
   5.154 +	struct smbios_structure_header header;
   5.155 +	uint32_t starting_address;
   5.156 +	uint32_t ending_address;
   5.157 +	uint16_t memory_array_handle;
   5.158 +	uint8_t partition_width;
   5.159 +} __attribute__ ((packed));
   5.160 +
   5.161 +/* SMBIOS type 20 - Memory Device Mapped Address */
   5.162 +struct smbios_type_20 {
   5.163 +	struct smbios_structure_header header;
   5.164 +	uint32_t starting_address;
   5.165 +	uint32_t ending_address;
   5.166 +	uint16_t memory_device_handle;
   5.167 +	uint16_t memory_array_mapped_address_handle;
   5.168 +	uint8_t partition_row_position;
   5.169 +	uint8_t interleave_position;
   5.170 +	uint8_t interleaved_data_depth;
   5.171 +} __attribute__ ((packed));
   5.172 +
   5.173 +/* SMBIOS type 32 - System Boot Information */
   5.174 +struct smbios_type_32 {
   5.175 +	struct smbios_structure_header header;
   5.176 +	uint8_t reserved[6];
   5.177 +	uint8_t boot_status;
   5.178 +} __attribute__ ((packed));
   5.179 +
   5.180 +/* SMBIOS type 127 -- End-of-table */
   5.181 +struct smbios_type_127 {
   5.182 +	struct smbios_structure_header header;
   5.183 +} __attribute__ ((packed));
   5.184 +
   5.185 +#endif /* SMBIOS_TYPES_H */