diff --git a/patches/0024-smbios-bios-type0.patch b/patches/0024-smbios-bios-type0.patch new file mode 100644 index 0000000..26c78f2 --- /dev/null +++ b/patches/0024-smbios-bios-type0.patch @@ -0,0 +1,25 @@ +qemu-spoof: SMBIOS type0 BIOS vendor / version / date + +Stock QEMU leaves type0 vendor/version/date unset, so the guest reads an empty or +firmware-default ("SeaBIOS") BIOS identity via WMI Win32_BIOS / dmidecode -- a tell. +Force a real, platform-anchored OEM BIOS identity (vendor coheres with the board; +version uses the vendor's real format) through smbios_set_defaults, so an explicit +-smbios type=0 still wins and an un-seeded VM stays stock. (spoof.h include added by +0015-smbios-vm-bit.) +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 7d71418..13ffa93 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -1027,6 +1027,12 @@ void smbios_set_defaults(const char *manufacturer, const char *product, + { + smbios_have_defaults = true; + ++ /* qemu-spoof: a real OEM BIOS identity (type0). Stock leaves vendor/version/date ++ * unset, so the guest reads an empty / firmware-default ("SeaBIOS") BIOS — a tell. ++ * Platform-anchored so the BIOS vendor coheres with the board. Inert without a seed. */ ++ SMBIOS_SET_DEFAULT(smbios_type0.vendor, spoof_bios_vendor(NULL)); ++ SMBIOS_SET_DEFAULT(smbios_type0.version, spoof_bios_version(NULL)); ++ SMBIOS_SET_DEFAULT(smbios_type0.date, spoof_bios_date(NULL)); + SMBIOS_SET_DEFAULT(smbios_type1.manufacturer, manufacturer); + SMBIOS_SET_DEFAULT(smbios_type1.product, product); + SMBIOS_SET_DEFAULT(smbios_type1.version, version); diff --git a/patches/README.md b/patches/README.md index ae7d40f..3e7c7c1 100644 --- a/patches/README.md +++ b/patches/README.md @@ -25,6 +25,7 @@ match exactly. Naming: `0002` = infra, `0010+` = one aspect each. | 0021-smbios-identity | SMBIOS type3 chassis / type4 socket + cpu-mfr / type11 OEM / type17 memory | | 0022-storage-extra | IDE WWN + rotation rate; NVMe EUI-64 + NGUID | | 0023-cpu-microcode | CPU microcode revision (IA32_UCODE_REV), vendor-positioned | +| 0024-smbios-bios-type0 | SMBIOS type0 BIOS vendor / version / date (platform-anchored OEM firmware) | ## Why 0018 is subsystem-only (the PCI-id problem) diff --git a/src/spoof-platform.c b/src/spoof-platform.c index bac6ebd..a8f3553 100644 --- a/src/spoof-platform.c +++ b/src/spoof-platform.c @@ -89,6 +89,49 @@ const char *spoof_bios_vendor(const char *def) { return spoof_on() ? spoof_plat_bios_vendor() : def; } +/* BIOS version in the format the platform's firmware vendor actually uses, so it + * coheres with the type0 vendor (AMI "x.yy", Dell "1.x.y", HP "S0x Ver…", etc). */ +const char *spoof_bios_version(const char *def) +{ + if (!spoof_on()) { + return def; + } + static char v[32]; + const char *b = spoof_plat_bios_vendor(); + if (strstr(b, "Megatrends")) { /* AMI Aptio */ + snprintf(v, sizeof(v), "%u.%02u", + 1 + (unsigned)(spoof_field("bios.ami.a") % 3), + (unsigned)(spoof_field("bios.ami.b") % 80)); + } else if (strstr(b, "Dell")) { + snprintf(v, sizeof(v), "1.%u.%u", + (unsigned)(spoof_field("bios.dell.a") % 25), + (unsigned)(spoof_field("bios.dell.b") % 10)); + } else if (strstr(b, "HP")) { + snprintf(v, sizeof(v), "S0%u Ver. 02.%02u.00", + 1 + (unsigned)(spoof_field("bios.hp.a") % 9), + (unsigned)(spoof_field("bios.hp.b") % 30)); + } else if (strstr(b, "LENOVO")) { + snprintf(v, sizeof(v), "M1%cKT%uA", + (char)('A' + spoof_field("bios.len.a") % 26), + (unsigned)(spoof_field("bios.len.b") % 90)); + } else { /* Insyde (Acer) */ + snprintf(v, sizeof(v), "V1.%02u", (unsigned)(spoof_field("bios.ins") % 40)); + } + return v; +} +/* Plausible BIOS release date (SMBIOS encodes it as MM/DD/YYYY). */ +const char *spoof_bios_date(const char *def) +{ + if (!spoof_on()) { + return def; + } + static char d[12]; + snprintf(d, sizeof(d), "%02u/%02u/%04u", + 1 + (unsigned)(spoof_field("bios.mon") % 12), + 1 + (unsigned)(spoof_field("bios.day") % 28), + 2020 + (unsigned)(spoof_field("bios.year") % 4)); + return d; +} const char *spoof_baseboard_manufacturer(const char *def) { return spoof_on() ? spoof_plat_baseboard() : def; diff --git a/src/spoof.h b/src/spoof.h index 1db4dd2..1765711 100644 --- a/src/spoof.h +++ b/src/spoof.h @@ -36,6 +36,8 @@ bool spoof_pvpanic_hide(void); /* drop the pvpanic device (_HID QEMU000 * The ACPI OEM id, machine desc, BIOS vendor and baseboard all come from a single * per-seed platform pick (OEM-prebuilt vendor code, or "ALASKA"/AMI for DIY). */ const char *spoof_bios_vendor(const char *def); /* SMBIOS type0 */ +const char *spoof_bios_version(const char *def); /* SMBIOS type0 (vendor-format) */ +const char *spoof_bios_date(const char *def); /* SMBIOS type0 (MM/DD/YYYY) */ const char *spoof_baseboard_manufacturer(const char *def); /* SMBIOS type2 */ /* ---- ACPI (spoof-acpi.c; hw/acpi, hw/i386/acpi-build) --------------------- */