blob: 43628d67579c2da5661c0bbf6307d5d1809b31ed [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Bin Meng721e9922015-10-12 05:23:41 -07002/*
3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
4 *
5 * Adapted from coreboot src/arch/x86/smbios.c
Bin Meng721e9922015-10-12 05:23:41 -07006 */
7
8#include <common.h>
Simon Glass78227d42020-11-05 06:32:07 -07009#include <dm.h>
Simon Glass7b51b572019-08-01 09:46:52 -060010#include <env.h>
Simon Glassa2505fc2018-11-22 13:46:37 -070011#include <mapmem.h>
Alexander Graf4b6dddc2016-08-19 01:23:23 +020012#include <smbios.h>
13#include <tables_csum.h>
Bin Meng721e9922015-10-12 05:23:41 -070014#include <version.h>
Alexander Graf96476202016-08-19 01:23:28 +020015#ifdef CONFIG_CPU
16#include <cpu.h>
Alexander Graf96476202016-08-19 01:23:28 +020017#include <dm/uclass-internal.h>
18#endif
Bin Meng721e9922015-10-12 05:23:41 -070019
Bin Meng721e9922015-10-12 05:23:41 -070020/**
Simon Glass1e8989a2021-02-04 21:17:17 -070021 * struct smbios_ctx - context for writing SMBIOS tables
22 *
23 * @node: node containing the information to write (ofnode_null() if none)
24 * @dev: sysinfo device to use (NULL if none)
Simon Glass0c95fff2021-02-04 21:17:18 -070025 * @eos: end-of-string pointer for the table being processed. This is set
26 * up when we start processing a table
Simon Glass1e8989a2021-02-04 21:17:17 -070027 */
28struct smbios_ctx {
29 ofnode node;
30 struct udevice *dev;
Simon Glass0c95fff2021-02-04 21:17:18 -070031 char *eos;
Simon Glass1e8989a2021-02-04 21:17:17 -070032};
33
34/**
Simon Glass0e89b852021-02-04 21:17:14 -070035 * Function prototype to write a specific type of SMBIOS structure
36 *
37 * @addr: start address to write the structure
38 * @handle: the structure's handle, a unique 16-bit number
Simon Glass1e8989a2021-02-04 21:17:17 -070039 * @ctx: context for writing the tables
Simon Glass0e89b852021-02-04 21:17:14 -070040 * @return: size of the structure
41 */
Simon Glass1e8989a2021-02-04 21:17:17 -070042typedef int (*smbios_write_type)(ulong *addr, int handle,
43 struct smbios_ctx *ctx);
Simon Glass0e89b852021-02-04 21:17:14 -070044
45/**
Simon Glass44ffb6f2020-11-05 06:32:08 -070046 * struct smbios_write_method - Information about a table-writing function
47 *
48 * @write: Function to call
49 * @subnode_name: Name of subnode which has the information for this function,
50 * NULL if none
51 */
52struct smbios_write_method {
53 smbios_write_type write;
54 const char *subnode_name;
55};
56
57/**
Bin Meng721e9922015-10-12 05:23:41 -070058 * smbios_add_string() - add a string to the string area
59 *
60 * This adds a string to the string area which is appended directly after
61 * the formatted portion of an SMBIOS structure.
62 *
Simon Glass0c95fff2021-02-04 21:17:18 -070063 * @ctx: SMBIOS context
Bin Meng721e9922015-10-12 05:23:41 -070064 * @str: string to add
Simon Glass78227d42020-11-05 06:32:07 -070065 * @return: string number in the string area (1 or more)
Bin Meng721e9922015-10-12 05:23:41 -070066 */
Simon Glass0c95fff2021-02-04 21:17:18 -070067static int smbios_add_string(struct smbios_ctx *ctx, const char *str)
Bin Meng721e9922015-10-12 05:23:41 -070068{
69 int i = 1;
Simon Glass0c95fff2021-02-04 21:17:18 -070070 char *p = ctx->eos;
71
Heinrich Schuchardt00a871d2020-06-01 15:44:00 +020072 if (!*str)
73 str = "Unknown";
Bin Meng721e9922015-10-12 05:23:41 -070074
75 for (;;) {
76 if (!*p) {
77 strcpy(p, str);
78 p += strlen(str);
79 *p++ = '\0';
80 *p++ = '\0';
81
82 return i;
83 }
84
85 if (!strcmp(p, str))
86 return i;
87
88 p += strlen(p) + 1;
89 i++;
90 }
91}
92
93/**
Simon Glass44ffb6f2020-11-05 06:32:08 -070094 * smbios_add_prop() - Add a property from the device tree
95 *
Simon Glass1e8989a2021-02-04 21:17:17 -070096 * @ctx: context for writing the tables
Simon Glass44ffb6f2020-11-05 06:32:08 -070097 * @prop: property to write
98 * @return 0 if not found, else SMBIOS string number (1 or more)
99 */
Simon Glass0c95fff2021-02-04 21:17:18 -0700100static int smbios_add_prop(struct smbios_ctx *ctx, const char *prop)
Simon Glass44ffb6f2020-11-05 06:32:08 -0700101{
Simon Glasse4f8e542020-11-05 06:32:18 -0700102 if (IS_ENABLED(CONFIG_OF_CONTROL)) {
103 const char *str;
104
Simon Glass1e8989a2021-02-04 21:17:17 -0700105 str = ofnode_read_string(ctx->node, prop);
Simon Glasse4f8e542020-11-05 06:32:18 -0700106 if (str)
Simon Glass0c95fff2021-02-04 21:17:18 -0700107 return smbios_add_string(ctx, str);
Simon Glasse4f8e542020-11-05 06:32:18 -0700108 }
109
110 return 0;
Simon Glass44ffb6f2020-11-05 06:32:08 -0700111}
112
Simon Glass0c95fff2021-02-04 21:17:18 -0700113static void smbios_set_eos(struct smbios_ctx *ctx, char *eos)
114{
115 ctx->eos = eos;
116}
117
Simon Glass44ffb6f2020-11-05 06:32:08 -0700118/**
Bin Meng721e9922015-10-12 05:23:41 -0700119 * smbios_string_table_len() - compute the string area size
120 *
121 * This computes the size of the string area including the string terminator.
122 *
123 * @start: string area start address
124 * @return: string area size
125 */
126static int smbios_string_table_len(char *start)
127{
128 char *p = start;
129 int i, len = 0;
130
131 while (*p) {
132 i = strlen(p) + 1;
133 p += i;
134 len += i;
135 }
136
137 return len + 1;
138}
139
Simon Glass1e8989a2021-02-04 21:17:17 -0700140static int smbios_write_type0(ulong *current, int handle,
141 struct smbios_ctx *ctx)
Bin Meng721e9922015-10-12 05:23:41 -0700142{
Simon Glassa2505fc2018-11-22 13:46:37 -0700143 struct smbios_type0 *t;
Bin Meng721e9922015-10-12 05:23:41 -0700144 int len = sizeof(struct smbios_type0);
145
Simon Glassa2505fc2018-11-22 13:46:37 -0700146 t = map_sysmem(*current, len);
Bin Meng721e9922015-10-12 05:23:41 -0700147 memset(t, 0, sizeof(struct smbios_type0));
148 fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
Simon Glass0c95fff2021-02-04 21:17:18 -0700149 smbios_set_eos(ctx, t->eos);
150 t->vendor = smbios_add_string(ctx, "U-Boot");
151 t->bios_ver = smbios_add_string(ctx, PLAIN_VERSION);
152 t->bios_release_date = smbios_add_string(ctx, U_BOOT_DMI_DATE);
Alexander Grafe663b352016-08-19 01:23:29 +0200153#ifdef CONFIG_ROM_SIZE
Bin Meng721e9922015-10-12 05:23:41 -0700154 t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
Alexander Grafe663b352016-08-19 01:23:29 +0200155#endif
Bin Meng721e9922015-10-12 05:23:41 -0700156 t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED |
157 BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
158 BIOS_CHARACTERISTICS_UPGRADEABLE;
159#ifdef CONFIG_GENERATE_ACPI_TABLE
160 t->bios_characteristics_ext1 = BIOS_CHARACTERISTICS_EXT1_ACPI;
161#endif
Alexander Grafe663b352016-08-19 01:23:29 +0200162#ifdef CONFIG_EFI_LOADER
163 t->bios_characteristics_ext1 |= BIOS_CHARACTERISTICS_EXT1_UEFI;
164#endif
Bin Meng721e9922015-10-12 05:23:41 -0700165 t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
Alexander Grafe663b352016-08-19 01:23:29 +0200166
Simon Glass7617f992021-02-04 21:17:16 -0700167 /* bios_major_release has only one byte, so drop century */
168 t->bios_major_release = U_BOOT_VERSION_NUM % 100;
169 t->bios_minor_release = U_BOOT_VERSION_NUM_PATCH;
Bin Meng721e9922015-10-12 05:23:41 -0700170 t->ec_major_release = 0xff;
171 t->ec_minor_release = 0xff;
172
173 len = t->length + smbios_string_table_len(t->eos);
174 *current += len;
Simon Glassa2505fc2018-11-22 13:46:37 -0700175 unmap_sysmem(t);
Bin Meng721e9922015-10-12 05:23:41 -0700176
177 return len;
178}
179
Simon Glass1e8989a2021-02-04 21:17:17 -0700180static int smbios_write_type1(ulong *current, int handle,
181 struct smbios_ctx *ctx)
Bin Meng721e9922015-10-12 05:23:41 -0700182{
Simon Glassa2505fc2018-11-22 13:46:37 -0700183 struct smbios_type1 *t;
Bin Meng721e9922015-10-12 05:23:41 -0700184 int len = sizeof(struct smbios_type1);
Simon Glass00caae62017-08-03 12:22:12 -0600185 char *serial_str = env_get("serial#");
Bin Meng721e9922015-10-12 05:23:41 -0700186
Simon Glassa2505fc2018-11-22 13:46:37 -0700187 t = map_sysmem(*current, len);
Bin Meng721e9922015-10-12 05:23:41 -0700188 memset(t, 0, sizeof(struct smbios_type1));
189 fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
Simon Glass0c95fff2021-02-04 21:17:18 -0700190 smbios_set_eos(ctx, t->eos);
191 t->manufacturer = smbios_add_prop(ctx, "manufacturer");
192 t->product_name = smbios_add_prop(ctx, "product");
193 t->version = smbios_add_prop(ctx, "version");
Alexander Graf6fb580d2016-08-19 01:23:31 +0200194 if (serial_str) {
Simon Glass0c95fff2021-02-04 21:17:18 -0700195 t->serial_number = smbios_add_string(ctx, serial_str);
Simon Glass44ffb6f2020-11-05 06:32:08 -0700196 strncpy((char *)t->uuid, serial_str, sizeof(t->uuid));
197 } else {
Simon Glass0c95fff2021-02-04 21:17:18 -0700198 t->serial_number = smbios_add_prop(ctx, "serial");
Alexander Graf6fb580d2016-08-19 01:23:31 +0200199 }
Simon Glass0c95fff2021-02-04 21:17:18 -0700200 t->sku_number = smbios_add_prop(ctx, "sku");
201 t->family = smbios_add_prop(ctx, "family");
Bin Meng721e9922015-10-12 05:23:41 -0700202
203 len = t->length + smbios_string_table_len(t->eos);
204 *current += len;
Simon Glassa2505fc2018-11-22 13:46:37 -0700205 unmap_sysmem(t);
Bin Meng721e9922015-10-12 05:23:41 -0700206
207 return len;
208}
209
Simon Glass1e8989a2021-02-04 21:17:17 -0700210static int smbios_write_type2(ulong *current, int handle,
211 struct smbios_ctx *ctx)
Bin Meng721e9922015-10-12 05:23:41 -0700212{
Simon Glassa2505fc2018-11-22 13:46:37 -0700213 struct smbios_type2 *t;
Bin Meng721e9922015-10-12 05:23:41 -0700214 int len = sizeof(struct smbios_type2);
215
Simon Glassa2505fc2018-11-22 13:46:37 -0700216 t = map_sysmem(*current, len);
Bin Meng721e9922015-10-12 05:23:41 -0700217 memset(t, 0, sizeof(struct smbios_type2));
218 fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
Simon Glass0c95fff2021-02-04 21:17:18 -0700219 smbios_set_eos(ctx, t->eos);
220 t->manufacturer = smbios_add_prop(ctx, "manufacturer");
221 t->product_name = smbios_add_prop(ctx, "product");
222 t->asset_tag_number = smbios_add_prop(ctx, "asset-tag");
Bin Meng721e9922015-10-12 05:23:41 -0700223 t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
224 t->board_type = SMBIOS_BOARD_MOTHERBOARD;
225
226 len = t->length + smbios_string_table_len(t->eos);
227 *current += len;
Simon Glassa2505fc2018-11-22 13:46:37 -0700228 unmap_sysmem(t);
Bin Meng721e9922015-10-12 05:23:41 -0700229
230 return len;
231}
232
Simon Glass1e8989a2021-02-04 21:17:17 -0700233static int smbios_write_type3(ulong *current, int handle,
234 struct smbios_ctx *ctx)
Bin Meng721e9922015-10-12 05:23:41 -0700235{
Simon Glassa2505fc2018-11-22 13:46:37 -0700236 struct smbios_type3 *t;
Bin Meng721e9922015-10-12 05:23:41 -0700237 int len = sizeof(struct smbios_type3);
238
Simon Glassa2505fc2018-11-22 13:46:37 -0700239 t = map_sysmem(*current, len);
Bin Meng721e9922015-10-12 05:23:41 -0700240 memset(t, 0, sizeof(struct smbios_type3));
241 fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
Simon Glass0c95fff2021-02-04 21:17:18 -0700242 smbios_set_eos(ctx, t->eos);
243 t->manufacturer = smbios_add_prop(ctx, "manufacturer");
Bin Meng721e9922015-10-12 05:23:41 -0700244 t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP;
245 t->bootup_state = SMBIOS_STATE_SAFE;
246 t->power_supply_state = SMBIOS_STATE_SAFE;
247 t->thermal_state = SMBIOS_STATE_SAFE;
248 t->security_status = SMBIOS_SECURITY_NONE;
249
250 len = t->length + smbios_string_table_len(t->eos);
251 *current += len;
Simon Glassa2505fc2018-11-22 13:46:37 -0700252 unmap_sysmem(t);
Bin Meng721e9922015-10-12 05:23:41 -0700253
254 return len;
255}
256
Simon Glass1e8989a2021-02-04 21:17:17 -0700257static void smbios_write_type4_dm(struct smbios_type4 *t,
258 struct smbios_ctx *ctx)
Alexander Graf96476202016-08-19 01:23:28 +0200259{
260 u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN;
261 const char *vendor = "Unknown";
262 const char *name = "Unknown";
263
264#ifdef CONFIG_CPU
265 char processor_name[49];
266 char vendor_name[49];
Simon Glass78227d42020-11-05 06:32:07 -0700267 struct udevice *cpu = NULL;
Alexander Graf96476202016-08-19 01:23:28 +0200268
Simon Glass78227d42020-11-05 06:32:07 -0700269 uclass_find_first_device(UCLASS_CPU, &cpu);
270 if (cpu) {
Simon Glass8a8d24b2020-12-03 16:55:23 -0700271 struct cpu_plat *plat = dev_get_parent_plat(cpu);
Alexander Graf96476202016-08-19 01:23:28 +0200272
273 if (plat->family)
274 processor_family = plat->family;
275 t->processor_id[0] = plat->id[0];
276 t->processor_id[1] = plat->id[1];
277
Simon Glass78227d42020-11-05 06:32:07 -0700278 if (!cpu_get_vendor(cpu, vendor_name, sizeof(vendor_name)))
Alexander Graf96476202016-08-19 01:23:28 +0200279 vendor = vendor_name;
Simon Glass78227d42020-11-05 06:32:07 -0700280 if (!cpu_get_desc(cpu, processor_name, sizeof(processor_name)))
Alexander Graf96476202016-08-19 01:23:28 +0200281 name = processor_name;
282 }
283#endif
284
285 t->processor_family = processor_family;
Simon Glass0c95fff2021-02-04 21:17:18 -0700286 t->processor_manufacturer = smbios_add_string(ctx, vendor);
287 t->processor_version = smbios_add_string(ctx, name);
Alexander Graf96476202016-08-19 01:23:28 +0200288}
289
Simon Glass1e8989a2021-02-04 21:17:17 -0700290static int smbios_write_type4(ulong *current, int handle,
291 struct smbios_ctx *ctx)
Bin Meng721e9922015-10-12 05:23:41 -0700292{
Simon Glassa2505fc2018-11-22 13:46:37 -0700293 struct smbios_type4 *t;
Bin Meng721e9922015-10-12 05:23:41 -0700294 int len = sizeof(struct smbios_type4);
Bin Meng721e9922015-10-12 05:23:41 -0700295
Simon Glassa2505fc2018-11-22 13:46:37 -0700296 t = map_sysmem(*current, len);
Bin Meng721e9922015-10-12 05:23:41 -0700297 memset(t, 0, sizeof(struct smbios_type4));
298 fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle);
Simon Glass0c95fff2021-02-04 21:17:18 -0700299 smbios_set_eos(ctx, t->eos);
Bin Meng721e9922015-10-12 05:23:41 -0700300 t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
Simon Glass1e8989a2021-02-04 21:17:17 -0700301 smbios_write_type4_dm(t, ctx);
Bin Meng721e9922015-10-12 05:23:41 -0700302 t->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
303 t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
304 t->l1_cache_handle = 0xffff;
305 t->l2_cache_handle = 0xffff;
306 t->l3_cache_handle = 0xffff;
307 t->processor_family2 = t->processor_family;
308
309 len = t->length + smbios_string_table_len(t->eos);
310 *current += len;
Simon Glassa2505fc2018-11-22 13:46:37 -0700311 unmap_sysmem(t);
Bin Meng721e9922015-10-12 05:23:41 -0700312
313 return len;
314}
315
Simon Glass1e8989a2021-02-04 21:17:17 -0700316static int smbios_write_type32(ulong *current, int handle,
317 struct smbios_ctx *ctx)
Bin Meng721e9922015-10-12 05:23:41 -0700318{
Simon Glassa2505fc2018-11-22 13:46:37 -0700319 struct smbios_type32 *t;
Bin Meng721e9922015-10-12 05:23:41 -0700320 int len = sizeof(struct smbios_type32);
321
Simon Glassa2505fc2018-11-22 13:46:37 -0700322 t = map_sysmem(*current, len);
Bin Meng721e9922015-10-12 05:23:41 -0700323 memset(t, 0, sizeof(struct smbios_type32));
324 fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
Simon Glass0c95fff2021-02-04 21:17:18 -0700325 smbios_set_eos(ctx, t->eos);
Bin Meng721e9922015-10-12 05:23:41 -0700326
327 *current += len;
Simon Glassa2505fc2018-11-22 13:46:37 -0700328 unmap_sysmem(t);
Bin Meng721e9922015-10-12 05:23:41 -0700329
330 return len;
331}
332
Simon Glass1e8989a2021-02-04 21:17:17 -0700333static int smbios_write_type127(ulong *current, int handle,
334 struct smbios_ctx *ctx)
Bin Meng721e9922015-10-12 05:23:41 -0700335{
Simon Glassa2505fc2018-11-22 13:46:37 -0700336 struct smbios_type127 *t;
Bin Meng721e9922015-10-12 05:23:41 -0700337 int len = sizeof(struct smbios_type127);
338
Simon Glassa2505fc2018-11-22 13:46:37 -0700339 t = map_sysmem(*current, len);
Bin Meng721e9922015-10-12 05:23:41 -0700340 memset(t, 0, sizeof(struct smbios_type127));
341 fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
342
343 *current += len;
Simon Glassa2505fc2018-11-22 13:46:37 -0700344 unmap_sysmem(t);
Bin Meng721e9922015-10-12 05:23:41 -0700345
346 return len;
347}
348
Simon Glass44ffb6f2020-11-05 06:32:08 -0700349static struct smbios_write_method smbios_write_funcs[] = {
350 { smbios_write_type0, },
351 { smbios_write_type1, "system", },
352 { smbios_write_type2, "baseboard", },
353 { smbios_write_type3, "chassis", },
354 { smbios_write_type4, },
355 { smbios_write_type32, },
356 { smbios_write_type127 },
Bin Meng721e9922015-10-12 05:23:41 -0700357};
358
Simon Glass42fd8c12017-01-16 07:03:35 -0700359ulong write_smbios_table(ulong addr)
Bin Meng721e9922015-10-12 05:23:41 -0700360{
Simon Glass44ffb6f2020-11-05 06:32:08 -0700361 ofnode parent_node = ofnode_null();
Bin Meng721e9922015-10-12 05:23:41 -0700362 struct smbios_entry *se;
Simon Glass1e8989a2021-02-04 21:17:17 -0700363 struct smbios_ctx ctx;
Simon Glassa2505fc2018-11-22 13:46:37 -0700364 ulong table_addr;
Simon Glass42fd8c12017-01-16 07:03:35 -0700365 ulong tables;
Bin Meng721e9922015-10-12 05:23:41 -0700366 int len = 0;
367 int max_struct_size = 0;
368 int handle = 0;
369 char *istart;
370 int isize;
371 int i;
372
Simon Glass1e8989a2021-02-04 21:17:17 -0700373 ctx.node = ofnode_null();
Simon Glass78227d42020-11-05 06:32:07 -0700374 if (IS_ENABLED(CONFIG_OF_CONTROL)) {
Simon Glass1e8989a2021-02-04 21:17:17 -0700375 uclass_first_device(UCLASS_SYSINFO, &ctx.dev);
376 if (ctx.dev)
377 parent_node = dev_read_subnode(ctx.dev, "smbios");
378 } else {
379 ctx.dev = NULL;
Simon Glass78227d42020-11-05 06:32:07 -0700380 }
381
Bin Meng721e9922015-10-12 05:23:41 -0700382 /* 16 byte align the table address */
383 addr = ALIGN(addr, 16);
384
Simon Glassa2505fc2018-11-22 13:46:37 -0700385 se = map_sysmem(addr, sizeof(struct smbios_entry));
Bin Meng721e9922015-10-12 05:23:41 -0700386 memset(se, 0, sizeof(struct smbios_entry));
387
388 addr += sizeof(struct smbios_entry);
389 addr = ALIGN(addr, 16);
390 tables = addr;
391
392 /* populate minimum required tables */
393 for (i = 0; i < ARRAY_SIZE(smbios_write_funcs); i++) {
Simon Glass44ffb6f2020-11-05 06:32:08 -0700394 const struct smbios_write_method *method;
Simon Glass44ffb6f2020-11-05 06:32:08 -0700395 int tmp;
396
397 method = &smbios_write_funcs[i];
398 if (IS_ENABLED(CONFIG_OF_CONTROL) && method->subnode_name)
Simon Glass1e8989a2021-02-04 21:17:17 -0700399 ctx.node = ofnode_find_subnode(parent_node,
400 method->subnode_name);
401 tmp = method->write((ulong *)&addr, handle++, &ctx);
Christian Gmeiner60a4df32018-07-30 13:22:07 +0200402
Bin Meng721e9922015-10-12 05:23:41 -0700403 max_struct_size = max(max_struct_size, tmp);
404 len += tmp;
405 }
406
407 memcpy(se->anchor, "_SM_", 4);
408 se->length = sizeof(struct smbios_entry);
409 se->major_ver = SMBIOS_MAJOR_VER;
410 se->minor_ver = SMBIOS_MINOR_VER;
411 se->max_struct_size = max_struct_size;
412 memcpy(se->intermediate_anchor, "_DMI_", 5);
413 se->struct_table_length = len;
Simon Glassa2505fc2018-11-22 13:46:37 -0700414
415 /*
416 * We must use a pointer here so things work correctly on sandbox. The
417 * user of this table is not aware of the mapping of addresses to
418 * sandbox's DRAM buffer.
419 */
420 table_addr = (ulong)map_sysmem(tables, 0);
421 if (sizeof(table_addr) > sizeof(u32) && table_addr > (ulong)UINT_MAX) {
422 /*
423 * We need to put this >32-bit pointer into the table but the
424 * field is only 32 bits wide.
425 */
426 printf("WARNING: SMBIOS table_address overflow %llx\n",
427 (unsigned long long)table_addr);
428 table_addr = 0;
429 }
430 se->struct_table_address = table_addr;
431
Bin Meng721e9922015-10-12 05:23:41 -0700432 se->struct_count = handle;
433
434 /* calculate checksums */
435 istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
436 isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
437 se->intermediate_checksum = table_compute_checksum(istart, isize);
438 se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
Simon Glassa2505fc2018-11-22 13:46:37 -0700439 unmap_sysmem(se);
Bin Meng721e9922015-10-12 05:23:41 -0700440
441 return addr;
442}