Commit b6f6e3d3a71cee61320216a42940cfaa9b42a162

Authored by aliguori
1 parent c4be29ff

qemu: Add support for SMBIOS command line otions (Alex Williamson)

Create a new -smbios option (x86-only) to allow binary SMBIOS entries
to be passed through to the BIOS or modify the default values of
individual fields of type 0 and 1 entries on the command line.

Binary SMBIOS entries can be generated as follows:

dmidecode -t 1 -u | grep $'^\t\t[^"]' | xargs -n1 | \
        perl -lne 'printf "%c", hex($_)' > smbios_type_1.bin

These can then be passed to the BIOS using this switch:

 -smbios file=smbios_type_1.bin

Command line generation supports the following syntax:

 -smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d]
 -smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]
              [,uuid=$(uuidgen)][,sku=str][,family=str]

For instance, to add a serial number to the type 1 table:

 -smbios type=1,serial=0123456789

Interface is extensible to support more fields/tables as needed.

aliguori: remove texi formatting from help output

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7163 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -576,7 +576,7 @@ OBJS+= ide.o pckbd.o vga.o $(SOUND_HW) dma.o
576 576 OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
577 577 OBJS+= cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
578 578 OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
579   -OBJS += device-hotplug.o pci-hotplug.o
  579 +OBJS += device-hotplug.o pci-hotplug.o smbios.o
580 580 CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
581 581 endif
582 582 ifeq ($(TARGET_BASE_ARCH), ppc)
... ...
... ... @@ -37,6 +37,7 @@
37 37 #include "virtio-balloon.h"
38 38 #include "virtio-console.h"
39 39 #include "hpet_emul.h"
  40 +#include "smbios.h"
40 41  
41 42 /* output Bochs bios info messages */
42 43 //#define DEBUG_BIOS
... ... @@ -51,6 +52,7 @@
51 52 #define ACPI_DATA_SIZE 0x10000
52 53 #define BIOS_CFG_IOPORT 0x510
53 54 #define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
  55 +#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
54 56  
55 57 #define MAX_IDE_BUS 2
56 58  
... ... @@ -425,6 +427,8 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
425 427 static void bochs_bios_init(void)
426 428 {
427 429 void *fw_cfg;
  430 + uint8_t *smbios_table;
  431 + size_t smbios_len;
428 432  
429 433 register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL);
430 434 register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL);
... ... @@ -442,6 +446,11 @@ static void bochs_bios_init(void)
442 446 fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
443 447 fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, (uint8_t *)acpi_tables,
444 448 acpi_tables_len);
  449 +
  450 + smbios_table = smbios_get_table(&smbios_len);
  451 + if (smbios_table)
  452 + fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
  453 + smbios_table, smbios_len);
