Blame view

lib/smbios.c 7.84 KB
721e992a8   Bin Meng   x86: Add SMBIOS t...
1
2
3
4
5
6
7
8
9
  /*
   * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
   *
   * Adapted from coreboot src/arch/x86/smbios.c
   *
   * SPDX-License-Identifier:	GPL-2.0+
   */
  
  #include <common.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
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
73
74
  
  DECLARE_GLOBAL_DATA_PTR;
  
  /**
   * 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...
75
  static int smbios_write_type0(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
76
77
78
79
80
81
82
83
84
  {
  	struct smbios_type0 *t = (struct smbios_type0 *)*current;
  	int len = sizeof(struct smbios_type0);
  
  	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...
85
  #ifdef CONFIG_ROM_SIZE
721e992a8   Bin Meng   x86: Add SMBIOS t...
86
  	t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
e663b350f   Alexander Graf   smbios: Expose in...
87
  #endif
721e992a8   Bin Meng   x86: Add SMBIOS t...
88
89
90
91
92
93
  	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...
94
95
96
  #ifdef CONFIG_EFI_LOADER
  	t->bios_characteristics_ext1 |= BIOS_CHARACTERISTICS_EXT1_UEFI;
  #endif
721e992a8   Bin Meng   x86: Add SMBIOS t...
97
  	t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
e663b350f   Alexander Graf   smbios: Expose in...
98

721e992a8   Bin Meng   x86: Add SMBIOS t...
99
100
101
102
103
104
105
106
107
108
  	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;
  
  	return len;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
109
  static int smbios_write_type1(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
110
111
112
  {
  	struct smbios_type1 *t = (struct smbios_type1 *)*current;
  	int len = sizeof(struct smbios_type1);
00caae6d4   Simon Glass   env: Rename geten...
113
  	char *serial_str = env_get("serial#");
721e992a8   Bin Meng   x86: Add SMBIOS t...
114
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
120
121
122
  	if (serial_str) {
  		strncpy((char*)t->uuid, serial_str, sizeof(t->uuid));
  		t->serial_number = smbios_add_string(t->eos, serial_str);
  	}
721e992a8   Bin Meng   x86: Add SMBIOS t...
123
124
125
126
127
128
  
  	len = t->length + smbios_string_table_len(t->eos);
  	*current += len;
  
  	return len;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
129
  static int smbios_write_type2(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
130
131
132
133
134
135
  {
  	struct smbios_type2 *t = (struct smbios_type2 *)*current;
  	int len = sizeof(struct smbios_type2);
  
  	memset(t, 0, sizeof(struct smbios_type2));
  	fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
4cdce9f5b   Bin Meng   x86: Switch to us...
136
137
  	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...
138
139
140
141
142
143
144
145
  	t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
  	t->board_type = SMBIOS_BOARD_MOTHERBOARD;
  
  	len = t->length + smbios_string_table_len(t->eos);
  	*current += len;
  
  	return len;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
146
  static int smbios_write_type3(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
147
148
149
150
151
152
  {
  	struct smbios_type3 *t = (struct smbios_type3 *)*current;
  	int len = sizeof(struct smbios_type3);
  
  	memset(t, 0, sizeof(struct smbios_type3));
  	fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
4cdce9f5b   Bin Meng   x86: Switch to us...
153
  	t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
721e992a8   Bin Meng   x86: Add SMBIOS t...
154
155
156
157
158
159
160
161
162
163
164
  	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;
  
  	return len;
  }
96476206c   Alexander Graf   smbios: Generate ...
165
166
167
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
  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...
196
  static int smbios_write_type4(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
197
198
199
  {
  	struct smbios_type4 *t = (struct smbios_type4 *)*current;
  	int len = sizeof(struct smbios_type4);
721e992a8   Bin Meng   x86: Add SMBIOS t...
200
201
202
203
  
  	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 ...
204
  	smbios_write_type4_dm(t);
721e992a8   Bin Meng   x86: Add SMBIOS t...
205
206
207
208
209
210
211
212
213
214
215
216
  	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;
  
  	return len;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
217
  static int smbios_write_type32(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
218
219
220
221
222
223
224
225
226
227
228
  {
  	struct smbios_type32 *t = (struct smbios_type32 *)*current;
  	int len = sizeof(struct smbios_type32);
  
  	memset(t, 0, sizeof(struct smbios_type32));
  	fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
  
  	*current += len;
  
  	return len;
  }
42fd8c19b   Simon Glass   x86: Use unsigned...
229
  static int smbios_write_type127(ulong *current, int handle)
721e992a8   Bin Meng   x86: Add SMBIOS t...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  {
  	struct smbios_type127 *t = (struct smbios_type127 *)*current;
  	int len = sizeof(struct smbios_type127);
  
  	memset(t, 0, sizeof(struct smbios_type127));
  	fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
  
  	*current += len;
  
  	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...
251
  ulong write_smbios_table(ulong addr)
721e992a8   Bin Meng   x86: Add SMBIOS t...
252
253
  {
  	struct smbios_entry *se;
42fd8c19b   Simon Glass   x86: Use unsigned...
254
  	ulong tables;
721e992a8   Bin Meng   x86: Add SMBIOS t...
255
256
257
258
259
260
261
262
263
  	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);
42fd8c19b   Simon Glass   x86: Use unsigned...
264
  	se = (struct smbios_entry *)(uintptr_t)addr;
721e992a8   Bin Meng   x86: Add SMBIOS t...
265
266
267
268
269
270
271
272
  	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...
273
  		int tmp = smbios_write_funcs[i]((ulong *)&addr, handle++);
721e992a8   Bin Meng   x86: Add SMBIOS t...
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  		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;
  	se->struct_table_address = tables;
  	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));
  
  	return addr;
  }