2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
29 #include <ipxe/settings.h>
30 #include <ipxe/init.h>
31 #include <ipxe/uuid.h>
32 #include <ipxe/smbios.h>
34 /** SMBIOS settings scope */
35 static const struct settings_scope smbios_settings_scope;
38 * Construct SMBIOS raw-data tag
40 * @v _type SMBIOS structure type number
41 * @v _structure SMBIOS structure data type
42 * @v _field Field within SMBIOS structure data type
43 * @ret tag SMBIOS setting tag
45 #define SMBIOS_RAW_TAG( _type, _structure, _field ) \
46 ( ( (_type) << 16 ) | \
47 ( offsetof ( _structure, _field ) << 8 ) | \
48 ( sizeof ( ( ( _structure * ) 0 )->_field ) ) )
51 * Construct SMBIOS string tag
53 * @v _type SMBIOS structure type number
54 * @v _structure SMBIOS structure data type
55 * @v _field Field within SMBIOS structure data type
56 * @ret tag SMBIOS setting tag
58 #define SMBIOS_STRING_TAG( _type, _structure, _field ) \
59 ( ( (_type) << 16 ) | \
60 ( offsetof ( _structure, _field ) << 8 ) )
63 * Check applicability of SMBIOS setting
65 * @v settings Settings block
67 * @ret applies Setting applies within this settings block
69 static int smbios_applies ( struct settings *settings __unused,
70 const struct setting *setting ) {
72 return ( setting->scope == &smbios_settings_scope );
76 * Fetch value of SMBIOS setting
78 * @v settings Settings block, or NULL to search all blocks
79 * @v setting Setting to fetch
80 * @v data Buffer to fill with setting data
81 * @v len Length of buffer
82 * @ret len Length of setting data, or negative error
84 static int smbios_fetch ( struct settings *settings __unused,
85 struct setting *setting,
86 void *data, size_t len ) {
87 struct smbios_structure structure;
88 unsigned int tag_instance;
89 unsigned int tag_type;
90 unsigned int tag_offset;
94 /* Split tag into instance, type, offset and length */
95 tag_instance = ( ( setting->tag >> 24 ) & 0xff );
96 tag_type = ( ( setting->tag >> 16 ) & 0xff );
97 tag_offset = ( ( setting->tag >> 8 ) & 0xff );
98 tag_len = ( setting->tag & 0xff );
100 /* Find SMBIOS structure */
101 if ( ( rc = find_smbios_structure ( tag_type, tag_instance,
102 &structure ) ) != 0 )
106 uint8_t buf[structure.header.len];
111 /* Read SMBIOS structure */
112 if ( ( rc = read_smbios_structure ( &structure, buf,
113 sizeof ( buf ) ) ) != 0 )
116 /* A <length> of zero indicates that the byte at
117 * <offset> contains a string index. An <offset> of
118 * zero indicates that the <length> contains a literal
121 if ( ( tag_len == 0 ) || ( tag_offset == 0 ) ) {
122 index = ( ( tag_offset == 0 ) ?
123 tag_len : buf[tag_offset] );
124 if ( ( rc = read_smbios_string ( &structure, index,
125 data, len ) ) < 0 ) {
128 if ( ! setting->type )
129 setting->type = &setting_type_string;
133 /* Mangle UUIDs if necessary. iPXE treats UUIDs as
134 * being in network byte order (big-endian). SMBIOS
135 * specification version 2.6 states that UUIDs are
136 * stored with little-endian values in the first three
137 * fields; earlier versions did not specify an
138 * endianness. dmidecode assumes that the byte order
139 * is little-endian if and only if the SMBIOS version
140 * is 2.6 or higher; we match this behaviour.
142 raw = &buf[tag_offset];
143 if ( ( setting->type == &setting_type_uuid ) &&
144 ( tag_len == sizeof ( uuid ) ) &&
145 ( smbios_version() >= SMBIOS_VERSION ( 2, 6 ) ) ) {
146 DBG ( "SMBIOS detected mangled UUID\n" );
147 memcpy ( &uuid, &buf[tag_offset], sizeof ( uuid ) );
148 uuid_mangle ( &uuid );
155 memcpy ( data, raw, len );
156 if ( ! setting->type )
157 setting->type = &setting_type_hex;
162 /** SMBIOS settings operations */
163 static struct settings_operations smbios_settings_operations = {
164 .applies = smbios_applies,
165 .fetch = smbios_fetch,
168 /** SMBIOS settings */
169 static struct settings smbios_settings = {
171 .siblings = LIST_HEAD_INIT ( smbios_settings.siblings ),
172 .children = LIST_HEAD_INIT ( smbios_settings.children ),
173 .op = &smbios_settings_operations,
174 .default_scope = &smbios_settings_scope,
177 /** Initialise SMBIOS settings */
178 static void smbios_init ( void ) {
181 if ( ( rc = register_settings ( &smbios_settings, NULL,
182 "smbios" ) ) != 0 ) {
183 DBG ( "SMBIOS could not register settings: %s\n",
189 /** SMBIOS settings initialiser */
190 struct init_fn smbios_init_fn __init_fn ( INIT_NORMAL ) = {
191 .initialise = smbios_init,
194 /** UUID setting obtained via SMBIOS */
195 const struct setting uuid_setting __setting ( SETTING_HOST, uuid ) = {
197 .description = "UUID",
198 .tag = SMBIOS_RAW_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
199 struct smbios_system_information, uuid ),
200 .type = &setting_type_uuid,
201 .scope = &smbios_settings_scope,
204 /** Manufacturer name setting */
205 const struct setting manufacturer_setting __setting ( SETTING_HOST_EXTRA,
207 .name = "manufacturer",
208 .description = "Manufacturer",
209 .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
210 struct smbios_system_information,
212 .type = &setting_type_string,
213 .scope = &smbios_settings_scope,
216 /** Product name setting */
217 const struct setting product_setting __setting ( SETTING_HOST_EXTRA, product )={
219 .description = "Product name",
220 .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
221 struct smbios_system_information,
223 .type = &setting_type_string,
224 .scope = &smbios_settings_scope,
227 /** Serial number setting */
228 const struct setting serial_setting __setting ( SETTING_HOST_EXTRA, serial ) = {
230 .description = "Serial number",
231 .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
232 struct smbios_system_information,
234 .type = &setting_type_string,
235 .scope = &smbios_settings_scope,
238 /** Asset tag setting */
239 const struct setting asset_setting __setting ( SETTING_HOST_EXTRA, asset ) = {
241 .description = "Asset tag",
242 .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_ENCLOSURE_INFORMATION,
243 struct smbios_enclosure_information,
245 .type = &setting_type_string,
246 .scope = &smbios_settings_scope,
249 /** Board serial number setting (may differ from chassis serial number) */
250 const struct setting board_serial_setting __setting ( SETTING_HOST_EXTRA,
252 .name = "board-serial",
253 .description = "Base board serial",
254 .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_BASE_BOARD_INFORMATION,
255 struct smbios_base_board_information,
257 .type = &setting_type_string,
258 .scope = &smbios_settings_scope,