blob: 51f1593075dc9a02a86594e08a6874ace177bb29 [file] [log] [blame]
Benjamin Doronea13dc32023-06-20 12:21:27 -04001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <assert.h>
4#include <string.h>
5#include <smbios.h>
6#include <console/console.h>
7#include <version.h>
8#include <device/device.h>
9#include <device/dram/spd.h>
10#include <elog.h>
11#include <endian.h>
12#include <memory_info.h>
13#include <spd.h>
14#include <cbmem.h>
15#include <commonlib/helpers.h>
16#include <device/pci_ids.h>
17#include <device/pci.h>
18#include <device/pci_def.h>
19#include <drivers/vpd/vpd.h>
20#include <stdlib.h>
21
22static u8 smbios_checksum(u8 *p, u32 length)
23{
24 u8 ret = 0;
25 while (length--)
26 ret += *p++;
27 return -ret;
28}
29
30int smbios_add_string(u8 *start, const char *str)
31{
32 int i = 1;
33 char *p = (char *)start;
34
35 /*
36 * Return 0 as required for empty strings.
37 * See Section 6.1.3 "Text Strings" of the SMBIOS specification.
38 */
39 if (str == NULL || *str == '\0')
40 return 0;
41
42 for (;;) {
43 if (!*p) {
44 strcpy(p, str);
45 p += strlen(str);
46 *p++ = '\0';
47 *p++ = '\0';
48 return i;
49 }
50
51 if (!strcmp(p, str))
52 return i;
53
54 p += strlen(p)+1;
55 i++;
56 }
57}
58
59int smbios_string_table_len(u8 *start)
60{
61 char *p = (char *)start;
62 int i, len = 0;
63
64 while (*p) {
65 i = strlen(p) + 1;
66 p += i;
67 len += i;
68 }
69
70 if (!len)
71 return 2;
72
73 return len + 1;
74}
75
76int smbios_full_table_len(struct smbios_header *header, u8 *str_table_start)
77{
78 return header->length + smbios_string_table_len(str_table_start);
79}
80
81void *smbios_carve_table(unsigned long start, u8 type, u8 length, u16 handle)
82{
83 struct smbios_header *t = (struct smbios_header *)start;
84
85 assert(length >= sizeof(*t));
86 memset(t, 0, length);
87 t->type = type;
88 t->length = length - 2;
89 t->handle = handle;
90 return t;
91}
92
93/* this function will fill the corresponding manufacturer */
94void smbios_fill_dimm_manufacturer_from_id(uint16_t mod_id, struct smbios_type17 *t)
95{
96 const char *const manufacturer = spd_manufacturer_name(mod_id);
97
98 if (manufacturer) {
99 t->manufacturer = smbios_add_string(t->eos, manufacturer);
100 } else {
101 char string_buffer[256];
102
103 snprintf(string_buffer, sizeof(string_buffer), "Unknown (%x)", mod_id);
104 t->manufacturer = smbios_add_string(t->eos, string_buffer);
105 }
106}
107
108static void trim_trailing_whitespace(char *buffer, size_t buffer_size)
109{
110 size_t len = strnlen(buffer, buffer_size);
111
112 if (len == 0)
113 return;
114
115 for (char *p = buffer + len - 1; p >= buffer; --p) {
116 if (*p == ' ')
117 *p = 0;
118 else
119 break;
120 }
121}
122
123/** This function will fill the corresponding part number */
124static void smbios_fill_dimm_part_number(const char *part_number, struct smbios_type17 *t)
125{
126 int invalid;
127 size_t i, len;
128 char trimmed_part_number[DIMM_INFO_PART_NUMBER_SIZE];
129
130 strncpy(trimmed_part_number, part_number, sizeof(trimmed_part_number));
131 trimmed_part_number[sizeof(trimmed_part_number) - 1] = '\0';
132
133 /*
134 * SPD mandates that unused characters be represented with a ' '.
135 * We don't want to publish the whitespace in the SMBIOS tables.
136 */
137 trim_trailing_whitespace(trimmed_part_number, sizeof(trimmed_part_number));
138
139 len = strlen(trimmed_part_number);
140
141 invalid = 0; /* assume valid */
142 for (i = 0; i < len; i++) {
143 if (trimmed_part_number[i] < ' ') {
144 invalid = 1;
145 trimmed_part_number[i] = '*';
146 }
147 }
148
149 if (len == 0) {
150 /* Null String in Part Number will have "None" instead. */
151 t->part_number = smbios_add_string(t->eos, "None");
152 } else if (invalid) {
153 char string_buffer[sizeof(trimmed_part_number) + 10];
154
155 snprintf(string_buffer, sizeof(string_buffer), "Invalid (%s)",
156 trimmed_part_number);
157 t->part_number = smbios_add_string(t->eos, string_buffer);
158 } else {
159 t->part_number = smbios_add_string(t->eos, trimmed_part_number);
160 }
161}
162
163/* Encodes the SPD serial number into hex */
164static void smbios_fill_dimm_serial_number(const struct dimm_info *dimm,
165 struct smbios_type17 *t)
166{
167 char serial[9];
168
169 snprintf(serial, sizeof(serial), "%02hhx%02hhx%02hhx%02hhx",
170 dimm->serial[0], dimm->serial[1], dimm->serial[2], dimm->serial[3]);
171
172 t->serial_number = smbios_add_string(t->eos, serial);
173}
174
175static const char *memory_device_type(u8 code)
176{
177 /* SMBIOS spec 3.6 7.18.2 */
178 static const char * const type[] = {
179 "Other",
180 "Unknown",
181 "DRAM",
182 "EDRAM",
183 "VRAM",
184 "SRAM",
185 "RAM",
186 "ROM",
187 "Flash",
188 "EEPROM",
189 "FEPROM",
190 "EPROM",
191 "CDRAM",
192 "3DRAM",
193 "SDRAM",
194 "SGRAM",
195 "RDRAM",
196 "DDR",
197 "DDR2",
198 "DDR2 FB-DIMM",
199 "Reserved",
200 "Reserved",
201 "Reserved",
202 "DDR3",
203 "FBD2",
204 "DDR4", /* 0x1A */
205 "LPDDR",
206 "LPDDR2",
207 "LPDDR3",
208 "LPDDR4",
209 "Logical non-volatile device",
210 "HBM",
211 "HBM2",
212 "DDR5",
213 "LPDDR5",
214 "HBM3", /* 0x24 */
215 };
216
217 if (code >= MEMORY_TYPE_OTHER && code <= MEMORY_TYPE_HBM3)
218 return type[code - 1];
Martin Roth3e25f852023-09-04 15:37:07 -0600219 return "Unsupported";
Benjamin Doronea13dc32023-06-20 12:21:27 -0400220}
221
222static void dump_smbios_type17(struct dimm_info *dimm)
223{
224 printk(BIOS_INFO, "memory at Channel-%d-DIMM-%d", dimm->channel_num, dimm->dimm_num);
225 printk(BIOS_INFO, " type is %s\n", memory_device_type(dimm->ddr_type));
226 printk(BIOS_INFO, "memory part number is %s\n", dimm->module_part_number);
227 if (dimm->max_speed_mts != 0)
228 printk(BIOS_INFO, "memory max speed is %d MT/s\n", dimm->max_speed_mts);
229 printk(BIOS_INFO, "memory speed is %d MT/s\n",
230 dimm->configured_speed_mts ? : dimm->ddr_frequency);
231 printk(BIOS_INFO, "memory size is %d MiB\n", dimm->dimm_size);
232}
233
234static int create_smbios_type17_for_dimm(struct dimm_info *dimm,
235 unsigned long *current, int *handle,
236 int type16_handle)
237{
238 struct spd_info info;
239 get_spd_info(dimm->ddr_type, dimm->mod_type, &info);
240
241 struct smbios_type17 *t = smbios_carve_table(*current, SMBIOS_MEMORY_DEVICE,
242 sizeof(*t), *handle);
243
244 t->memory_type = dimm->ddr_type;
245 if (dimm->configured_speed_mts != 0)
246 t->clock_speed = dimm->configured_speed_mts;
247 else
248 t->clock_speed = dimm->ddr_frequency;
249 if (dimm->max_speed_mts != 0)
250 t->speed = dimm->max_speed_mts;
251 else
252 t->speed = dimm->ddr_frequency;
253 if (dimm->dimm_size < 0x7fff) {
254 t->size = dimm->dimm_size;
255 } else {
256 t->size = 0x7fff;
257 t->extended_size = dimm->dimm_size & 0x7fffffff;
258 }
259 t->data_width = 8 * (1 << (dimm->bus_width & 0x7));
260 t->total_width = t->data_width + 8 * ((dimm->bus_width & 0x18) >> 3);
261 t->form_factor = info.form_factor;
262
263 smbios_fill_dimm_manufacturer_from_id(dimm->mod_id, t);
264 smbios_fill_dimm_serial_number(dimm, t);
265 smbios_fill_dimm_asset_tag(dimm, t);
266 smbios_fill_dimm_locator(dimm, t);
267
268 /* put '\0' in the end of data */
269 dimm->module_part_number[DIMM_INFO_PART_NUMBER_SIZE - 1] = '\0';
270 smbios_fill_dimm_part_number((char *)dimm->module_part_number, t);
271
272 /* Voltage Levels */
273 t->configured_voltage = dimm->vdd_voltage;
274 t->minimum_voltage = dimm->vdd_voltage;
275 t->maximum_voltage = dimm->vdd_voltage;
276
277 /* Fill in type detail */
278 t->type_detail = info.type_detail;
279
280 /* Synchronous = 1 */
281 t->type_detail |= MEMORY_TYPE_DETAIL_SYNCHRONOUS;
282 /* no handle for error information */
283 t->memory_error_information_handle = 0xFFFE;
284 t->attributes = dimm->rank_per_dimm;
285 t->phys_memory_array_handle = type16_handle;
286
287 *handle += 1;
288 return smbios_full_table_len(&t->header, t->eos);
289}
290
291static int create_smbios_type17_for_empty_slot(struct dimm_info *dimm,
292 unsigned long *current, int *handle,
293 int type16_handle)
294{
295 struct smbios_type17 *t = smbios_carve_table(*current, SMBIOS_MEMORY_DEVICE,
296 sizeof(*t), *handle);
297 t->phys_memory_array_handle = type16_handle;
298 /* no handle for error information */
299 t->memory_error_information_handle = 0xfffe;
300 t->total_width = 0xffff; /* Unknown */
301 t->data_width = 0xffff; /* Unknown */
302 t->form_factor = 0x2; /* Unknown */
303 smbios_fill_dimm_locator(dimm, t); /* Device and Bank */
304 t->memory_type = 0x2; /* Unknown */
305 t->type_detail = 0x2; /* Unknown */
306
307 *handle += 1;
308 if (CONFIG(DUMP_SMBIOS_TYPE17))
309 dump_smbios_type17(dimm);
310
311 return smbios_full_table_len(&t->header, t->eos);
312}
313
314#define VERSION_VPD "firmware_version"
315static const char *vpd_get_bios_version(void)
316{
317 int size;
318 const char *s;
319 char *version;
320
321 s = vpd_find(VERSION_VPD, &size, VPD_RO);
322 if (!s) {
323 printk(BIOS_ERR, "Find version from VPD %s failed\n", VERSION_VPD);
324 return NULL;
325 }
326
327 version = malloc(size + 1);
328 if (!version) {
329 printk(BIOS_ERR, "Failed to malloc %d bytes for VPD version\n", size + 1);
330 return NULL;
331 }
332 memcpy(version, s, size);
333 version[size] = '\0';
334 printk(BIOS_DEBUG, "Firmware version %s from VPD %s\n", version, VERSION_VPD);
335 return version;
336}
337
338static const char *get_bios_version(void)
339{
340 const char *s;
341
342#define SPACES \
343 " "
344
345 if (CONFIG(CHROMEOS))
346 return SPACES;
347
348 if (CONFIG(VPD_SMBIOS_VERSION)) {
349 s = vpd_get_bios_version();
350 if (s != NULL)
351 return s;
352 }
353
354 s = smbios_mainboard_bios_version();
355 if (s != NULL)
356 return s;
357
358 if (strlen(CONFIG_LOCALVERSION) != 0) {
359 printk(BIOS_DEBUG, "BIOS version set to CONFIG_LOCALVERSION: '%s'\n",
360 CONFIG_LOCALVERSION);
361 return CONFIG_LOCALVERSION;
362 }
363
364 printk(BIOS_DEBUG, "SMBIOS firmware version is set to coreboot_version: '%s'\n",
365 coreboot_version);
366 return coreboot_version;
367}
368
369static int smbios_write_type0(unsigned long *current, int handle)
370{
371 struct smbios_type0 *t = smbios_carve_table(*current, SMBIOS_BIOS_INFORMATION,
372 sizeof(*t), handle);
373
Hao Wang634c7a42022-06-14 10:56:40 +0800374 t->vendor = smbios_add_string(t->eos, CONFIG_BIOS_VENDOR);
Benjamin Doronea13dc32023-06-20 12:21:27 -0400375 t->bios_release_date = smbios_add_string(t->eos, coreboot_dmi_date);
376
377 if (CONFIG(CHROMEOS_NVS)) {
378 uintptr_t version_address = (uintptr_t)t->eos;
379 /* SMBIOS offsets start at 1 rather than 0 */
380 version_address += (u32)smbios_string_table_len(t->eos) - 1;
381 smbios_type0_bios_version(version_address);
382 }
383 t->bios_version = smbios_add_string(t->eos, get_bios_version());
384 uint32_t rom_size = CONFIG_ROM_SIZE;
385 rom_size = MIN(CONFIG_ROM_SIZE, 16 * MiB);
386 t->bios_rom_size = (rom_size / 65535) - 1;
387
388 if (CONFIG_ROM_SIZE >= 1 * GiB)
389 t->extended_bios_rom_size = DIV_ROUND_UP(CONFIG_ROM_SIZE, GiB) | (1 << 14);
390 else
391 t->extended_bios_rom_size = DIV_ROUND_UP(CONFIG_ROM_SIZE, MiB);
392
393 t->system_bios_major_release = coreboot_major_revision;
394 t->system_bios_minor_release = coreboot_minor_revision;
395
396 smbios_ec_revision(&t->ec_major_release, &t->ec_minor_release);
397
398 t->bios_characteristics =
399 BIOS_CHARACTERISTICS_PCI_SUPPORTED |
400 BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
401 BIOS_CHARACTERISTICS_UPGRADEABLE;
402
403 if (CONFIG(CARDBUS_PLUGIN_SUPPORT))
404 t->bios_characteristics |= BIOS_CHARACTERISTICS_PC_CARD;
405
406 if (CONFIG(HAVE_ACPI_TABLES))
407 t->bios_characteristics_ext1 = BIOS_EXT1_CHARACTERISTICS_ACPI;
408
409 t->bios_characteristics_ext2 = BIOS_EXT2_CHARACTERISTICS_TARGET;
410 const int len = smbios_full_table_len(&t->header, t->eos);
411 *current += len;
412 return len;
413}
414
415unsigned int __weak smbios_processor_external_clock(void)
416{
417 return 0; /* Unknown */
418}
419
420unsigned int __weak smbios_processor_characteristics(void)
421{
422 return 0;
423}
424
425unsigned int __weak smbios_cache_error_correction_type(u8 level)
426{
427 return SMBIOS_CACHE_ERROR_CORRECTION_UNKNOWN;
428}
429
430unsigned int __weak smbios_cache_sram_type(void)
431{
432 return SMBIOS_CACHE_SRAM_TYPE_UNKNOWN;
433}
434
435unsigned int __weak smbios_cache_conf_operation_mode(u8 level)
436{
437 return SMBIOS_CACHE_OP_MODE_UNKNOWN; /* Unknown */
438}
439
440/* Returns the processor voltage in 100mV units */
441unsigned int __weak smbios_cpu_get_voltage(void)
442{
443 return 0; /* Unknown */
444}
445
446static int smbios_write_type1(unsigned long *current, int handle)
447{
448 struct smbios_type1 *t = smbios_carve_table(*current, SMBIOS_SYSTEM_INFORMATION,
449 sizeof(*t), handle);
450
451 t->manufacturer = smbios_add_string(t->eos, smbios_system_manufacturer());
452 t->product_name = smbios_add_string(t->eos, smbios_system_product_name());
453 t->serial_number = smbios_add_string(t->eos, smbios_system_serial_number());
454 t->wakeup_type = smbios_system_wakeup_type();
455 t->sku = smbios_add_string(t->eos, smbios_system_sku());
456 t->version = smbios_add_string(t->eos, smbios_system_version());
457#ifdef CONFIG_MAINBOARD_FAMILY
458 t->family = smbios_add_string(t->eos, CONFIG_MAINBOARD_FAMILY);
459#endif
460 smbios_system_set_uuid(t->uuid);
461 const int len = smbios_full_table_len(&t->header, t->eos);
462 *current += len;
463 return len;
464}
465
466static int smbios_write_type2(unsigned long *current, int handle, const int chassis_handle)
467{
468 struct smbios_type2 *t = smbios_carve_table(*current, SMBIOS_BOARD_INFORMATION,
469 sizeof(*t), handle);
470
471 t->manufacturer = smbios_add_string(t->eos, smbios_mainboard_manufacturer());
472 t->product_name = smbios_add_string(t->eos, smbios_mainboard_product_name());
473 t->serial_number = smbios_add_string(t->eos, smbios_mainboard_serial_number());
474 t->version = smbios_add_string(t->eos, smbios_mainboard_version());
475 t->asset_tag = smbios_add_string(t->eos, smbios_mainboard_asset_tag());
476 t->feature_flags = smbios_mainboard_feature_flags();
477 t->location_in_chassis = smbios_add_string(t->eos,
478 smbios_mainboard_location_in_chassis());
479 t->board_type = smbios_mainboard_board_type();
480 t->chassis_handle = chassis_handle;
481 const int len = smbios_full_table_len(&t->header, t->eos);
482 *current += len;
483 return len;
484}
485
486static int smbios_write_type3(unsigned long *current, int handle)
487{
488 struct smbios_type3 *t = smbios_carve_table(*current, SMBIOS_SYSTEM_ENCLOSURE,
489 sizeof(*t), handle);
490
491 t->manufacturer = smbios_add_string(t->eos, smbios_system_manufacturer());
492 t->bootup_state = SMBIOS_STATE_SAFE;
493 t->power_supply_state = SMBIOS_STATE_SAFE;
494 t->thermal_state = SMBIOS_STATE_SAFE;
495 t->_type = smbios_mainboard_enclosure_type();
496 t->security_status = SMBIOS_STATE_SAFE;
497 t->number_of_power_cords = smbios_chassis_power_cords();
498 t->asset_tag_number = smbios_add_string(t->eos, smbios_mainboard_asset_tag());
499 t->version = smbios_add_string(t->eos, smbios_chassis_version());
500 t->serial_number = smbios_add_string(t->eos, smbios_chassis_serial_number());
501 const int len = smbios_full_table_len(&t->header, t->eos);
502 *current += len;
503 return len;
504}
505
506/*
507 * Write SMBIOS type 7.
508 * Fill in some fields with constant values, as gathering the information
509 * from CPUID is impossible.
510 */
511int smbios_write_type7(unsigned long *current,
512 const int handle,
513 const u8 level,
514 const u8 sram_type,
515 const enum smbios_cache_associativity associativity,
516 const enum smbios_cache_type type,
517 const size_t max_cache_size,
518 const size_t cache_size)
519{
520 char buf[8];
521
522 struct smbios_type7 *t = smbios_carve_table(*current, SMBIOS_CACHE_INFORMATION,
523 sizeof(*t), handle);
524
525 snprintf(buf, sizeof(buf), "CACHE%x", level);
526 t->socket_designation = smbios_add_string(t->eos, buf);
527
528 t->cache_configuration = SMBIOS_CACHE_CONF_LEVEL(level) |
529 SMBIOS_CACHE_CONF_LOCATION(0) | /* Internal */
530 SMBIOS_CACHE_CONF_ENABLED(1) | /* Enabled */
531 SMBIOS_CACHE_CONF_OPERATION_MODE(smbios_cache_conf_operation_mode(level));
532
533 if (max_cache_size < (SMBIOS_CACHE_SIZE_MASK * KiB)) {
534 t->max_cache_size = max_cache_size / KiB;
535 t->max_cache_size2 = t->max_cache_size;
536
537 t->max_cache_size |= SMBIOS_CACHE_SIZE_UNIT_1KB;
538 t->max_cache_size2 |= SMBIOS_CACHE_SIZE2_UNIT_1KB;
539 } else {
540 if (max_cache_size < (SMBIOS_CACHE_SIZE_MASK * 64 * KiB))
541 t->max_cache_size = max_cache_size / (64 * KiB);
542 else
543 t->max_cache_size = SMBIOS_CACHE_SIZE_OVERFLOW;
544 t->max_cache_size2 = max_cache_size / (64 * KiB);
545
546 t->max_cache_size |= SMBIOS_CACHE_SIZE_UNIT_64KB;
547 t->max_cache_size2 |= SMBIOS_CACHE_SIZE2_UNIT_64KB;
548 }
549
550 if (cache_size < (SMBIOS_CACHE_SIZE_MASK * KiB)) {
551 t->installed_size = cache_size / KiB;
552 t->installed_size2 = t->installed_size;
553
554 t->installed_size |= SMBIOS_CACHE_SIZE_UNIT_1KB;
555 t->installed_size2 |= SMBIOS_CACHE_SIZE2_UNIT_1KB;
556 } else {
557 if (cache_size < (SMBIOS_CACHE_SIZE_MASK * 64 * KiB))
558 t->installed_size = cache_size / (64 * KiB);
559 else
560 t->installed_size = SMBIOS_CACHE_SIZE_OVERFLOW;
561 t->installed_size2 = cache_size / (64 * KiB);
562
563 t->installed_size |= SMBIOS_CACHE_SIZE_UNIT_64KB;
564 t->installed_size2 |= SMBIOS_CACHE_SIZE2_UNIT_64KB;
565 }
566
567 t->associativity = associativity;
568 t->supported_sram_type = sram_type;
569 t->current_sram_type = sram_type;
570 t->cache_speed = 0; /* Unknown */
571 t->error_correction_type = smbios_cache_error_correction_type(level);
572 t->system_cache_type = type;
573
574 const int len = smbios_full_table_len(&t->header, t->eos);
575 *current += len;
576 return len;
577}
578
579/* Convert the associativity as integer to the SMBIOS enum if available */
580enum smbios_cache_associativity smbios_cache_associativity(const u8 num)
581{
582 switch (num) {
583 case 1:
584 return SMBIOS_CACHE_ASSOCIATIVITY_DIRECT;
585 case 2:
586 return SMBIOS_CACHE_ASSOCIATIVITY_2WAY;
587 case 4:
588 return SMBIOS_CACHE_ASSOCIATIVITY_4WAY;
589 case 8:
590 return SMBIOS_CACHE_ASSOCIATIVITY_8WAY;
591 case 12:
592 return SMBIOS_CACHE_ASSOCIATIVITY_12WAY;
593 case 16:
594 return SMBIOS_CACHE_ASSOCIATIVITY_16WAY;
595 case 20:
596 return SMBIOS_CACHE_ASSOCIATIVITY_20WAY;
597 case 24:
598 return SMBIOS_CACHE_ASSOCIATIVITY_24WAY;
599 case 32:
600 return SMBIOS_CACHE_ASSOCIATIVITY_32WAY;
601 case 48:
602 return SMBIOS_CACHE_ASSOCIATIVITY_48WAY;
603 case 64:
604 return SMBIOS_CACHE_ASSOCIATIVITY_64WAY;
605 case 0xff:
606 return SMBIOS_CACHE_ASSOCIATIVITY_FULL;
607 default:
608 return SMBIOS_CACHE_ASSOCIATIVITY_UNKNOWN;
609 };
610}
611
612int smbios_write_type8(unsigned long *current, int *handle,
613 const struct port_information *port,
614 size_t num_ports)
615{
616 unsigned int totallen = 0, i;
617
618 for (i = 0; i < num_ports; i++, port++) {
619 struct smbios_type8 *t = smbios_carve_table(*current,
620 SMBIOS_PORT_CONNECTOR_INFORMATION,
621 sizeof(*t), *handle);
622 t->internal_reference_designator =
623 smbios_add_string(t->eos, port->internal_reference_designator);
624 t->internal_connector_type = port->internal_connector_type;
625 t->external_reference_designator =
626 smbios_add_string(t->eos, port->external_reference_designator);
627 t->external_connector_type = port->external_connector_type;
628 t->port_type = port->port_type;
629 *handle += 1;
630 const int len = smbios_full_table_len(&t->header, t->eos);
631 *current += len;
632 totallen += len;
633 }
634 return totallen;
635}
636
637int smbios_write_type9(unsigned long *current, int *handle,
638 const char *name, const enum misc_slot_type type,
639 const enum slot_data_bus_bandwidth bandwidth,
640 const enum misc_slot_usage usage,
641 const enum misc_slot_length length,
Felix Heldd4594032024-01-11 21:50:36 +0100642 const u16 id, u8 slot_char1, u8 slot_char2,
643 u8 segment_group, u8 bus, u8 dev_func)
Benjamin Doronea13dc32023-06-20 12:21:27 -0400644{
645 struct smbios_type9 *t = smbios_carve_table(*current, SMBIOS_SYSTEM_SLOTS,
646 sizeof(*t), *handle);
647
648 t->slot_designation = smbios_add_string(t->eos, name ? name : "SLOT");
649 t->slot_type = type;
Martin Roth3e25f852023-09-04 15:37:07 -0600650 /* TODO add slot_id support, will be "_SUN" for ACPI devices */
Benjamin Doronea13dc32023-06-20 12:21:27 -0400651 t->slot_id = id;
652 t->slot_data_bus_width = bandwidth;
653 t->current_usage = usage;
654 t->slot_length = length;
655 t->slot_characteristics_1 = slot_char1;
656 t->slot_characteristics_2 = slot_char2;
Felix Heldd4594032024-01-11 21:50:36 +0100657 t->segment_group_number = segment_group;
Benjamin Doronea13dc32023-06-20 12:21:27 -0400658 t->bus_number = bus;
659 t->device_function_number = dev_func;
660 t->data_bus_width = SlotDataBusWidthOther;
661
662 const int len = smbios_full_table_len(&t->header, t->eos);
663 *current += len;
664 *handle += 1;
665 return len;
666}
667
668static int smbios_write_type11(unsigned long *current, int *handle)
669{
670 struct device *dev;
671 struct smbios_type11 *t = smbios_carve_table(*current, SMBIOS_OEM_STRINGS,
672 sizeof(*t), *handle);
673
674 for (dev = all_devices; dev; dev = dev->next) {
675 if (dev->ops && dev->ops->get_smbios_strings)
676 dev->ops->get_smbios_strings(dev, t);
677 }
678
679 if (t->count == 0) {
680 memset(t, 0, sizeof(*t));
681 return 0;
682 }
683
684 const int len = smbios_full_table_len(&t->header, t->eos);
685 *current += len;
686 (*handle)++;
687 return len;
688}
689
690static int smbios_write_type16(unsigned long *current, int *handle)
691{
692 int i;
693 uint64_t max_capacity;
694
695 struct memory_info *meminfo;
696 meminfo = cbmem_find(CBMEM_ID_MEMINFO);
697 if (meminfo == NULL)
698 return 0; /* can't find mem info in cbmem */
699
700 printk(BIOS_INFO, "Create SMBIOS type 16\n");
701
702 if (meminfo->max_capacity_mib == 0 || meminfo->number_of_devices == 0) {
703 /* Fill in defaults if not provided */
704 meminfo->number_of_devices = 0;
705 meminfo->max_capacity_mib = 0;
706 for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
707 meminfo->max_capacity_mib += meminfo->dimm[i].dimm_size;
708 meminfo->number_of_devices += !!meminfo->dimm[i].dimm_size;
709 }
710 }
711
712 struct smbios_type16 *t = smbios_carve_table(*current, SMBIOS_PHYS_MEMORY_ARRAY,
713 sizeof(*t), *handle);
714
715 t->location = MEMORY_ARRAY_LOCATION_SYSTEM_BOARD;
716 t->use = MEMORY_ARRAY_USE_SYSTEM;
717 t->memory_error_correction = meminfo->ecc_type;
718
719 /* no error information handle available */
720 t->memory_error_information_handle = 0xFFFE;
721 max_capacity = meminfo->max_capacity_mib;
722 if (max_capacity * (MiB / KiB) < SMBIOS_USE_EXTENDED_MAX_CAPACITY)
723 t->maximum_capacity = max_capacity * (MiB / KiB);
724 else {
725 t->maximum_capacity = SMBIOS_USE_EXTENDED_MAX_CAPACITY;
726 t->extended_maximum_capacity = max_capacity * MiB;
727 }
728 t->number_of_memory_devices = meminfo->number_of_devices;
729
730 const int len = smbios_full_table_len(&t->header, t->eos);
731 *current += len;
732 (*handle)++;
733 return len;
734}
735
736static int smbios_write_type17(unsigned long *current, int *handle, int type16)
737{
738 int totallen = 0;
739 int i;
740
741 struct memory_info *meminfo;
742 meminfo = cbmem_find(CBMEM_ID_MEMINFO);
743 if (meminfo == NULL)
744 return 0; /* can't find mem info in cbmem */
745
746 printk(BIOS_INFO, "Create SMBIOS type 17\n");
747 for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
748 struct dimm_info *d = &meminfo->dimm[i];
749 /*
750 * Windows 10 GetPhysicallyInstalledSystemMemory functions reads SMBIOS tables
751 * type 16 and type 17. The type 17 tables need to point to a type 16 table.
752 * Otherwise, the physical installed memory size is guessed from the system
753 * memory map, which results in a slightly smaller value than the actual size.
754 */
755 int len;
756 if (d->dimm_size > 0)
757 len = create_smbios_type17_for_dimm(d, current, handle, type16);
758 else
759 len = create_smbios_type17_for_empty_slot(d, current, handle, type16);
760
761 *current += len;
762 totallen += len;
763 }
764 return totallen;
765}
766
767static int smbios_write_type19(unsigned long *current, int *handle, int type16)
768{
769 int i;
770
771 struct memory_info *meminfo;
772 meminfo = cbmem_find(CBMEM_ID_MEMINFO);
773 if (meminfo == NULL)
774 return 0; /* can't find mem info in cbmem */
775
776 struct smbios_type19 *t = smbios_carve_table(*current,
777 SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS,
778 sizeof(*t), *handle);
779
780 t->memory_array_handle = type16;
781
782 for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
783 if (meminfo->dimm[i].dimm_size > 0) {
784 t->extended_ending_address += meminfo->dimm[i].dimm_size;
785 t->partition_width++;
786 }
787 }
788 t->extended_ending_address *= MiB;
789
790 /* Check if it fits into regular address */
791 if (t->extended_ending_address >= KiB &&
792 t->extended_ending_address < 0x40000000000ULL) {
793 /*
794 * FIXME: The starting address is SoC specific, but SMBIOS tables are only
795 * exported on x86 where it's always 0.
796 */
797
798 t->starting_address = 0;
799 t->ending_address = t->extended_ending_address / KiB - 1;
800 t->extended_starting_address = ~0;
801 t->extended_ending_address = ~0;
802 } else {
803 t->starting_address = ~0;
804 t->ending_address = ~0;
805 t->extended_starting_address = 0;
806 t->extended_ending_address--;
807 }
808
809 const int len = smbios_full_table_len(&t->header, t->eos);
810 *current += len;
811 *handle += 1;
812 return len;
813}
814
815static int smbios_write_type20_table(unsigned long *current, int *handle, u32 addr_start,
816 u32 addr_end, int type17_handle, int type19_handle)
817{
818 struct smbios_type20 *t = smbios_carve_table(*current, SMBIOS_MEMORY_DEVICE_MAPPED_ADDRESS,
819 sizeof(*t), *handle);
820
821 t->memory_device_handle = type17_handle;
822 t->memory_array_mapped_address_handle = type19_handle;
823 t->addr_start = addr_start;
824 t->addr_end = addr_end;
825 t->partition_row_pos = 0xff;
826 t->interleave_pos = 0xff;
827 t->interleave_depth = 0xff;
828
829 const int len = smbios_full_table_len(&t->header, t->eos);
830 *current += len;
831 *handle += 1;
832 return len;
833}
834
835static int smbios_write_type20(unsigned long *current, int *handle,
836 int type17_handle, int type19_handle)
837{
838 u32 start_addr = 0;
839 int totallen = 0;
840 int i;
841
842 struct memory_info *meminfo;
843 meminfo = cbmem_find(CBMEM_ID_MEMINFO);
844 if (meminfo == NULL)
845 return 0; /* can't find mem info in cbmem */
846
847 printk(BIOS_INFO, "Create SMBIOS type 20\n");
848 for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
849 struct dimm_info *dimm;
850 dimm = &meminfo->dimm[i];
851 if (dimm->dimm_size == 0)
852 continue;
853
854 u32 end_addr = start_addr + (dimm->dimm_size << 10) - 1;
855 totallen += smbios_write_type20_table(current, handle, start_addr, end_addr,
856 type17_handle, type19_handle);
857 start_addr = end_addr + 1;
858 }
859 return totallen;
860}
861
862int smbios_write_type28(unsigned long *current, int *handle,
863 const char *name,
864 const enum smbios_temp_location location,
865 const enum smbios_temp_status status,
866 u16 max_value, u16 min_value,
867 u16 resolution, u16 tolerance,
868 u16 accuracy,
869 u32 oem,
870 u16 nominal_value)
871{
872 struct smbios_type28 *t = smbios_carve_table(*current, SMBIOS_TEMPERATURE_PROBE,
873 sizeof(*t), *handle);
874
875 t->description = smbios_add_string(t->eos, name ? name : "Temperature");
876 t->location_and_status = location | (status << 5);
877 t->maximum_value = max_value;
878 t->minimum_value = min_value;
879 t->resolution = resolution;
880 t->tolerance = tolerance;
881 t->accuracy = accuracy;
882 t->oem_defined = oem;
883 t->nominal_value = nominal_value;
884
885 const int len = smbios_full_table_len(&t->header, t->eos);
886 *current += len;
887 *handle += 1;
888 return len;
889}
890
891static int smbios_write_type32(unsigned long *current, int handle)
892{
893 struct smbios_type32 *t = smbios_carve_table(*current, SMBIOS_SYSTEM_BOOT_INFORMATION,
894 sizeof(*t), handle);
895
896 const int len = smbios_full_table_len(&t->header, t->eos);
897 *current += len;
898 return len;
899}
900
901int smbios_write_type38(unsigned long *current, int *handle,
902 const enum smbios_bmc_interface_type interface_type,
903 const u8 ipmi_rev, const u8 i2c_addr, const u8 nv_addr,
904 const u64 base_addr, const u8 base_modifier,
905 const u8 irq)
906{
907 struct smbios_type38 *t = smbios_carve_table(*current, SMBIOS_IPMI_DEVICE_INFORMATION,
908 sizeof(*t), *handle);
909
910 t->interface_type = interface_type;
911 t->ipmi_rev = ipmi_rev;
912 t->i2c_slave_addr = i2c_addr;
913 t->nv_storage_addr = nv_addr;
914 t->base_address = base_addr;
915 t->base_address_modifier = base_modifier;
916 t->irq = irq;
917
918 const int len = smbios_full_table_len(&t->header, t->eos);
919 *current += len;
920 *handle += 1;
921 return len;
922}
923
924int smbios_write_type39(unsigned long *current, int *handle,
925 u8 unit_group, const char *loc, const char *dev_name,
926 const char *man, const char *serial_num,
927 const char *tag_num, const char *part_num,
928 const char *rev_lvl, u16 max_pow_cap,
929 const struct power_supply_ch *ps_ch)
930{
931 struct smbios_type39 *t = smbios_carve_table(*current,
932 SMBIOS_SYSTEM_POWER_SUPPLY,
933 sizeof(*t), *handle);
934
935 uint16_t val = 0;
936 uint16_t ps_type, ps_status, vol_switch, ps_unplug, ps_present, hot_rep;
937
938 t->power_unit_group = unit_group;
939 t->location = smbios_add_string(t->eos, loc);
940 t->device_name = smbios_add_string(t->eos, dev_name);
941 t->manufacturer = smbios_add_string(t->eos, man);
942 t->serial_number = smbios_add_string(t->eos, serial_num);
943 t->asset_tag_number = smbios_add_string(t->eos, tag_num);
944 t->model_part_number = smbios_add_string(t->eos, part_num);
945 t->revision_level = smbios_add_string(t->eos, rev_lvl);
946 t->max_power_capacity = max_pow_cap;
947
948 ps_type = ps_ch->power_supply_type & 0xF;
949 ps_status = ps_ch->power_supply_status & 0x7;
950 vol_switch = ps_ch->input_voltage_range_switch & 0xF;
951 ps_unplug = ps_ch->power_supply_unplugged & 0x1;
952 ps_present = ps_ch->power_supply_present & 0x1;
953 hot_rep = ps_ch->power_supply_hot_replaceble & 0x1;
954
955 val |= (ps_type << 10);
956 val |= (ps_status << 7);
957 val |= (vol_switch << 3);
958 val |= (ps_unplug << 2);
959 val |= (ps_present << 1);
960 val |= hot_rep;
961 t->power_supply_characteristics = val;
962
963 t->input_voltage_probe_handle = 0xFFFF;
964 t->cooling_device_handle = 0xFFFF;
965 t->input_current_probe_handle = 0xFFFF;
966
967 const int len = smbios_full_table_len(&t->header, t->eos);
968 *current += len;
969 *handle += 1;
970 return len;
971}
972
973int smbios_write_type41(unsigned long *current, int *handle,
Felix Held363ac8b2024-01-11 21:51:19 +0100974 const char *name, u8 instance, u16 segment_group,
Benjamin Doronea13dc32023-06-20 12:21:27 -0400975 u8 bus, u8 device, u8 function, u8 device_type)
976{
977 struct smbios_type41 *t = smbios_carve_table(*current,
978 SMBIOS_ONBOARD_DEVICES_EXTENDED_INFORMATION,
979 sizeof(*t), *handle);
980
981 t->reference_designation = smbios_add_string(t->eos, name);
982 t->device_type = device_type;
983 t->device_status = 1;
984 t->device_type_instance = instance;
Felix Held363ac8b2024-01-11 21:51:19 +0100985 t->segment_group_number = segment_group;
Benjamin Doronea13dc32023-06-20 12:21:27 -0400986 t->bus_number = bus;
987 t->device_number = device;
988 t->function_number = function;
989
990 const int len = smbios_full_table_len(&t->header, t->eos);
991 *current += len;
992 *handle += 1;
993 return len;
994}
995
996int smbios_write_type43(unsigned long *current, int *handle, const u32 vendor_id,
997 const u8 major_spec_ver, const u8 minor_spec_ver,
998 const u32 fw_ver1, const u32 fw_ver2, const char *description,
999 const u64 characteristics, const u32 oem_defined)
1000{
1001 struct smbios_type43 *t = smbios_carve_table(*current, SMBIOS_TPM_DEVICE,
1002 sizeof(*t), *handle);
1003
1004 t->vendor_id = vendor_id;
1005 t->major_spec_ver = major_spec_ver;
1006 t->minor_spec_ver = minor_spec_ver;
1007 t->fw_ver1 = fw_ver1;
1008 t->fw_ver2 = fw_ver2;
1009 t->characteristics = characteristics;
1010 t->oem_defined = oem_defined;
1011 t->description = smbios_add_string(t->eos, description);
1012
1013 const int len = smbios_full_table_len(&t->header, t->eos);
1014 *current += len;
1015 *handle += 1;
1016 return len;
1017}
1018
1019static int smbios_write_type127(unsigned long *current, int handle)
1020{
1021 struct smbios_type127 *t = smbios_carve_table(*current, SMBIOS_END_OF_TABLE,
1022 sizeof(*t), handle);
1023
1024 const int len = smbios_full_table_len(&t->header, t->eos);
1025 *current += len;
1026 return len;
1027}
1028
1029/* Get the device type 41 from the dev struct */
1030static u8 smbios_get_device_type_from_dev(struct device *dev)
1031{
1032 u16 pci_basesubclass = (dev->class >> 8) & 0xFFFF;
1033
1034 switch (pci_basesubclass) {
1035 case PCI_CLASS_NOT_DEFINED:
1036 return SMBIOS_DEVICE_TYPE_OTHER;
1037 case PCI_CLASS_DISPLAY_VGA:
1038 case PCI_CLASS_DISPLAY_XGA:
1039 case PCI_CLASS_DISPLAY_3D:
1040 case PCI_CLASS_DISPLAY_OTHER:
1041 return SMBIOS_DEVICE_TYPE_VIDEO;
1042 case PCI_CLASS_STORAGE_SCSI:
1043 return SMBIOS_DEVICE_TYPE_SCSI;
1044 case PCI_CLASS_NETWORK_ETHERNET:
1045 return SMBIOS_DEVICE_TYPE_ETHERNET;
1046 case PCI_CLASS_NETWORK_TOKEN_RING:
1047 return SMBIOS_DEVICE_TYPE_TOKEN_RING;
1048 case PCI_CLASS_MULTIMEDIA_VIDEO:
1049 case PCI_CLASS_MULTIMEDIA_AUDIO:
1050 case PCI_CLASS_MULTIMEDIA_PHONE:
1051 case PCI_CLASS_MULTIMEDIA_OTHER:
1052 return SMBIOS_DEVICE_TYPE_SOUND;
1053 case PCI_CLASS_STORAGE_ATA:
1054 return SMBIOS_DEVICE_TYPE_PATA;
1055 case PCI_CLASS_STORAGE_SATA:
1056 return SMBIOS_DEVICE_TYPE_SATA;
1057 case PCI_CLASS_STORAGE_SAS:
1058 return SMBIOS_DEVICE_TYPE_SAS;
1059 default:
1060 return SMBIOS_DEVICE_TYPE_UNKNOWN;
1061 }
1062}
1063
1064static bool smbios_get_type41_instance_id(struct device *dev, u8 device_type, u8 *instance_id)
1065{
1066#if CONFIG(SMBIOS_TYPE41_PROVIDED_BY_DEVTREE)
1067 *instance_id = dev->smbios_instance_id;
1068 return dev->smbios_instance_id_valid;
1069#else
1070 static u8 type41_inst_cnt[SMBIOS_DEVICE_TYPE_COUNT + 1] = {};
1071
1072 if (device_type == SMBIOS_DEVICE_TYPE_OTHER ||
1073 device_type == SMBIOS_DEVICE_TYPE_UNKNOWN)
1074 return false;
1075
1076 if (device_type > SMBIOS_DEVICE_TYPE_COUNT)
1077 return false;
1078
1079 *instance_id = type41_inst_cnt[device_type]++;
1080 return true;
1081#endif
1082}
1083
1084static const char *smbios_get_type41_refdes(struct device *dev)
1085{
1086#if CONFIG(SMBIOS_TYPE41_PROVIDED_BY_DEVTREE)
1087 if (dev->smbios_refdes)
1088 return dev->smbios_refdes;
1089#endif
1090#if CONFIG(PCI)
1091 return get_pci_subclass_name(dev);
1092#else
1093 return "???";
1094#endif
1095}
1096
1097static int smbios_generate_type41_from_devtree(struct device *dev, int *handle,
1098 unsigned long *current)
1099{
1100 if (dev->path.type != DEVICE_PATH_PCI)
1101 return 0;
1102 if (!dev->on_mainboard)
1103 return 0;
1104
1105 const u8 device_type = smbios_get_device_type_from_dev(dev);
1106
1107 u8 instance_id;
1108
1109 if (!smbios_get_type41_instance_id(dev, device_type, &instance_id))
1110 return 0;
1111
1112 const char *name = smbios_get_type41_refdes(dev);
1113
1114 return smbios_write_type41(current, handle,
1115 name, // name
1116 instance_id, // inst
Felix Held3b5b66d2024-01-11 22:26:18 +01001117 dev->bus->segment_group, // segment group
Benjamin Doronea13dc32023-06-20 12:21:27 -04001118 dev->bus->secondary, //bus
1119 PCI_SLOT(dev->path.pci.devfn), // device
1120 PCI_FUNC(dev->path.pci.devfn), // func
1121 device_type);
1122}
1123
1124static int smbios_generate_type9_from_devtree(struct device *dev, int *handle,
1125 unsigned long *current)
1126{
1127 enum misc_slot_usage usage;
1128 enum slot_data_bus_bandwidth bandwidth;
1129 enum misc_slot_type type;
1130 enum misc_slot_length length;
1131
1132 if (dev->path.type != DEVICE_PATH_PCI)
1133 return 0;
1134
1135 if (!dev->smbios_slot_type && !dev->smbios_slot_data_width &&
1136 !dev->smbios_slot_designation && !dev->smbios_slot_length)
1137 return 0;
1138
1139 if (dev_is_active_bridge(dev))
1140 usage = SlotUsageInUse;
1141 else if (dev->enabled)
1142 usage = SlotUsageAvailable;
1143 else
1144 usage = SlotUsageUnknown;
1145
1146 if (dev->smbios_slot_data_width)
1147 bandwidth = dev->smbios_slot_data_width;
1148 else
1149 bandwidth = SlotDataBusWidthUnknown;
1150
1151 if (dev->smbios_slot_type)
1152 type = dev->smbios_slot_type;
1153 else
1154 type = SlotTypeUnknown;
1155
1156 if (dev->smbios_slot_length)
1157 length = dev->smbios_slot_length;
1158 else
1159 length = SlotLengthUnknown;
1160
1161 return smbios_write_type9(current, handle,
1162 dev->smbios_slot_designation,
1163 type,
1164 bandwidth,
1165 usage,
1166 length,
1167 0,
1168 1,
1169 0,
Felix Held3b5b66d2024-01-11 22:26:18 +01001170 dev->bus->segment_group,
Benjamin Doronea13dc32023-06-20 12:21:27 -04001171 dev->bus->secondary,
1172 dev->path.pci.devfn);
1173}
1174
1175int get_smbios_data(struct device *dev, int *handle, unsigned long *current)
1176{
1177 int len = 0;
1178
1179 len += smbios_generate_type9_from_devtree(dev, handle, current);
1180 len += smbios_generate_type41_from_devtree(dev, handle, current);
1181
1182 return len;
1183}
1184
1185static int smbios_walk_device_tree(struct device *tree, int *handle, unsigned long *current)
1186{
1187 struct device *dev;
1188 int len = 0;
1189
1190 for (dev = tree; dev; dev = dev->next) {
1191 if (!dev->enabled)
1192 continue;
1193
1194 if (dev->ops && dev->ops->get_smbios_data) {
1195 printk(BIOS_INFO, "%s (%s)\n", dev_path(dev), dev_name(dev));
1196 len += dev->ops->get_smbios_data(dev, handle, current);
1197 } else {
1198 len += get_smbios_data(dev, handle, current);
1199 }
1200 }
1201 return len;
1202}
1203
1204unsigned long smbios_write_tables(unsigned long current)
1205{
1206 struct smbios_entry *se;
1207 struct smbios_entry30 *se3;
1208 unsigned long tables;
1209 int len = 0;
1210 int max_struct_size = 0;
1211 int handle = 0;
1212
1213 current = ALIGN_UP(current, 16);
1214 printk(BIOS_DEBUG, "%s: %08lx\n", __func__, current);
1215
1216 se = (struct smbios_entry *)current;
1217 current += sizeof(*se);
1218 current = ALIGN_UP(current, 16);
1219
1220 se3 = (struct smbios_entry30 *)current;
1221 current += sizeof(*se3);
1222 current = ALIGN_UP(current, 16);
1223
1224 tables = current;
1225 update_max(len, max_struct_size, smbios_write_type0(&current, handle++));
1226 update_max(len, max_struct_size, smbios_write_type1(&current, handle++));
1227
1228 /* The chassis handle is the next one */
1229 update_max(len, max_struct_size, smbios_write_type2(&current, handle, handle + 1));
1230 handle++;
1231 update_max(len, max_struct_size, smbios_write_type3(&current, handle++));
1232
1233 struct smbios_type4 *type4 = (struct smbios_type4 *)current;
1234 update_max(len, max_struct_size, smbios_write_type4(&current, handle++));
1235 len += smbios_write_type7_cache_parameters(&current, &handle, &max_struct_size, type4);
1236 update_max(len, max_struct_size, smbios_write_type11(&current, &handle));
1237 if (CONFIG(ELOG))
1238 update_max(len, max_struct_size,
1239 elog_smbios_write_type15(&current, handle++));
1240
1241 const int type16 = handle;
1242 update_max(len, max_struct_size, smbios_write_type16(&current, &handle));
1243 const int type17 = handle;
1244 update_max(len, max_struct_size, smbios_write_type17(&current, &handle, type16));
1245 const int type19 = handle;
1246 update_max(len, max_struct_size, smbios_write_type19(&current, &handle, type16));
1247 update_max(len, max_struct_size,
1248 smbios_write_type20(&current, &handle, type17, type19));
1249 update_max(len, max_struct_size, smbios_write_type32(&current, handle++));
1250
1251 update_max(len, max_struct_size, smbios_walk_device_tree(all_devices,
1252 &handle, &current));
1253
1254 update_max(len, max_struct_size, smbios_write_type127(&current, handle++));
1255
1256 /* Install SMBIOS 2.1 entry point */
1257 memset(se, 0, sizeof(*se));
1258 memcpy(se->anchor, "_SM_", 4);
1259 se->length = sizeof(*se);
1260 se->major_version = 3;
1261 se->minor_version = 0;
1262 se->max_struct_size = max_struct_size;
1263 se->struct_count = handle;
1264 memcpy(se->intermediate_anchor_string, "_DMI_", 5);
1265
1266 se->struct_table_address = (u32)tables;
1267 se->struct_table_length = len;
1268
1269 se->intermediate_checksum = smbios_checksum((u8 *)se + 0x10, sizeof(*se) - 0x10);
1270 se->checksum = smbios_checksum((u8 *)se, sizeof(*se));
1271
1272 /* Install SMBIOS 3.0 entry point */
1273 memset(se3, 0, sizeof(*se3));
1274 memcpy(se3->anchor, "_SM3_", 5);
1275 se3->length = sizeof(*se3);
1276 se3->major_version = 3;
1277 se3->minor_version = 0;
1278
1279 se3->struct_table_address = (u64)tables;
1280 se3->struct_table_length = len;
1281
1282 se3->checksum = smbios_checksum((u8 *)se3, sizeof(*se3));
1283
1284 return current;
1285}