1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
5 * Adapted from coreboot src/arch/x86/smbios.c
13 #include <tables_csum.h>
17 #include <dm/uclass-internal.h>
21 * struct smbios_write_method - Information about a table-writing function
23 * @write: Function to call
24 * @subnode_name: Name of subnode which has the information for this function,
27 struct smbios_write_method {
28 smbios_write_type write;
29 const char *subnode_name;
33 * smbios_add_string() - add a string to the string area
35 * This adds a string to the string area which is appended directly after
36 * the formatted portion of an SMBIOS structure.
38 * @start: string area start address
40 * @return: string number in the string area (1 or more)
42 static int smbios_add_string(char *start, const char *str)
68 * smbios_add_prop_default() - Add a property from the device tree or default
70 * @start: string area start address
71 * @node: node containing the information to write (ofnode_null() if none)
72 * @prop: property to write
73 * @def: default string if the node has no such property
74 * @return 0 if not found, else SMBIOS string number (1 or more)
76 static int smbios_add_prop_default(char *start, ofnode node, const char *prop,
79 const char *str = NULL;
81 if (IS_ENABLED(CONFIG_OF_CONTROL))
82 str = ofnode_read_string(node, prop);
84 return smbios_add_string(start, str);
86 return smbios_add_string(start, def);
92 * smbios_add_prop() - Add a property from the device tree
94 * @start: string area start address
95 * @node: node containing the information to write (ofnode_null() if none)
96 * @prop: property to write
97 * @return 0 if not found, else SMBIOS string number (1 or more)
99 static int smbios_add_prop(char *start, ofnode node, const char *prop)
101 return smbios_add_prop_default(start, node, prop, NULL);
105 * smbios_string_table_len() - compute the string area size
107 * This computes the size of the string area including the string terminator.
109 * @start: string area start address
110 * @return: string area size
112 static int smbios_string_table_len(char *start)
126 static int smbios_write_type0(ulong *current, int handle, ofnode node)
128 struct smbios_type0 *t;
129 int len = sizeof(struct smbios_type0);
131 t = map_sysmem(*current, len);
132 memset(t, 0, sizeof(struct smbios_type0));
133 fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
134 t->vendor = smbios_add_string(t->eos, "U-Boot");
135 t->bios_ver = smbios_add_string(t->eos, PLAIN_VERSION);
136 t->bios_release_date = smbios_add_string(t->eos, U_BOOT_DMI_DATE);
137 #ifdef CONFIG_ROM_SIZE
138 t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
140 t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED |
141 BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
142 BIOS_CHARACTERISTICS_UPGRADEABLE;
143 #ifdef CONFIG_GENERATE_ACPI_TABLE
144 t->bios_characteristics_ext1 = BIOS_CHARACTERISTICS_EXT1_ACPI;
146 #ifdef CONFIG_EFI_LOADER
147 t->bios_characteristics_ext1 |= BIOS_CHARACTERISTICS_EXT1_UEFI;
149 t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
151 t->bios_major_release = 0xff;
152 t->bios_minor_release = 0xff;
153 t->ec_major_release = 0xff;
154 t->ec_minor_release = 0xff;
156 len = t->length + smbios_string_table_len(t->eos);
163 static int smbios_write_type1(ulong *current, int handle, ofnode node)
165 struct smbios_type1 *t;
166 int len = sizeof(struct smbios_type1);
167 char *serial_str = env_get("serial#");
169 t = map_sysmem(*current, len);
170 memset(t, 0, sizeof(struct smbios_type1));
171 fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
172 t->manufacturer = smbios_add_prop_default(t->eos, node, "manufacturer",
173 CONFIG_SMBIOS_MANUFACTURER);
174 t->product_name = smbios_add_prop_default(t->eos, node, "product",
175 CONFIG_SMBIOS_PRODUCT_NAME);
177 t->serial_number = smbios_add_string(t->eos, serial_str);
178 strncpy((char *)t->uuid, serial_str, sizeof(t->uuid));
180 t->serial_number = smbios_add_prop(t->eos, node, "serial");
183 len = t->length + smbios_string_table_len(t->eos);
190 static int smbios_write_type2(ulong *current, int handle, ofnode node)
192 struct smbios_type2 *t;
193 int len = sizeof(struct smbios_type2);
195 t = map_sysmem(*current, len);
196 memset(t, 0, sizeof(struct smbios_type2));
197 fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
198 t->manufacturer = smbios_add_prop_default(t->eos, node, "manufacturer",
199 CONFIG_SMBIOS_MANUFACTURER);
200 t->product_name = smbios_add_prop_default(t->eos, node, "product",
201 CONFIG_SMBIOS_PRODUCT_NAME);
202 t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
203 t->board_type = SMBIOS_BOARD_MOTHERBOARD;
205 len = t->length + smbios_string_table_len(t->eos);
212 static int smbios_write_type3(ulong *current, int handle, ofnode node)
214 struct smbios_type3 *t;
215 int len = sizeof(struct smbios_type3);
217 t = map_sysmem(*current, len);
218 memset(t, 0, sizeof(struct smbios_type3));
219 fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
220 t->manufacturer = smbios_add_prop_default(t->eos, node, "manufacturer",
221 CONFIG_SMBIOS_MANUFACTURER);
222 t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP;
223 t->bootup_state = SMBIOS_STATE_SAFE;
224 t->power_supply_state = SMBIOS_STATE_SAFE;
225 t->thermal_state = SMBIOS_STATE_SAFE;
226 t->security_status = SMBIOS_SECURITY_NONE;
228 len = t->length + smbios_string_table_len(t->eos);
235 static void smbios_write_type4_dm(struct smbios_type4 *t, ofnode node)
237 u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN;
238 const char *vendor = "Unknown";
239 const char *name = "Unknown";
242 char processor_name[49];
243 char vendor_name[49];
244 struct udevice *cpu = NULL;
246 uclass_find_first_device(UCLASS_CPU, &cpu);
248 struct cpu_platdata *plat = dev_get_parent_platdata(cpu);
251 processor_family = plat->family;
252 t->processor_id[0] = plat->id[0];
253 t->processor_id[1] = plat->id[1];
255 if (!cpu_get_vendor(cpu, vendor_name, sizeof(vendor_name)))
256 vendor = vendor_name;
257 if (!cpu_get_desc(cpu, processor_name, sizeof(processor_name)))
258 name = processor_name;
262 t->processor_family = processor_family;
263 t->processor_manufacturer = smbios_add_string(t->eos, vendor);
264 t->processor_version = smbios_add_string(t->eos, name);
267 static int smbios_write_type4(ulong *current, int handle, ofnode node)
269 struct smbios_type4 *t;
270 int len = sizeof(struct smbios_type4);
272 t = map_sysmem(*current, len);
273 memset(t, 0, sizeof(struct smbios_type4));
274 fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle);
275 t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
276 smbios_write_type4_dm(t, node);
277 t->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
278 t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
279 t->l1_cache_handle = 0xffff;
280 t->l2_cache_handle = 0xffff;
281 t->l3_cache_handle = 0xffff;
282 t->processor_family2 = t->processor_family;
284 len = t->length + smbios_string_table_len(t->eos);
291 static int smbios_write_type32(ulong *current, int handle, ofnode node)
293 struct smbios_type32 *t;
294 int len = sizeof(struct smbios_type32);
296 t = map_sysmem(*current, len);
297 memset(t, 0, sizeof(struct smbios_type32));
298 fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
306 static int smbios_write_type127(ulong *current, int handle, ofnode node)
308 struct smbios_type127 *t;
309 int len = sizeof(struct smbios_type127);
311 t = map_sysmem(*current, len);
312 memset(t, 0, sizeof(struct smbios_type127));
313 fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
321 static struct smbios_write_method smbios_write_funcs[] = {
322 { smbios_write_type0, },
323 { smbios_write_type1, "system", },
324 { smbios_write_type2, "baseboard", },
325 { smbios_write_type3, "chassis", },
326 { smbios_write_type4, },
327 { smbios_write_type32, },
328 { smbios_write_type127 },
331 ulong write_smbios_table(ulong addr)
333 ofnode parent_node = ofnode_null();
334 struct smbios_entry *se;
339 int max_struct_size = 0;
345 if (IS_ENABLED(CONFIG_OF_CONTROL)) {
346 uclass_first_device(UCLASS_SYSINFO, &dev);
348 parent_node = dev_read_subnode(dev, "smbios");
351 /* 16 byte align the table address */
352 addr = ALIGN(addr, 16);
354 se = map_sysmem(addr, sizeof(struct smbios_entry));
355 memset(se, 0, sizeof(struct smbios_entry));
357 addr += sizeof(struct smbios_entry);
358 addr = ALIGN(addr, 16);
361 /* populate minimum required tables */
362 for (i = 0; i < ARRAY_SIZE(smbios_write_funcs); i++) {
363 const struct smbios_write_method *method;
364 ofnode node = ofnode_null();
367 method = &smbios_write_funcs[i];
368 if (IS_ENABLED(CONFIG_OF_CONTROL) && method->subnode_name)
369 node = ofnode_find_subnode(parent_node,
370 method->subnode_name);
371 tmp = method->write((ulong *)&addr, handle++, node);
373 max_struct_size = max(max_struct_size, tmp);
377 memcpy(se->anchor, "_SM_", 4);
378 se->length = sizeof(struct smbios_entry);
379 se->major_ver = SMBIOS_MAJOR_VER;
380 se->minor_ver = SMBIOS_MINOR_VER;
381 se->max_struct_size = max_struct_size;
382 memcpy(se->intermediate_anchor, "_DMI_", 5);
383 se->struct_table_length = len;
386 * We must use a pointer here so things work correctly on sandbox. The
387 * user of this table is not aware of the mapping of addresses to
388 * sandbox's DRAM buffer.
390 table_addr = (ulong)map_sysmem(tables, 0);
391 if (sizeof(table_addr) > sizeof(u32) && table_addr > (ulong)UINT_MAX) {
393 * We need to put this >32-bit pointer into the table but the
394 * field is only 32 bits wide.
396 printf("WARNING: SMBIOS table_address overflow %llx\n",
397 (unsigned long long)table_addr);
400 se->struct_table_address = table_addr;
402 se->struct_count = handle;
404 /* calculate checksums */
405 istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
406 isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
407 se->intermediate_checksum = table_compute_checksum(istart, isize);
408 se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));