445 454 }
446 455  
447 456 /* Generate an initial boot sector which sets state and jump to
... ...
hw/smbios.c 0 → 100644
  1 +/*
  2 + * SMBIOS Support
  3 + *
  4 + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
  5 + *
  6 + * Authors:
  7 + * Alex Williamson <alex.williamson@hp.com>
  8 + *
  9 + * This work is licensed under the terms of the GNU GPL, version 2. See
  10 + * the COPYING file in the top-level directory.
  11 + *
  12 + */
  13 +
  14 +#include "sysemu.h"
  15 +#include "smbios.h"
  16 +
  17 +/*
  18 + * Structures shared with the BIOS
  19 + */
  20 +struct smbios_header {
  21 + uint16_t length;
  22 + uint8_t type;
  23 +} __attribute__((__packed__));
  24 +
  25 +struct smbios_field {
  26 + struct smbios_header header;
  27 + uint8_t type;
  28 + uint16_t offset;
  29 + uint8_t data[];
  30 +} __attribute__((__packed__));
  31 +
  32 +struct smbios_table {
  33 + struct smbios_header header;
  34 + uint8_t data[];
  35 +} __attribute__((__packed__));
  36 +
  37 +#define SMBIOS_FIELD_ENTRY 0
  38 +#define SMBIOS_TABLE_ENTRY 1
  39 +
  40 +
  41 +static uint8_t *smbios_entries;
  42 +static size_t smbios_entries_len;
  43 +
  44 +uint8_t *smbios_get_table(size_t *length)
  45 +{
  46 + *length = smbios_entries_len;
  47 + return smbios_entries;
  48 +}
  49 +
  50 +/*
  51 + * To avoid unresolvable overlaps in data, don't allow both
  52 + * tables and fields for the same smbios type.
  53 + */
  54 +static void smbios_check_collision(int type, int entry)
  55 +{
  56 + uint16_t *num_entries = (uint16_t *)smbios_entries;
  57 + struct smbios_header *header;
  58 + char *p;
  59 + int i;
  60 +
  61 + if (!num_entries)
  62 + return;
  63 +
  64 + p = (char *)(num_entries + 1);
  65 +
  66 + for (i = 0; i < *num_entries; i++) {
  67 + header = (struct smbios_header *)p;
  68 + if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) {
  69 + struct smbios_field *field = (void *)header;
  70 + if (type == field->type) {
  71 + fprintf(stderr, "SMBIOS type %d field already defined, "
  72 + "cannot add table\n", type);
  73 + exit(1);
  74 + }
  75 + } else if (entry == SMBIOS_FIELD_ENTRY &&
  76 + header->type == SMBIOS_TABLE_ENTRY) {
  77 + struct smbios_structure_header *table = (void *)(header + 1);
  78 + if (type == table->type) {
  79 + fprintf(stderr, "SMBIOS type %d table already defined, "
  80 + "cannot add field\n", type);
  81 + exit(1);
  82 + }
  83 + }
  84 + p += le16_to_cpu(header->length);
  85 + }
  86 +}
  87 +
  88 +void smbios_add_field(int type, int offset, int len, void *data)
  89 +{
  90 + struct smbios_field *field;
  91 +
  92 + smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
  93 +
  94 + if (!smbios_entries) {
  95 + smbios_entries_len = sizeof(uint16_t);
  96 + smbios_entries = qemu_mallocz(smbios_entries_len);
  97 + }
  98 + smbios_entries = qemu_realloc(smbios_entries, smbios_entries_len +
  99 + sizeof(*field) + len);
  100 + field = (struct smbios_field *)(smbios_entries + smbios_entries_len);
  101 + field->header.type = SMBIOS_FIELD_ENTRY;
  102 + field->header.length = cpu_to_le16(sizeof(*field) + len);
  103 +
  104 + field->type = type;
  105 + field->offset = cpu_to_le16(offset);
  106 + memcpy(field->data, data, len);
  107 +
  108 + smbios_entries_len += sizeof(*field) + len;
  109 + (*(uint16_t *)smbios_entries) =
  110 + cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
  111 +}
  112 +
  113 +static void smbios_build_type_0_fields(const char *t)
  114 +{
  115 + char buf[1024];
  116 +
  117 + if (get_param_value(buf, sizeof(buf), "vendor", t))
  118 + smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
  119 + strlen(buf) + 1, buf);
  120 + if (get_param_value(buf, sizeof(buf), "version", t))
  121 + smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
  122 + strlen(buf) + 1, buf);
  123 + if (get_param_value(buf, sizeof(buf), "date", t))
  124 + smbios_add_field(0, offsetof(struct smbios_type_0,
  125 + bios_release_date_str),
  126 + strlen(buf) + 1, buf);
  127 + if (get_param_value(buf, sizeof(buf), "release", t)) {
  128 + int major, minor;
  129 + sscanf(buf, "%d.%d", &major, &minor);
  130 + smbios_add_field(0, offsetof(struct smbios_type_0,
  131 + system_bios_major_release), 1, &major);
  132 + smbios_add_field(0, offsetof(struct smbios_type_0,
  133 + system_bios_minor_release), 1, &minor);
  134 + }
  135 +}
  136 +
  137 +static void smbios_build_type_1_fields(const char *t)
  138 +{
  139 + char buf[1024];
  140 +
  141 + if (get_param_value(buf, sizeof(buf), "manufacturer", t))
  142 + smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
  143 + strlen(buf) + 1, buf);
  144 + if (get_param_value(buf, sizeof(buf), "product", t))
  145 + smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
  146 + strlen(buf) + 1, buf);
  147 + if (get_param_value(buf, sizeof(buf), "version", t))
  148 + smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
  149 + strlen(buf) + 1, buf);
  150 + if (get_param_value(buf, sizeof(buf), "serial", t))
  151 + smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
  152 + strlen(buf) + 1, buf);
  153 + if (get_param_value(buf, sizeof(buf), "uuid", t)) {
  154 + if (qemu_uuid_parse(buf, qemu_uuid) != 0) {
  155 + fprintf(stderr, "Invalid SMBIOS UUID string\n");
  156 + exit(1);
  157 + }
  158 + }
  159 + if (get_param_value(buf, sizeof(buf), "sku", t))
  160 + smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
  161 + strlen(buf) + 1, buf);
  162 + if (get_param_value(buf, sizeof(buf), "family", t))
  163 + smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
  164 + strlen(buf) + 1, buf);
  165 +}
  166 +
  167 +int smbios_entry_add(const char *t)
  168 +{
  169 + char buf[1024];
  170 +
  171 + if (get_param_value(buf, sizeof(buf), "file", t)) {
  172 + struct smbios_structure_header *header;
  173 + struct smbios_table *table;
  174 + int size = get_image_size(buf);
  175 +
  176 + if (size < sizeof(struct smbios_structure_header)) {
  177 + fprintf(stderr, "Cannot read smbios file %s", buf);
  178 + exit(1);
  179 + }
  180 +
  181 + if (!smbios_entries) {
  182 + smbios_entries_len = sizeof(uint16_t);
  183 + smbios_entries = qemu_mallocz(smbios_entries_len);
  184 + }
  185 +
  186 + smbios_entries = qemu_realloc(smbios_entries, smbios_entries_len +
  187 + sizeof(*table) + size);
  188 + table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
  189 + table->header.type = SMBIOS_TABLE_ENTRY;
  190 + table->header.length = cpu_to_le16(sizeof(*table) + size);
  191 +
  192 + if (load_image(buf, table->data) != size) {
  193 + fprintf(stderr, "Failed to load smbios file %s", buf);
  194 + exit(1);
  195 + }
  196 +
  197 + header = (struct smbios_structure_header *)(table->data);
  198 + smbios_check_collision(header->type, SMBIOS_TABLE_ENTRY);
  199 +
  200 + smbios_entries_len += sizeof(*table) + size;
  201 + (*(uint16_t *)smbios_entries) =
  202 + cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
  203 + return 0;
  204 + }
  205 +
  206 + if (get_param_value(buf, sizeof(buf), "type", t)) {
  207 + unsigned long type = strtoul(buf, NULL, 0);
  208 + switch (type) {
  209 + case 0:
  210 + smbios_build_type_0_fields(t);
  211 + return 0;
  212 + case 1:
  213 + smbios_build_type_1_fields(t);
  214 + return 0;
  215 + default:
  216 + fprintf(stderr, "Don't know how to build fields for SMBIOS type "
  217 + "%ld\n", type);
  218 + exit(1);
  219 + }
  220 + }
  221 +
  222 + fprintf(stderr, "smbios: must specify type= or file=\n");
  223 + return -1;
  224 +}
