aboutsummaryrefslogtreecommitdiff
path: root/hw/i386
diff options
context:
space:
mode:
authorEduardo Habkost <ehabkost@redhat.com>2014-10-29 11:26:08 -0200
committerMichael S. Tsirkin <mst@redhat.com>2014-11-02 13:44:52 +0200
commitcaad057bb6ce86a9cb71520af395fd0bd04a659f (patch)
tree9b26db555e09f85d22fd934e334769d124fb2997 /hw/i386
parent2cad57c7177766e2779f30fed9e4578bc7ad62ac (diff)
smbios: Encode UUID according to SMBIOS specification
Differently from older versions, SMBIOS version 2.6 is explicit about the encoding of UUID fields: > Although RFC 4122 recommends network byte order for all fields, the PC > industry (including the ACPI, UEFI, and Microsoft specifications) has > consistently used little-endian byte encoding for the first three fields: > time_low, time_mid, time_hi_and_version. The same encoding, also known as > wire format, should also be used for the SMBIOS representation of the UUID. > > The UUID {00112233-4455-6677-8899-AABBCCDDEEFF} would thus be represented > as 33 22 11 00 55 44 77 66 88 99 AA BB CC DD EE FF. The dmidecode tool implements this and decodes the above "wire format" when SMBIOS version >= 2.6. We moved from SMBIOS version 2.4 to 2.8 when we started building the SMBIOS entry point inside QEMU, on commit c97294ec1b9e36887e119589d456557d72ab37b5. Change smbios_build_type_1_table() to encode the UUID as specified. To make sure we won't change the guest-visible UUID when upgrading to a newer QEMU version, keep the old behavior on pc-*-2.1 and older. Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/i386')
-rw-r--r--hw/i386/pc_piix.c4
-rw-r--r--hw/i386/pc_q35.c4
-rw-r--r--hw/i386/smbios.c27
3 files changed, 30 insertions, 5 deletions
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index ce8745df25..200ea4f009 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -63,6 +63,7 @@ static bool has_acpi_build = true;
static int legacy_acpi_table_size;
static bool smbios_defaults = true;
static bool smbios_legacy_mode;
+static bool smbios_uuid_encoded = true;
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
* pages in the host.
@@ -172,7 +173,7 @@ static void pc_init1(MachineState *machine,
MachineClass *mc = MACHINE_GET_CLASS(machine);
/* These values are guest ABI, do not change */
smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
- mc->name, smbios_legacy_mode);
+ mc->name, smbios_legacy_mode, smbios_uuid_encoded);
}
/* allocate ram and load rom/bios */
@@ -304,6 +305,7 @@ static void pc_init_pci(MachineState *machine)
static void pc_compat_2_1(MachineState *machine)
{
+ smbios_uuid_encoded = false;
}
static void pc_compat_2_0(MachineState *machine)
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index aef4628f92..f69e4a1bfa 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -52,6 +52,7 @@
static bool has_acpi_build = true;
static bool smbios_defaults = true;
static bool smbios_legacy_mode;
+static bool smbios_uuid_encoded = true;
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
* pages in the host.
@@ -163,7 +164,7 @@ static void pc_q35_init(MachineState *machine)
MachineClass *mc = MACHINE_GET_CLASS(machine);
/* These values are guest ABI, do not change */
smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
- mc->name, smbios_legacy_mode);
+ mc->name, smbios_legacy_mode, smbios_uuid_encoded);
}
/* allocate ram and load rom/bios */
@@ -283,6 +284,7 @@ static void pc_q35_init(MachineState *machine)
static void pc_compat_2_1(MachineState *machine)
{
+ smbios_uuid_encoded = false;
}
static void pc_compat_2_0(MachineState *machine)
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index 0ae5960b8c..8a7ad48921 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -48,6 +48,7 @@ struct smbios_table {
static uint8_t *smbios_entries;
static size_t smbios_entries_len;
static bool smbios_legacy = true;
+static bool smbios_uuid_encoded = true;
/* end: legacy structures & constants for <= 2.0 machines */
@@ -391,6 +392,11 @@ static void smbios_build_type_1_fields(void)
smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str),
type1.family);
if (qemu_uuid_set) {
+ /* We don't encode the UUID in the "wire format" here because this
+ * function is for legacy mode and needs to keep the guest ABI, and
+ * because we don't know what's the SMBIOS version advertised by the
+ * BIOS.
+ */
smbios_add_field(1, offsetof(struct smbios_type_1, uuid),
qemu_uuid, 16);
}
@@ -523,6 +529,19 @@ static void smbios_build_type_0_table(void)
SMBIOS_BUILD_TABLE_POST;
}
+/* Encode UUID from the big endian encoding described on RFC4122 to the wire
+ * format specified by SMBIOS version 2.6.
+ */
+static void smbios_encode_uuid(struct smbios_uuid *uuid, const uint8_t *buf)
+{
+ memcpy(uuid, buf, 16);
+ if (smbios_uuid_encoded) {
+ uuid->time_low = bswap32(uuid->time_low);
+ uuid->time_mid = bswap16(uuid->time_mid);
+ uuid->time_hi_and_version = bswap16(uuid->time_hi_and_version);
+ }
+}
+
static void smbios_build_type_1_table(void)
{
SMBIOS_BUILD_TABLE_PRE(1, 0x100, true); /* required */
@@ -532,9 +551,9 @@ static void smbios_build_type_1_table(void)
SMBIOS_TABLE_SET_STR(1, version_str, type1.version);
SMBIOS_TABLE_SET_STR(1, serial_number_str, type1.serial);
if (qemu_uuid_set) {
- memcpy(t->uuid, qemu_uuid, 16);
+ smbios_encode_uuid(&t->uuid, qemu_uuid);
} else {
- memset(t->uuid, 0, 16);
+ memset(&t->uuid, 0, 16);
}
t->wake_up_type = 0x06; /* power switch */
SMBIOS_TABLE_SET_STR(1, sku_number_str, type1.sku);
@@ -746,10 +765,12 @@ void smbios_set_cpuid(uint32_t version, uint32_t features)
}
void smbios_set_defaults(const char *manufacturer, const char *product,
- const char *version, bool legacy_mode)
+ const char *version, bool legacy_mode,
+ bool uuid_encoded)
{
smbios_have_defaults = true;
smbios_legacy = legacy_mode;
+ smbios_uuid_encoded = uuid_encoded;
/* drop unwanted version of command-line file blob(s) */
if (smbios_legacy) {