1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
4 *
5 * Adapted from coreboot src/include/smbios.h
6 */
7
8#ifndef _SMBIOS_H_
9#define _SMBIOS_H_
10
11#include <linux/types.h>
12
13/* SMBIOS spec version implemented */
14#define SMBIOS_MAJOR_VER	3
15#define SMBIOS_MINOR_VER	7
16
17enum {
18	SMBIOS_STR_MAX	= 64,	/* Maximum length allowed for a string */
19};
20
21/* SMBIOS structure types */
22enum {
23	SMBIOS_BIOS_INFORMATION = 0,
24	SMBIOS_SYSTEM_INFORMATION = 1,
25	SMBIOS_BOARD_INFORMATION = 2,
26	SMBIOS_SYSTEM_ENCLOSURE = 3,
27	SMBIOS_PROCESSOR_INFORMATION = 4,
28	SMBIOS_CACHE_INFORMATION = 7,
29	SMBIOS_SYSTEM_SLOTS = 9,
30	SMBIOS_PHYS_MEMORY_ARRAY = 16,
31	SMBIOS_MEMORY_DEVICE = 17,
32	SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS = 19,
33	SMBIOS_SYSTEM_BOOT_INFORMATION = 32,
34	SMBIOS_END_OF_TABLE = 127
35};
36
37#define SMBIOS_INTERMEDIATE_OFFSET	16
38#define SMBIOS_STRUCT_EOS_BYTES		2
39
40struct __packed smbios_entry {
41	u8 anchor[4];
42	u8 checksum;
43	u8 length;
44	u8 major_ver;
45	u8 minor_ver;
46	u16 max_struct_size;
47	u8 entry_point_rev;
48	u8 formatted_area[5];
49	u8 intermediate_anchor[5];
50	u8 intermediate_checksum;
51	u16 struct_table_length;
52	u32 struct_table_address;
53	u16 struct_count;
54	u8 bcd_rev;
55};
56
57/**
58 * struct smbios3_entry - SMBIOS 3.0 (64-bit) Entry Point structure
59 */
60struct __packed smbios3_entry {
61	/** @anchor: anchor string */
62	u8 anchor[5];
63	/** @checksum: checksum of the entry point structure */
64	u8 checksum;
65	/** @length: length of the entry point structure */
66	u8 length;
67	/** @major_ver: major version of the SMBIOS specification */
68	u8 major_ver;
69	/** @minor_ver: minor version of the SMBIOS specification */
70	u8 minor_ver;
71	/** @docrev: revision of the SMBIOS specification */
72	u8 doc_rev;
73	/** @entry_point_rev: revision of the entry point structure */
74	u8 entry_point_rev;
75	/** @reserved: reserved */
76	u8 reserved;
77	/** maximum size of SMBIOS table */
78	u32 table_maximum_size;
79	/** @struct_table_address: 64-bit physical starting address */
80	u64 struct_table_address;
81};
82
83/* BIOS characteristics */
84#define BIOS_CHARACTERISTICS_PCI_SUPPORTED	(1 << 7)
85#define BIOS_CHARACTERISTICS_UPGRADEABLE	(1 << 11)
86#define BIOS_CHARACTERISTICS_SELECTABLE_BOOT	(1 << 16)
87
88#define BIOS_CHARACTERISTICS_EXT1_ACPI		(1 << 0)
89#define BIOS_CHARACTERISTICS_EXT2_UEFI		(1 << 3)
90#define BIOS_CHARACTERISTICS_EXT2_TARGET	(1 << 2)
91
92struct __packed smbios_type0 {
93	u8 type;
94	u8 length;
95	u16 handle;
96	u8 vendor;
97	u8 bios_ver;
98	u16 bios_start_segment;
99	u8 bios_release_date;
100	u8 bios_rom_size;
101	u64 bios_characteristics;
102	u8 bios_characteristics_ext1;
103	u8 bios_characteristics_ext2;
104	u8 bios_major_release;
105	u8 bios_minor_release;
106	u8 ec_major_release;
107	u8 ec_minor_release;
108	char eos[SMBIOS_STRUCT_EOS_BYTES];
109};
110
111/**
112 * enum smbios_wakeup_type - wake-up type
113 *
114 * These constants are used for the Wake-Up Type field in the SMBIOS
115 * System Information (Type 1) structure.
116 */
117enum smbios_wakeup_type {
118	/** @SMBIOS_WAKEUP_TYPE_RESERVED: Reserved */
119	SMBIOS_WAKEUP_TYPE_RESERVED,
120	/** @SMBIOS_WAKEUP_TYPE_OTHER: Other */
121	SMBIOS_WAKEUP_TYPE_OTHER,
122	/** @SMBIOS_WAKEUP_TYPE_UNKNOWN: Unknown */
123	SMBIOS_WAKEUP_TYPE_UNKNOWN,
124	/** @SMBIOS_WAKEUP_TYPE_APM_TIMER: APM Timer */
125	SMBIOS_WAKEUP_TYPE_APM_TIMER,
126	/** @SMBIOS_WAKEUP_TYPE_MODEM_RING: Modem Ring */
127	SMBIOS_WAKEUP_TYPE_MODEM_RING,
128	/** @SMBIOS_WAKEUP_TYPE_LAN_REMOTE: LAN Remote */
129	SMBIOS_WAKEUP_TYPE_LAN_REMOTE,
130	/** @SMBIOS_WAKEUP_TYPE_POWER_SWITCH: Power Switch */
131	SMBIOS_WAKEUP_TYPE_POWER_SWITCH,
132	/** @SMBIOS_WAKEUP_TYPE_PCI_PME: PCI PME# */
133	SMBIOS_WAKEUP_TYPE_PCI_PME,
134	/** @SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED: AC Power Restored */
135	SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED,
136};
137
138struct __packed smbios_type1 {
139	u8 type;
140	u8 length;
141	u16 handle;
142	u8 manufacturer;
143	u8 product_name;
144	u8 version;
145	u8 serial_number;
146	u8 uuid[16];
147	u8 wakeup_type;
148	u8 sku_number;
149	u8 family;
150	char eos[SMBIOS_STRUCT_EOS_BYTES];
151};
152
153#define SMBIOS_BOARD_FEATURE_HOSTING	(1 << 0)
154#define SMBIOS_BOARD_MOTHERBOARD	10
155
156struct __packed smbios_type2 {
157	u8 type;
158	u8 length;
159	u16 handle;
160	u8 manufacturer;
161	u8 product_name;
162	u8 version;
163	u8 serial_number;
164	u8 asset_tag_number;
165	u8 feature_flags;
166	u8 chassis_location;
167	u16 chassis_handle;
168	u8 board_type;
169	u8 number_contained_objects;
170	char eos[SMBIOS_STRUCT_EOS_BYTES];
171};
172
173#define SMBIOS_ENCLOSURE_DESKTOP	3
174#define SMBIOS_STATE_SAFE		3
175#define SMBIOS_SECURITY_NONE		3
176
177struct __packed smbios_type3 {
178	u8 type;
179	u8 length;
180	u16 handle;
181	u8 manufacturer;
182	u8 chassis_type;
183	u8 version;
184	u8 serial_number;
185	u8 asset_tag_number;
186	u8 bootup_state;
187	u8 power_supply_state;
188	u8 thermal_state;
189	u8 security_status;
190	u32 oem_defined;
191	u8 height;
192	u8 number_of_power_cords;
193	u8 element_count;
194	u8 element_record_length;
195	char eos[SMBIOS_STRUCT_EOS_BYTES];
196};
197
198#define SMBIOS_PROCESSOR_TYPE_CENTRAL	3
199#define SMBIOS_PROCESSOR_STATUS_ENABLED	1
200#define SMBIOS_PROCESSOR_UPGRADE_NONE	6
201
202#define SMBIOS_PROCESSOR_FAMILY_OTHER	1
203#define SMBIOS_PROCESSOR_FAMILY_UNKNOWN	2
204
205struct __packed smbios_type4 {
206	u8 type;
207	u8 length;
208	u16 handle;
209	u8 socket_designation;
210	u8 processor_type;
211	u8 processor_family;
212	u8 processor_manufacturer;
213	u32 processor_id[2];
214	u8 processor_version;
215	u8 voltage;
216	u16 external_clock;
217	u16 max_speed;
218	u16 current_speed;
219	u8 status;
220	u8 processor_upgrade;
221	u16 l1_cache_handle;
222	u16 l2_cache_handle;
223	u16 l3_cache_handle;
224	u8 serial_number;
225	u8 asset_tag;
226	u8 part_number;
227	u8 core_count;
228	u8 core_enabled;
229	u8 thread_count;
230	u16 processor_characteristics;
231	u16 processor_family2;
232	u16 core_count2;
233	u16 core_enabled2;
234	u16 thread_count2;
235	char eos[SMBIOS_STRUCT_EOS_BYTES];
236};
237
238struct __packed smbios_type32 {
239	u8 type;
240	u8 length;
241	u16 handle;
242	u8 reserved[6];
243	u8 boot_status;
244	char eos[SMBIOS_STRUCT_EOS_BYTES];
245};
246
247struct __packed smbios_type127 {
248	u8 type;
249	u8 length;
250	u16 handle;
251	char eos[SMBIOS_STRUCT_EOS_BYTES];
252};
253
254struct __packed smbios_header {
255	u8 type;
256	u8 length;
257	u16 handle;
258};
259
260/**
261 * fill_smbios_header() - Fill the header of an SMBIOS table
262 *
263 * This fills the header of an SMBIOS table structure.
264 *
265 * @table:	start address of the structure
266 * @type:	the type of structure
267 * @length:	the length of the formatted area of the structure
268 * @handle:	the structure's handle, a unique 16-bit number
269 */
270static inline void fill_smbios_header(void *table, int type,
271				      int length, int handle)
272{
273	struct smbios_header *header = table;
274
275	header->type = type;
276	header->length = length - SMBIOS_STRUCT_EOS_BYTES;
277	header->handle = handle;
278}
279
280/**
281 * write_smbios_table() - Write SMBIOS table
282 *
283 * This writes SMBIOS table at a given address.
284 *
285 * @addr:	start address to write SMBIOS table, 16-byte-alignment
286 * recommended. Note that while the SMBIOS tables themself have no alignment
287 * requirement, some systems may requires alignment. For example x86 systems
288 * which put tables at f0000 require 16-byte alignment
289 *
290 * Return:	end address of SMBIOS table (and start address for next entry)
291 *		or NULL in case of an error
292 */
293ulong write_smbios_table(ulong addr);
294
295/**
296 * smbios_entry() - Get a valid struct smbios_entry pointer
297 *
298 * @address:   address where smbios tables is located
299 * @size:      size of smbios table
300 * @return:    NULL or a valid pointer to a struct smbios_entry
301 */
302const struct smbios_entry *smbios_entry(u64 address, u32 size);
303
304/**
305 * smbios_header() - Search for SMBIOS header type
306 *
307 * @entry:     pointer to a struct smbios_entry
308 * @type:      SMBIOS type
309 * @return:    NULL or a valid pointer to a struct smbios_header
310 */
311const struct smbios_header *smbios_header(const struct smbios_entry *entry, int type);
312
313/**
314 * smbios_string() - Return string from SMBIOS
315 *
316 * @header:    pointer to struct smbios_header
317 * @index:     string index
318 * @return:    NULL or a valid char pointer
319 */
320char *smbios_string(const struct smbios_header *header, int index);
321
322/**
323 * smbios_update_version() - Update the version string
324 *
325 * This can be called after the SMBIOS tables are written (e.g. after the U-Boot
326 * main loop has started) to update the BIOS version string (SMBIOS table 0).
327 *
328 * @version: New version string to use
329 * Return: 0 if OK, -ENOENT if no version string was previously written,
330 *	-ENOSPC if the new string is too large to fit
331 */
332int smbios_update_version(const char *version);
333
334/**
335 * smbios_update_version_full() - Update the version string
336 *
337 * This can be called after the SMBIOS tables are written (e.g. after the U-Boot
338 * main loop has started) to update the BIOS version string (SMBIOS table 0).
339 * It scans for the correct place to put the version, so does not need U-Boot
340 * to have actually written the tables itself (e.g. if a previous bootloader
341 * did it).
342 *
343 * @smbios_tab: Start of SMBIOS tables
344 * @version: New version string to use
345 * Return: 0 if OK, -ENOENT if no version string was previously written,
346 *	-ENOSPC if the new string is too large to fit
347 */
348int smbios_update_version_full(void *smbios_tab, const char *version);
349
350/**
351 * smbios_prepare_measurement() - Update smbios table for the measurement
352 *
353 * TCG specification requires to measure static configuration information.
354 * This function clear the device dependent parameters such as
355 * serial number for the measurement.
356 *
357 * @entry: pointer to a struct smbios3_entry
358 * @header: pointer to a struct smbios_header
359 */
360void smbios_prepare_measurement(const struct smbios3_entry *entry,
361				struct smbios_header *header);
362
363#endif /* _SMBIOS_H_ */
364