Blame view

lib/smbios.c 8.5 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
721e992a8   Bin Meng   x86: Add SMBIOS t...
2
3
4
5
  /*
   * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
   *
   * Adapted from coreboot src/arch/x86/smbios.c
721e992a8   Bin Meng   x86: Add SMBIOS t...
6
7
8
   */
  
  #include <common.h>
a2505fc8a   Simon Glass   sandbox: smbios: ...
9
  #include <mapmem.h>
4b6dddc29   Alexander Graf   x86: Move smbios ...
10
11
  #include <smbios.h>
  #include <tables_csum.h>
721e992a8   Bin Meng   x86: Add SMBIOS t...
12
  #include <version.h>
96476206c   Alexander Graf   smbios: Generate ...
13
14
15
16
17
  #ifdef CONFIG_CPU
  #include <cpu.h>
  #include <dm.h>
  #include <dm/uclass-internal.h>
  #endif
721e992a8   Bin Meng   x86: Add SMBIOS t...
18

721e992a8   Bin Meng   x86: Add SMBIOS t...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  /**
   * smbios_add_string() - add a string to the string area
   *
   * This adds a string to the string area which is appended directly after
   * the formatted portion of an SMBIOS structure.
   *
   * @start:	string area start address
   * @str:	string to add
   * @return:	string number in the string area
   */
  static int smbios_add_string(char *start, const char *str)
  {
  	int i = 1;
  	char *p = start;
  
  	for (;;) {
  		if (!*p) {
  			strcpy(p, str);
  			p += strlen(str);
  			*p++ = '\0';
  			*p++ = '\0';
  
  			return i;
  		}
  
  		if (!strcmp(p, str))
  			return i;
  
  		p += strlen(p) + 1;
  		i++;
  	}
  }
  
  /**
   * smbios_string_table_len() - compute the string area size
   *
   * This computes the size of the string area including the string terminator.
   *
   * @start:	string area start address
   * @return:	string area size
   */
  static int smbios_string_table_len(char *start)
  {
  	char *p = start;
  	int i, len = 0;
  
  	while (*p) {
  		i = strlen(p) + 1;
  		p += i;
  		len += i;
  	}
  
  	return len + 1;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
73
  static int smbios_write_type0(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
74
  {
a2505fc8a   Simon Glass   sandbox: smbios: ...
75
  	struct smbios_type0 *t;
721e992a8   Bin Meng   x86: Add SMBIOS t...
76
  	int len = sizeof(struct smbios_type0);
a2505fc8a   Simon Glass   sandbox: smbios: ...
77
  	t = map_sysmem(*current, len);
721e992a8   Bin Meng   x86: Add SMBIOS t...
78
79
80
81
82
  	memset(t, 0, sizeof(struct smbios_type0));
  	fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
  	t->vendor = smbios_add_string(t->eos, "U-Boot");
  	t->bios_ver = smbios_add_string(t->eos, PLAIN_VERSION);
  	t->bios_release_date = smbios_add_string(t->eos, U_BOOT_DMI_DATE);
e663b350f   Alexander Graf   smbios: Expose in...
83
  #ifdef CONFIG_ROM_SIZE
721e992a8   Bin Meng   x86: Add SMBIOS t...
84
  	t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
e663b350f   Alexander Graf   smbios: Expose in...
85
  #endif
721e992a8   Bin Meng   x86: Add SMBIOS t...
86
87
88
89
90
91
  	t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED |
  				  BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
  				  BIOS_CHARACTERISTICS_UPGRADEABLE;
  #ifdef CONFIG_GENERATE_ACPI_TABLE
  	t->bios_characteristics_ext1 = BIOS_CHARACTERISTICS_EXT1_ACPI;
  #endif
e663b350f   Alexander Graf   smbios: Expose in...
92
93
94
  #ifdef CONFIG_EFI_LOADER
  	t->bios_characteristics_ext1 |= BIOS_CHARACTERISTICS_EXT1_UEFI;
  #endif
721e992a8   Bin Meng   x86: Add SMBIOS t...
95
  	t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
e663b350f   Alexander Graf   smbios: Expose in...
96

721e992a8   Bin Meng   x86: Add SMBIOS t...
97
98
99
100
101
102
103
  	t->bios_major_release = 0xff;
  	t->bios_minor_release = 0xff;
  	t->ec_major_release = 0xff;
  	t->ec_minor_release = 0xff;
  
  	len = t->length + smbios_string_table_len(t->eos);
  	*current += len;
a2505fc8a   Simon Glass   sandbox: smbios: ...
104
  	unmap_sysmem(t);
721e992a8   Bin Meng   x86: Add SMBIOS t...
105
106
107
  
  	return len;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
108
  static int smbios_write_type1(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
109
  {
a2505fc8a   Simon Glass   sandbox: smbios: ...
110
  	struct smbios_type1 *t;
721e992a8   Bin Meng   x86: Add SMBIOS t...
111
  	int len = sizeof(struct smbios_type1);
00caae6d4   Simon Glass   env: Rename geten...
112
  	char *serial_str = env_get("serial#");
721e992a8   Bin Meng   x86: Add SMBIOS t...
113

a2505fc8a   Simon Glass   sandbox: smbios: ...
114
  	t = map_sysmem(*current, len);
721e992a8   Bin Meng   x86: Add SMBIOS t...
115
116
  	memset(t, 0, sizeof(struct smbios_type1));
  	fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
4cdce9f5b   Bin Meng   x86: Switch to us...
117
118
  	t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
  	t->product_name = smbios_add_string(t->eos, CONFIG_SMBIOS_PRODUCT_NAME);
6fb580d7b   Alexander Graf   smbios: Provide s...
119
  	if (serial_str) {
5113ff8a9   Christian Gmeiner   smbios: fix check...
120
  		strncpy((char *)t->uuid, serial_str, sizeof(t->uuid));
6fb580d7b   Alexander Graf   smbios: Provide s...
121
122
  		t->serial_number = smbios_add_string(t->eos, serial_str);
  	}
721e992a8   Bin Meng   x86: Add SMBIOS t...
123
124
125
  
  	len = t->length + smbios_string_table_len(t->eos);
  	*current += len;
a2505fc8a   Simon Glass   sandbox: smbios: ...
126
  	unmap_sysmem(t);
721e992a8   Bin Meng   x86: Add SMBIOS t...
127
128
129
  
  	return len;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
130
  static int smbios_write_type2(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
131
  {
a2505fc8a   Simon Glass   sandbox: smbios: ...
132
  	struct smbios_type2 *t;
721e992a8   Bin Meng   x86: Add SMBIOS t...
133
  	int len = sizeof(struct smbios_type2);
a2505fc8a   Simon Glass   sandbox: smbios: ...
134
  	t = map_sysmem(*current, len);
721e992a8   Bin Meng   x86: Add SMBIOS t...
135
136
  	memset(t, 0, sizeof(struct smbios_type2));
  	fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
4cdce9f5b   Bin Meng   x86: Switch to us...
137
138
  	t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
  	t->product_name = smbios_add_string(t->eos, CONFIG_SMBIOS_PRODUCT_NAME);
721e992a8   Bin Meng   x86: Add SMBIOS t...
139
140
141
142
143
  	t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
  	t->board_type = SMBIOS_BOARD_MOTHERBOARD;
  
  	len = t->length + smbios_string_table_len(t->eos);
  	*current += len;
a2505fc8a   Simon Glass   sandbox: smbios: ...
144
  	unmap_sysmem(t);
721e992a8   Bin Meng   x86: Add SMBIOS t...
145
146
147
  
  	return len;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
148
  static int smbios_write_type3(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
149
  {
a2505fc8a   Simon Glass   sandbox: smbios: ...
150
  	struct smbios_type3 *t;
721e992a8   Bin Meng   x86: Add SMBIOS t...
151
  	int len = sizeof(struct smbios_type3);
a2505fc8a   Simon Glass   sandbox: smbios: ...
152
  	t = map_sysmem(*current, len);
721e992a8   Bin Meng   x86: Add SMBIOS t...
153
154
  	memset(t, 0, sizeof(struct smbios_type3));
  	fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
4cdce9f5b   Bin Meng   x86: Switch to us...
155
  	t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
721e992a8   Bin Meng   x86: Add SMBIOS t...
156
157
158
159
160
161
162
163
  	t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP;
  	t->bootup_state = SMBIOS_STATE_SAFE;
  	t->power_supply_state = SMBIOS_STATE_SAFE;
  	t->thermal_state = SMBIOS_STATE_SAFE;
  	t->security_status = SMBIOS_SECURITY_NONE;
  
  	len = t->length + smbios_string_table_len(t->eos);
  	*current += len;
a2505fc8a   Simon Glass   sandbox: smbios: ...
164
  	unmap_sysmem(t);
721e992a8   Bin Meng   x86: Add SMBIOS t...
165
166
167
  
  	return len;
  }
96476206c   Alexander Graf   smbios: Generate ...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  static void smbios_write_type4_dm(struct smbios_type4 *t)
  {
  	u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN;
  	const char *vendor = "Unknown";
  	const char *name = "Unknown";
  
  #ifdef CONFIG_CPU
  	char processor_name[49];
  	char vendor_name[49];
  	struct udevice *dev = NULL;
  
  	uclass_find_first_device(UCLASS_CPU, &dev);
  	if (dev) {
  		struct cpu_platdata *plat = dev_get_parent_platdata(dev);
  
  		if (plat->family)
  			processor_family = plat->family;
  		t->processor_id[0] = plat->id[0];
  		t->processor_id[1] = plat->id[1];
  
  		if (!cpu_get_vendor(dev, vendor_name, sizeof(vendor_name)))
  			vendor = vendor_name;
  		if (!cpu_get_desc(dev, processor_name, sizeof(processor_name)))
  			name = processor_name;
  	}
  #endif
  
  	t->processor_family = processor_family;
  	t->processor_manufacturer = smbios_add_string(t->eos, vendor);
  	t->processor_version = smbios_add_string(t->eos, name);
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
199
  static int smbios_write_type4(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
200
  {
a2505fc8a   Simon Glass   sandbox: smbios: ...
201
  	struct smbios_type4 *t;
721e992a8   Bin Meng   x86: Add SMBIOS t...
202
  	int len = sizeof(struct smbios_type4);
721e992a8   Bin Meng   x86: Add SMBIOS t...
203

a2505fc8a   Simon Glass   sandbox: smbios: ...
204
  	t = map_sysmem(*current, len);
721e992a8   Bin Meng   x86: Add SMBIOS t...
205
206
207
  	memset(t, 0, sizeof(struct smbios_type4));
  	fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle);
  	t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
96476206c   Alexander Graf   smbios: Generate ...
208
  	smbios_write_type4_dm(t);
721e992a8   Bin Meng   x86: Add SMBIOS t...
209
210
211
212
213
214
215
216
217
  	t->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
  	t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
  	t->l1_cache_handle = 0xffff;
  	t->l2_cache_handle = 0xffff;
  	t->l3_cache_handle = 0xffff;
  	t->processor_family2 = t->processor_family;
  
  	len = t->length + smbios_string_table_len(t->eos);
  	*current += len;
a2505fc8a   Simon Glass   sandbox: smbios: ...
218
  	unmap_sysmem(t);
721e992a8   Bin Meng   x86: Add SMBIOS t...
219
220
221
  
  	return len;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
222
  static int smbios_write_type32(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
223
  {
a2505fc8a   Simon Glass   sandbox: smbios: ...
224
  	struct smbios_type32 *t;
721e992a8   Bin Meng   x86: Add SMBIOS t...
225
  	int len = sizeof(struct smbios_type32);
a2505fc8a   Simon Glass   sandbox: smbios: ...
226
  	t = map_sysmem(*current, len);
721e992a8   Bin Meng   x86: Add SMBIOS t...
227
228
229
230
  	memset(t, 0, sizeof(struct smbios_type32));
  	fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
  
  	*current += len;
a2505fc8a   Simon Glass   sandbox: smbios: ...
231
  	unmap_sysmem(t);
721e992a8   Bin Meng   x86: Add SMBIOS t...
232
233
234
  
  	return len;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
235
  static int smbios_write_type127(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
236
  {
a2505fc8a   Simon Glass   sandbox: smbios: ...
237
  	struct smbios_type127 *t;
721e992a8   Bin Meng   x86: Add SMBIOS t...
238
  	int len = sizeof(struct smbios_type127);
a2505fc8a   Simon Glass   sandbox: smbios: ...
239
  	t = map_sysmem(*current, len);
721e992a8   Bin Meng   x86: Add SMBIOS t...
240
241
242
243
  	memset(t, 0, sizeof(struct smbios_type127));
  	fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
  
  	*current += len;
a2505fc8a   Simon Glass   sandbox: smbios: ...
244
  	unmap_sysmem(t);
721e992a8   Bin Meng   x86: Add SMBIOS t...
245
246
247
248
249
250
251
252
253
254
255
256
257
  
  	return len;
  }
  
  static smbios_write_type smbios_write_funcs[] = {
  	smbios_write_type0,
  	smbios_write_type1,
  	smbios_write_type2,
  	smbios_write_type3,
  	smbios_write_type4,
  	smbios_write_type32,
  	smbios_write_type127
  };
42fd8c19b   Simon Glass   x86: Use unsigned...
258
  ulong write_smbios_table(ulong addr)
721e992a8   Bin Meng   x86: Add SMBIOS t...
259
260
  {
  	struct smbios_entry *se;
a2505fc8a   Simon Glass   sandbox: smbios: ...
261
  	ulong table_addr;
42fd8c19b   Simon Glass   x86: Use unsigned...
262
  	ulong tables;
721e992a8   Bin Meng   x86: Add SMBIOS t...
263
264
265
266
267
268
269
270
271
  	int len = 0;
  	int max_struct_size = 0;
  	int handle = 0;
  	char *istart;
  	int isize;
  	int i;
  
  	/* 16 byte align the table address */
  	addr = ALIGN(addr, 16);
a2505fc8a   Simon Glass   sandbox: smbios: ...
272
  	se = map_sysmem(addr, sizeof(struct smbios_entry));
721e992a8   Bin Meng   x86: Add SMBIOS t...
273
274
275
276
277
278
279
280
  	memset(se, 0, sizeof(struct smbios_entry));
  
  	addr += sizeof(struct smbios_entry);
  	addr = ALIGN(addr, 16);
  	tables = addr;
  
  	/* populate minimum required tables */
  	for (i = 0; i < ARRAY_SIZE(smbios_write_funcs); i++) {
42fd8c19b   Simon Glass   x86: Use unsigned...
281
  		int tmp = smbios_write_funcs[i]((ulong *)&addr, handle++);
60a4df326   Christian Gmeiner   smbios: fix check...
282

721e992a8   Bin Meng   x86: Add SMBIOS t...
283
284
285
286
287
288
289
290
291
292
293
  		max_struct_size = max(max_struct_size, tmp);
  		len += tmp;
  	}
  
  	memcpy(se->anchor, "_SM_", 4);
  	se->length = sizeof(struct smbios_entry);
  	se->major_ver = SMBIOS_MAJOR_VER;
  	se->minor_ver = SMBIOS_MINOR_VER;
  	se->max_struct_size = max_struct_size;
  	memcpy(se->intermediate_anchor, "_DMI_", 5);
  	se->struct_table_length = len;
a2505fc8a   Simon Glass   sandbox: smbios: ...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  
  	/*
  	 * We must use a pointer here so things work correctly on sandbox. The
  	 * user of this table is not aware of the mapping of addresses to
  	 * sandbox's DRAM buffer.
  	 */
  	table_addr = (ulong)map_sysmem(tables, 0);
  	if (sizeof(table_addr) > sizeof(u32) && table_addr > (ulong)UINT_MAX) {
  		/*
  		 * We need to put this >32-bit pointer into the table but the
  		 * field is only 32 bits wide.
  		 */
  		printf("WARNING: SMBIOS table_address overflow %llx
  ",
  		       (unsigned long long)table_addr);
  		table_addr = 0;
  	}
  	se->struct_table_address = table_addr;
721e992a8   Bin Meng   x86: Add SMBIOS t...
312
313
314
315
316
317
318
  	se->struct_count = handle;
  
  	/* calculate checksums */
  	istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
  	isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
  	se->intermediate_checksum = table_compute_checksum(istart, isize);
  	se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
a2505fc8a   Simon Glass   sandbox: smbios: ...
319
  	unmap_sysmem(se);
721e992a8   Bin Meng   x86: Add SMBIOS t...
320
321
322
  
  	return addr;
  }