soc/intel/common/block: fix storage size of HEST log address
[coreboot.git] / src / arch / x86 / smbios.c
blob9b47ff67aef899e6bc9a017e321d5738f09c944c
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <string.h>
4 #include <smbios.h>
5 #include <console/console.h>
6 #include <version.h>
7 #include <device/device.h>
8 #include <device/dram/spd.h>
9 #include <arch/cpu.h>
10 #include <cpu/x86/name.h>
11 #include <elog.h>
12 #include <endian.h>
13 #include <memory_info.h>
14 #include <spd.h>
15 #include <cbmem.h>
16 #include <commonlib/helpers.h>
17 #include <device/pci_ids.h>
18 #include <device/pci_def.h>
19 #include <device/pci.h>
20 #include <drivers/vpd/vpd.h>
21 #include <stdlib.h>
23 #define update_max(len, max_len, stmt) \
24 do { \
25 int tmp = stmt; \
27 max_len = MAX(max_len, tmp); \
28 len += tmp; \
29 } while (0)
31 static u8 smbios_checksum(u8 *p, u32 length)
33 u8 ret = 0;
34 while (length--)
35 ret += *p++;
36 return -ret;
39 /* Get the device type 41 from the dev struct */
40 static u8 smbios_get_device_type_from_dev(struct device *dev)
42 u16 pci_basesubclass = (dev->class >> 8) & 0xFFFF;
44 switch (pci_basesubclass) {
45 case PCI_CLASS_NOT_DEFINED:
46 return SMBIOS_DEVICE_TYPE_OTHER;
47 case PCI_CLASS_DISPLAY_VGA:
48 case PCI_CLASS_DISPLAY_XGA:
49 case PCI_CLASS_DISPLAY_3D:
50 case PCI_CLASS_DISPLAY_OTHER:
51 return SMBIOS_DEVICE_TYPE_VIDEO;
52 case PCI_CLASS_STORAGE_SCSI:
53 return SMBIOS_DEVICE_TYPE_SCSI;
54 case PCI_CLASS_NETWORK_ETHERNET:
55 return SMBIOS_DEVICE_TYPE_ETHERNET;
56 case PCI_CLASS_NETWORK_TOKEN_RING:
57 return SMBIOS_DEVICE_TYPE_TOKEN_RING;
58 case PCI_CLASS_MULTIMEDIA_VIDEO:
59 case PCI_CLASS_MULTIMEDIA_AUDIO:
60 case PCI_CLASS_MULTIMEDIA_PHONE:
61 case PCI_CLASS_MULTIMEDIA_OTHER:
62 return SMBIOS_DEVICE_TYPE_SOUND;
63 case PCI_CLASS_STORAGE_ATA:
64 return SMBIOS_DEVICE_TYPE_PATA;
65 case PCI_CLASS_STORAGE_SATA:
66 return SMBIOS_DEVICE_TYPE_SATA;
67 case PCI_CLASS_STORAGE_SAS:
68 return SMBIOS_DEVICE_TYPE_SAS;
69 default:
70 return SMBIOS_DEVICE_TYPE_UNKNOWN;
74 int smbios_add_string(u8 *start, const char *str)
76 int i = 1;
77 char *p = (char *)start;
80 * Return 0 as required for empty strings.
81 * See Section 6.1.3 "Text Strings" of the SMBIOS specification.
83 if (*str == '\0')
84 return 0;
86 for (;;) {
87 if (!*p) {
88 strcpy(p, str);
89 p += strlen(str);
90 *p++ = '\0';
91 *p++ = '\0';
92 return i;
95 if (!strcmp(p, str))
96 return i;
98 p += strlen(p)+1;
99 i++;
103 int smbios_string_table_len(u8 *start)
105 char *p = (char *)start;
106 int i, len = 0;
108 while (*p) {
109 i = strlen(p) + 1;
110 p += i;
111 len += i;
114 if (!len)
115 return 2;
117 return len + 1;
120 static int smbios_cpu_vendor(u8 *start)
122 if (cpu_have_cpuid()) {
123 u32 tmp[4];
124 const struct cpuid_result res = cpuid(0);
125 tmp[0] = res.ebx;
126 tmp[1] = res.edx;
127 tmp[2] = res.ecx;
128 tmp[3] = 0;
129 return smbios_add_string(start, (const char *)tmp);
130 } else {
131 return smbios_add_string(start, "Unknown");
135 static int smbios_processor_name(u8 *start)
137 u32 tmp[13];
138 const char *str = "Unknown Processor Name";
139 if (cpu_have_cpuid()) {
140 int i;
141 struct cpuid_result res = cpuid(0x80000000);
142 if (res.eax >= 0x80000004) {
143 int j = 0;
144 for (i = 0; i < 3; i++) {
145 res = cpuid(0x80000002 + i);
146 tmp[j++] = res.eax;
147 tmp[j++] = res.ebx;
148 tmp[j++] = res.ecx;
149 tmp[j++] = res.edx;
151 tmp[12] = 0;
152 str = (const char *)tmp;
155 return smbios_add_string(start, str);
158 /* this function will fill the corresponding manufacturer */
159 void smbios_fill_dimm_manufacturer_from_id(uint16_t mod_id, struct smbios_type17 *t)
161 const char *const manufacturer = spd_manufacturer_name(mod_id);
163 if (manufacturer) {
164 t->manufacturer = smbios_add_string(t->eos, manufacturer);
165 } else {
166 char string_buffer[256];
168 snprintf(string_buffer, sizeof(string_buffer), "Unknown (%x)", mod_id);
169 t->manufacturer = smbios_add_string(t->eos, string_buffer);
173 static void trim_trailing_whitespace(char *buffer, size_t buffer_size)
175 size_t len = strnlen(buffer, buffer_size);
177 if (len == 0)
178 return;
180 for (char *p = buffer + len - 1; p >= buffer; --p) {
181 if (*p == ' ')
182 *p = 0;
183 else
184 break;
188 /** This function will fill the corresponding part number */
189 static void smbios_fill_dimm_part_number(const char *part_number, struct smbios_type17 *t)
191 int invalid;
192 size_t i, len;
193 char trimmed_part_number[DIMM_INFO_PART_NUMBER_SIZE];
195 strncpy(trimmed_part_number, part_number, sizeof(trimmed_part_number));
196 trimmed_part_number[sizeof(trimmed_part_number) - 1] = '\0';
199 * SPD mandates that unused characters be represented with a ' '.
200 * We don't want to publish the whitespace in the SMBIOS tables.
202 trim_trailing_whitespace(trimmed_part_number, sizeof(trimmed_part_number));
204 len = strlen(trimmed_part_number);
206 invalid = 0; /* assume valid */
207 for (i = 0; i < len; i++) {
208 if (trimmed_part_number[i] < ' ') {
209 invalid = 1;
210 trimmed_part_number[i] = '*';
214 if (len == 0) {
215 /* Null String in Part Number will have "None" instead. */
216 t->part_number = smbios_add_string(t->eos, "None");
217 } else if (invalid) {
218 char string_buffer[sizeof(trimmed_part_number) + 10];
220 snprintf(string_buffer, sizeof(string_buffer), "Invalid (%s)",
221 trimmed_part_number);
222 t->part_number = smbios_add_string(t->eos, string_buffer);
223 } else {
224 t->part_number = smbios_add_string(t->eos, trimmed_part_number);
228 /* Encodes the SPD serial number into hex */
229 static void smbios_fill_dimm_serial_number(const struct dimm_info *dimm,
230 struct smbios_type17 *t)
232 char serial[9];
234 snprintf(serial, sizeof(serial), "%02hhx%02hhx%02hhx%02hhx",
235 dimm->serial[0], dimm->serial[1], dimm->serial[2], dimm->serial[3]);
237 t->serial_number = smbios_add_string(t->eos, serial);
240 static int create_smbios_type17_for_dimm(struct dimm_info *dimm,
241 unsigned long *current, int *handle,
242 int type16_handle)
244 struct smbios_type17 *t = (struct smbios_type17 *)*current;
246 memset(t, 0, sizeof(struct smbios_type17));
247 t->memory_type = dimm->ddr_type;
248 if (dimm->configured_speed_mts != 0)
249 t->clock_speed = dimm->configured_speed_mts;
250 else
251 t->clock_speed = dimm->ddr_frequency;
252 if (dimm->max_speed_mts != 0)
253 t->speed = dimm->max_speed_mts;
254 else
255 t->speed = dimm->ddr_frequency;
256 t->type = SMBIOS_MEMORY_DEVICE;
257 if (dimm->dimm_size < 0x7fff) {
258 t->size = dimm->dimm_size;
259 } else {
260 t->size = 0x7fff;
261 t->extended_size = dimm->dimm_size & 0x7fffffff;
263 t->data_width = 8 * (1 << (dimm->bus_width & 0x7));
264 t->total_width = t->data_width + 8 * ((dimm->bus_width & 0x18) >> 3);
266 switch (dimm->mod_type) {
267 case SPD_RDIMM:
268 case SPD_MINI_RDIMM:
269 t->form_factor = MEMORY_FORMFACTOR_RIMM;
270 break;
271 case SPD_UDIMM:
272 case SPD_MICRO_DIMM:
273 case SPD_MINI_UDIMM:
274 t->form_factor = MEMORY_FORMFACTOR_DIMM;
275 break;
276 case SPD_SODIMM:
277 t->form_factor = MEMORY_FORMFACTOR_SODIMM;
278 break;
279 default:
280 t->form_factor = MEMORY_FORMFACTOR_UNKNOWN;
281 break;
284 smbios_fill_dimm_manufacturer_from_id(dimm->mod_id, t);
285 smbios_fill_dimm_serial_number(dimm, t);
286 smbios_fill_dimm_asset_tag(dimm, t);
287 smbios_fill_dimm_locator(dimm, t);
289 /* put '\0' in the end of data */
290 dimm->module_part_number[DIMM_INFO_PART_NUMBER_SIZE - 1] = '\0';
291 smbios_fill_dimm_part_number((char *)dimm->module_part_number, t);
293 /* Voltage Levels */
294 t->configured_voltage = dimm->vdd_voltage;
295 t->minimum_voltage = dimm->vdd_voltage;
296 t->maximum_voltage = dimm->vdd_voltage;
298 /* Fill in type detail */
299 switch (dimm->mod_type) {
300 case SPD_RDIMM:
301 case SPD_MINI_RDIMM:
302 t->type_detail = MEMORY_TYPE_DETAIL_REGISTERED;
303 break;
304 case SPD_UDIMM:
305 case SPD_MINI_UDIMM:
306 t->type_detail = MEMORY_TYPE_DETAIL_UNBUFFERED;
307 break;
308 default:
309 t->type_detail = MEMORY_TYPE_DETAIL_UNKNOWN;
310 break;
312 /* Synchronous = 1 */
313 t->type_detail |= MEMORY_TYPE_DETAIL_SYNCHRONOUS;
314 /* no handle for error information */
315 t->memory_error_information_handle = 0xFFFE;
316 t->attributes = dimm->rank_per_dimm;
317 t->handle = *handle;
318 t->phys_memory_array_handle = type16_handle;
320 *handle += 1;
321 t->length = sizeof(struct smbios_type17) - 2;
322 return t->length + smbios_string_table_len(t->eos);
325 #define VERSION_VPD "firmware_version"
326 static const char *vpd_get_bios_version(void)
328 int size;
329 const char *s;
330 char *version;
332 s = vpd_find(VERSION_VPD, &size, VPD_RO);
333 if (!s) {
334 printk(BIOS_ERR, "Find version from VPD %s failed\n", VERSION_VPD);
335 return NULL;
338 version = malloc(size + 1);
339 if (!version) {
340 printk(BIOS_ERR, "Failed to malloc %d bytes for VPD version\n", size + 1);
341 return NULL;
343 memcpy(version, s, size);
344 version[size] = '\0';
345 printk(BIOS_DEBUG, "Firmware version %s from VPD %s\n", version, VERSION_VPD);
346 return version;
349 static const char *get_bios_version(void)
351 const char *s;
353 #define SPACES \
356 if (CONFIG(CHROMEOS))
357 return SPACES;
359 if (CONFIG(VPD_SMBIOS_VERSION)) {
360 s = vpd_get_bios_version();
361 if (s != NULL)
362 return s;
365 s = smbios_mainboard_bios_version();
366 if (s != NULL)
367 return s;
369 if (strlen(CONFIG_LOCALVERSION) != 0) {
370 printk(BIOS_DEBUG, "BIOS version set to CONFIG_LOCALVERSION: '%s'\n",
371 CONFIG_LOCALVERSION);
372 return CONFIG_LOCALVERSION;
375 printk(BIOS_DEBUG, "SMBIOS firmware version is set to coreboot_version: '%s'\n",
376 coreboot_version);
377 return coreboot_version;
380 static int smbios_write_type0(unsigned long *current, int handle)
382 struct smbios_type0 *t = (struct smbios_type0 *)*current;
383 int len = sizeof(struct smbios_type0);
385 memset(t, 0, sizeof(struct smbios_type0));
386 t->type = SMBIOS_BIOS_INFORMATION;
387 t->handle = handle;
388 t->length = len - 2;
390 t->vendor = smbios_add_string(t->eos, "coreboot");
391 t->bios_release_date = smbios_add_string(t->eos, coreboot_dmi_date);
393 if (CONFIG(CHROMEOS_NVS)) {
394 uintptr_t version_address = (uintptr_t)t->eos;
395 /* SMBIOS offsets start at 1 rather than 0 */
396 version_address += (u32)smbios_string_table_len(t->eos) - 1;
397 smbios_type0_bios_version(version_address);
399 t->bios_version = smbios_add_string(t->eos, get_bios_version());
400 uint32_t rom_size = CONFIG_ROM_SIZE;
401 rom_size = MIN(CONFIG_ROM_SIZE, 16 * MiB);
402 t->bios_rom_size = (rom_size / 65535) - 1;
404 if (CONFIG_ROM_SIZE >= 1 * GiB) {
405 t->extended_bios_rom_size = DIV_ROUND_UP(CONFIG_ROM_SIZE, GiB) | (1 << 14);
406 } else {
407 t->extended_bios_rom_size = DIV_ROUND_UP(CONFIG_ROM_SIZE, MiB);
410 t->system_bios_major_release = coreboot_major_revision;
411 t->system_bios_minor_release = coreboot_minor_revision;
413 smbios_ec_revision(&t->ec_major_release, &t->ec_minor_release);
415 t->bios_characteristics =
416 BIOS_CHARACTERISTICS_PCI_SUPPORTED |
417 BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
418 BIOS_CHARACTERISTICS_UPGRADEABLE;
420 if (CONFIG(CARDBUS_PLUGIN_SUPPORT))
421 t->bios_characteristics |= BIOS_CHARACTERISTICS_PC_CARD;
423 if (CONFIG(HAVE_ACPI_TABLES))
424 t->bios_characteristics_ext1 = BIOS_EXT1_CHARACTERISTICS_ACPI;
426 t->bios_characteristics_ext2 = BIOS_EXT2_CHARACTERISTICS_TARGET;
427 len = t->length + smbios_string_table_len(t->eos);
428 *current += len;
429 return len;
432 static int get_socket_type(void)
434 if (CONFIG(CPU_INTEL_SLOT_1))
435 return 0x08;
436 if (CONFIG(CPU_INTEL_SOCKET_MPGA604))
437 return 0x13;
438 if (CONFIG(CPU_INTEL_SOCKET_LGA775))
439 return 0x15;
440 if (CONFIG(XEON_SP_COMMON_BASE))
441 return 0x36;
443 return 0x02; /* Unknown */
446 unsigned int __weak smbios_processor_external_clock(void)
448 return 0; /* Unknown */
451 unsigned int __weak smbios_processor_characteristics(void)
453 return 0;
456 unsigned int __weak smbios_processor_family(struct cpuid_result res)
458 return (res.eax > 0) ? 0x0c : 0x6;
461 unsigned int __weak smbios_cache_error_correction_type(u8 level)
463 return SMBIOS_CACHE_ERROR_CORRECTION_UNKNOWN;
466 unsigned int __weak smbios_cache_sram_type(void)
468 return SMBIOS_CACHE_SRAM_TYPE_UNKNOWN;
471 unsigned int __weak smbios_cache_conf_operation_mode(u8 level)
473 return SMBIOS_CACHE_OP_MODE_UNKNOWN; /* Unknown */
476 /* Returns the processor voltage in 100mV units */
477 unsigned int __weak smbios_cpu_get_voltage(void)
479 return 0; /* Unknown */
482 static size_t get_number_of_caches(struct cpuid_result res_deterministic_cache)
484 size_t max_logical_cpus_sharing_cache = 0;
485 size_t number_of_cpus_per_package = 0;
486 size_t max_logical_cpus_per_package = 0;
487 struct cpuid_result res;
489 if (!cpu_have_cpuid())
490 return 1;
492 res = cpuid(1);
494 max_logical_cpus_per_package = (res.ebx >> 16) & 0xff;
496 max_logical_cpus_sharing_cache = ((res_deterministic_cache.eax >> 14) & 0xfff) + 1;
498 /* Check if it's last level cache */
499 if (max_logical_cpus_sharing_cache == max_logical_cpus_per_package)
500 return 1;
502 if (cpuid_get_max_func() >= 0xb) {
503 res = cpuid_ext(0xb, 1);
504 number_of_cpus_per_package = res.ebx & 0xff;
505 } else {
506 number_of_cpus_per_package = max_logical_cpus_per_package;
509 return number_of_cpus_per_package / max_logical_cpus_sharing_cache;
512 static int smbios_write_type1(unsigned long *current, int handle)
514 struct smbios_type1 *t = (struct smbios_type1 *)*current;
515 int len = sizeof(struct smbios_type1);
517 memset(t, 0, sizeof(struct smbios_type1));
518 t->type = SMBIOS_SYSTEM_INFORMATION;
519 t->handle = handle;
520 t->length = len - 2;
521 t->manufacturer = smbios_add_string(t->eos, smbios_system_manufacturer());
522 t->product_name = smbios_add_string(t->eos, smbios_system_product_name());
523 t->serial_number = smbios_add_string(t->eos, smbios_system_serial_number());
524 t->sku = smbios_add_string(t->eos, smbios_system_sku());
525 t->version = smbios_add_string(t->eos, smbios_system_version());
526 #ifdef CONFIG_MAINBOARD_FAMILY
527 t->family = smbios_add_string(t->eos, CONFIG_MAINBOARD_FAMILY);
528 #endif
529 smbios_system_set_uuid(t->uuid);
530 len = t->length + smbios_string_table_len(t->eos);
531 *current += len;
532 return len;
535 static int smbios_write_type2(unsigned long *current, int handle, const int chassis_handle)
537 struct smbios_type2 *t = (struct smbios_type2 *)*current;
538 int len = sizeof(struct smbios_type2);
540 memset(t, 0, sizeof(struct smbios_type2));
541 t->type = SMBIOS_BOARD_INFORMATION;
542 t->handle = handle;
543 t->length = len - 2;
544 t->manufacturer = smbios_add_string(t->eos, smbios_mainboard_manufacturer());
545 t->product_name = smbios_add_string(t->eos, smbios_mainboard_product_name());
546 t->serial_number = smbios_add_string(t->eos, smbios_mainboard_serial_number());
547 t->version = smbios_add_string(t->eos, smbios_mainboard_version());
548 t->asset_tag = smbios_add_string(t->eos, smbios_mainboard_asset_tag());
549 t->feature_flags = smbios_mainboard_feature_flags();
550 t->location_in_chassis = smbios_add_string(t->eos,
551 smbios_mainboard_location_in_chassis());
552 t->board_type = smbios_mainboard_board_type();
553 t->chassis_handle = chassis_handle;
554 len = t->length + smbios_string_table_len(t->eos);
555 *current += len;
556 return len;
559 static int smbios_write_type3(unsigned long *current, int handle)
561 struct smbios_type3 *t = (struct smbios_type3 *)*current;
562 int len = sizeof(struct smbios_type3);
564 memset(t, 0, sizeof(struct smbios_type3));
565 t->type = SMBIOS_SYSTEM_ENCLOSURE;
566 t->handle = handle;
567 t->length = len - 2;
568 t->manufacturer = smbios_add_string(t->eos, smbios_system_manufacturer());
569 t->bootup_state = SMBIOS_STATE_SAFE;
570 t->power_supply_state = SMBIOS_STATE_SAFE;
571 t->thermal_state = SMBIOS_STATE_SAFE;
572 t->_type = smbios_mainboard_enclosure_type();
573 t->security_status = SMBIOS_STATE_SAFE;
574 t->number_of_power_cords = smbios_chassis_power_cords();
575 t->asset_tag_number = smbios_add_string(t->eos, smbios_mainboard_asset_tag());
576 t->version = smbios_add_string(t->eos, smbios_chassis_version());
577 t->serial_number = smbios_add_string(t->eos, smbios_chassis_serial_number());
578 len = t->length + smbios_string_table_len(t->eos);
579 *current += len;
580 return len;
583 static int smbios_write_type4(unsigned long *current, int handle)
585 unsigned int cpu_voltage;
586 struct cpuid_result res;
587 struct smbios_type4 *t = (struct smbios_type4 *)*current;
588 int len = sizeof(struct smbios_type4);
589 uint16_t characteristics = 0;
590 static unsigned int cnt = 0;
591 char buf[8];
593 /* Provide sane defaults even for CPU without CPUID */
594 res.eax = res.edx = 0;
595 res.ebx = 0x10000;
597 if (cpu_have_cpuid())
598 res = cpuid(1);
600 memset(t, 0, sizeof(struct smbios_type4));
601 t->type = SMBIOS_PROCESSOR_INFORMATION;
602 t->handle = handle;
603 t->length = len - 2;
605 snprintf(buf, sizeof(buf), "CPU%d", cnt++);
606 t->socket_designation = smbios_add_string(t->eos, buf);
608 t->processor_id[0] = res.eax;
609 t->processor_id[1] = res.edx;
610 t->processor_manufacturer = smbios_cpu_vendor(t->eos);
611 t->processor_version = smbios_processor_name(t->eos);
612 t->processor_family = smbios_processor_family(res);
613 t->processor_type = 3; /* System Processor */
615 * If CPUID leaf 11 is available, calculate "core count" by dividing
616 * SMT_ID (logical processors in a core) by Core_ID (number of cores).
617 * This seems to be the way to arrive to a number of cores mentioned on
618 * ark.intel.com.
620 if (cpu_have_cpuid() && cpuid_get_max_func() >= 0xb) {
621 uint32_t leaf_b_cores = 0, leaf_b_threads = 0;
622 res = cpuid_ext(0xb, 1);
623 leaf_b_cores = res.ebx;
624 res = cpuid_ext(0xb, 0);
625 leaf_b_threads = res.ebx;
626 /* if hyperthreading is not available, pretend this is 1 */
627 if (leaf_b_threads == 0) {
628 leaf_b_threads = 1;
630 t->core_count2 = leaf_b_cores / leaf_b_threads;
631 t->core_count = t->core_count2 > 0xff ? 0xff : t->core_count2;
632 t->thread_count2 = leaf_b_cores;
633 t->thread_count = t->thread_count2 > 0xff ? 0xff : t->thread_count2;
634 } else {
635 t->core_count = (res.ebx >> 16) & 0xff;
636 t->core_count2 = t->core_count;
637 t->thread_count2 = t->core_count2;
638 t->thread_count = t->thread_count2;
640 /* Assume we enable all the cores always, capped only by MAX_CPUS */
641 t->core_enabled = MIN(t->core_count, CONFIG_MAX_CPUS);
642 t->core_enabled2 = MIN(t->core_count2, CONFIG_MAX_CPUS);
643 t->l1_cache_handle = 0xffff;
644 t->l2_cache_handle = 0xffff;
645 t->l3_cache_handle = 0xffff;
646 t->serial_number = smbios_add_string(t->eos, smbios_processor_serial_number());
647 t->status = SMBIOS_PROCESSOR_STATUS_CPU_ENABLED | SMBIOS_PROCESSOR_STATUS_POPULATED;
648 t->processor_upgrade = get_socket_type();
649 len = t->length + smbios_string_table_len(t->eos);
650 if (cpu_have_cpuid() && cpuid_get_max_func() >= 0x16) {
651 t->current_speed = cpuid_eax(0x16); /* base frequency */
652 t->external_clock = cpuid_ecx(0x16);
653 } else {
654 t->current_speed = smbios_cpu_get_current_speed_mhz();
655 t->external_clock = smbios_processor_external_clock();
658 /* This field identifies a capability for the system, not the processor itself. */
659 t->max_speed = smbios_cpu_get_max_speed_mhz();
661 if (cpu_have_cpuid()) {
662 res = cpuid(1);
664 if ((res.ecx) & BIT(5))
665 characteristics |= BIT(6); /* BIT6: Enhanced Virtualization */
667 if ((res.edx) & BIT(28))
668 characteristics |= BIT(4); /* BIT4: Hardware Thread */
670 if (((cpuid_eax(0x80000000) - 0x80000000) + 1) > 2) {
671 res = cpuid(0x80000001);
673 if ((res.edx) & BIT(20))
674 characteristics |= BIT(5); /* BIT5: Execute Protection */
677 t->processor_characteristics = characteristics | smbios_processor_characteristics();
678 cpu_voltage = smbios_cpu_get_voltage();
679 if (cpu_voltage > 0)
680 t->voltage = 0x80 | cpu_voltage;
682 *current += len;
683 return len;
687 * Write SMBIOS type 7.
688 * Fill in some fields with constant values, as gathering the information
689 * from CPUID is impossible.
691 static int smbios_write_type7(unsigned long *current,
692 const int handle,
693 const u8 level,
694 const u8 sram_type,
695 const enum smbios_cache_associativity associativity,
696 const enum smbios_cache_type type,
697 const size_t max_cache_size,
698 const size_t cache_size)
700 struct smbios_type7 *t = (struct smbios_type7 *)*current;
701 int len = sizeof(struct smbios_type7);
702 char buf[8];
704 memset(t, 0, sizeof(struct smbios_type7));
705 t->type = SMBIOS_CACHE_INFORMATION;
706 t->handle = handle;
707 t->length = len - 2;
709 snprintf(buf, sizeof(buf), "CACHE%x", level);
710 t->socket_designation = smbios_add_string(t->eos, buf);
712 t->cache_configuration = SMBIOS_CACHE_CONF_LEVEL(level) |
713 SMBIOS_CACHE_CONF_LOCATION(0) | /* Internal */
714 SMBIOS_CACHE_CONF_ENABLED(1) | /* Enabled */
715 SMBIOS_CACHE_CONF_OPERATION_MODE(smbios_cache_conf_operation_mode(level));
717 if (max_cache_size < (SMBIOS_CACHE_SIZE_MASK * KiB)) {
718 t->max_cache_size = max_cache_size / KiB;
719 t->max_cache_size2 = t->max_cache_size;
721 t->max_cache_size |= SMBIOS_CACHE_SIZE_UNIT_1KB;
722 t->max_cache_size2 |= SMBIOS_CACHE_SIZE2_UNIT_1KB;
723 } else {
724 if (max_cache_size < (SMBIOS_CACHE_SIZE_MASK * 64 * KiB))
725 t->max_cache_size = max_cache_size / (64 * KiB);
726 else
727 t->max_cache_size = SMBIOS_CACHE_SIZE_OVERFLOW;
728 t->max_cache_size2 = max_cache_size / (64 * KiB);
730 t->max_cache_size |= SMBIOS_CACHE_SIZE_UNIT_64KB;
731 t->max_cache_size2 |= SMBIOS_CACHE_SIZE2_UNIT_64KB;
734 if (cache_size < (SMBIOS_CACHE_SIZE_MASK * KiB)) {
735 t->installed_size = cache_size / KiB;
736 t->installed_size2 = t->installed_size;
738 t->installed_size |= SMBIOS_CACHE_SIZE_UNIT_1KB;
739 t->installed_size2 |= SMBIOS_CACHE_SIZE2_UNIT_1KB;
740 } else {
741 if (cache_size < (SMBIOS_CACHE_SIZE_MASK * 64 * KiB))
742 t->installed_size = cache_size / (64 * KiB);
743 else
744 t->installed_size = SMBIOS_CACHE_SIZE_OVERFLOW;
745 t->installed_size2 = cache_size / (64 * KiB);
747 t->installed_size |= SMBIOS_CACHE_SIZE_UNIT_64KB;
748 t->installed_size2 |= SMBIOS_CACHE_SIZE2_UNIT_64KB;
751 t->associativity = associativity;
752 t->supported_sram_type = sram_type;
753 t->current_sram_type = sram_type;
754 t->cache_speed = 0; /* Unknown */
755 t->error_correction_type = smbios_cache_error_correction_type(level);
756 t->system_cache_type = type;
758 len = t->length + smbios_string_table_len(t->eos);
759 *current += len;
760 return len;
763 /* Convert the associativity as integer to the SMBIOS enum if available */
764 static enum smbios_cache_associativity smbios_cache_associativity(const u8 num)
766 switch (num) {
767 case 1:
768 return SMBIOS_CACHE_ASSOCIATIVITY_DIRECT;
769 case 2:
770 return SMBIOS_CACHE_ASSOCIATIVITY_2WAY;
771 case 4:
772 return SMBIOS_CACHE_ASSOCIATIVITY_4WAY;
773 case 8:
774 return SMBIOS_CACHE_ASSOCIATIVITY_8WAY;
775 case 12:
776 return SMBIOS_CACHE_ASSOCIATIVITY_12WAY;
777 case 16:
778 return SMBIOS_CACHE_ASSOCIATIVITY_16WAY;
779 case 20:
780 return SMBIOS_CACHE_ASSOCIATIVITY_20WAY;
781 case 24:
782 return SMBIOS_CACHE_ASSOCIATIVITY_24WAY;
783 case 32:
784 return SMBIOS_CACHE_ASSOCIATIVITY_32WAY;
785 case 48:
786 return SMBIOS_CACHE_ASSOCIATIVITY_48WAY;
787 case 64:
788 return SMBIOS_CACHE_ASSOCIATIVITY_64WAY;
789 case 0xff:
790 return SMBIOS_CACHE_ASSOCIATIVITY_FULL;
791 default:
792 return SMBIOS_CACHE_ASSOCIATIVITY_UNKNOWN;
797 * Parse the "Deterministic Cache Parameters" as provided by Intel in
798 * leaf 4 or AMD in extended leaf 0x8000001d.
800 * @param current Pointer to memory address to write the tables to
801 * @param handle Pointer to handle for the tables
802 * @param max_struct_size Pointer to maximum struct size
803 * @param type4 Pointer to SMBIOS type 4 structure
805 static int smbios_write_type7_cache_parameters(unsigned long *current,
806 int *handle,
807 int *max_struct_size,
808 struct smbios_type4 *type4)
810 struct cpuid_result res;
811 unsigned int cnt = 0;
812 int len = 0;
813 u32 leaf;
815 if (!cpu_have_cpuid())
816 return len;
818 if (cpu_is_intel()) {
819 res = cpuid(0);
820 if (res.eax < 4)
821 return len;
822 leaf = 4;
823 } else if (cpu_is_amd()) {
824 res = cpuid(0x80000000);
825 if (res.eax < 0x80000001)
826 return len;
828 res = cpuid(0x80000001);
829 if (!(res.ecx & (1 << 22)))
830 return len;
832 leaf = 0x8000001d;
833 } else {
834 printk(BIOS_DEBUG, "SMBIOS: Unknown CPU\n");
835 return len;
838 while (1) {
839 enum smbios_cache_associativity associativity;
840 enum smbios_cache_type type;
842 res = cpuid_ext(leaf, cnt++);
844 const u8 cache_type = CPUID_CACHE_TYPE(res);
845 const u8 level = CPUID_CACHE_LEVEL(res);
846 const size_t assoc = CPUID_CACHE_WAYS_OF_ASSOC(res) + 1;
847 const size_t partitions = CPUID_CACHE_PHYS_LINE(res) + 1;
848 const size_t cache_line_size = CPUID_CACHE_COHER_LINE(res) + 1;
849 const size_t number_of_sets = CPUID_CACHE_NO_OF_SETS(res) + 1;
850 const size_t cache_size = assoc * partitions * cache_line_size * number_of_sets
851 * get_number_of_caches(res);
853 if (!cache_type)
854 /* No more caches in the system */
855 break;
857 switch (cache_type) {
858 case 1:
859 type = SMBIOS_CACHE_TYPE_DATA;
860 break;
861 case 2:
862 type = SMBIOS_CACHE_TYPE_INSTRUCTION;
863 break;
864 case 3:
865 type = SMBIOS_CACHE_TYPE_UNIFIED;
866 break;
867 default:
868 type = SMBIOS_CACHE_TYPE_UNKNOWN;
869 break;
872 if (CPUID_CACHE_FULL_ASSOC(res))
873 associativity = SMBIOS_CACHE_ASSOCIATIVITY_FULL;
874 else
875 associativity = smbios_cache_associativity(assoc);
877 const int h = (*handle)++;
879 update_max(len, *max_struct_size, smbios_write_type7(current, h,
880 level, smbios_cache_sram_type(), associativity,
881 type, cache_size, cache_size));
883 if (type4) {
884 switch (level) {
885 case 1:
886 type4->l1_cache_handle = h;
887 break;
888 case 2:
889 type4->l2_cache_handle = h;
890 break;
891 case 3:
892 type4->l3_cache_handle = h;
893 break;
898 return len;
901 int smbios_write_type8(unsigned long *current, int *handle,
902 const struct port_information *port,
903 size_t num_ports)
905 int len = sizeof(struct smbios_type8);
906 unsigned int totallen = 0, i;
908 for (i = 0; i < num_ports; i++, port++) {
909 struct smbios_type8 *t = (struct smbios_type8 *)*current;
910 memset(t, 0, sizeof(struct smbios_type8));
911 t->type = SMBIOS_PORT_CONNECTOR_INFORMATION;
912 t->handle = *handle;
913 t->length = len - 2;
914 t->internal_reference_designator =
915 smbios_add_string(t->eos, port->internal_reference_designator);
916 t->internal_connector_type = port->internal_connector_type;
917 t->external_reference_designator =
918 smbios_add_string(t->eos, port->external_reference_designator);
919 t->external_connector_type = port->external_connector_type;
920 t->port_type = port->port_type;
921 *handle += 1;
922 *current += t->length + smbios_string_table_len(t->eos);
923 totallen += t->length + smbios_string_table_len(t->eos);
925 return totallen;
928 int smbios_write_type9(unsigned long *current, int *handle,
929 const char *name, const enum misc_slot_type type,
930 const enum slot_data_bus_bandwidth bandwidth,
931 const enum misc_slot_usage usage,
932 const enum misc_slot_length length,
933 const u16 id, u8 slot_char1, u8 slot_char2, u8 bus, u8 dev_func)
935 struct smbios_type9 *t = (struct smbios_type9 *)*current;
936 int len = sizeof(struct smbios_type9);
938 memset(t, 0, sizeof(struct smbios_type9));
939 t->type = SMBIOS_SYSTEM_SLOTS;
940 t->handle = *handle;
941 t->length = len - 2;
942 t->slot_designation = smbios_add_string(t->eos, name ? name : "SLOT");
943 t->slot_type = type;
944 /* TODO add slot_id supoort, will be "_SUN" for ACPI devices */
945 t->slot_id = id;
946 t->slot_data_bus_width = bandwidth;
947 t->current_usage = usage;
948 t->slot_length = length;
949 t->slot_characteristics_1 = slot_char1;
950 t->slot_characteristics_2 = slot_char2;
951 t->segment_group_number = 0;
952 t->bus_number = bus;
953 t->device_function_number = dev_func;
954 t->data_bus_width = SlotDataBusWidthOther;
956 len = t->length + smbios_string_table_len(t->eos);
957 *current += len;
958 *handle += 1;
959 return len;
962 static int smbios_write_type11(unsigned long *current, int *handle)
964 struct smbios_type11 *t = (struct smbios_type11 *)*current;
965 int len;
966 struct device *dev;
968 memset(t, 0, sizeof(*t));
969 t->type = SMBIOS_OEM_STRINGS;
970 t->handle = *handle;
971 t->length = len = sizeof(*t) - 2;
973 for (dev = all_devices; dev; dev = dev->next) {
974 if (dev->ops && dev->ops->get_smbios_strings)
975 dev->ops->get_smbios_strings(dev, t);
978 if (t->count == 0) {
979 memset(t, 0, sizeof(*t));
980 return 0;
983 len += smbios_string_table_len(t->eos);
985 *current += len;
986 (*handle)++;
987 return len;
990 static int smbios_write_type16(unsigned long *current, int *handle)
992 struct smbios_type16 *t = (struct smbios_type16 *)*current;
994 int len;
995 int i;
996 uint64_t max_capacity;
998 struct memory_info *meminfo;
999 meminfo = cbmem_find(CBMEM_ID_MEMINFO);
1000 if (meminfo == NULL)
1001 return 0; /* can't find mem info in cbmem */
1003 printk(BIOS_INFO, "Create SMBIOS type 16\n");
1005 if (meminfo->max_capacity_mib == 0 || meminfo->number_of_devices == 0) {
1006 /* Fill in defaults if not provided */
1007 meminfo->number_of_devices = 0;
1008 meminfo->max_capacity_mib = 0;
1009 for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
1010 meminfo->max_capacity_mib += meminfo->dimm[i].dimm_size;
1011 meminfo->number_of_devices += !!meminfo->dimm[i].dimm_size;
1015 memset(t, 0, sizeof(*t));
1016 t->type = SMBIOS_PHYS_MEMORY_ARRAY;
1017 t->handle = *handle;
1018 t->length = len = sizeof(*t) - 2;
1020 t->location = MEMORY_ARRAY_LOCATION_SYSTEM_BOARD;
1021 t->use = MEMORY_ARRAY_USE_SYSTEM;
1022 t->memory_error_correction = meminfo->ecc_type;
1024 /* no error information handle available */
1025 t->memory_error_information_handle = 0xFFFE;
1026 max_capacity = meminfo->max_capacity_mib;
1027 if (max_capacity * (MiB / KiB) < SMBIOS_USE_EXTENDED_MAX_CAPACITY)
1028 t->maximum_capacity = max_capacity * (MiB / KiB);
1029 else {
1030 t->maximum_capacity = SMBIOS_USE_EXTENDED_MAX_CAPACITY;
1031 t->extended_maximum_capacity = max_capacity * MiB;
1033 t->number_of_memory_devices = meminfo->number_of_devices;
1035 len += smbios_string_table_len(t->eos);
1037 *current += len;
1038 (*handle)++;
1039 return len;
1042 static int smbios_write_type17(unsigned long *current, int *handle, int type16)
1044 int len = sizeof(struct smbios_type17);
1045 int totallen = 0;
1046 int i;
1048 struct memory_info *meminfo;
1049 meminfo = cbmem_find(CBMEM_ID_MEMINFO);
1050 if (meminfo == NULL)
1051 return 0; /* can't find mem info in cbmem */
1053 printk(BIOS_INFO, "Create SMBIOS type 17\n");
1054 for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
1055 struct dimm_info *dimm;
1056 dimm = &meminfo->dimm[i];
1058 * Windows 10 GetPhysicallyInstalledSystemMemory functions reads SMBIOS tables
1059 * type 16 and type 17. The type 17 tables need to point to a type 16 table.
1060 * Otherwise, the physical installed memory size is guessed from the system
1061 * memory map, which results in a slightly smaller value than the actual size.
1063 len = create_smbios_type17_for_dimm(dimm, current, handle, type16);
1064 *current += len;
1065 totallen += len;
1067 return totallen;
1070 static int smbios_write_type19(unsigned long *current, int *handle, int type16)
1072 struct smbios_type19 *t = (struct smbios_type19 *)*current;
1073 int len = sizeof(struct smbios_type19);
1074 int i;
1076 struct memory_info *meminfo;
1077 meminfo = cbmem_find(CBMEM_ID_MEMINFO);
1078 if (meminfo == NULL)
1079 return 0; /* can't find mem info in cbmem */
1081 memset(t, 0, sizeof(struct smbios_type19));
1083 t->type = SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS;
1084 t->length = len - 2;
1085 t->handle = *handle;
1086 t->memory_array_handle = type16;
1088 for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
1089 if (meminfo->dimm[i].dimm_size > 0) {
1090 t->extended_ending_address += meminfo->dimm[i].dimm_size;
1091 t->partition_width++;
1094 t->extended_ending_address *= MiB;
1096 /* Check if it fits into regular address */
1097 if (t->extended_ending_address >= KiB &&
1098 t->extended_ending_address < 0x40000000000ULL) {
1100 * FIXME: The starting address is SoC specific, but SMBIOS tables are only
1101 * exported on x86 where it's always 0.
1104 t->starting_address = 0;
1105 t->ending_address = t->extended_ending_address / KiB - 1;
1106 t->extended_starting_address = ~0;
1107 t->extended_ending_address = ~0;
1108 } else {
1109 t->starting_address = ~0;
1110 t->ending_address = ~0;
1111 t->extended_starting_address = 0;
1112 t->extended_ending_address--;
1115 len = t->length + smbios_string_table_len(t->eos);
1116 *current += len;
1117 *handle += 1;
1118 return len;
1121 static int smbios_write_type32(unsigned long *current, int handle)
1123 struct smbios_type32 *t = (struct smbios_type32 *)*current;
1124 int len = sizeof(struct smbios_type32);
1126 memset(t, 0, sizeof(struct smbios_type32));
1127 t->type = SMBIOS_SYSTEM_BOOT_INFORMATION;
1128 t->handle = handle;
1129 t->length = len - 2;
1130 *current += len;
1131 return len;
1134 int smbios_write_type38(unsigned long *current, int *handle,
1135 const enum smbios_bmc_interface_type interface_type,
1136 const u8 ipmi_rev, const u8 i2c_addr, const u8 nv_addr,
1137 const u64 base_addr, const u8 base_modifier,
1138 const u8 irq)
1140 struct smbios_type38 *t = (struct smbios_type38 *)*current;
1141 int len = sizeof(struct smbios_type38);
1143 memset(t, 0, sizeof(struct smbios_type38));
1144 t->type = SMBIOS_IPMI_DEVICE_INFORMATION;
1145 t->handle = *handle;
1146 t->length = len - 2;
1147 t->interface_type = interface_type;
1148 t->ipmi_rev = ipmi_rev;
1149 t->i2c_slave_addr = i2c_addr;
1150 t->nv_storage_addr = nv_addr;
1151 t->base_address = base_addr;
1152 t->base_address_modifier = base_modifier;
1153 t->irq = irq;
1155 *current += len;
1156 *handle += 1;
1158 return len;
1161 int smbios_write_type41(unsigned long *current, int *handle,
1162 const char *name, u8 instance, u16 segment,
1163 u8 bus, u8 device, u8 function, u8 device_type)
1165 struct smbios_type41 *t = (struct smbios_type41 *)*current;
1166 int len = sizeof(struct smbios_type41);
1168 memset(t, 0, sizeof(struct smbios_type41));
1169 t->type = SMBIOS_ONBOARD_DEVICES_EXTENDED_INFORMATION;
1170 t->handle = *handle;
1171 t->length = len - 2;
1172 t->reference_designation = smbios_add_string(t->eos, name);
1173 t->device_type = device_type;
1174 t->device_status = 1;
1175 t->device_type_instance = instance;
1176 t->segment_group_number = segment;
1177 t->bus_number = bus;
1178 t->device_number = device;
1179 t->function_number = function;
1181 len = t->length + smbios_string_table_len(t->eos);
1182 *current += len;
1183 *handle += 1;
1184 return len;
1187 static int smbios_write_type127(unsigned long *current, int handle)
1189 struct smbios_type127 *t = (struct smbios_type127 *)*current;
1190 int len = sizeof(struct smbios_type127);
1192 memset(t, 0, sizeof(struct smbios_type127));
1193 t->type = SMBIOS_END_OF_TABLE;
1194 t->handle = handle;
1195 t->length = len - 2;
1196 *current += len;
1197 return len;
1200 /* Generate Type41 entries from devicetree */
1201 static int smbios_walk_device_tree_type41(struct device *dev, int *handle,
1202 unsigned long *current)
1204 static u8 type41_inst_cnt[SMBIOS_DEVICE_TYPE_COUNT + 1] = {};
1206 if (dev->path.type != DEVICE_PATH_PCI)
1207 return 0;
1208 if (!dev->on_mainboard)
1209 return 0;
1211 u8 device_type = smbios_get_device_type_from_dev(dev);
1213 if (device_type == SMBIOS_DEVICE_TYPE_OTHER ||
1214 device_type == SMBIOS_DEVICE_TYPE_UNKNOWN)
1215 return 0;
1217 if (device_type > SMBIOS_DEVICE_TYPE_COUNT)
1218 return 0;
1220 const char *name = get_pci_subclass_name(dev);
1222 return smbios_write_type41(current, handle,
1223 name, // name
1224 type41_inst_cnt[device_type]++, // inst
1225 0, // segment
1226 dev->bus->secondary, //bus
1227 PCI_SLOT(dev->path.pci.devfn), // device
1228 PCI_FUNC(dev->path.pci.devfn), // func
1229 device_type);
1232 /* Generate Type9 entries from devicetree */
1233 static int smbios_walk_device_tree_type9(struct device *dev, int *handle,
1234 unsigned long *current)
1236 enum misc_slot_usage usage;
1237 enum slot_data_bus_bandwidth bandwidth;
1238 enum misc_slot_type type;
1239 enum misc_slot_length length;
1241 if (dev->path.type != DEVICE_PATH_PCI)
1242 return 0;
1244 if (!dev->smbios_slot_type && !dev->smbios_slot_data_width &&
1245 !dev->smbios_slot_designation && !dev->smbios_slot_length)
1246 return 0;
1248 if (dev_is_active_bridge(dev))
1249 usage = SlotUsageInUse;
1250 else if (dev->enabled)
1251 usage = SlotUsageAvailable;
1252 else
1253 usage = SlotUsageUnknown;
1255 if (dev->smbios_slot_data_width)
1256 bandwidth = dev->smbios_slot_data_width;
1257 else
1258 bandwidth = SlotDataBusWidthUnknown;
1260 if (dev->smbios_slot_type)
1261 type = dev->smbios_slot_type;
1262 else
1263 type = SlotTypeUnknown;
1265 if (dev->smbios_slot_length)
1266 length = dev->smbios_slot_length;
1267 else
1268 length = SlotLengthUnknown;
1270 return smbios_write_type9(current, handle,
1271 dev->smbios_slot_designation,
1272 type,
1273 bandwidth,
1274 usage,
1275 length,
1279 dev->bus->secondary,
1280 dev->path.pci.devfn);
1283 static int smbios_walk_device_tree(struct device *tree, int *handle, unsigned long *current)
1285 struct device *dev;
1286 int len = 0;
1288 for (dev = tree; dev; dev = dev->next) {
1289 if (dev->enabled && dev->ops && dev->ops->get_smbios_data) {
1290 printk(BIOS_INFO, "%s (%s)\n", dev_path(dev), dev_name(dev));
1291 len += dev->ops->get_smbios_data(dev, handle, current);
1293 len += smbios_walk_device_tree_type9(dev, handle, current);
1294 len += smbios_walk_device_tree_type41(dev, handle, current);
1296 return len;
1299 unsigned long smbios_write_tables(unsigned long current)
1301 struct smbios_entry *se;
1302 struct smbios_entry30 *se3;
1303 unsigned long tables;
1304 int len = 0;
1305 int max_struct_size = 0;
1306 int handle = 0;
1308 current = ALIGN_UP(current, 16);
1309 printk(BIOS_DEBUG, "%s: %08lx\n", __func__, current);
1311 se = (struct smbios_entry *)current;
1312 current += sizeof(struct smbios_entry);
1313 current = ALIGN_UP(current, 16);
1315 se3 = (struct smbios_entry30 *)current;
1316 current += sizeof(struct smbios_entry30);
1317 current = ALIGN_UP(current, 16);
1319 tables = current;
1320 update_max(len, max_struct_size, smbios_write_type0(&current, handle++));
1321 update_max(len, max_struct_size, smbios_write_type1(&current, handle++));
1323 /* The chassis handle is the next one */
1324 update_max(len, max_struct_size, smbios_write_type2(&current, handle, handle + 1));
1325 handle++;
1326 update_max(len, max_struct_size, smbios_write_type3(&current, handle++));
1328 struct smbios_type4 *type4 = (struct smbios_type4 *)current;
1329 update_max(len, max_struct_size, smbios_write_type4(&current, handle++));
1330 len += smbios_write_type7_cache_parameters(&current, &handle, &max_struct_size, type4);
1331 update_max(len, max_struct_size, smbios_write_type11(&current, &handle));
1332 if (CONFIG(ELOG))
1333 update_max(len, max_struct_size,
1334 elog_smbios_write_type15(&current, handle++));
1336 const int type16 = handle;
1337 update_max(len, max_struct_size, smbios_write_type16(&current, &handle));
1338 update_max(len, max_struct_size, smbios_write_type17(&current, &handle, type16));
1339 update_max(len, max_struct_size, smbios_write_type19(&current, &handle, type16));
1340 update_max(len, max_struct_size, smbios_write_type32(&current, handle++));
1342 update_max(len, max_struct_size, smbios_walk_device_tree(all_devices,
1343 &handle, &current));
1345 update_max(len, max_struct_size, smbios_write_type127(&current, handle++));
1347 /* Install SMBIOS 2.1 entry point */
1348 memset(se, 0, sizeof(struct smbios_entry));
1349 memcpy(se->anchor, "_SM_", 4);
1350 se->length = sizeof(struct smbios_entry);
1351 se->major_version = 3;
1352 se->minor_version = 0;
1353 se->max_struct_size = max_struct_size;
1354 se->struct_count = handle;
1355 memcpy(se->intermediate_anchor_string, "_DMI_", 5);
1357 se->struct_table_address = (u32)tables;
1358 se->struct_table_length = len;
1360 se->intermediate_checksum = smbios_checksum((u8 *)se + 0x10,
1361 sizeof(struct smbios_entry) - 0x10);
1362 se->checksum = smbios_checksum((u8 *)se, sizeof(struct smbios_entry));
1364 /* Install SMBIOS 3.0 entry point */
1365 memset(se3, 0, sizeof(struct smbios_entry30));
1366 memcpy(se3->anchor, "_SM3_", 5);
1367 se3->length = sizeof(struct smbios_entry30);
1368 se3->major_version = 3;
1369 se3->minor_version = 0;
1371 se3->struct_table_address = (u64)tables;
1372 se3->struct_table_length = len;
1374 se3->checksum = smbios_checksum((u8 *)se3, sizeof(struct smbios_entry30));
1376 return current;