2 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
4 * Adapted from coreboot src/arch/x86/smbios.c
6 * SPDX-License-Identifier: GPL-2.0+
11 #include <tables_csum.h>
15 DECLARE_GLOBAL_DATA_PTR;
18 * smbios_add_string() - add a string to the string area
20 * This adds a string to the string area which is appended directly after
21 * the formatted portion of an SMBIOS structure.
23 * @start: string area start address
25 * @return: string number in the string area
27 static int smbios_add_string(char *start, const char *str)
51 * smbios_string_table_len() - compute the string area size
53 * This computes the size of the string area including the string terminator.
55 * @start: string area start address
56 * @return: string area size
58 static int smbios_string_table_len(char *start)
72 static int smbios_write_type0(u32 *current, int handle)
74 struct smbios_type0 *t = (struct smbios_type0 *)*current;
75 int len = sizeof(struct smbios_type0);
77 memset(t, 0, sizeof(struct smbios_type0));
78 fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
79 t->vendor = smbios_add_string(t->eos, "U-Boot");
80 t->bios_ver = smbios_add_string(t->eos, PLAIN_VERSION);
81 t->bios_release_date = smbios_add_string(t->eos, U_BOOT_DMI_DATE);
82 t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
83 t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED |
84 BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
85 BIOS_CHARACTERISTICS_UPGRADEABLE;
86 #ifdef CONFIG_GENERATE_ACPI_TABLE
87 t->bios_characteristics_ext1 = BIOS_CHARACTERISTICS_EXT1_ACPI;
89 t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
90 t->bios_major_release = 0xff;
91 t->bios_minor_release = 0xff;
92 t->ec_major_release = 0xff;
93 t->ec_minor_release = 0xff;
95 len = t->length + smbios_string_table_len(t->eos);
101 static int smbios_write_type1(u32 *current, int handle)
103 struct smbios_type1 *t = (struct smbios_type1 *)*current;
104 int len = sizeof(struct smbios_type1);
106 memset(t, 0, sizeof(struct smbios_type1));
107 fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
108 t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
109 t->product_name = smbios_add_string(t->eos, CONFIG_SMBIOS_PRODUCT_NAME);
111 len = t->length + smbios_string_table_len(t->eos);
117 static int smbios_write_type2(u32 *current, int handle)
119 struct smbios_type2 *t = (struct smbios_type2 *)*current;
120 int len = sizeof(struct smbios_type2);
122 memset(t, 0, sizeof(struct smbios_type2));
123 fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
124 t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
125 t->product_name = smbios_add_string(t->eos, CONFIG_SMBIOS_PRODUCT_NAME);
126 t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
127 t->board_type = SMBIOS_BOARD_MOTHERBOARD;
129 len = t->length + smbios_string_table_len(t->eos);
135 static int smbios_write_type3(u32 *current, int handle)
137 struct smbios_type3 *t = (struct smbios_type3 *)*current;
138 int len = sizeof(struct smbios_type3);
140 memset(t, 0, sizeof(struct smbios_type3));
141 fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
142 t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
143 t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP;
144 t->bootup_state = SMBIOS_STATE_SAFE;
145 t->power_supply_state = SMBIOS_STATE_SAFE;
146 t->thermal_state = SMBIOS_STATE_SAFE;
147 t->security_status = SMBIOS_SECURITY_NONE;
149 len = t->length + smbios_string_table_len(t->eos);
155 static int smbios_write_type4(u32 *current, int handle)
157 struct smbios_type4 *t = (struct smbios_type4 *)*current;
158 int len = sizeof(struct smbios_type4);
161 char processor_name[CPU_MAX_NAME_LEN];
162 struct cpuid_result res;
164 memset(t, 0, sizeof(struct smbios_type4));
165 fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle);
166 t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
167 t->processor_family = gd->arch.x86;
168 vendor = cpu_vendor_name(gd->arch.x86_vendor);
169 t->processor_manufacturer = smbios_add_string(t->eos, vendor);
171 t->processor_id[0] = res.eax;
172 t->processor_id[1] = res.edx;
173 name = cpu_get_name(processor_name);
174 t->processor_version = smbios_add_string(t->eos, name);
175 t->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
176 t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
177 t->l1_cache_handle = 0xffff;
178 t->l2_cache_handle = 0xffff;
179 t->l3_cache_handle = 0xffff;
180 t->processor_family2 = t->processor_family;
182 len = t->length + smbios_string_table_len(t->eos);
188 static int smbios_write_type32(u32 *current, int handle)
190 struct smbios_type32 *t = (struct smbios_type32 *)*current;
191 int len = sizeof(struct smbios_type32);
193 memset(t, 0, sizeof(struct smbios_type32));
194 fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
201 static int smbios_write_type127(u32 *current, int handle)
203 struct smbios_type127 *t = (struct smbios_type127 *)*current;
204 int len = sizeof(struct smbios_type127);
206 memset(t, 0, sizeof(struct smbios_type127));
207 fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
214 static smbios_write_type smbios_write_funcs[] = {
224 u32 write_smbios_table(u32 addr)
226 struct smbios_entry *se;
229 int max_struct_size = 0;
235 /* 16 byte align the table address */
236 addr = ALIGN(addr, 16);
238 se = (struct smbios_entry *)addr;
239 memset(se, 0, sizeof(struct smbios_entry));
241 addr += sizeof(struct smbios_entry);
242 addr = ALIGN(addr, 16);
245 /* populate minimum required tables */
246 for (i = 0; i < ARRAY_SIZE(smbios_write_funcs); i++) {
247 int tmp = smbios_write_funcs[i](&addr, handle++);
248 max_struct_size = max(max_struct_size, tmp);
252 memcpy(se->anchor, "_SM_", 4);
253 se->length = sizeof(struct smbios_entry);
254 se->major_ver = SMBIOS_MAJOR_VER;
255 se->minor_ver = SMBIOS_MINOR_VER;
256 se->max_struct_size = max_struct_size;
257 memcpy(se->intermediate_anchor, "_DMI_", 5);
258 se->struct_table_length = len;
259 se->struct_table_address = tables;
260 se->struct_count = handle;
262 /* calculate checksums */
263 istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
264 isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
265 se->intermediate_checksum = table_compute_checksum(istart, isize);
266 se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));