xref: /aosp_15_r20/external/coreboot/src/lib/smbios.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* 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 <drivers/vpd/vpd.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 
smbios_checksum(u8 * p,u32 length)22 static u8 smbios_checksum(u8 *p, u32 length)
23 {
24 	u8 ret = 0;
25 	while (length--)
26 		ret += *p++;
27 	return -ret;
28 }
29 
smbios_add_string(u8 * start,const char * str)30 int 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 
smbios_string_table_len(u8 * start)59 int 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 
smbios_full_table_len(struct smbios_header * header,u8 * str_table_start)76 int 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 
smbios_carve_table(unsigned long start,u8 type,u8 length,u16 handle)81 void *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 */
smbios_fill_dimm_manufacturer_from_id(uint16_t mod_id,struct smbios_type17 * t)94 void 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 
trim_trailing_whitespace(char * buffer,size_t buffer_size)108 static 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 */
smbios_fill_dimm_part_number(const char * part_number,struct smbios_type17 * t)124 static 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 */
smbios_fill_dimm_serial_number(const struct dimm_info * dimm,struct smbios_type17 * t)164 static 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 
memory_device_type(u8 code)175 static 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];
219 	return "Unsupported";
220 }
221 
dump_smbios_type17(struct dimm_info * dimm)222 static 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 
create_smbios_type17_for_dimm(struct dimm_info * dimm,unsigned long * current,int * handle,int type16_handle)234 static 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 
create_smbios_type17_for_empty_slot(struct dimm_info * dimm,unsigned long * current,int * handle,int type16_handle)291 static 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"
vpd_get_bios_version(void)315 static 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 
get_bios_version(void)338 static 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 
smbios_write_type0(unsigned long * current,int handle)369 static 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 
374 	t->vendor = smbios_add_string(t->eos, CONFIG_BIOS_VENDOR);
375 	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 
smbios_processor_external_clock(void)415 unsigned int __weak smbios_processor_external_clock(void)
416 {
417 	return 0; /* Unknown */
418 }
419 
smbios_processor_characteristics(void)420 unsigned int __weak smbios_processor_characteristics(void)
421 {
422 	return 0;
423 }
424 
smbios_cache_error_correction_type(u8 level)425 unsigned int __weak smbios_cache_error_correction_type(u8 level)
426 {
427 	return SMBIOS_CACHE_ERROR_CORRECTION_UNKNOWN;
428 }
429 
smbios_cache_sram_type(void)430 unsigned int __weak smbios_cache_sram_type(void)
431 {
432 	return SMBIOS_CACHE_SRAM_TYPE_UNKNOWN;
433 }
434 
smbios_cache_conf_operation_mode(u8 level)435 unsigned 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 */
smbios_cpu_get_voltage(void)441 unsigned int __weak smbios_cpu_get_voltage(void)
442 {
443 	return 0; /* Unknown */
444 }
445 
smbios_write_type1(unsigned long * current,int handle)446 static 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 
smbios_write_type2(unsigned long * current,int handle,const int chassis_handle)466 static 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 
smbios_write_type3(unsigned long * current,int handle)486 static 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  */
smbios_write_type7(unsigned long * current,const int handle,const u8 level,const u8 sram_type,const enum smbios_cache_associativity associativity,const enum smbios_cache_type type,const size_t max_cache_size,const size_t cache_size)511 int 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 */
smbios_cache_associativity(const u8 num)580 enum 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 
smbios_write_type8(unsigned long * current,int * handle,const struct port_information * port,size_t num_ports)612 int 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 
smbios_write_type9(unsigned long * current,int * handle,const char * name,const enum misc_slot_type type,const enum slot_data_bus_bandwidth bandwidth,const enum misc_slot_usage usage,const enum misc_slot_length length,const u16 id,u8 slot_char1,u8 slot_char2,u8 segment_group,u8 bus,u8 dev_func)637 int 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,
642 			const u16 id, u8 slot_char1, u8 slot_char2,
643 			u8 segment_group, u8 bus, u8 dev_func)
644 {
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;
650 	/* TODO add slot_id support, will be "_SUN" for ACPI devices */
651 	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;
657 	t->segment_group_number = segment_group;
658 	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 
smbios_write_type11(unsigned long * current,int * handle)668 static 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 
smbios_write_type16(unsigned long * current,int * handle)690 static 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 
smbios_write_type17(unsigned long * current,int * handle,int type16)736 static 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 
smbios_write_type19(unsigned long * current,int * handle,int type16)767 static 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 
smbios_write_type20_table(unsigned long * current,int * handle,u32 addr_start,u32 addr_end,int type17_handle,int type19_handle)815 static 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 
smbios_write_type20(unsigned long * current,int * handle,int type17_handle,int type19_handle)835 static 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 
smbios_write_type28(unsigned long * current,int * handle,const char * name,const enum smbios_temp_location location,const enum smbios_temp_status status,u16 max_value,u16 min_value,u16 resolution,u16 tolerance,u16 accuracy,u32 oem,u16 nominal_value)862 int 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 
smbios_write_type32(unsigned long * current,int handle)891 static 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 
smbios_write_type38(unsigned long * current,int * handle,const enum smbios_bmc_interface_type interface_type,const u8 ipmi_rev,const u8 i2c_addr,const u8 nv_addr,const u64 base_addr,const u8 base_modifier,const u8 irq)901 int 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 
smbios_write_type39(unsigned long * current,int * handle,u8 unit_group,const char * loc,const char * dev_name,const char * man,const char * serial_num,const char * tag_num,const char * part_num,const char * rev_lvl,u16 max_pow_cap,const struct power_supply_ch * ps_ch)924 int 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 
smbios_write_type41(unsigned long * current,int * handle,const char * name,u8 instance,u16 segment_group,u8 bus,u8 device,u8 function,u8 device_type)973 int smbios_write_type41(unsigned long *current, int *handle,
974 			const char *name, u8 instance, u16 segment_group,
975 			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;
985 	t->segment_group_number = segment_group;
986 	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 
smbios_write_type43(unsigned long * current,int * handle,const u32 vendor_id,const u8 major_spec_ver,const u8 minor_spec_ver,const u32 fw_ver1,const u32 fw_ver2,const char * description,const u64 characteristics,const u32 oem_defined)996 int 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 
smbios_write_type127(unsigned long * current,int handle)1019 static 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 */
smbios_get_device_type_from_dev(struct device * dev)1030 static 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 
smbios_get_type41_instance_id(struct device * dev,u8 device_type,u8 * instance_id)1064 static 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 
smbios_get_type41_refdes(struct device * dev)1084 static 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 
smbios_generate_type41_from_devtree(struct device * dev,int * handle,unsigned long * current)1097 static 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
1117 					dev->upstream->segment_group, // segment group
1118 					dev->upstream->secondary, //bus
1119 					PCI_SLOT(dev->path.pci.devfn), // device
1120 					PCI_FUNC(dev->path.pci.devfn), // func
1121 					device_type);
1122 }
1123 
smbios_generate_type9_from_devtree(struct device * dev,int * handle,unsigned long * current)1124 static 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,
1170 				  dev->upstream->segment_group,
1171 				  dev->upstream->secondary,
1172 				  dev->path.pci.devfn);
1173 }
1174 
get_smbios_data(struct device * dev,int * handle,unsigned long * current)1175 int 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 
smbios_walk_device_tree(struct device * tree,int * handle,unsigned long * current)1185 static 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 
smbios_write_tables(unsigned long current)1204 unsigned long smbios_write_tables(unsigned long current)
1205 {
1206 	struct smbios_entry *se = NULL;
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 	// only add a 32 bit entry point if SMBIOS table is below 4G
1217 	if (current < UINT32_MAX) {
1218 		se = (struct smbios_entry *)current;
1219 		current += sizeof(*se);
1220 		current = ALIGN_UP(current, 16);
1221 	}
1222 
1223 	se3 = (struct smbios_entry30 *)current;
1224 	current += sizeof(*se3);
1225 	current = ALIGN_UP(current, 16);
1226 
1227 	tables = current;
1228 	update_max(len, max_struct_size, smbios_write_type0(&current, handle++));
1229 	update_max(len, max_struct_size, smbios_write_type1(&current, handle++));
1230 
1231 	/* The chassis handle is the next one */
1232 	update_max(len, max_struct_size, smbios_write_type2(&current, handle, handle + 1));
1233 	handle++;
1234 	update_max(len, max_struct_size, smbios_write_type3(&current, handle++));
1235 
1236 	struct smbios_type4 *type4 = (struct smbios_type4 *)current;
1237 	update_max(len, max_struct_size, smbios_write_type4(&current, handle++));
1238 	len += smbios_write_type7_cache_parameters(&current, &handle, &max_struct_size, type4);
1239 	update_max(len, max_struct_size, smbios_write_type11(&current, &handle));
1240 	if (CONFIG(ELOG))
1241 		update_max(len, max_struct_size,
1242 			elog_smbios_write_type15(&current, handle++));
1243 
1244 	const int type16 = handle;
1245 	update_max(len, max_struct_size, smbios_write_type16(&current, &handle));
1246 	const int type17 = handle;
1247 	update_max(len, max_struct_size, smbios_write_type17(&current, &handle, type16));
1248 	const int type19 = handle;
1249 	update_max(len, max_struct_size, smbios_write_type19(&current, &handle, type16));
1250 	update_max(len, max_struct_size,
1251 			smbios_write_type20(&current, &handle, type17, type19));
1252 	update_max(len, max_struct_size, smbios_write_type32(&current, handle++));
1253 
1254 	update_max(len, max_struct_size, smbios_walk_device_tree(all_devices,
1255 								 &handle, &current));
1256 
1257 	update_max(len, max_struct_size, smbios_write_type127(&current, handle++));
1258 
1259 	if (se) {
1260 		/* Install SMBIOS 2.1 entry point */
1261 		memset(se, 0, sizeof(*se));
1262 		memcpy(se->anchor, "_SM_", 4);
1263 		se->length = sizeof(*se);
1264 		se->major_version = 3;
1265 		se->minor_version = 0;
1266 		se->max_struct_size = max_struct_size;
1267 		se->struct_count = handle;
1268 		memcpy(se->intermediate_anchor_string, "_DMI_", 5);
1269 
1270 		se->struct_table_address = (u32)tables;
1271 		se->struct_table_length = len;
1272 
1273 		se->intermediate_checksum = smbios_checksum((u8 *)se + 0x10, sizeof(*se) - 0x10);
1274 		se->checksum = smbios_checksum((u8 *)se, sizeof(*se));
1275 	}
1276 
1277 	/* Install SMBIOS 3.0 entry point */
1278 	memset(se3, 0, sizeof(*se3));
1279 	memcpy(se3->anchor, "_SM3_", 5);
1280 	se3->length = sizeof(*se3);
1281 	se3->major_version = 3;
1282 	se3->minor_version = 0;
1283 
1284 	se3->struct_table_address = (u64)tables;
1285 	se3->struct_table_length = len;
1286 
1287 	se3->checksum = smbios_checksum((u8 *)se3, sizeof(*se3));
1288 
1289 	return current;
1290 }
1291