/* * 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; }