blob: 40812e3b977cb1abe36c006841cebf5b919cf0fd [file] [log] [blame]
Kevin O'Connor0525d292008-07-04 06:18:30 -04001// smbios table generation (on emulators)
Kevin O'Connora4d35762008-03-08 15:43:03 -05002//
Kevin O'Connor0525d292008-07-04 06:18:30 -04003// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4// Copyright (C) 2006 Fabrice Bellard
Kevin O'Connora4d35762008-03-08 15:43:03 -05005//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05006// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connora4d35762008-03-08 15:43:03 -05007
Kevin O'Connorac8df8c2008-05-24 23:46:33 -04008#include "util.h" // dprintf
Kevin O'Connorc7812932008-06-08 23:08:12 -04009#include "memmap.h" // bios_table_cur_addr
Kevin O'Connor9521e262008-07-04 13:04:29 -040010#include "biosvar.h" // GET_EBDA
Kevin O'Connora4d35762008-03-08 15:43:03 -050011
Kevin O'Connora4d35762008-03-08 15:43:03 -050012
Kevin O'Connor0525d292008-07-04 06:18:30 -040013/****************************************************************
14 * UUID probe
15 ****************************************************************/
16
Kevin O'Connor20543002008-10-25 15:43:46 -040017#define QEMU_CFG_SIGNATURE 0x00
18#define QEMU_CFG_ID 0x01
19#define QEMU_CFG_UUID 0x02
20
21static void
22qemu_cfg_read(u8 *buf, u16 f, int len)
23{
24 outw(f, PORT_QEMU_CFG_CTL);
25 while (len--)
26 *(buf++) = inb(PORT_QEMU_CFG_DATA);
27}
28
29static int
30qemu_cfg_port_probe()
31{
32 u8 sig[4] = "QEMU";
33 u8 buf[4];
34 qemu_cfg_read(buf, QEMU_CFG_SIGNATURE, 4);
35 return *(u32*)buf == *(u32*)sig;
36}
37
Kevin O'Connor0525d292008-07-04 06:18:30 -040038static void
39uuid_probe(u8 *bios_uuid)
Kevin O'Connora4d35762008-03-08 15:43:03 -050040{
Kevin O'Connor31299842008-07-04 04:47:09 -040041 // Default to UUID not set
42 memset(bios_uuid, 0, 16);
43
Kevin O'Connor6cb8ba92008-08-17 11:03:24 -040044 if (! CONFIG_UUID_BACKDOOR)
Kevin O'Connor31299842008-07-04 04:47:09 -040045 return;
Kevin O'Connor1d247db2008-08-29 21:19:53 -040046 if (CONFIG_COREBOOT)
47 return;
Kevin O'Connor20543002008-10-25 15:43:46 -040048 if (! qemu_cfg_port_probe())
49 // Feature not available
Kevin O'Connor31299842008-07-04 04:47:09 -040050 return;
51
Kevin O'Connor20543002008-10-25 15:43:46 -040052 qemu_cfg_read(bios_uuid, QEMU_CFG_UUID, 16);
Kevin O'Connora4d35762008-03-08 15:43:03 -050053}
54
Kevin O'Connora4d35762008-03-08 15:43:03 -050055
Kevin O'Connor0525d292008-07-04 06:18:30 -040056/****************************************************************
57 * smbios tables
58 ****************************************************************/
Kevin O'Connora4d35762008-03-08 15:43:03 -050059
Kevin O'Connora4d35762008-03-08 15:43:03 -050060/* SMBIOS entry point -- must be written to a 16-bit aligned address
61 between 0xf0000 and 0xfffff.
62 */
63struct smbios_entry_point {
64 char anchor_string[4];
Kevin O'Connore51313d2008-03-12 21:19:34 -040065 u8 checksum;
66 u8 length;
67 u8 smbios_major_version;
68 u8 smbios_minor_version;
69 u16 max_structure_size;
70 u8 entry_point_revision;
71 u8 formatted_area[5];
Kevin O'Connora4d35762008-03-08 15:43:03 -050072 char intermediate_anchor_string[5];
Kevin O'Connore51313d2008-03-12 21:19:34 -040073 u8 intermediate_checksum;
74 u16 structure_table_length;
75 u32 structure_table_address;
76 u16 number_of_structures;
77 u8 smbios_bcd_revision;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -040078} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -050079
80/* This goes at the beginning of every SMBIOS structure. */
81struct smbios_structure_header {
Kevin O'Connore51313d2008-03-12 21:19:34 -040082 u8 type;
83 u8 length;
84 u16 handle;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -040085} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -050086
87/* SMBIOS type 0 - BIOS Information */
88struct smbios_type_0 {
89 struct smbios_structure_header header;
Kevin O'Connore51313d2008-03-12 21:19:34 -040090 u8 vendor_str;
91 u8 bios_version_str;
92 u16 bios_starting_address_segment;
93 u8 bios_release_date_str;
94 u8 bios_rom_size;
95 u8 bios_characteristics[8];
96 u8 bios_characteristics_extension_bytes[2];
97 u8 system_bios_major_release;
98 u8 system_bios_minor_release;
99 u8 embedded_controller_major_release;
100 u8 embedded_controller_minor_release;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -0400101} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500102
103/* SMBIOS type 1 - System Information */
104struct smbios_type_1 {
105 struct smbios_structure_header header;
Kevin O'Connore51313d2008-03-12 21:19:34 -0400106 u8 manufacturer_str;
107 u8 product_name_str;
108 u8 version_str;
109 u8 serial_number_str;
110 u8 uuid[16];
111 u8 wake_up_type;
112 u8 sku_number_str;
113 u8 family_str;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -0400114} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500115
116/* SMBIOS type 3 - System Enclosure (v2.3) */
117struct smbios_type_3 {
118 struct smbios_structure_header header;
Kevin O'Connore51313d2008-03-12 21:19:34 -0400119 u8 manufacturer_str;
120 u8 type;
121 u8 version_str;
122 u8 serial_number_str;
123 u8 asset_tag_number_str;
124 u8 boot_up_state;
125 u8 power_supply_state;
126 u8 thermal_state;
127 u8 security_status;
128 u32 oem_defined;
129 u8 height;
130 u8 number_of_power_cords;
131 u8 contained_element_count;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500132 // contained elements follow
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -0400133} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500134
135/* SMBIOS type 4 - Processor Information (v2.0) */
136struct smbios_type_4 {
137 struct smbios_structure_header header;
Kevin O'Connore51313d2008-03-12 21:19:34 -0400138 u8 socket_designation_str;
139 u8 processor_type;
140 u8 processor_family;
141 u8 processor_manufacturer_str;
142 u32 processor_id[2];
143 u8 processor_version_str;
144 u8 voltage;
145 u16 external_clock;
146 u16 max_speed;
147 u16 current_speed;
148 u8 status;
149 u8 processor_upgrade;
Kevin O'Connorf2ce1912008-10-25 15:23:53 -0400150 u16 l1_cache_handle;
151 u16 l2_cache_handle;
152 u16 l3_cache_handle;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -0400153} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500154
155/* SMBIOS type 16 - Physical Memory Array
156 * Associated with one type 17 (Memory Device).
157 */
158struct smbios_type_16 {
159 struct smbios_structure_header header;
Kevin O'Connore51313d2008-03-12 21:19:34 -0400160 u8 location;
161 u8 use;
162 u8 error_correction;
163 u32 maximum_capacity;
164 u16 memory_error_information_handle;
165 u16 number_of_memory_devices;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -0400166} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500167
168/* SMBIOS type 17 - Memory Device
169 * Associated with one type 19
170 */
171struct smbios_type_17 {
172 struct smbios_structure_header header;
Kevin O'Connore51313d2008-03-12 21:19:34 -0400173 u16 physical_memory_array_handle;
174 u16 memory_error_information_handle;
175 u16 total_width;
176 u16 data_width;
177 u16 size;
178 u8 form_factor;
179 u8 device_set;
180 u8 device_locator_str;
181 u8 bank_locator_str;
182 u8 memory_type;
183 u16 type_detail;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -0400184} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500185
186/* SMBIOS type 19 - Memory Array Mapped Address */
187struct smbios_type_19 {
188 struct smbios_structure_header header;
Kevin O'Connore51313d2008-03-12 21:19:34 -0400189 u32 starting_address;
190 u32 ending_address;
191 u16 memory_array_handle;
192 u8 partition_width;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -0400193} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500194
195/* SMBIOS type 20 - Memory Device Mapped Address */
196struct smbios_type_20 {
197 struct smbios_structure_header header;
Kevin O'Connore51313d2008-03-12 21:19:34 -0400198 u32 starting_address;
199 u32 ending_address;
200 u16 memory_device_handle;
201 u16 memory_array_mapped_address_handle;
202 u8 partition_row_position;
203 u8 interleave_position;
204 u8 interleaved_data_depth;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -0400205} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500206
207/* SMBIOS type 32 - System Boot Information */
208struct smbios_type_32 {
209 struct smbios_structure_header header;
Kevin O'Connore51313d2008-03-12 21:19:34 -0400210 u8 reserved[6];
211 u8 boot_status;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -0400212} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500213
214/* SMBIOS type 127 -- End-of-table */
215struct smbios_type_127 {
216 struct smbios_structure_header header;
Kevin O'Connor3a3fb4e2008-10-25 14:39:56 -0400217} PACKED;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500218
Kevin O'Connor0525d292008-07-04 06:18:30 -0400219
220/****************************************************************
221 * smbios init
222 ****************************************************************/
223
Kevin O'Connora4d35762008-03-08 15:43:03 -0500224static void
225smbios_entry_point_init(void *start,
Kevin O'Connore51313d2008-03-12 21:19:34 -0400226 u16 max_structure_size,
227 u16 structure_table_length,
228 u32 structure_table_address,
229 u16 number_of_structures)
Kevin O'Connora4d35762008-03-08 15:43:03 -0500230{
Kevin O'Connora4d35762008-03-08 15:43:03 -0500231 struct smbios_entry_point *ep = (struct smbios_entry_point *)start;
232
233 memcpy(ep->anchor_string, "_SM_", 4);
234 ep->length = 0x1f;
235 ep->smbios_major_version = 2;
236 ep->smbios_minor_version = 4;
237 ep->max_structure_size = max_structure_size;
238 ep->entry_point_revision = 0;
239 memset(ep->formatted_area, 0, 5);
240 memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
241
242 ep->structure_table_length = structure_table_length;
243 ep->structure_table_address = structure_table_address;
244 ep->number_of_structures = number_of_structures;
245 ep->smbios_bcd_revision = 0x24;
246
247 ep->checksum = 0;
248 ep->intermediate_checksum = 0;
249
Kevin O'Connor2e7ab8b2008-03-29 14:29:35 -0400250 ep->checksum = -checksum(start, 0x10);
Kevin O'Connora4d35762008-03-08 15:43:03 -0500251
Kevin O'Connor2e7ab8b2008-03-29 14:29:35 -0400252 ep->intermediate_checksum = -checksum(start + 0x10, ep->length - 0x10);
253}
Kevin O'Connora4d35762008-03-08 15:43:03 -0500254
255/* Type 0 -- BIOS Information */
256#define RELEASE_DATE_STR "01/01/2007"
257static void *
258smbios_type_0_init(void *start)
259{
260 struct smbios_type_0 *p = (struct smbios_type_0 *)start;
261
262 p->header.type = 0;
263 p->header.length = sizeof(struct smbios_type_0);
264 p->header.handle = 0;
265
266 p->vendor_str = 1;
267 p->bios_version_str = 1;
268 p->bios_starting_address_segment = 0xe800;
269 p->bios_release_date_str = 2;
270 p->bios_rom_size = 0; /* FIXME */
271
Kevin O'Connor230a7b82008-10-25 14:43:11 -0400272 memset(p->bios_characteristics, 0, sizeof(p->bios_characteristics));
273 p->bios_characteristics[0] = 0x08; /* BIOS characteristics not supported */
Kevin O'Connora4d35762008-03-08 15:43:03 -0500274 p->bios_characteristics_extension_bytes[0] = 0;
275 p->bios_characteristics_extension_bytes[1] = 0;
276
277 p->system_bios_major_release = 1;
278 p->system_bios_minor_release = 0;
279 p->embedded_controller_major_release = 0xff;
280 p->embedded_controller_minor_release = 0xff;
281
282 start += sizeof(struct smbios_type_0);
Kevin O'Connord9b06592008-05-06 20:00:12 -0400283 memcpy((char *)start, CONFIG_APPNAME, sizeof(CONFIG_APPNAME));
284 start += sizeof(CONFIG_APPNAME);
Kevin O'Connora4d35762008-03-08 15:43:03 -0500285 memcpy((char *)start, RELEASE_DATE_STR, sizeof(RELEASE_DATE_STR));
286 start += sizeof(RELEASE_DATE_STR);
Kevin O'Connore51313d2008-03-12 21:19:34 -0400287 *((u8 *)start) = 0;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500288
289 return start+1;
290}
291
292/* Type 1 -- System Information */
293static void *
294smbios_type_1_init(void *start)
295{
296 struct smbios_type_1 *p = (struct smbios_type_1 *)start;
297 p->header.type = 1;
298 p->header.length = sizeof(struct smbios_type_1);
299 p->header.handle = 0x100;
300
301 p->manufacturer_str = 0;
302 p->product_name_str = 0;
303 p->version_str = 0;
304 p->serial_number_str = 0;
305
Kevin O'Connor0525d292008-07-04 06:18:30 -0400306 uuid_probe(p->uuid);
Kevin O'Connora4d35762008-03-08 15:43:03 -0500307
308 p->wake_up_type = 0x06; /* power switch */
309 p->sku_number_str = 0;
310 p->family_str = 0;
311
312 start += sizeof(struct smbios_type_1);
Kevin O'Connore51313d2008-03-12 21:19:34 -0400313 *((u16 *)start) = 0;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500314
315 return start+2;
316}
317
318/* Type 3 -- System Enclosure */
319static void *
320smbios_type_3_init(void *start)
321{
322 struct smbios_type_3 *p = (struct smbios_type_3 *)start;
323
324 p->header.type = 3;
325 p->header.length = sizeof(struct smbios_type_3);
326 p->header.handle = 0x300;
327
328 p->manufacturer_str = 0;
329 p->type = 0x01; /* other */
330 p->version_str = 0;
331 p->serial_number_str = 0;
332 p->asset_tag_number_str = 0;
333 p->boot_up_state = 0x03; /* safe */
334 p->power_supply_state = 0x03; /* safe */
335 p->thermal_state = 0x03; /* safe */
336 p->security_status = 0x02; /* unknown */
337 p->oem_defined = 0;
338 p->height = 0;
339 p->number_of_power_cords = 0;
340 p->contained_element_count = 0;
341
342 start += sizeof(struct smbios_type_3);
Kevin O'Connore51313d2008-03-12 21:19:34 -0400343 *((u16 *)start) = 0;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500344
345 return start+2;
346}
347
348/* Type 4 -- Processor Information */
349static void *
350smbios_type_4_init(void *start, unsigned int cpu_number)
351{
352 struct smbios_type_4 *p = (struct smbios_type_4 *)start;
353
354 p->header.type = 4;
355 p->header.length = sizeof(struct smbios_type_4);
356 p->header.handle = 0x400 + cpu_number;
357
358 p->socket_designation_str = 1;
359 p->processor_type = 0x03; /* CPU */
360 p->processor_family = 0x01; /* other */
361 p->processor_manufacturer_str = 0;
362
Kevin O'Connor0525d292008-07-04 06:18:30 -0400363 u32 cpuid_signature, ebx, ecx, cpuid_features;
364 cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
Kevin O'Connora4d35762008-03-08 15:43:03 -0500365 p->processor_id[0] = cpuid_signature;
366 p->processor_id[1] = cpuid_features;
367
368 p->processor_version_str = 0;
369 p->voltage = 0;
370 p->external_clock = 0;
371
372 p->max_speed = 0; /* unknown */
373 p->current_speed = 0; /* unknown */
374
375 p->status = 0x41; /* socket populated, CPU enabled */
376 p->processor_upgrade = 0x01; /* other */
377
Kevin O'Connorf2ce1912008-10-25 15:23:53 -0400378 p->l1_cache_handle = 0xffff; /* cache information structure not provided */
379 p->l2_cache_handle = 0xffff;
380 p->l3_cache_handle = 0xffff;
381
Kevin O'Connora4d35762008-03-08 15:43:03 -0500382 start += sizeof(struct smbios_type_4);
383
384 memcpy((char *)start, "CPU " "\0" "" "\0" "", 7);
385 ((char *)start)[4] = cpu_number + '0';
386
387 return start+7;
388}
389
390/* Type 16 -- Physical Memory Array */
391static void *
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400392smbios_type_16_init(void *start)
Kevin O'Connora4d35762008-03-08 15:43:03 -0500393{
394 struct smbios_type_16 *p = (struct smbios_type_16*)start;
395
396 p->header.type = 16;
397 p->header.length = sizeof(struct smbios_type_16);
398 p->header.handle = 0x1000;
399
400 p->location = 0x01; /* other */
401 p->use = 0x03; /* system memory */
402 p->error_correction = 0x01; /* other */
Kevin O'Connore7916362008-12-28 22:03:17 -0500403 u64 memsize = RamSize + RamSizeOver4G;
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400404 p->maximum_capacity = memsize / 1024;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500405 p->memory_error_information_handle = 0xfffe; /* none provided */
406 p->number_of_memory_devices = 1;
407
408 start += sizeof(struct smbios_type_16);
Kevin O'Connore51313d2008-03-12 21:19:34 -0400409 *((u16 *)start) = 0;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500410
411 return start + 2;
412}
413
414/* Type 17 -- Memory Device */
415static void *
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400416smbios_type_17_init(void *start)
Kevin O'Connora4d35762008-03-08 15:43:03 -0500417{
418 struct smbios_type_17 *p = (struct smbios_type_17 *)start;
419
420 p->header.type = 17;
421 p->header.length = sizeof(struct smbios_type_17);
422 p->header.handle = 0x1100;
423
424 p->physical_memory_array_handle = 0x1000;
425 p->total_width = 64;
426 p->data_width = 64;
427 /* truncate memory_size_mb to 16 bits and clear most significant
428 bit [indicates size in MB] */
Kevin O'Connore7916362008-12-28 22:03:17 -0500429 u64 memsize = RamSize + RamSizeOver4G;
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400430 p->size = (u16) (memsize / (1024*1024)) & 0x7fff;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500431 p->form_factor = 0x09; /* DIMM */
432 p->device_set = 0;
433 p->device_locator_str = 1;
434 p->bank_locator_str = 0;
435 p->memory_type = 0x07; /* RAM */
436 p->type_detail = 0;
437
438 start += sizeof(struct smbios_type_17);
439 memcpy((char *)start, "DIMM 1", 7);
440 start += 7;
Kevin O'Connore51313d2008-03-12 21:19:34 -0400441 *((u8 *)start) = 0;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500442
443 return start+1;
444}
445
446/* Type 19 -- Memory Array Mapped Address */
447static void *
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400448smbios_type_19_init(void *start)
Kevin O'Connora4d35762008-03-08 15:43:03 -0500449{
450 struct smbios_type_19 *p = (struct smbios_type_19 *)start;
451
452 p->header.type = 19;
453 p->header.length = sizeof(struct smbios_type_19);
454 p->header.handle = 0x1300;
455
456 p->starting_address = 0;
Kevin O'Connore7916362008-12-28 22:03:17 -0500457 u64 memsize = RamSizeOver4G;
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400458 if (memsize)
459 memsize += 0x100000000ull;
460 else
Kevin O'Connore7916362008-12-28 22:03:17 -0500461 memsize = RamSize;
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400462 p->ending_address = memsize / 1024 - 1;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500463 p->memory_array_handle = 0x1000;
464 p->partition_width = 1;
465
466 start += sizeof(struct smbios_type_19);
Kevin O'Connore51313d2008-03-12 21:19:34 -0400467 *((u16 *)start) = 0;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500468
469 return start + 2;
470}
471
472/* Type 20 -- Memory Device Mapped Address */
473static void *
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400474smbios_type_20_init(void *start)
Kevin O'Connora4d35762008-03-08 15:43:03 -0500475{
476 struct smbios_type_20 *p = (struct smbios_type_20 *)start;
477
478 p->header.type = 20;
479 p->header.length = sizeof(struct smbios_type_20);
480 p->header.handle = 0x1400;
481
482 p->starting_address = 0;
Kevin O'Connore7916362008-12-28 22:03:17 -0500483 u64 memsize = RamSizeOver4G;
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400484 if (memsize)
485 memsize += 0x100000000ull;
486 else
Kevin O'Connore7916362008-12-28 22:03:17 -0500487 memsize = RamSize;
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400488 p->ending_address = memsize / 1024 - 1;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500489 p->memory_device_handle = 0x1100;
490 p->memory_array_mapped_address_handle = 0x1300;
491 p->partition_row_position = 1;
492 p->interleave_position = 0;
493 p->interleaved_data_depth = 0;
494
495 start += sizeof(struct smbios_type_20);
496
Kevin O'Connore51313d2008-03-12 21:19:34 -0400497 *((u16 *)start) = 0;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500498 return start+2;
499}
500
501/* Type 32 -- System Boot Information */
502static void *
503smbios_type_32_init(void *start)
504{
505 struct smbios_type_32 *p = (struct smbios_type_32 *)start;
506
507 p->header.type = 32;
508 p->header.length = sizeof(struct smbios_type_32);
509 p->header.handle = 0x2000;
510 memset(p->reserved, 0, 6);
511 p->boot_status = 0; /* no errors detected */
512
513 start += sizeof(struct smbios_type_32);
Kevin O'Connore51313d2008-03-12 21:19:34 -0400514 *((u16 *)start) = 0;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500515
516 return start+2;
517}
518
519/* Type 127 -- End of Table */
520static void *
521smbios_type_127_init(void *start)
522{
523 struct smbios_type_127 *p = (struct smbios_type_127 *)start;
524
525 p->header.type = 127;
526 p->header.length = sizeof(struct smbios_type_127);
527 p->header.handle = 0x7f00;
528
529 start += sizeof(struct smbios_type_127);
Kevin O'Connore51313d2008-03-12 21:19:34 -0400530 *((u16 *)start) = 0;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500531
532 return start + 2;
533}
534
Kevin O'Connor0525d292008-07-04 06:18:30 -0400535void
536smbios_init(void)
Kevin O'Connora4d35762008-03-08 15:43:03 -0500537{
Kevin O'Connor6cb8ba92008-08-17 11:03:24 -0400538 if (! CONFIG_SMBIOS)
539 return;
540
Kevin O'Connor7b49cd92008-11-08 10:35:26 -0500541 dprintf(3, "init SMBIOS tables\n");
542
Kevin O'Connora4d35762008-03-08 15:43:03 -0500543 unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
544 char *start, *p, *q;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500545
Kevin O'Connor276d4a92008-06-11 22:47:01 -0400546 bios_table_cur_addr = ALIGN(bios_table_cur_addr, 16);
Kevin O'Connora4d35762008-03-08 15:43:03 -0500547 start = (void *)(bios_table_cur_addr);
Kevin O'Connora4d35762008-03-08 15:43:03 -0500548
Kevin O'Connor2ad37442008-05-06 19:49:01 -0400549 p = (char *)start + sizeof(struct smbios_entry_point);
Kevin O'Connora4d35762008-03-08 15:43:03 -0500550
551#define add_struct(fn) { \
552 q = (fn); \
553 nr_structs++; \
554 if ((q - p) > max_struct_size) \
555 max_struct_size = q - p; \
556 p = q; \
557}
558
559 add_struct(smbios_type_0_init(p));
560 add_struct(smbios_type_1_init(p));
561 add_struct(smbios_type_3_init(p));
Kevin O'Connore97ca7b2009-06-21 09:10:28 -0400562 int smp_cpus = CountCPUs;
Kevin O'Connora4d35762008-03-08 15:43:03 -0500563 for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
564 add_struct(smbios_type_4_init(p, cpu_num));
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400565 add_struct(smbios_type_16_init(p));
566 add_struct(smbios_type_17_init(p));
567 add_struct(smbios_type_19_init(p));
568 add_struct(smbios_type_20_init(p));
Kevin O'Connora4d35762008-03-08 15:43:03 -0500569 add_struct(smbios_type_32_init(p));
570 add_struct(smbios_type_127_init(p));
571
572#undef add_struct
573
574 smbios_entry_point_init(
575 start, max_struct_size,
576 (p - (char *)start) - sizeof(struct smbios_entry_point),
Kevin O'Connore51313d2008-03-12 21:19:34 -0400577 (u32)(start + sizeof(struct smbios_entry_point)),
Kevin O'Connora4d35762008-03-08 15:43:03 -0500578 nr_structs);
579
Kevin O'Connora4d35762008-03-08 15:43:03 -0500580 bios_table_cur_addr += (p - (char *)start);
Kevin O'Connora4d35762008-03-08 15:43:03 -0500581
Kevin O'Connorac8df8c2008-05-24 23:46:33 -0400582 dprintf(1, "SMBIOS table addr=0x%08lx\n", (unsigned long)start);
Kevin O'Connora4d35762008-03-08 15:43:03 -0500583}