... ...
hw/smbios.h 0 → 100644
  1 +#ifndef QEMU_SMBIOS_H
  2 +#define QEMU_SMBIOS_H
  3 +/*
  4 + * SMBIOS Support
  5 + *
  6 + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
  7 + *
  8 + * Authors:
  9 + * Alex Williamson <alex.williamson@hp.com>
  10 + *
  11 + * This work is licensed under the terms of the GNU GPL, version 2. See
  12 + * the COPYING file in the top-level directory.
  13 + *
  14 + */
  15 +
  16 +int smbios_entry_add(const char *t);
  17 +void smbios_add_field(int type, int offset, int len, void *data);
  18 +uint8_t *smbios_get_table(size_t *length);
  19 +
  20 +/*
  21 + * SMBIOS spec defined tables
  22 + */
  23 +
  24 +/* This goes at the beginning of every SMBIOS structure. */
  25 +struct smbios_structure_header {
  26 + uint8_t type;
  27 + uint8_t length;
  28 + uint16_t handle;
  29 +} __attribute__((__packed__));
  30 +
  31 +/* SMBIOS type 0 - BIOS Information */
  32 +struct smbios_type_0 {
  33 + struct smbios_structure_header header;
  34 + uint8_t vendor_str;
  35 + uint8_t bios_version_str;
  36 + uint16_t bios_starting_address_segment;
  37 + uint8_t bios_release_date_str;
  38 + uint8_t bios_rom_size;
  39 + uint8_t bios_characteristics[8];
  40 + uint8_t bios_characteristics_extension_bytes[2];
  41 + uint8_t system_bios_major_release;
  42 + uint8_t system_bios_minor_release;
  43 + uint8_t embedded_controller_major_release;
  44 + uint8_t embedded_controller_minor_release;
  45 +} __attribute__((__packed__));
  46 +
  47 +/* SMBIOS type 1 - System Information */
  48 +struct smbios_type_1 {
  49 + struct smbios_structure_header header;
  50 + uint8_t manufacturer_str;
  51 + uint8_t product_name_str;
  52 + uint8_t version_str;
  53 + uint8_t serial_number_str;
  54 + uint8_t uuid[16];
  55 + uint8_t wake_up_type;
  56 + uint8_t sku_number_str;
  57 + uint8_t family_str;
  58 +} __attribute__((__packed__));
  59 +
  60 +/* SMBIOS type 3 - System Enclosure (v2.3) */
  61 +struct smbios_type_3 {
  62 + struct smbios_structure_header header;
  63 + uint8_t manufacturer_str;
  64 + uint8_t type;
  65 + uint8_t version_str;
  66 + uint8_t serial_number_str;
  67 + uint8_t asset_tag_number_str;
  68 + uint8_t boot_up_state;
  69 + uint8_t power_supply_state;
  70 + uint8_t thermal_state;
  71 + uint8_t security_status;
  72 + uint32_t oem_defined;
  73 + uint8_t height;
  74 + uint8_t number_of_power_cords;
  75 + uint8_t contained_element_count;
  76 + // contained elements follow
  77 +} __attribute__((__packed__));
  78 +
  79 +/* SMBIOS type 4 - Processor Information (v2.0) */
  80 +struct smbios_type_4 {
  81 + struct smbios_structure_header header;
  82 + uint8_t socket_designation_str;
  83 + uint8_t processor_type;
  84 + uint8_t processor_family;
  85 + uint8_t processor_manufacturer_str;
  86 + uint32_t processor_id[2];
  87 + uint8_t processor_version_str;
  88 + uint8_t voltage;
  89 + uint16_t external_clock;
  90 + uint16_t max_speed;
  91 + uint16_t current_speed;
  92 + uint8_t status;
  93 + uint8_t processor_upgrade;
  94 + uint16_t l1_cache_handle;
  95 + uint16_t l2_cache_handle;
  96 + uint16_t l3_cache_handle;
  97 +} __attribute__((__packed__));
  98 +
  99 +/* SMBIOS type 16 - Physical Memory Array
  100 + * Associated with one type 17 (Memory Device).
  101 + */
  102 +struct smbios_type_16 {
  103 + struct smbios_structure_header header;
  104 + uint8_t location;
  105 + uint8_t use;
  106 + uint8_t error_correction;
  107 + uint32_t maximum_capacity;
  108 + uint16_t memory_error_information_handle;
  109 + uint16_t number_of_memory_devices;
  110 +} __attribute__((__packed__));
  111 +/* SMBIOS type 17 - Memory Device
  112 + * Associated with one type 19
  113 + */
  114 +struct smbios_type_17 {
  115 + struct smbios_structure_header header;
  116 + uint16_t physical_memory_array_handle;
  117 + uint16_t memory_error_information_handle;
  118 + uint16_t total_width;
  119 + uint16_t data_width;
  120 + uint16_t size;
  121 + uint8_t form_factor;
  122 + uint8_t device_set;
  123 + uint8_t device_locator_str;
  124 + uint8_t bank_locator_str;
  125 + uint8_t memory_type;
  126 + uint16_t type_detail;
  127 +} __attribute__((__packed__));
  128 +
  129 +/* SMBIOS type 19 - Memory Array Mapped Address */
  130 +struct smbios_type_19 {
  131 + struct smbios_structure_header header;
  132 + uint32_t starting_address;
  133 + uint32_t ending_address;
  134 + uint16_t memory_array_handle;
  135 + uint8_t partition_width;
  136 +} __attribute__((__packed__));
  137 +
  138 +/* SMBIOS type 20 - Memory Device Mapped Address */
  139 +struct smbios_type_20 {
  140 + struct smbios_structure_header header;
  141 + uint32_t starting_address;
  142 + uint32_t ending_address;
  143 + uint16_t memory_device_handle;
  144 + uint16_t memory_array_mapped_address_handle;
  145 + uint8_t partition_row_position;
  146 + uint8_t interleave_position;
  147 + uint8_t interleaved_data_depth;
  148 +} __attribute__((__packed__));
  149 +
  150 +/* SMBIOS type 32 - System Boot Information */
  151 +struct smbios_type_32 {
  152 + struct smbios_structure_header header;
  153 + uint8_t reserved[6];
  154 + uint8_t boot_status;
  155 +} __attribute__((__packed__));
  156 +
  157 +/* SMBIOS type 127 -- End-of-table */
  158 +struct smbios_type_127 {
  159 + struct smbios_structure_header header;
  160 +} __attribute__((__packed__));
  161 +
  162 +#endif /*QEMU_SMBIOS_H */
