ia64/xen-unstable
changeset 11715: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>
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 - 2.113 - structure_table_length = smbios_table_size(vcpus, xen_version, 2.114 - cpu_manufacturer); 2.115 + p = (char *)start + sizeof(struct smbios_entry_point); 2.116 2.117 - if (structure_table_length + sizeof(struct smbios_entry_point) > max_size) 2.118 - return 0; 2.119 - 2.120 - p = smbios_entry_point_init(p, sizeof(struct smbios_type_4), 2.121 - structure_table_length, 2.122 - (uint32_t)start + 2.123 - sizeof(struct smbios_entry_point), 2.124 - 9 + vcpus); 2.125 +#define do_struct(fn) do { \ 2.126 + q = (fn); \ 2.127 + nr_structs++; \ 2.128 + if ((q - p) > max_struct_size) \ 2.129 + max_struct_size = q - p; \ 2.130 + p = q; \ 2.131 +} while (0) 2.132 2.133 - p = smbios_type_0_init(p, xen_version, xen_major_version, 2.134 - xen_minor_version); 2.135 - p = smbios_type_1_init(p, xen_version, uuid); 2.136 - p = smbios_type_3_init(p); 2.137 - for (cpu_num = 1; cpu_num <= vcpus; ++cpu_num) 2.138 - p = smbios_type_4_init(p, cpu_num, cpu_manufacturer); 2.139 - p = smbios_type_16_init(p, memsize); 2.140 - p = smbios_type_17_init(p, memsize); 2.141 - p = smbios_type_19_init(p, memsize); 2.142 - p = smbios_type_20_init(p, memsize); 2.143 - p = smbios_type_32_init(p); 2.144 - p = smbios_type_127_init(p); 2.145 + do_struct(smbios_type_0_init(p, xen_version, xen_major_version, 2.146 + xen_minor_version)); 2.147 + do_struct(smbios_type_1_init(p, xen_version, uuid)); 2.148 + do_struct(smbios_type_3_init(p)); 2.149 + for (cpu_num = 1; cpu_num <= vcpus; cpu_num++) 2.150 + do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer)); 2.151 + do_struct(smbios_type_16_init(p, memsize)); 2.152 + do_struct(smbios_type_17_init(p, memsize)); 2.153 + do_struct(smbios_type_19_init(p, memsize)); 2.154 + do_struct(smbios_type_20_init(p, memsize)); 2.155 + do_struct(smbios_type_32_init(p)); 2.156 + do_struct(smbios_type_127_init(p)); 2.157 2.158 - return (size_t)((char*)p - (char*)start); 2.159 +#undef do_struct 2.160 + 2.161 + smbios_entry_point_init( 2.162 + start, max_struct_size, 2.163 + (p - (char *)start) - sizeof(struct smbios_entry_point), 2.164 + SMBIOS_PHYSICAL_ADDRESS + sizeof(struct smbios_entry_point), 2.165 + nr_structs); 2.166 + 2.167 + return (size_t)((char *)p - (char *)start); 2.168 } 2.169 2.170 /* This tries to figure out how much pseudo-physical memory (in MB) 2.171 @@ -278,10 +232,16 @@ hvm_write_smbios_tables(void) 2.172 2.173 xen_version_str[sizeof(xen_version_str)-1] = '\0'; 2.174 2.175 - write_smbios_tables((void *) SMBIOS_PHYSICAL_ADDRESS, 2.176 - SMBIOS_SIZE_LIMIT, get_vcpu_nr(), get_memsize(), 2.177 - uuid, xen_version_str, 2.178 - xen_major_version, xen_minor_version); 2.179 + /* NB. 0xC0000 is a safe large memory area for scratch. */ 2.180 + len = write_smbios_tables((void *)0xC0000, 2.181 + get_vcpu_nr(), get_memsize(), 2.182 + uuid, xen_version_str, 2.183 + xen_major_version, xen_minor_version); 2.184 + if (len > SMBIOS_SIZE_LIMIT) 2.185 + goto error_out; 2.186 + /* Okay, not too large: copy out of scratch to final location. */ 2.187 + memcpy((void *)SMBIOS_PHYSICAL_ADDRESS, (void *)0xC0000, len); 2.188 + 2.189 return; 2.190 2.191 error_out: 2.192 @@ -290,7 +250,7 @@ hvm_write_smbios_tables(void) 2.193 } 2.194 2.195 2.196 -static void * 2.197 +static void 2.198 smbios_entry_point_init(void *start, 2.199 uint16_t max_structure_size, 2.200 uint16_t structure_table_length, 2.201 @@ -327,8 +287,6 @@ smbios_entry_point_init(void *start, 2.202 for (i = 0x10; i < ep->length; ++i) 2.203 sum += ((int8_t *)start)[i]; 2.204 ep->intermediate_checksum = -sum; 2.205 - 2.206 - return (char *)start + sizeof(struct smbios_entry_point); 2.207 } 2.208 2.209 /* Type 0 -- BIOS Information */ 2.210 @@ -597,7 +555,7 @@ smbios_type_32_init(void *start) 2.211 } 2.212 2.213 /* Type 127 -- End of Table */ 2.214 -void * 2.215 +static void * 2.216 smbios_type_127_init(void *start) 2.217 { 2.218 struct smbios_type_127 *p = (struct smbios_type_127 *)start;