Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / interface / smbios / smbios_settings.c
1 /*
2  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <stdint.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <ipxe/settings.h>
26 #include <ipxe/init.h>
27 #include <ipxe/uuid.h>
28 #include <ipxe/smbios.h>
29
30 /** SMBIOS settings scope */
31 static const struct settings_scope smbios_settings_scope;
32
33 /**
34  * Construct SMBIOS raw-data tag
35  *
36  * @v _type             SMBIOS structure type number
37  * @v _structure        SMBIOS structure data type
38  * @v _field            Field within SMBIOS structure data type
39  * @ret tag             SMBIOS setting tag
40  */
41 #define SMBIOS_RAW_TAG( _type, _structure, _field )             \
42         ( ( (_type) << 16 ) |                                   \
43           ( offsetof ( _structure, _field ) << 8 ) |            \
44           ( sizeof ( ( ( _structure * ) 0 )->_field ) ) )
45
46 /**
47  * Construct SMBIOS string tag
48  *
49  * @v _type             SMBIOS structure type number
50  * @v _structure        SMBIOS structure data type
51  * @v _field            Field within SMBIOS structure data type
52  * @ret tag             SMBIOS setting tag
53  */
54 #define SMBIOS_STRING_TAG( _type, _structure, _field )          \
55         ( ( (_type) << 16 ) |                                   \
56           ( offsetof ( _structure, _field ) << 8 ) )
57
58 /**
59  * Check applicability of SMBIOS setting
60  *
61  * @v settings          Settings block
62  * @v setting           Setting
63  * @ret applies         Setting applies within this settings block
64  */
65 static int smbios_applies ( struct settings *settings __unused,
66                             const struct setting *setting ) {
67
68         return ( setting->scope == &smbios_settings_scope );
69 }
70
71 /**
72  * Fetch value of SMBIOS setting
73  *
74  * @v settings          Settings block, or NULL to search all blocks
75  * @v setting           Setting to fetch
76  * @v data              Buffer to fill with setting data
77  * @v len               Length of buffer
78  * @ret len             Length of setting data, or negative error
79  */
80 static int smbios_fetch ( struct settings *settings __unused,
81                           struct setting *setting,
82                           void *data, size_t len ) {
83         struct smbios_structure structure;
84         unsigned int tag_instance;
85         unsigned int tag_type;
86         unsigned int tag_offset;
87         unsigned int tag_len;
88         int rc;
89
90         /* Split tag into instance, type, offset and length */
91         tag_instance = ( ( setting->tag >> 24 ) & 0xff );
92         tag_type = ( ( setting->tag >> 16 ) & 0xff );
93         tag_offset = ( ( setting->tag >> 8 ) & 0xff );
94         tag_len = ( setting->tag & 0xff );
95
96         /* Find SMBIOS structure */
97         if ( ( rc = find_smbios_structure ( tag_type, tag_instance,
98                                             &structure ) ) != 0 )
99                 return rc;
100
101         {
102                 uint8_t buf[structure.header.len];
103                 const void *raw;
104                 union uuid uuid;
105                 unsigned int index;
106
107                 /* Read SMBIOS structure */
108                 if ( ( rc = read_smbios_structure ( &structure, buf,
109                                                     sizeof ( buf ) ) ) != 0 )
110                         return rc;
111
112                 /* A <length> of zero indicates that the byte at
113                  * <offset> contains a string index.  An <offset> of
114                  * zero indicates that the <length> contains a literal
115                  * string index.
116                  */
117                 if ( ( tag_len == 0 ) || ( tag_offset == 0 ) ) {
118                         index = ( ( tag_offset == 0 ) ?
119                                   tag_len : buf[tag_offset] );
120                         if ( ( rc = read_smbios_string ( &structure, index,
121                                                          data, len ) ) < 0 ) {
122                                 return rc;
123                         }
124                         if ( ! setting->type )
125                                 setting->type = &setting_type_string;
126                         return rc;
127                 }
128
129                 /* Mangle UUIDs if necessary.  iPXE treats UUIDs as
130                  * being in network byte order (big-endian).  SMBIOS
131                  * specification version 2.6 states that UUIDs are
132                  * stored with little-endian values in the first three
133                  * fields; earlier versions did not specify an
134                  * endianness.  dmidecode assumes that the byte order
135                  * is little-endian if and only if the SMBIOS version
136                  * is 2.6 or higher; we match this behaviour.
137                  */
138                 raw = &buf[tag_offset];
139                 if ( ( setting->type == &setting_type_uuid ) &&
140                      ( tag_len == sizeof ( uuid ) ) &&
141                      ( smbios_version() >= SMBIOS_VERSION ( 2, 6 ) ) ) {
142                         DBG ( "SMBIOS detected mangled UUID\n" );
143                         memcpy ( &uuid, &buf[tag_offset], sizeof ( uuid ) );
144                         uuid_mangle ( &uuid );
145                         raw = &uuid;
146                 }
147
148                 /* Return data */
149                 if ( len > tag_len )
150                         len = tag_len;
151                 memcpy ( data, raw, len );
152                 if ( ! setting->type )
153                         setting->type = &setting_type_hex;
154                 return tag_len;
155         }
156 }
157
158 /** SMBIOS settings operations */
159 static struct settings_operations smbios_settings_operations = {
160         .applies = smbios_applies,
161         .fetch = smbios_fetch,
162 };
163
164 /** SMBIOS settings */
165 static struct settings smbios_settings = {
166         .refcnt = NULL,
167         .siblings = LIST_HEAD_INIT ( smbios_settings.siblings ),
168         .children = LIST_HEAD_INIT ( smbios_settings.children ),
169         .op = &smbios_settings_operations,
170         .default_scope = &smbios_settings_scope,
171 };
172
173 /** Initialise SMBIOS settings */
174 static void smbios_init ( void ) {
175         int rc;
176
177         if ( ( rc = register_settings ( &smbios_settings, NULL,
178                                         "smbios" ) ) != 0 ) {
179                 DBG ( "SMBIOS could not register settings: %s\n",
180                       strerror ( rc ) );
181                 return;
182         }
183 }
184
185 /** SMBIOS settings initialiser */
186 struct init_fn smbios_init_fn __init_fn ( INIT_NORMAL ) = {
187         .initialise = smbios_init,
188 };
189
190 /** UUID setting obtained via SMBIOS */
191 const struct setting uuid_setting __setting ( SETTING_HOST, uuid ) = {
192         .name = "uuid",
193         .description = "UUID",
194         .tag = SMBIOS_RAW_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
195                                 struct smbios_system_information, uuid ),
196         .type = &setting_type_uuid,
197         .scope = &smbios_settings_scope,
198 };
199
200 /** Manufacturer name setting */
201 const struct setting manufacturer_setting __setting ( SETTING_HOST_EXTRA,
202                                                       manufacturer ) = {
203         .name = "manufacturer",
204         .description = "Manufacturer",
205         .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
206                                    struct smbios_system_information,
207                                    manufacturer ),
208         .type = &setting_type_string,
209         .scope = &smbios_settings_scope,
210 };
211
212 /** Product name setting */
213 const struct setting product_setting __setting ( SETTING_HOST_EXTRA, product )={
214         .name = "product",
215         .description = "Product name",
216         .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
217                                    struct smbios_system_information,
218                                    product ),
219         .type = &setting_type_string,
220         .scope = &smbios_settings_scope,
221 };
222
223 /** Serial number setting */
224 const struct setting serial_setting __setting ( SETTING_HOST_EXTRA, serial ) = {
225         .name = "serial",
226         .description = "Serial number",
227         .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION,
228                                    struct smbios_system_information,
229                                    serial ),
230         .type = &setting_type_string,
231         .scope = &smbios_settings_scope,
232 };
233
234 /** Asset tag setting */
235 const struct setting asset_setting __setting ( SETTING_HOST_EXTRA, asset ) = {
236         .name = "asset",
237         .description = "Asset tag",
238         .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_ENCLOSURE_INFORMATION,
239                                    struct smbios_enclosure_information,
240                                    asset_tag ),
241         .type = &setting_type_string,
242         .scope = &smbios_settings_scope,
243 };
244
245 /** Board serial number setting (may differ from chassis serial number) */
246 const struct setting board_serial_setting __setting ( SETTING_HOST_EXTRA,
247                                                       board_serial ) = {
248         .name = "board-serial",
249         .description = "Base board serial",
250         .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_BASE_BOARD_INFORMATION,
251                                    struct smbios_base_board_information,
252                                    serial ),
253         .type = &setting_type_string,
254         .scope = &smbios_settings_scope,
255 };