... ...
pc-bios/bios-pq/0012-load-smbios-entries-and-files-from-qemu.patch 0 → 100644
  1 +qemu:bios: Load SMBIOS entries and files from qemu (Alex Williamson)
  2 +
  3 +Allow SMBIOS fields to be overridden and entries replaced by those
  4 +read from qemu.
  5 +
  6 +Signed-off-by: Alex Williamson <alex.williamson@hp.com>
  7 +Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
  8 +
  9 +diff --git a/bios/rombios32.c b/bios/rombios32.c
  10 +index 7be4216..1a1ed64 100644
  11 +--- a/bios/rombios32.c
  12 ++++ b/bios/rombios32.c
  13 +@@ -441,7 +441,6 @@ uint32_t cpuid_features;
  14 + uint32_t cpuid_ext_features;
  15 + unsigned long ram_size;
  16 + uint64_t ram_end;
  17 +-uint8_t bios_uuid[16];
  18 + #ifdef BX_USE_EBDA_TABLES
  19 + unsigned long ebda_cur_addr;
  20 + #endif
  21 +@@ -471,6 +470,7 @@ void wrmsr_smp(uint32_t index, uint64_t val)
  22 + #define QEMU_CFG_UUID 0x02
  23 + #define QEMU_CFG_ARCH_LOCAL 0x8000
  24 + #define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0)
  25 ++#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1)
  26 +
  27 + int qemu_cfg_port;
  28 +
  29 +@@ -519,19 +519,17 @@ static int acpi_load_table(int i, uint32_t addr, uint16_t *len)
  30 + qemu_cfg_read((uint8_t*)addr, *len);
  31 + return 0;
  32 + }
  33 +-#endif
  34 +
  35 +-void uuid_probe(void)
  36 ++static uint16_t smbios_entries(void)
  37 + {
  38 +-#ifdef BX_QEMU
  39 +- if(qemu_cfg_port) {
  40 +- qemu_cfg_select(QEMU_CFG_UUID);
  41 +- qemu_cfg_read(bios_uuid, 16);
  42 +- return;
  43 +- }
  44 +-#endif
  45 +- memset(bios_uuid, 0, 16);
  46 ++ uint16_t cnt;
  47 ++
  48 ++ qemu_cfg_select(QEMU_CFG_SMBIOS_ENTRIES);
  49 ++ qemu_cfg_read((uint8_t*)&cnt, sizeof(cnt));
  50 ++
  51 ++ return cnt;
  52 + }
  53 ++#endif
  54 +
  55 + void cpu_probe(void)
  56 + {
  57 +@@ -1963,21 +1961,105 @@ smbios_entry_point_init(void *start,
  58 + ep->intermediate_checksum = -sum;
  59 + }
  60 +
  61 ++struct smbios_header {
  62 ++ uint16_t length;
  63 ++ uint8_t type;
  64 ++} __attribute__((__packed__));
  65 ++
  66 ++struct smbios_field {
  67 ++ struct smbios_header header;
  68 ++ uint8_t type;
  69 ++ uint16_t offset;
  70 ++ uint8_t data[];
  71 ++} __attribute__((__packed__));
  72 ++
  73 ++struct smbios_table {
  74 ++ struct smbios_header header;
  75 ++ uint8_t data[];
  76 ++} __attribute__((__packed__));
  77 ++
  78 ++#define SMBIOS_FIELD_ENTRY 0
  79 ++#define SMBIOS_TABLE_ENTRY 1
  80 ++
  81 ++static size_t
  82 ++smbios_load_field(int type, size_t offset, void *addr)
  83 ++{
  84 ++#ifdef BX_QEMU
  85 ++ int i;
  86 ++
  87 ++ for (i = smbios_entries(); i > 0; i--) {
  88 ++ struct smbios_field field;
  89 ++
  90 ++ qemu_cfg_read((uint8_t *)&field, sizeof(struct smbios_header));
  91 ++ field.header.length -= sizeof(struct smbios_header);
  92 ++
  93 ++ if (field.header.type != SMBIOS_FIELD_ENTRY) {
  94 ++ while (field.header.length--)
  95 ++ inb(QEMU_CFG_DATA_PORT);
  96 ++ continue;
  97 ++ }
  98 ++
  99 ++ qemu_cfg_read((uint8_t *)&field.type,
  100 ++ sizeof(field) - sizeof(struct smbios_header));
  101 ++ field.header.length -= sizeof(field) - sizeof(struct smbios_header);
  102 ++
  103 ++ if (field.type != type || field.offset != offset) {
  104 ++ while (field.header.length--)
  105 ++ inb(QEMU_CFG_DATA_PORT);
  106 ++ continue;
  107 ++ }
  108 ++
  109 ++ qemu_cfg_read(addr, field.header.length);
  110 ++ return (size_t)field.header.length;
  111 ++ }
  112 ++#endif
  113 ++ return 0;
  114 ++}
  115 ++
  116 ++#define load_str_field_with_default(type, field, def) do { \
  117 ++ size = smbios_load_field(type, offsetof(struct smbios_type_##type, \
  118 ++ field), end); \
  119 ++ if (size > 0) { \
  120 ++ end += size; \
  121 ++ } else { \
  122 ++ memcpy(end, def, sizeof(def)); \
  123 ++ end += sizeof(def); \
  124 ++ } \
  125 ++ p->field = ++str_index; \
  126 ++} while (0)
  127 ++
  128 ++#define load_str_field_or_skip(type, field) do { \
  129 ++ size = smbios_load_field(type, offsetof(struct smbios_type_##type, \
  130 ++ field), end); \
  131 ++ if (size > 0) { \
  132 ++ end += size; \
  133 ++ p->field = ++str_index; \
  134 ++ } else { \
  135 ++ p->field = 0; \
  136 ++ } \
  137 ++} while (0)
  138 ++
  139 + /* Type 0 -- BIOS Information */
  140 + #define RELEASE_DATE_STR "01/01/2007"
  141 + static void *
  142 +-smbios_type_0_init(void *start)
  143 ++smbios_init_type_0(void *start)
  144 + {
  145 + struct smbios_type_0 *p = (struct smbios_type_0 *)start;
  146 ++ char *end = (char *)start + sizeof(struct smbios_type_0);
  147 ++ size_t size;
  148 ++ int str_index = 0;
  149 +
  150 + p->header.type = 0;
  151 + p->header.length = sizeof(struct smbios_type_0);
  152 + p->header.handle = 0;
  153 +
  154 +- p->vendor_str = 1;
  155 +- p->bios_version_str = 1;
  156 ++ load_str_field_with_default(0, vendor_str, BX_APPNAME);
  157 ++ load_str_field_with_default(0, bios_version_str, BX_APPNAME);
  158 ++
  159 + p->bios_starting_address_segment = 0xe800;
  160 +- p->bios_release_date_str = 2;
  161 ++
  162 ++ load_str_field_with_default(0, bios_release_date_str, RELEASE_DATE_STR);
  163 ++
  164 + p->bios_rom_size = 0; /* FIXME */
  165 +
  166 + memset(p->bios_characteristics, 0, 8);
  167 +@@ -1985,50 +2067,66 @@ smbios_type_0_init(void *start)
  168 + p->bios_characteristics_extension_bytes[0] = 0;
  169 + p->bios_characteristics_extension_bytes[1] = 0;
  170 +
  171 +- p->system_bios_major_release = 1;
  172 +- p->system_bios_minor_release = 0;
  173 ++ if (!smbios_load_field(0, offsetof(struct smbios_type_0,
  174 ++ system_bios_major_release),
  175 ++ &p->system_bios_major_release))
  176 ++ p->system_bios_major_release = 1;
  177 ++
  178 ++ if (!smbios_load_field(0, offsetof(struct smbios_type_0,
  179 ++ system_bios_minor_release),
  180 ++ &p->system_bios_minor_release))
  181 ++ p->system_bios_minor_release = 0;
  182 ++
  183 + p->embedded_controller_major_release = 0xff;
  184 + p->embedded_controller_minor_release = 0xff;
  185 +
  186 +- start += sizeof(struct smbios_type_0);
  187 +- memcpy((char *)start, BX_APPNAME, sizeof(BX_APPNAME));
  188 +- start += sizeof(BX_APPNAME);
  189 +- memcpy((char *)start, RELEASE_DATE_STR, sizeof(RELEASE_DATE_STR));
  190 +- start += sizeof(RELEASE_DATE_STR);
  191 +- *((uint8_t *)start) = 0;
  192 ++ *end = 0;
  193 ++ end++;
  194 +
  195 +- return start+1;
  196 ++ return end;
  197 + }
  198 +
  199 + /* Type 1 -- System Information */
  200 + static void *
  201 +-smbios_type_1_init(void *start)
  202 ++smbios_init_type_1(void *start)
  203 + {
  204 + struct smbios_type_1 *p = (struct smbios_type_1 *)start;
  205 ++ char *end = (char *)start + sizeof(struct smbios_type_1);
  206 ++ size_t size;
  207 ++ int str_index = 0;
  208 ++
  209 + p->header.type = 1;
  210 + p->header.length = sizeof(struct smbios_type_1);
  211 + p->header.handle = 0x100;
  212 +
  213 +- p->manufacturer_str = 0;
  214 +- p->product_name_str = 0;
  215 +- p->version_str = 0;
  216 +- p->serial_number_str = 0;
  217 ++ load_str_field_or_skip(1, manufacturer_str);
  218 ++ load_str_field_or_skip(1, product_name_str);
  219 ++ load_str_field_or_skip(1, version_str);
  220 ++ load_str_field_or_skip(1, serial_number_str);
  221 +
  222 +- memcpy(p->uuid, bios_uuid, 16);
  223 ++ size = smbios_load_field(1, offsetof(struct smbios_type_1,
  224 ++ uuid), &p->uuid);
  225 ++ if (size == 0)
  226 ++ memset(p->uuid, 0, 16);
  227 +
  228 + p->wake_up_type = 0x06; /* power switch */
  229 +- p->sku_number_str = 0;
  230 +- p->family_str = 0;
  231 +
  232 +- start += sizeof(struct smbios_type_1);
  233 +- *((uint16_t *)start) = 0;
  234 ++ load_str_field_or_skip(1, sku_number_str);
  235 ++ load_str_field_or_skip(1, family_str);
  236 +
  237 +- return start+2;
  238 ++ *end = 0;
  239 ++ end++;
  240 ++ if (!str_index) {
  241 ++ *end = 0;
  242 ++ end++;
  243 ++ }
  244 ++
  245 ++ return end;
  246 + }
  247 +
  248 + /* Type 3 -- System Enclosure */
  249 + static void *
  250 +-smbios_type_3_init(void *start)
  251 ++smbios_init_type_3(void *start)
  252 + {
  253 + struct smbios_type_3 *p = (struct smbios_type_3 *)start;
  254 +
  255 +@@ -2058,7 +2156,7 @@ smbios_type_3_init(void *start)
  256 +
  257 + /* Type 4 -- Processor Information */
  258 + static void *
  259 +-smbios_type_4_init(void *start, unsigned int cpu_number)
  260 ++smbios_init_type_4(void *start, unsigned int cpu_number)
  261 + {
  262 + struct smbios_type_4 *p = (struct smbios_type_4 *)start;
  263 +
  264 +@@ -2098,7 +2196,7 @@ smbios_type_4_init(void *start, unsigned int cpu_number)
  265 +
  266 + /* Type 16 -- Physical Memory Array */
  267 + static void *
  268 +-smbios_type_16_init(void *start, uint32_t memsize, int nr_mem_devs)
  269 ++smbios_init_type_16(void *start, uint32_t memsize, int nr_mem_devs)
  270 + {
  271 + struct smbios_type_16 *p = (struct smbios_type_16*)start;
  272 +
  273 +@@ -2121,7 +2219,7 @@ smbios_type_16_init(void *start, uint32_t memsize, int nr_mem_devs)
  274 +
  275 + /* Type 17 -- Memory Device */
  276 + static void *
  277 +-smbios_type_17_init(void *start, uint32_t memory_size_mb, int instance)
  278 ++smbios_init_type_17(void *start, uint32_t memory_size_mb, int instance)
  279 + {
  280 + struct smbios_type_17 *p = (struct smbios_type_17 *)start;
  281 +
  282 +@@ -2151,7 +2249,7 @@ smbios_type_17_init(void *start, uint32_t memory_size_mb, int instance)
  283 +
  284 + /* Type 19 -- Memory Array Mapped Address */
  285 + static void *
  286 +-smbios_type_19_init(void *start, uint32_t memory_size_mb, int instance)
  287 ++smbios_init_type_19(void *start, uint32_t memory_size_mb, int instance)
  288 + {
  289 + struct smbios_type_19 *p = (struct smbios_type_19 *)start;
  290 +
  291 +@@ -2172,7 +2270,7 @@ smbios_type_19_init(void *start, uint32_t memory_size_mb, int instance)
  292 +
  293 + /* Type 20 -- Memory Device Mapped Address */
  294 + static void *
  295 +-smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance)
  296 ++smbios_init_type_20(void *start, uint32_t memory_size_mb, int instance)
  297 + {
  298 + struct smbios_type_20 *p = (struct smbios_type_20 *)start;
  299 +
  300 +@@ -2196,7 +2294,7 @@ smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance)
  301 +
  302 + /* Type 32 -- System Boot Information */
  303 + static void *
  304 +-smbios_type_32_init(void *start)
  305 ++smbios_init_type_32(void *start)
  306 + {
  307 + struct smbios_type_32 *p = (struct smbios_type_32 *)start;
  308 +
  309 +@@ -2214,7 +2312,7 @@ smbios_type_32_init(void *start)
  310 +
  311 + /* Type 127 -- End of Table */
  312 + static void *
  313 +-smbios_type_127_init(void *start)
  314 ++smbios_init_type_127(void *start)
  315 + {
  316 + struct smbios_type_127 *p = (struct smbios_type_127 *)start;
  317 +
  318 +@@ -2228,6 +2326,78 @@ smbios_type_127_init(void *start)
  319 + return start + 2;
  320 + }
  321 +
  322 ++static int
  323 ++smbios_load_external(int type, char **p, unsigned *nr_structs,
  324 ++ unsigned *max_struct_size)
  325 ++{
  326 ++#ifdef BX_QEMU
  327 ++ static uint64_t used_bitmap[4] = { 0 };
  328 ++ char *start = *p;
  329 ++ int i;
  330 ++
  331 ++ /* Check if we've already reported these tables */
  332 ++ if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f)))
  333 ++ return 1;
  334 ++
  335 ++ /* Don't introduce spurious end markers */
  336 ++ if (type == 127)
  337 ++ return 0;
  338 ++
  339 ++ for (i = smbios_entries(); i > 0; i--) {
  340 ++ struct smbios_table table;
  341 ++ struct smbios_structure_header *header = (void *)*p;
  342 ++ int string;
  343 ++
  344 ++ qemu_cfg_read((uint8_t *)&table, sizeof(struct smbios_header));
  345 ++ table.header.length -= sizeof(struct smbios_header);
  346 ++
  347 ++ if (table.header.type != SMBIOS_TABLE_ENTRY) {
  348 ++ while (table.header.length--)
  349 ++ inb(QEMU_CFG_DATA_PORT);
  350 ++ continue;
  351 ++ }
  352 ++
  353 ++ qemu_cfg_read((uint8_t *)*p, sizeof(struct smbios_structure_header));
  354 ++ table.header.length -= sizeof(struct smbios_structure_header);
  355 ++
  356 ++ if (header->type != type) {
  357 ++ while (table.header.length--)
  358 ++ inb(QEMU_CFG_DATA_PORT);
  359 ++ continue;
  360 ++ }
  361 ++
  362 ++ *p += sizeof(struct smbios_structure_header);
  363 ++
  364 ++ /* Entries end with a double NULL char, if there's a string at
  365 ++ * the end (length is greater than formatted length), the string
  366 ++ * terminator provides the first NULL. */
  367 ++ string = header->length < table.header.length +
  368 ++ sizeof(struct smbios_structure_header);
  369 ++
  370 ++ /* Read the rest and terminate the entry */
  371 ++ qemu_cfg_read((uint8_t *)*p, table.header.length);
  372 ++ *p += table.header.length;
  373 ++ *((uint8_t*)*p) = 0;
  374 ++ (*p)++;
  375 ++ if (!string) {
  376 ++ *((uint8_t*)*p) = 0;
  377 ++ (*p)++;
  378 ++ }
  379 ++
  380 ++ (*nr_structs)++;
  381 ++ if (*p - (char *)header > *max_struct_size)
  382 ++ *max_struct_size = *p - (char *)header;
  383 ++ }
  384 ++
  385 ++ /* Mark that we've reported on this type */
  386 ++ used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f));
  387 ++
  388 ++ return (start != *p);
  389 ++#else /* !BX_QEMU */
  390 ++ return 0;
  391 ++#endif
  392 ++}
  393 ++
  394 + void smbios_init(void)
  395 + {
  396 + unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
  397 +@@ -2246,34 +2416,39 @@ void smbios_init(void)
  398 +
  399 + p = (char *)start + sizeof(struct smbios_entry_point);
  400 +
  401 +-#define add_struct(fn) do{ \
  402 +- q = (fn); \
  403 +- nr_structs++; \
  404 +- if ((q - p) > max_struct_size) \
  405 +- max_struct_size = q - p; \
  406 +- p = q; \
  407 +-}while (0)
  408 +-
  409 +- add_struct(smbios_type_0_init(p));
  410 +- add_struct(smbios_type_1_init(p));
  411 +- add_struct(smbios_type_3_init(p));
  412 ++#define add_struct(type, args...) do { \
  413 ++ if (!smbios_load_external(type, &p, &nr_structs, &max_struct_size)) { \
  414 ++ q = smbios_init_type_##type(args); \
  415 ++ nr_structs++; \
  416 ++ if ((q - p) > max_struct_size) \
  417 ++ max_struct_size = q - p; \
  418 ++ p = q; \
  419 ++ } \
  420 ++} while (0)
  421 ++
  422 ++ add_struct(0, p);
  423 ++ add_struct(1, p);
  424 ++ add_struct(3, p);
  425 + for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
  426 +- add_struct(smbios_type_4_init(p, cpu_num));
  427 ++ add_struct(4, p, cpu_num);
  428 +
  429 + /* Each 'memory device' covers up to 16GB of address space. */
  430 + nr_mem_devs = (memsize + 0x3fff) >> 14;
  431 +- add_struct(smbios_type_16_init(p, memsize, nr_mem_devs));
  432 ++ add_struct(16, p, memsize, nr_mem_devs);
  433 + for ( i = 0; i < nr_mem_devs; i++ )
  434 + {
  435 + uint32_t dev_memsize = ((i == (nr_mem_devs - 1))
  436 + ? (((memsize-1) & 0x3fff)+1) : 0x4000);
  437 +- add_struct(smbios_type_17_init(p, dev_memsize, i));
  438 +- add_struct(smbios_type_19_init(p, dev_memsize, i));
  439 +- add_struct(smbios_type_20_init(p, dev_memsize, i));
  440 ++ add_struct(17, p, dev_memsize, i);
  441 ++ add_struct(19, p, dev_memsize, i);
  442 ++ add_struct(20, p, dev_memsize, i);
  443 + }
  444 +
  445 +- add_struct(smbios_type_32_init(p));
  446 +- add_struct(smbios_type_127_init(p));
  447 ++ add_struct(32, p);
  448 ++ /* Add any remaining provided entries before the end marker */
  449 ++ for (i = 0; i < 256; i++)
  450 ++ smbios_load_external(i, &p, &nr_structs, &max_struct_size);
  451 ++ add_struct(127, p);
  452 +
  453 + #undef add_struct
  454 +
  455 +@@ -2380,8 +2555,6 @@ void rombios32_init(uint32_t *s3_resume_vector, uint8_t *shutdown_flag)
  456 +
  457 + mptable_init();
  458 +
  459 +- uuid_probe();
  460 +-
  461 + smbios_init();
  462 +
  463 + if (acpi_enabled)
  464 +
  465 +
  466 +--
  467 +To unsubscribe from this list: send the line "unsubscribe kvm" in
  468 +the body of a message to majordomo@vger.kernel.org
  469 +More majordomo info at http://vger.kernel.org/majordomo-info.html
  470 +
