4 * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
5 * Copyright (C) 2013 Red Hat, Inc.
8 * Alex Williamson <alex.williamson@hp.com>
9 * Markus Armbruster <armbru@redhat.com>
11 * This work is licensed under the terms of the GNU GPL, version 2. See
12 * the COPYING file in the top-level directory.
14 * Contributions after 2012-01-13 are licensed under the terms of the
15 * GNU GPL, version 2 or (at your option) any later version.
18 #include "qemu/config-file.h"
19 #include "qemu/error-report.h"
20 #include "sysemu/sysemu.h"
21 #include "hw/i386/smbios.h"
22 #include "hw/loader.h"
25 /* legacy structures and constants for <= 2.0 machines */
26 struct smbios_header
{
32 struct smbios_header header
;
39 struct smbios_header header
;
43 #define SMBIOS_FIELD_ENTRY 0
44 #define SMBIOS_TABLE_ENTRY 1
46 static uint8_t *smbios_entries
;
47 static size_t smbios_entries_len
;
48 /* end: legacy structures & constants for <= 2.0 machines */
51 static int smbios_type4_count
= 0;
52 static bool smbios_immutable
;
54 static DECLARE_BITMAP(have_binfile_bitmap
, SMBIOS_MAX_TYPE
+1);
55 static DECLARE_BITMAP(have_fields_bitmap
, SMBIOS_MAX_TYPE
+1);
58 const char *vendor
, *version
, *date
;
59 bool have_major_minor
;
64 const char *manufacturer
, *product
, *version
, *serial
, *sku
, *family
;
65 /* uuid is in qemu_uuid[] */
68 static QemuOptsList qemu_smbios_opts
= {
70 .head
= QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts
.head
),
73 * no elements => accept any params
74 * validation will happen later
80 static const QemuOptDesc qemu_smbios_file_opts
[] = {
83 .type
= QEMU_OPT_STRING
,
84 .help
= "binary file containing an SMBIOS element",
89 static const QemuOptDesc qemu_smbios_type0_opts
[] = {
92 .type
= QEMU_OPT_NUMBER
,
93 .help
= "SMBIOS element type",
96 .type
= QEMU_OPT_STRING
,
97 .help
= "vendor name",
100 .type
= QEMU_OPT_STRING
,
101 .help
= "version number",
104 .type
= QEMU_OPT_STRING
,
105 .help
= "release date",
108 .type
= QEMU_OPT_STRING
,
109 .help
= "revision number",
111 { /* end of list */ }
114 static const QemuOptDesc qemu_smbios_type1_opts
[] = {
117 .type
= QEMU_OPT_NUMBER
,
118 .help
= "SMBIOS element type",
120 .name
= "manufacturer",
121 .type
= QEMU_OPT_STRING
,
122 .help
= "manufacturer name",
125 .type
= QEMU_OPT_STRING
,
126 .help
= "product name",
129 .type
= QEMU_OPT_STRING
,
130 .help
= "version number",
133 .type
= QEMU_OPT_STRING
,
134 .help
= "serial number",
137 .type
= QEMU_OPT_STRING
,
141 .type
= QEMU_OPT_STRING
,
142 .help
= "SKU number",
145 .type
= QEMU_OPT_STRING
,
146 .help
= "family name",
148 { /* end of list */ }
151 static void smbios_register_config(void)
153 qemu_add_opts(&qemu_smbios_opts
);
156 machine_init(smbios_register_config
);
158 static void smbios_validate_table(void)
160 if (smbios_type4_count
&& smbios_type4_count
!= smp_cpus
) {
161 error_report("Number of SMBIOS Type 4 tables must match cpu count");
167 /* legacy setup functions for <= 2.0 machines */
168 static void smbios_add_field(int type
, int offset
, const void *data
, size_t len
)
170 struct smbios_field
*field
;
172 if (!smbios_entries
) {
173 smbios_entries_len
= sizeof(uint16_t);
174 smbios_entries
= g_malloc0(smbios_entries_len
);
176 smbios_entries
= g_realloc(smbios_entries
, smbios_entries_len
+
177 sizeof(*field
) + len
);
178 field
= (struct smbios_field
*)(smbios_entries
+ smbios_entries_len
);
179 field
->header
.type
= SMBIOS_FIELD_ENTRY
;
180 field
->header
.length
= cpu_to_le16(sizeof(*field
) + len
);
183 field
->offset
= cpu_to_le16(offset
);
184 memcpy(field
->data
, data
, len
);
186 smbios_entries_len
+= sizeof(*field
) + len
;
187 (*(uint16_t *)smbios_entries
) =
188 cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries
) + 1);
191 static void smbios_maybe_add_str(int type
, int offset
, const char *data
)
194 smbios_add_field(type
, offset
, data
, strlen(data
) + 1);
198 static void smbios_build_type_0_fields(void)
200 smbios_maybe_add_str(0, offsetof(struct smbios_type_0
, vendor_str
),
202 smbios_maybe_add_str(0, offsetof(struct smbios_type_0
, bios_version_str
),
204 smbios_maybe_add_str(0, offsetof(struct smbios_type_0
,
205 bios_release_date_str
),
207 if (type0
.have_major_minor
) {
208 smbios_add_field(0, offsetof(struct smbios_type_0
,
209 system_bios_major_release
),
211 smbios_add_field(0, offsetof(struct smbios_type_0
,
212 system_bios_minor_release
),
217 static void smbios_build_type_1_fields(void)
219 smbios_maybe_add_str(1, offsetof(struct smbios_type_1
, manufacturer_str
),
221 smbios_maybe_add_str(1, offsetof(struct smbios_type_1
, product_name_str
),
223 smbios_maybe_add_str(1, offsetof(struct smbios_type_1
, version_str
),
225 smbios_maybe_add_str(1, offsetof(struct smbios_type_1
, serial_number_str
),
227 smbios_maybe_add_str(1, offsetof(struct smbios_type_1
, sku_number_str
),
229 smbios_maybe_add_str(1, offsetof(struct smbios_type_1
, family_str
),
232 smbios_add_field(1, offsetof(struct smbios_type_1
, uuid
),
237 uint8_t *smbios_get_table_legacy(size_t *length
)
239 if (!smbios_immutable
) {
240 smbios_build_type_0_fields();
241 smbios_build_type_1_fields();
242 smbios_validate_table();
243 smbios_immutable
= true;
245 *length
= smbios_entries_len
;
246 return smbios_entries
;
248 /* end: legacy setup functions for <= 2.0 machines */
251 #define SMBIOS_SET_DEFAULT(field, value) \
256 void smbios_set_defaults(const char *manufacturer
, const char *product
,
259 SMBIOS_SET_DEFAULT(type1
.manufacturer
, manufacturer
);
260 SMBIOS_SET_DEFAULT(type1
.product
, product
);
261 SMBIOS_SET_DEFAULT(type1
.version
, version
);
264 static void save_opt(const char **dest
, QemuOpts
*opts
, const char *name
)
266 const char *val
= qemu_opt_get(opts
, name
);
273 void smbios_entry_add(QemuOpts
*opts
)
275 Error
*local_err
= NULL
;
278 assert(!smbios_immutable
);
279 val
= qemu_opt_get(opts
, "file");
281 struct smbios_structure_header
*header
;
282 struct smbios_table
*table
;
285 qemu_opts_validate(opts
, qemu_smbios_file_opts
, &local_err
);
287 error_report("%s", error_get_pretty(local_err
));
291 size
= get_image_size(val
);
292 if (size
== -1 || size
< sizeof(struct smbios_structure_header
)) {
293 error_report("Cannot read SMBIOS file %s", val
);
297 if (!smbios_entries
) {
298 smbios_entries_len
= sizeof(uint16_t);
299 smbios_entries
= g_malloc0(smbios_entries_len
);
302 smbios_entries
= g_realloc(smbios_entries
, smbios_entries_len
+
303 sizeof(*table
) + size
);
304 table
= (struct smbios_table
*)(smbios_entries
+ smbios_entries_len
);
305 table
->header
.type
= SMBIOS_TABLE_ENTRY
;
306 table
->header
.length
= cpu_to_le16(sizeof(*table
) + size
);
308 if (load_image(val
, table
->data
) != size
) {
309 error_report("Failed to load SMBIOS file %s", val
);
313 header
= (struct smbios_structure_header
*)(table
->data
);
315 if (test_bit(header
->type
, have_fields_bitmap
)) {
316 error_report("can't load type %d struct, fields already specified!",
320 set_bit(header
->type
, have_binfile_bitmap
);
322 if (header
->type
== 4) {
323 smbios_type4_count
++;
326 smbios_entries_len
+= sizeof(*table
) + size
;
327 (*(uint16_t *)smbios_entries
) =
328 cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries
) + 1);
332 val
= qemu_opt_get(opts
, "type");
334 unsigned long type
= strtoul(val
, NULL
, 0);
336 if (type
> SMBIOS_MAX_TYPE
) {
337 error_report("out of range!");
341 if (test_bit(type
, have_binfile_bitmap
)) {
342 error_report("can't add fields, binary file already loaded!");
345 set_bit(type
, have_fields_bitmap
);
349 qemu_opts_validate(opts
, qemu_smbios_type0_opts
, &local_err
);
351 error_report("%s", error_get_pretty(local_err
));
354 save_opt(&type0
.vendor
, opts
, "vendor");
355 save_opt(&type0
.version
, opts
, "version");
356 save_opt(&type0
.date
, opts
, "date");
358 val
= qemu_opt_get(opts
, "release");
360 if (sscanf(val
, "%hhu.%hhu", &type0
.major
, &type0
.minor
) != 2) {
361 error_report("Invalid release");
364 type0
.have_major_minor
= true;
368 qemu_opts_validate(opts
, qemu_smbios_type1_opts
, &local_err
);
370 error_report("%s", error_get_pretty(local_err
));
373 save_opt(&type1
.manufacturer
, opts
, "manufacturer");
374 save_opt(&type1
.product
, opts
, "product");
375 save_opt(&type1
.version
, opts
, "version");
376 save_opt(&type1
.serial
, opts
, "serial");
377 save_opt(&type1
.sku
, opts
, "sku");
378 save_opt(&type1
.family
, opts
, "family");
380 val
= qemu_opt_get(opts
, "uuid");
382 if (qemu_uuid_parse(val
, qemu_uuid
) != 0) {
383 error_report("Invalid UUID");
386 qemu_uuid_set
= true;
390 error_report("Don't know how to build fields for SMBIOS type %ld",
396 error_report("Must specify type= or file=");