From e6c3fbfc82863180007569cf2a9132c28a47bf1f Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 20 Jan 2020 16:13:08 +0000 Subject: [PATCH 01/18] hw/smbios: set new default SMBIOS fields for Windows driver support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Daniel P. Berrange Message-id: <20200120161308.584989-2-berrange@redhat.com> Patchwork-id: 93422 O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 1/1] hw/smbios: set new default SMBIOS fields for Windows driver support Bugzilla: 1782529 RH-Acked-by: Eduardo Habkost RH-Acked-by: Igor Mammedov RH-Acked-by: Laszlo Ersek For Windows driver support, we have to follow this doc in order to enable Windows to automatically determine the right drivers to install for a given guest / host combination: https://docs.microsoft.com/en-us/windows-hardware/drivers/install/specifying-hardware-ids-for-a-computer Out of the choices available, it was decided that the Windows drivers will be written to expect use of the scheme documented as "HardwareID-6" against Windows 10. This uses SMBIOS System (Type 1) and Base Board (Type 2) tables and will match on System Manufacturer = Red Hat System SKU Number = 8.2.0 Baseboard Manufacturer = Red Hat Baseboard Product = RHEL-AV The new SMBIOS fields will be tied to machine type and only reported for pc-q35-8.2.0 machine and later. The old SMBIOS fields, previously reported by all machines were: System Manufacturer: Red Hat System Product Name: KVM System Version: RHEL-8.2.0 PC (Q35 + ICH9, 2009) System Family: Red Hat Enterprise Linux Baseboard Manufacturer: Red Hat Baseboard Product Name: KVM Baseboard Version: RHEL-8.2.0 PC (Q35 + ICH9, 2009) Chassis Manufacturer: Red Hat Chassis Product Name: KVM Chassis Version: RHEL-8.2.0 PC (Q35 + ICH9, 2009) Processor Manufacturer: Red Hat Processor Product Name: KVM Processor Version: RHEL-8.2.0 PC (Q35 + ICH9, 2009) This information will continue to be reported for all machines, except where it conflicts with the requirement of the new SMBIOS data. IOW, the "Baseboard Product Name" will change to "RHEL-AV" for pc-q35-8.2.0 machine types and later. Management applications MUST NEVER override the 4 new SMBIOS fields that are used for Windows driver matching, with differing values. Aside from this, they are free to override any other field, including those from the old SMBIOS field data. In particular if a management application wants to report its own product name and version, it is recommended to use "System product" and "System version" as identifying fields, as these avoid a clash with the new SMBIOS fields used for Windows drivers. Note that until now the Baseboard (type 2) table has only been generated by QEMU if explicitly asked for on the CLI. This patch makes it always present for new machine types. Signed-off-by: Daniel P. Berrangé Signed-off-by: Danilo C. L. de Paula --- hw/arm/virt.c | 2 +- hw/i386/pc_piix.c | 2 ++ hw/i386/pc_q35.c | 8 ++++++++ hw/smbios/smbios.c | 45 +++++++++++++++++++++++++++++++++++++++++--- include/hw/firmware/smbios.h | 5 ++++- include/hw/i386/pc.h | 3 +++ 6 files changed, 60 insertions(+), 5 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index d30d38c..2dcf6e7 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1423,7 +1423,7 @@ static void virt_build_smbios(VirtMachineState *vms) smbios_set_defaults("QEMU", product, vmc->smbios_old_sys_ver ? "1.0" : mc->name, false, - true, SMBIOS_ENTRY_POINT_30); + true, NULL, NULL, SMBIOS_ENTRY_POINT_30); smbios_get_tables(MACHINE(vms), NULL, 0, &smbios_tables, &smbios_tables_len, &smbios_anchor, &smbios_anchor_len); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index bd7fdb9..2ac94d5 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -177,6 +177,8 @@ static void pc_init1(MachineState *machine, smbios_set_defaults("Red Hat", "KVM", mc->desc, pcmc->smbios_legacy_mode, pcmc->smbios_uuid_encoded, + pcmc->smbios_stream_product, + pcmc->smbios_stream_version, SMBIOS_ENTRY_POINT_21); } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 7531d8e..e975643 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -200,6 +200,8 @@ static void pc_q35_init(MachineState *machine) smbios_set_defaults("Red Hat", "KVM", mc->desc, pcmc->smbios_legacy_mode, pcmc->smbios_uuid_encoded, + pcmc->smbios_stream_product, + pcmc->smbios_stream_version, SMBIOS_ENTRY_POINT_21); } @@ -565,8 +567,11 @@ static void pc_q35_init_rhel820(MachineState *machine) static void pc_q35_machine_rhel820_options(MachineClass *m) { + PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_machine_rhel_options(m); m->desc = "RHEL-8.2.0 PC (Q35 + ICH9, 2009)"; + pcmc->smbios_stream_product = "RHEL-AV"; + pcmc->smbios_stream_version = "8.2.0"; } DEFINE_PC_MACHINE(q35_rhel820, "pc-q35-rhel8.2.0", pc_q35_init_rhel820, @@ -579,9 +584,12 @@ static void pc_q35_init_rhel810(MachineState *machine) static void pc_q35_machine_rhel810_options(MachineClass *m) { + PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_machine_rhel820_options(m); m->desc = "RHEL-8.1.0 PC (Q35 + ICH9, 2009)"; m->alias = NULL; + pcmc->smbios_stream_product = NULL; + pcmc->smbios_stream_version = NULL; compat_props_add(m->compat_props, hw_compat_rhel_8_1, hw_compat_rhel_8_1_len); compat_props_add(m->compat_props, pc_rhel_8_1_compat, pc_rhel_8_1_compat_len); } diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index e6e9355..d65c149 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -57,6 +57,9 @@ static bool smbios_legacy = true; static bool smbios_uuid_encoded = true; /* end: legacy structures & constants for <= 2.0 machines */ +/* Set to true for modern Windows 10 HardwareID-6 compat */ +static bool smbios_type2_required; + uint8_t *smbios_tables; size_t smbios_tables_len; @@ -532,7 +535,7 @@ static void smbios_build_type_1_table(void) static void smbios_build_type_2_table(void) { - SMBIOS_BUILD_TABLE_PRE(2, 0x200, false); /* optional */ + SMBIOS_BUILD_TABLE_PRE(2, 0x200, smbios_type2_required); SMBIOS_TABLE_SET_STR(2, manufacturer_str, type2.manufacturer); SMBIOS_TABLE_SET_STR(2, product_str, type2.product); @@ -753,7 +756,10 @@ 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, - bool uuid_encoded, SmbiosEntryPointType ep_type) + bool uuid_encoded, + const char *stream_product, + const char *stream_version, + SmbiosEntryPointType ep_type) { smbios_have_defaults = true; smbios_legacy = legacy_mode; @@ -774,12 +780,45 @@ void smbios_set_defaults(const char *manufacturer, const char *product, g_free(smbios_entries); } + /* + * If @stream_product & @stream_version are non-NULL, then + * we're following rules for new Windows driver support. + * The data we have to report is defined in this doc: + * + * https://docs.microsoft.com/en-us/windows-hardware/drivers/install/specifying-hardware-ids-for-a-computer + * + * The Windows drivers are written to expect use of the + * scheme documented as "HardwareID-6" against Windows 10, + * which uses SMBIOS System (Type 1) and Base Board (Type 2) + * tables and will match on + * + * System Manufacturer = Red Hat (@manufacturer) + * System SKU Number = 8.2.0 (@stream_version) + * Baseboard Manufacturer = Red Hat (@manufacturer) + * Baseboard Product = RHEL-AV (@stream_product) + * + * NB, SKU must be changed with each RHEL-AV release + * + * Other fields can be freely used by applications using + * QEMU. For example apps can use the "System product" + * and "System version" to identify themselves. + * + * We get 'System Manufacturer' and 'Baseboard Manufacturer' + */ SMBIOS_SET_DEFAULT(type1.manufacturer, manufacturer); SMBIOS_SET_DEFAULT(type1.product, product); SMBIOS_SET_DEFAULT(type1.version, version); SMBIOS_SET_DEFAULT(type1.family, "Red Hat Enterprise Linux"); + if (stream_version != NULL) { + SMBIOS_SET_DEFAULT(type1.sku, stream_version); + } SMBIOS_SET_DEFAULT(type2.manufacturer, manufacturer); - SMBIOS_SET_DEFAULT(type2.product, product); + if (stream_product != NULL) { + SMBIOS_SET_DEFAULT(type2.product, stream_product); + smbios_type2_required = true; + } else { + SMBIOS_SET_DEFAULT(type2.product, product); + } SMBIOS_SET_DEFAULT(type2.version, version); SMBIOS_SET_DEFAULT(type3.manufacturer, manufacturer); SMBIOS_SET_DEFAULT(type3.version, version); diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h index 02a0ced..67e38a1 100644 --- a/include/hw/firmware/smbios.h +++ b/include/hw/firmware/smbios.h @@ -267,7 +267,10 @@ void smbios_entry_add(QemuOpts *opts, Error **errp); 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, - bool uuid_encoded, SmbiosEntryPointType ep_type); + bool uuid_encoded, + const char *stream_product, + const char *stream_version, + SmbiosEntryPointType ep_type); uint8_t *smbios_get_table_legacy(MachineState *ms, size_t *length); void smbios_get_tables(MachineState *ms, const struct smbios_phys_mem_area *mem_array, diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 2e362c8..b9f29ba 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -109,6 +109,9 @@ typedef struct PCMachineClass { bool smbios_defaults; bool smbios_legacy_mode; bool smbios_uuid_encoded; + /* New fields needed for Windows HardwareID-6 matching */ + const char *smbios_stream_product; + const char *smbios_stream_version; /* RAM / address space compat: */ bool gigabyte_align; -- 1.8.3.1