... ...
pc-bios/bios-pq/series
... ... @@ -9,3 +9,4 @@
9 9 0009_qemu-bios-pci-hotplug-support.patch
10 10 0010_bios-mark-the-acpi-sci-interrupt-as-connected-to-irq-9.patch
11 11 0011_read-additional-acpi-tables-from-a-vm.patch
  12 +0012-load-smbios-entries-and-files-from-qemu.patch
... ...
pc-bios/bios.bin
No preview for this file type
qemu-options.hx
... ... @@ -683,6 +683,27 @@ Add ACPI table with specified header fields and context from specified files.
683 683 ETEXI
684 684  
685 685 #ifdef TARGET_I386
  686 +DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
  687 + "-smbios file=binary\n"
  688 + " Load SMBIOS entry from binary file\n"
  689 + "-smbios type=0[,vendor=str][,version=str][,date=str][,release=%%d.%%d]\n"
  690 + " Specify SMBIOS type 0 fields\n"
  691 + "-smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]\n"
  692 + " [,uuid=uuid][,sku=str][,family=str]\n"
  693 + " Specify SMBIOS type 1 fields\n")
  694 +#endif
  695 +STEXI
  696 +@item -smbios file=@var{binary}
  697 +Load SMBIOS entry from binary file.
  698 +
  699 +@item -smbios type=0[,vendor=@var{str}][,version=@var{str}][,date=@var{str}][,release=@var{%d.%d}]
  700 +Specify SMBIOS type 0 fields
  701 +
  702 +@item -smbios type=1[,manufacturer=@var{str}][,product=@var{str}][,version=@var{str}][,serial=@var{str}][,uuid=@var{uuid}][,sku=@var{str}][,family=@var{str}]
  703 +Specify SMBIOS type 1 fields
  704 +ETEXI
  705 +
  706 +#ifdef TARGET_I386
