9b17bdfa33
Force a real, platform-anchored OEM BIOS identity into SMBIOS type0 (patch 0024 + spoof_bios_version/spoof_bios_date getters) so the guest does not read an empty or firmware-default BIOS vendor via WMI/dmidecode. Vendor coheres with the board; version uses the vendor real format. Inert without a seed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
139 lines
7.5 KiB
C
139 lines
7.5 KiB
C
/*
|
|
* spoof-platform.c — the PLATFORM anchor: one seed draw selects a coherent
|
|
* machine identity (ACPI OEM id, ACPI table id, BIOS vendor, baseboard, the
|
|
* board model AND its socket). The board list is split by CPU vendor and indexed
|
|
* by the CPU anchor, so the board's chipset/socket always matches the CPU
|
|
* (no "Intel H510 board + AMD CPU"). The board's own socket feeds SMBIOS type4.
|
|
*
|
|
* Two classes: OEM prebuilt (ACPI OEM = vendor code) and DIY/retail (AMI Aptio
|
|
* firmware -> ACPI OEM "ALASKA"/"A M I"; the board brand is in the baseboard).
|
|
*/
|
|
#include "qemu/osdep.h"
|
|
#include "hw/misc/spoof.h"
|
|
#include "hw/misc/spoof-core.h"
|
|
|
|
typedef struct { const char *model, *socket; } Board;
|
|
|
|
/* --- OEM prebuilt: real Intel and (separate) AMD desktop SKUs --- */
|
|
static const Board DELL_I[] = { {"OptiPlex 7090","LGA1200"}, {"OptiPlex 5090","LGA1200"},
|
|
{"Precision 3650 Tower","LGA1200"}, {"OptiPlex 7000","LGA1700"} };
|
|
static const Board DELL_A[] = { {"OptiPlex 5055","AM4"}, {"OptiPlex 7010 AMD","AM4"} };
|
|
static const Board HP_I[] = { {"HP EliteDesk 800 G6","LGA1200"}, {"HP ProDesk 600 G6","LGA1200"},
|
|
{"HP Z2 Tower G5","LGA1200"}, {"HP EliteDesk 800 G9","LGA1700"} };
|
|
static const Board HP_A[] = { {"HP ProDesk 405 G6","AM4"}, {"HP ProDesk 485 G4","AM4"} };
|
|
static const Board LEN_I[] = { {"ThinkCentre M720q","LGA1151"}, {"ThinkCentre M920t","LGA1151"},
|
|
{"ThinkStation P340","LGA1200"}, {"ThinkCentre M70q Gen 3","LGA1700"} };
|
|
static const Board LEN_A[] = { {"ThinkCentre M75q Gen 2","AM4"}, {"ThinkCentre M75s Gen 2","AM4"} };
|
|
static const Board ACE_I[] = { {"Veriton M4660G","LGA1151"}, {"Aspire TC-895","LGA1200"},
|
|
{"Aspire TC-1760","LGA1700"} };
|
|
static const Board ACE_A[] = { {"Nitro N50-110","AM4"}, {"Aspire TC-380","AM4"} };
|
|
|
|
/* --- DIY/retail boards: the model unambiguously implies the socket --- */
|
|
static const Board ASUS_I[] = { {"ROG STRIX Z590-E GAMING WIFI","LGA1200"}, {"PRIME B560M-A","LGA1200"},
|
|
{"TUF GAMING Z690-PLUS WIFI","LGA1700"}, {"PRIME H610M-E D4","LGA1700"} };
|
|
static const Board ASUS_A[] = { {"TUF GAMING B550M-PLUS","AM4"}, {"ROG STRIX X570-E GAMING","AM4"},
|
|
{"PRIME B650M-A","AM5"}, {"ProArt X670E-CREATOR WIFI","AM5"} };
|
|
static const Board GBT_I[] = { {"Z390 AORUS PRO","LGA1151"}, {"B660M DS3H DDR4","LGA1700"},
|
|
{"Z690 AORUS ELITE AX","LGA1700"} };
|
|
static const Board GBT_A[] = { {"X570 AORUS ELITE","AM4"}, {"B450 AORUS M","AM4"}, {"B650 AORUS ELITE AX","AM5"} };
|
|
static const Board MSI_I[] = { {"MAG B560 TOMAHAWK","LGA1200"}, {"PRO B660M-A DDR4","LGA1700"},
|
|
{"MPG Z690 CARBON WIFI","LGA1700"} };
|
|
static const Board MSI_A[] = { {"MPG B550 GAMING PLUS","AM4"}, {"B450 TOMAHAWK MAX","AM4"},
|
|
{"MAG B650 TOMAHAWK WIFI","AM5"} };
|
|
static const Board ASR_I[] = { {"H510M-HVS","LGA1200"}, {"B660M Pro RS","LGA1700"},
|
|
{"Z690 Steel Legend","LGA1700"} };
|
|
static const Board ASR_A[] = { {"X570 Taichi","AM4"}, {"B450M Steel Legend","AM4"}, {"B650M PG Riptide","AM5"} };
|
|
|
|
typedef struct {
|
|
const char *oem, *table, *bios, *board, *oemstr;
|
|
const Board *intel; size_t ni;
|
|
const Board *amd; size_t na;
|
|
} Platform;
|
|
|
|
#define BL(a) (a), ARRAY_SIZE(a)
|
|
static const Platform PLAT[] = {
|
|
/* --- OEM prebuilt: ACPI OEM id = vendor code --- */
|
|
{ "DELL ", "QA09 ", "Dell Inc.", "Dell Inc.", "Dell System", BL(DELL_I), BL(DELL_A) },
|
|
{ "HPQOEM", "8054 ", "HP", "HP", "HP", BL(HP_I), BL(HP_A) },
|
|
{ "LENOVO", "TP-N1Q ", "LENOVO", "LENOVO", "LENOVO", BL(LEN_I), BL(LEN_A) },
|
|
{ "ACRSYS", "ACRSYS ", "Insyde Corp.", "Acer", "Acer System", BL(ACE_I), BL(ACE_A) },
|
|
/* --- DIY/retail (AMI firmware): ACPI OEM id "ALASKA"; brand in baseboard --- */
|
|
{ "ALASKA", "A M I ", "American Megatrends Inc.", "ASUSTeK COMPUTER INC.", "$ASUS$", BL(ASUS_I), BL(ASUS_A) },
|
|
{ "ALASKA", "A M I ", "American Megatrends Inc.", "Gigabyte Technology Co., Ltd.", "GIGABYTE", BL(GBT_I), BL(GBT_A) },
|
|
{ "ALASKA", "A M I ", "American Megatrends Inc.", "Micro-Star International Co., Ltd.", "MSI", BL(MSI_I), BL(MSI_A) },
|
|
{ "ALASKA", "A M I ", "American Megatrends Inc.", "ASRock", "ASRock", BL(ASR_I), BL(ASR_A) },
|
|
};
|
|
|
|
static const Platform *plat(void)
|
|
{
|
|
return &PLAT[spoof_field("anchor.platform") % ARRAY_SIZE(PLAT)];
|
|
}
|
|
/* the chosen board for THIS platform under the CPU-vendor anchor (Intel/AMD). */
|
|
static const Board *chosen_board(void)
|
|
{
|
|
const Platform *p = plat();
|
|
const Board *list = spoof_anchor_vendor() ? p->amd : p->intel;
|
|
size_t n = spoof_anchor_vendor() ? p->na : p->ni;
|
|
return &list[spoof_field("mach.board") % n];
|
|
}
|
|
|
|
const char *spoof_plat_acpi_oem(void) { return plat()->oem; }
|
|
const char *spoof_plat_acpi_table(void) { return plat()->table; }
|
|
const char *spoof_plat_bios_vendor(void) { return plat()->bios; }
|
|
const char *spoof_plat_baseboard(void) { return plat()->board; }
|
|
const char *spoof_plat_machine_desc(void) { return chosen_board()->model; }
|
|
const char *spoof_plat_socket(void) { return chosen_board()->socket; }
|
|
const char *spoof_plat_oem_string(void) { return plat()->oemstr; }
|
|
|
|
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;
|
|
}
|