xen-unstable.hg

changeset 11686:f426f6e646eb

[HVMLOADER] Clean up SMBIOS table-length computations.
It's easier and less prone to error not to attempt the
length computation up front.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Oct 02 18:04:56 2006 +0100 (2006-10-02)
parents 0d796dced5f7
children 51fa58f0583b
files tools/firmware/hvmloader/hvmloader.c tools/firmware/hvmloader/smbios.c
line diff
     1.1 --- a/tools/firmware/hvmloader/hvmloader.c	Mon Oct 02 16:12:41 2006 +0100
     1.2 +++ b/tools/firmware/hvmloader/hvmloader.c	Mon Oct 02 18:04:56 2006 +0100
     1.3 @@ -170,6 +170,9 @@ main(void)
     1.4  
     1.5  	init_hypercalls();
     1.6  
     1.7 +	puts("Writing SMBIOS tables ...\n");
     1.8 +	hvm_write_smbios_tables();
     1.9 +
    1.10  	puts("Loading ROMBIOS ...\n");
    1.11  	memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
    1.12  
    1.13 @@ -201,9 +204,6 @@ main(void)
    1.14  		}
    1.15  	}
    1.16  
    1.17 -	puts("Writing SMBIOS tables ...\n");
    1.18 -	hvm_write_smbios_tables();
    1.19 -
    1.20  	if (check_amd()) {
    1.21  		/* AMD implies this is SVM */
    1.22                  puts("SVM go ...\n");
     2.1 --- a/tools/firmware/hvmloader/smbios.c	Mon Oct 02 16:12:41 2006 +0100
     2.2 +++ b/tools/firmware/hvmloader/smbios.c	Mon Oct 02 18:04:56 2006 +0100
     2.3 @@ -28,23 +28,15 @@
     2.4  #include "util.h"
     2.5  #include "hypercall.h"
     2.6  
     2.7 -/* write SMBIOS tables starting at 'start', without writing more
     2.8 -   than 'max_size' bytes.
     2.9 -
    2.10 -   Return the number of bytes written
    2.11 -*/
    2.12  static size_t
    2.13 -write_smbios_tables(void *start, size_t max_size,
    2.14 +write_smbios_tables(void *start,
    2.15  		    uint32_t vcpus, uint64_t memsize,
    2.16  		    uint8_t uuid[16], char *xen_version,
    2.17  		    uint32_t xen_major_version, uint32_t xen_minor_version);
    2.18  
    2.19  static void
    2.20  get_cpu_manufacturer(char *buf, int len);
    2.21 -static size_t
    2.22 -smbios_table_size(uint32_t vcpus, const char *xen_version,
    2.23 -		  const char *processor_manufacturer);
    2.24 -static void *
    2.25 +static void
    2.26  smbios_entry_point_init(void *start,
    2.27  			uint16_t max_structure_size,
    2.28  			uint16_t structure_table_length,
    2.29 @@ -71,7 +63,7 @@ static void *
    2.30  smbios_type_20_init(void *start, uint32_t memory_size_mb);
    2.31  static void *
    2.32  smbios_type_32_init(void *start);
    2.33 -void *
    2.34 +static void *
    2.35  smbios_type_127_init(void *start);
    2.36  
    2.37  static void
    2.38 @@ -80,7 +72,8 @@ get_cpu_manufacturer(char *buf, int len)
    2.39  	char id[12];
    2.40  	uint32_t eax = 0;
    2.41  
    2.42 -	cpuid(0, &eax, (uint32_t *)&id[0], (uint32_t *)&id[8], (uint32_t *)&id[4]);
    2.43 +	cpuid(0, &eax, (uint32_t *)&id[0], (uint32_t *)&id[8],
    2.44 +	      (uint32_t *)&id[4]);
    2.45  
    2.46  	if (memcmp(id, "GenuineIntel", 12) == 0)
    2.47  		strncpy(buf, "Intel", len);
    2.48 @@ -90,90 +83,51 @@ get_cpu_manufacturer(char *buf, int len)
    2.49  		strncpy(buf, "unknown", len);
    2.50  }
    2.51  
    2.52 -
    2.53 -/* Calculate the size of the SMBIOS structure table.
    2.54 -*/
    2.55  static size_t
    2.56 -smbios_table_size(uint32_t vcpus, const char *xen_version,
    2.57 -		  const char *processor_manufacturer)
    2.58 -{
    2.59 -	size_t size;
    2.60 -
    2.61 -	/* first compute size without strings or terminating 0 bytes */
    2.62 -	size =  sizeof(struct smbios_type_0) + sizeof(struct smbios_type_1) +
    2.63 -		sizeof(struct smbios_type_3) + sizeof(struct smbios_type_4)*vcpus +
    2.64 -		sizeof(struct smbios_type_16) + sizeof(struct smbios_type_17) +
    2.65 -		sizeof(struct smbios_type_19) + sizeof(struct smbios_type_20) +
    2.66 -		sizeof(struct smbios_type_32) + sizeof(struct smbios_type_127);
    2.67 -
    2.68 -	/* 5 structures with no strings, 2 null bytes each */
    2.69 -	size += 10;
    2.70 -
    2.71 -	/* Need to include 1 null byte per structure with strings (first
    2.72 -	   terminating null byte comes from the string terminator of the
    2.73 -	   last string). */
    2.74 -	size += 4 + vcpus;
    2.75 -
    2.76 -	/* type 0: "Xen", xen_version, and release_date */
    2.77 -	size += strlen("Xen") + strlen(xen_version) + 2;
    2.78 -	/* type 1: "Xen", xen_version, "HVM domU", UUID as string for 
    2.79 -                   serial number */
    2.80 -	size += strlen("Xen") + strlen("HVM domU") + strlen(xen_version) +
    2.81 -			36 + 4;
    2.82 -	/* type 3: "Xen" */
    2.83 -	size += strlen("Xen") + 1;
    2.84 -	/* type 4: socket designation ("CPU n"), processor_manufacturer */
    2.85 -	size += vcpus * (strlen("CPU n") + strlen(processor_manufacturer) + 2);
    2.86 -	/* Make room for two-digit CPU numbers if necessary -- doesn't handle
    2.87 -	   vcpus > 99 */
    2.88 -	if (vcpus > 9)
    2.89 -		size += vcpus - 9;
    2.90 -	/* type 17: device locator string ("DIMM 1") */
    2.91 -	size += strlen("DIMM 1") + 1;
    2.92 -
    2.93 -	return size;
    2.94 -}
    2.95 -
    2.96 -static size_t
    2.97 -write_smbios_tables(void *start, size_t max_size,
    2.98 +write_smbios_tables(void *start,
    2.99  		    uint32_t vcpus, uint64_t memsize,
   2.100  		    uint8_t uuid[16], char *xen_version,
   2.101  		    uint32_t xen_major_version, uint32_t xen_minor_version)
   2.102  {
   2.103 -	unsigned cpu_num;
   2.104 -	void *p = start;
   2.105 +	unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
   2.106 +	char *p, *q;
   2.107  	char cpu_manufacturer[15];
   2.108  	size_t structure_table_length;
   2.109  
   2.110  	get_cpu_manufacturer(cpu_manufacturer, 15);
   2.111  
   2.112 +	p = (char *)start + sizeof(struct smbios_entry_point);
   2.113  
   2.114 -	structure_table_length = smbios_table_size(vcpus, xen_version,
   2.115 -						   cpu_manufacturer);
   2.116 +#define do_struct(fn) do {			\
   2.117 +	q = (fn);				\
   2.118 +	nr_structs++;				\
   2.119 +	if ((q - p) > max_struct_size)		\
   2.120 +		max_struct_size = q - p;	\
   2.121 +	p = q;					\
   2.122 +} while (0)
   2.123  
   2.124 -	if (structure_table_length + sizeof(struct smbios_entry_point) > max_size)
   2.125 -		return 0;
   2.126 +	do_struct(smbios_type_0_init(p, xen_version, xen_major_version,
   2.127 +				     xen_minor_version));
   2.128 +	do_struct(smbios_type_1_init(p, xen_version, uuid));
   2.129 +	do_struct(smbios_type_3_init(p));
   2.130 +	for (cpu_num = 1; cpu_num <= vcpus; cpu_num++)
   2.131 +		do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer));
   2.132 +	do_struct(smbios_type_16_init(p, memsize));
   2.133 +	do_struct(smbios_type_17_init(p, memsize));
   2.134 +	do_struct(smbios_type_19_init(p, memsize));
   2.135 +	do_struct(smbios_type_20_init(p, memsize));
   2.136 +	do_struct(smbios_type_32_init(p));
   2.137 +	do_struct(smbios_type_127_init(p));
   2.138  
   2.139 -	p = smbios_entry_point_init(p, sizeof(struct smbios_type_4), 
   2.140 -				    structure_table_length,
   2.141 -				    (uint32_t)start + 
   2.142 -				    sizeof(struct smbios_entry_point),
   2.143 -				    9 + vcpus);
   2.144 +#undef do_struct
   2.145  
   2.146 -	p = smbios_type_0_init(p, xen_version, xen_major_version,
   2.147 -			       xen_minor_version);
   2.148 -	p = smbios_type_1_init(p, xen_version, uuid);
   2.149 -	p = smbios_type_3_init(p);
   2.150 -	for (cpu_num = 1; cpu_num <= vcpus; ++cpu_num)
   2.151 -		p = smbios_type_4_init(p, cpu_num, cpu_manufacturer);
   2.152 -	p = smbios_type_16_init(p, memsize);
   2.153 -	p = smbios_type_17_init(p, memsize);
   2.154 -	p = smbios_type_19_init(p, memsize);
   2.155 -	p = smbios_type_20_init(p, memsize);
   2.156 -	p = smbios_type_32_init(p);
   2.157 -	p = smbios_type_127_init(p);
   2.158 +	smbios_entry_point_init(
   2.159 +		start, max_struct_size,
   2.160 +		(p - (char *)start) - sizeof(struct smbios_entry_point),
   2.161 +		SMBIOS_PHYSICAL_ADDRESS + sizeof(struct smbios_entry_point),
   2.162 +		nr_structs);
   2.163  
   2.164 -	return (size_t)((char*)p - (char*)start);
   2.165 +	return (size_t)((char *)p - (char *)start);
   2.166  }
   2.167  
   2.168  /* This tries to figure out how much pseudo-physical memory (in MB)
   2.169 @@ -278,10 +232,16 @@ hvm_write_smbios_tables(void)
   2.170  
   2.171  	xen_version_str[sizeof(xen_version_str)-1] = '\0';
   2.172  
   2.173 -	write_smbios_tables((void *) SMBIOS_PHYSICAL_ADDRESS,
   2.174 -			    SMBIOS_SIZE_LIMIT, get_vcpu_nr(), get_memsize(),
   2.175 -			    uuid, xen_version_str,
   2.176 -			    xen_major_version, xen_minor_version);
   2.177 +	/* NB. 0xC0000 is a safe large memory area for scratch. */
   2.178 +	len = write_smbios_tables((void *)0xC0000,
   2.179 +				  get_vcpu_nr(), get_memsize(),
   2.180 +				  uuid, xen_version_str,
   2.181 +				  xen_major_version, xen_minor_version);
   2.182 +	if (len > SMBIOS_SIZE_LIMIT)
   2.183 +		goto error_out;
   2.184 +	/* Okay, not too large: copy out of scratch to final location. */
   2.185 +	memcpy((void *)SMBIOS_PHYSICAL_ADDRESS, (void *)0xC0000, len);
   2.186 +
   2.187  	return;
   2.188  
   2.189   error_out:
   2.190 @@ -290,7 +250,7 @@ hvm_write_smbios_tables(void)
   2.191  }
   2.192  
   2.193  
   2.194 -static void *
   2.195 +static void
   2.196  smbios_entry_point_init(void *start,
   2.197  			uint16_t max_structure_size,
   2.198  			uint16_t structure_table_length,
   2.199 @@ -327,8 +287,6 @@ smbios_entry_point_init(void *start,
   2.200  	for (i = 0x10; i < ep->length; ++i)
   2.201  		sum += ((int8_t *)start)[i];
   2.202  	ep->intermediate_checksum = -sum;
   2.203 -
   2.204 -	return (char *)start + sizeof(struct smbios_entry_point);
   2.205  }
   2.206  
   2.207  /* Type 0 -- BIOS Information */
   2.208 @@ -597,7 +555,7 @@ smbios_type_32_init(void *start)
   2.209  }
   2.210  
   2.211  /* Type 127 -- End of Table */
   2.212 -void *
   2.213 +static void *
   2.214  smbios_type_127_init(void *start)
   2.215  {
   2.216  	struct smbios_type_127 *p = (struct smbios_type_127 *)start;