686 707 DEFHEADING()
687 708 #endif
688 709 STEXI
... ...
... ... @@ -138,6 +138,7 @@ int main(int argc, char **argv)
138 138 #include "hw/isa.h"
139 139 #include "hw/baum.h"
140 140 #include "hw/bt.h"
  141 +#include "hw/smbios.h"
141 142 #include "bt-host.h"
142 143 #include "net.h"
143 144 #include "monitor.h"
... ... @@ -4214,6 +4215,10 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid)
4214 4215 if(ret != 16)
4215 4216 return -1;
4216 4217  
  4218 +#ifdef TARGET_I386
  4219 + smbios_add_field(1, offsetof(struct smbios_type_1, uuid), 16, uuid);
  4220 +#endif
  4221 +
4217 4222 return 0;
4218 4223 }
4219 4224  
... ... @@ -4797,6 +4802,12 @@ int main(int argc, char **argv, char **envp)
4797 4802 exit(1);
4798 4803 }
4799 4804 break;
  4805 + case QEMU_OPTION_smbios:
  4806 + if(smbios_entry_add(optarg) < 0) {
  4807 + fprintf(stderr, "Wrong smbios provided\n");
  4808 + exit(1);
  4809 + }
  4810 + break;
4800 4811 #endif
4801 4812 #ifdef USE_KQEMU
4802 4813 case QEMU_OPTION_no_kqemu:
... ...