From 76424950e373d3b04ac3dd13019151bfba3e8423 Mon Sep 17 00:00:00 2001 From: sumuel Date: Mon, 17 Aug 2026 20:44:55 +0000 Subject: Add the files --- src/detection/host/host.h | 20 ++ src/detection/host/host_android.c | 27 +++ src/detection/host/host_apple.c | 68 ++++++ src/detection/host/host_bsd.c | 26 +++ src/detection/host/host_linux.c | 117 ++++++++++ src/detection/host/host_mac.c | 444 ++++++++++++++++++++++++++++++++++++ src/detection/host/host_nbsd.c | 25 ++ src/detection/host/host_nosupport.c | 5 + src/detection/host/host_obsd.c | 22 ++ src/detection/host/host_windows.c | 74 ++++++ 10 files changed, 828 insertions(+) create mode 100644 src/detection/host/host.h create mode 100644 src/detection/host/host_android.c create mode 100644 src/detection/host/host_apple.c create mode 100644 src/detection/host/host_bsd.c create mode 100644 src/detection/host/host_linux.c create mode 100644 src/detection/host/host_mac.c create mode 100644 src/detection/host/host_nbsd.c create mode 100644 src/detection/host/host_nosupport.c create mode 100644 src/detection/host/host_obsd.c create mode 100644 src/detection/host/host_windows.c (limited to 'src/detection/host') diff --git a/src/detection/host/host.h b/src/detection/host/host.h new file mode 100644 index 0000000..a6fe3fb --- /dev/null +++ b/src/detection/host/host.h @@ -0,0 +1,20 @@ +#pragma once + +#include "fastfetch.h" +#include "modules/host/option.h" + +typedef struct FFHostResult { + FFstrbuf family; + FFstrbuf name; + FFstrbuf version; + FFstrbuf sku; + FFstrbuf serial; + FFstrbuf uuid; + FFstrbuf vendor; +} FFHostResult; + +const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel); +#if __x86_64__ +bool ffHostDetectMac(FFHostResult* host); +#endif +const char* ffDetectHost(FFHostResult* host); diff --git a/src/detection/host/host_android.c b/src/detection/host/host_android.c new file mode 100644 index 0000000..1157a92 --- /dev/null +++ b/src/detection/host/host_android.c @@ -0,0 +1,27 @@ +#include "host.h" +#include "common/settings.h" + +#include + +const char* ffDetectHost(FFHostResult* host) { + // http://newandroidbook.com/ddb/ + ffSettingsGetAndroidProperty("ro.product.device", &host->family); + + ffSettingsGetAndroidProperty("ro.product.marketname", &host->name) || ffSettingsGetAndroidProperty("ro.vendor.product.display", &host->name) || ffSettingsGetAndroidProperty("ro.vivo.market.name", &host->name) || ffSettingsGetAndroidProperty("ro.product.oppo_model", &host->name) || ffSettingsGetAndroidProperty("ro.oppo.market.name", &host->name) || ffSettingsGetAndroidProperty("ro.vendor.oplus.market.enname", &host->name) || ffSettingsGetAndroidProperty("ro.config.devicename", &host->name) || ffSettingsGetAndroidProperty("ro.config.marketing_name", &host->name) || ffSettingsGetAndroidProperty("ro.product.vendor.model", &host->name) || ffSettingsGetAndroidProperty("ro.product.brand", &host->name); + + if (ffSettingsGetAndroidProperty("ro.product.model", &host->version)) { + if (ffStrbufStartsWithIgnCase(&host->version, &host->name)) { + ffStrbufSubstrAfter(&host->version, host->name.length); + ffStrbufTrimLeft(&host->version, ' '); + } + } + + ffSettingsGetAndroidProperty("ro.product.manufacturer", &host->vendor); + + if (host->vendor.length && !ffStrbufStartsWithIgnCase(&host->name, &host->vendor)) { + ffStrbufPrependS(&host->name, " "); + ffStrbufPrepend(&host->name, &host->vendor); + } + + return NULL; +} diff --git a/src/detection/host/host_apple.c b/src/detection/host/host_apple.c new file mode 100644 index 0000000..a177bf4 --- /dev/null +++ b/src/detection/host/host_apple.c @@ -0,0 +1,68 @@ +#include "host.h" +#include "common/sysctl.h" +#include "common/apple/cf_helpers.h" + +#include + +const char* getProductNameWithIokit(FFstrbuf* result) { + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/product"); + if (!registryEntry) { + return "IOServiceGetMatchingService() failed"; + } + + FF_CFTYPE_AUTO_RELEASE CFStringRef productName = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("product-name"), kCFAllocatorDefault, kNilOptions); + if (!productName) { + return "IORegistryEntryCreateCFProperty() failed"; + } + + return ffCfStrGetString(productName, result); +} + +const char* getOthersByIokit(FFHostResult* host) { + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t registryEntry = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("IOPlatformExpertDevice")); + if (!registryEntry) { + return "IOServiceGetMatchingService() failed"; + } + + FF_CFTYPE_AUTO_RELEASE CFStringRef serialNumber = IORegistryEntryCreateCFProperty(registryEntry, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, kNilOptions); + if (serialNumber) { + ffCfStrGetString(serialNumber, &host->serial); + } + + FF_CFTYPE_AUTO_RELEASE CFStringRef uuid = IORegistryEntryCreateCFProperty(registryEntry, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, kNilOptions); + if (uuid) { + ffCfStrGetString(uuid, &host->uuid); + } + + FF_CFTYPE_AUTO_RELEASE CFStringRef manufacturer = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions); + if (manufacturer) { + ffCfStrGetString(manufacturer, &host->vendor); + } + + FF_CFTYPE_AUTO_RELEASE CFStringRef version = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("version"), kCFAllocatorDefault, kNilOptions); + if (version) { + ffCfStrGetString(version, &host->version); + } + + return NULL; +} + +const char* ffDetectHost(FFHostResult* host) { + const char* error = ffSysctlGetString("hw.product", &host->family); + if (error) { + error = ffSysctlGetString("hw.model", &host->family); + } + if (error) { + return error; + } + + ffStrbufSetStatic(&host->name, ffHostGetMacProductNameWithHwModel(&host->family)); + if (host->name.length == 0) { + getProductNameWithIokit(&host->name); + } + if (host->name.length == 0) { + ffStrbufSet(&host->name, &host->family); + } + getOthersByIokit(host); + return NULL; +} diff --git a/src/detection/host/host_bsd.c b/src/detection/host/host_bsd.c new file mode 100644 index 0000000..3eb547d --- /dev/null +++ b/src/detection/host/host_bsd.c @@ -0,0 +1,26 @@ +#include "host.h" +#include "common/settings.h" +#include "common/smbios.h" + +const char* ffDetectHost(FFHostResult* host) { + ffSettingsGetFreeBSDKenv("smbios.system.product", &host->name); + ffCleanUpSmbiosValue(&host->name); + ffSettingsGetFreeBSDKenv("smbios.system.family", &host->family); + ffCleanUpSmbiosValue(&host->family); + ffSettingsGetFreeBSDKenv("smbios.system.version", &host->version); + ffCleanUpSmbiosValue(&host->version); + ffSettingsGetFreeBSDKenv("smbios.system.sku", &host->sku); + ffCleanUpSmbiosValue(&host->sku); + ffSettingsGetFreeBSDKenv("smbios.system.serial", &host->serial); + ffCleanUpSmbiosValue(&host->serial); + ffSettingsGetFreeBSDKenv("smbios.system.uuid", &host->uuid); + ffCleanUpSmbiosValue(&host->uuid); + ffSettingsGetFreeBSDKenv("smbios.system.maker", &host->vendor); + ffCleanUpSmbiosValue(&host->vendor); + +#ifdef __x86_64__ + ffHostDetectMac(host); +#endif + + return NULL; +} diff --git a/src/detection/host/host_linux.c b/src/detection/host/host_linux.c new file mode 100644 index 0000000..81418a8 --- /dev/null +++ b/src/detection/host/host_linux.c @@ -0,0 +1,117 @@ +#include "host.h" +#include "common/io.h" +#include "common/processing.h" +#include "common/smbios.h" + +#include + +static bool getHostProductName(FFstrbuf* name) { + if (ffReadFileBuffer("/sys/firmware/devicetree/base/model", name) || + ffReadFileBuffer("/sys/firmware/devicetree/base/banner-name", name)) { + ffStrbufTrimRight(name, '\0'); + return true; + } + + if (ffReadFileBuffer("/tmp/sysinfo/model", name)) { + ffStrbufTrimRightSpace(name); + ffStrbufTrimRight(name, '\0'); + if (ffIsSmbiosValueSet(name)) { + return true; + } + } + + return false; +} + +static bool getHostSerialNumber(FFstrbuf* serial) { + if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/system/serial", serial) || + ffReadFileBuffer("/sys/firmware/devicetree/base/serial-number", serial)) { + ffStrbufTrimRight(serial, '\0'); + return true; + } + return false; +} + +static bool getHostProductFamily(FFstrbuf* family) { + if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/system/family", family) || + ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/system/product", family)) { + ffStrbufTrimRight(family, '\0'); + return true; + } + return false; +} + +static bool getHostVendor(FFstrbuf* vendor) { + if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/system/manufacturer", vendor)) { + ffStrbufTrimRight(vendor, '\0'); + return true; + } + return false; +} + +const char* ffDetectHost(FFHostResult* host) { + // This is a hack for Asahi Linux, whose product_family is empty + bool productName = ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", &host->name); + bool productFamily = ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->family); + if (productName || productFamily) { + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->version); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->sku); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_serial", "/sys/class/dmi/id/product_serial", &host->serial); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->vendor); + +#if __x86_64__ + ffHostDetectMac(host); +#endif + + // KVM/Qemu virtual machine + if (ffStrbufStartsWithS(&host->name, "Standard PC")) { + ffStrbufPrependS(&host->name, "KVM/QEMU "); + } +#if __aarch64__ + else if (host->family.length == 0 && ffStrbufEqualS(&host->vendor, "Apple Inc.") && ffStrbufStartsWithS(&host->name, "Mac")) { + // Hack for Asahi Linux + ffStrbufDestroy(&host->family); + ffStrbufInitMove(&host->family, &host->name); + getHostProductName(&host->name); + getHostSerialNumber(&host->serial); + } +#endif + } else { + getHostProductFamily(&host->family); + getHostProductName(&host->name); + getHostSerialNumber(&host->serial); + getHostVendor(&host->vendor); + } + + if (host->family.length == 0 && host->name.length == 0) { + const char* wslDistroName = getenv("WSL_DISTRO_NAME"); + // On WSL, the real host can't be detected. Instead use WSL as host. + if (wslDistroName != NULL || getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL) { + ffStrbufSetStatic(&host->name, "Windows Subsystem for Linux"); + if (wslDistroName) { + ffStrbufAppendF(&host->name, " - %s", wslDistroName); + } + ffStrbufSetStatic(&host->family, "WSL"); + ffStrbufSetStatic(&host->vendor, "Microsoft Corporation"); + + if (instance.config.general.detectVersion) { + ffProcessAppendStdOut(&host->version, (char* const[]) { + "wslinfo", + "--wsl-version", + "-n", + NULL, + }); // supported in 2.2.3 and later + } + } else if (ffStrbufStartsWithS(&instance.state.platform.sysinfo.version, "FreeBSD ")) { + ffStrbufSetStatic(&host->name, "Linux Binary Compatibility on FreeBSD"); + ffStrbufSetStatic(&host->family, "FreeBSD"); + ffStrbufSetStatic(&host->vendor, "FreeBSD Foundation"); + if (instance.config.general.detectVersion) { + ffStrbufSetS(&host->version, instance.state.platform.sysinfo.version.chars + strlen("FreeBSD ")); + ffStrbufSubstrBeforeFirstC(&host->version, ' '); + } + } + } + + return NULL; +} diff --git a/src/detection/host/host_mac.c b/src/detection/host/host_mac.c new file mode 100644 index 0000000..d680332 --- /dev/null +++ b/src/detection/host/host_mac.c @@ -0,0 +1,444 @@ +#include "host.h" +#include "common/strutil.h" + +const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel) { + // Macbook Pro: https://support.apple.com/en-us/HT201300 + // Macbook Air: https://support.apple.com/en-us/HT201862 + // Mac mini: https://support.apple.com/en-us/HT201894 + // iMac: https://support.apple.com/en-us/HT201634 + // Mac Pro: https://support.apple.com/en-us/HT202888 + // Mac Studio: https://support.apple.com/en-us/HT213073 + + if (ffStrbufStartsWithS(hwModel, "MacBookPro")) { + const char* version = hwModel->chars + strlen("MacBookPro"); + if (ffStrEquals(version, "18,3") || + ffStrEquals(version, "18,4")) { + return "MacBook Pro (14-inch, 2021)"; + } + if (ffStrEquals(version, "18,1") || + ffStrEquals(version, "18,2")) { + return "MacBook Pro (16-inch, 2021)"; + } + if (ffStrEquals(version, "17,1")) { + return "MacBook Pro (13-inch, M1, 2020)"; + } + if (ffStrEquals(version, "16,3")) { + return "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)"; + } + if (ffStrEquals(version, "16,2")) { + return "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)"; + } + if (ffStrEquals(version, "16,4") || + ffStrEquals(version, "16,1")) { + return "MacBook Pro (16-inch, 2019)"; + } + if (ffStrEquals(version, "15,4")) { + return "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)"; + } + if (ffStrEquals(version, "15,3")) { + return "MacBook Pro (15-inch, 2019)"; + } + if (ffStrEquals(version, "15,2")) { + return "MacBook Pro (13-inch, 2018/2019, Four Thunderbolt 3 ports)"; + } + if (ffStrEquals(version, "15,1")) { + return "MacBook Pro (15-inch, 2018/2019)"; + } + if (ffStrEquals(version, "14,3")) { + return "MacBook Pro (15-inch, 2017)"; + } + if (ffStrEquals(version, "14,2")) { + return "MacBook Pro (13-inch, 2017, Four Thunderbolt 3 ports)"; + } + if (ffStrEquals(version, "14,1")) { + return "MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)"; + } + if (ffStrEquals(version, "13,3")) { + return "MacBook Pro (15-inch, 2016)"; + } + if (ffStrEquals(version, "13,2")) { + return "MacBook Pro (13-inch, 2016, Four Thunderbolt 3 ports)"; + } + if (ffStrEquals(version, "13,1")) { + return "MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)"; + } + if (ffStrEquals(version, "12,1")) { + return "MacBook Pro (Retina, 13-inch, Early 2015)"; + } + if (ffStrEquals(version, "11,4") || + ffStrEquals(version, "11,5")) { + return "MacBook Pro (Retina, 15-inch, Mid 2015)"; + } + if (ffStrEquals(version, "11,2") || + ffStrEquals(version, "11,3")) { + return "MacBook Pro (Retina, 15-inch, Late 2013/Mid 2014)"; + } + if (ffStrEquals(version, "11,1")) { + return "MacBook Pro (Retina, 13-inch, Late 2013/Mid 2014)"; + } + if (ffStrEquals(version, "10,2")) { + return "MacBook Pro (Retina, 13-inch, Late 2012/Early 2013)"; + } + if (ffStrEquals(version, "10,1")) { + return "MacBook Pro (Retina, 15-inch, Mid 2012/Early 2013)"; + } + if (ffStrEquals(version, "9,2")) { + return "MacBook Pro (13-inch, Mid 2012)"; + } + if (ffStrEquals(version, "9,1")) { + return "MacBook Pro (15-inch, Mid 2012)"; + } + if (ffStrEquals(version, "8,3")) { + return "MacBook Pro (17-inch, 2011)"; + } + if (ffStrEquals(version, "8,2")) { + return "MacBook Pro (15-inch, 2011)"; + } + if (ffStrEquals(version, "8,1")) { + return "MacBook Pro (13-inch, 2011)"; + } + if (ffStrEquals(version, "7,1")) { + return "MacBook Pro (13-inch, Mid 2010)"; + } + if (ffStrEquals(version, "6,2")) { + return "MacBook Pro (15-inch, Mid 2010)"; + } + if (ffStrEquals(version, "6,1")) { + return "MacBook Pro (17-inch, Mid 2010)"; + } + if (ffStrEquals(version, "5,5")) { + return "MacBook Pro (13-inch, Mid 2009)"; + } + if (ffStrEquals(version, "5,3")) { + return "MacBook Pro (15-inch, Mid 2009)"; + } + if (ffStrEquals(version, "5,2")) { + return "MacBook Pro (17-inch, Mid/Early 2009)"; + } + if (ffStrEquals(version, "5,1")) { + return "MacBook Pro (15-inch, Late 2008)"; + } + if (ffStrEquals(version, "4,1")) { + return "MacBook Pro (17/15-inch, Early 2008)"; + } + } else if (ffStrbufStartsWithS(hwModel, "MacBookAir")) { + const char* version = hwModel->chars + strlen("MacBookAir"); + if (ffStrEquals(version, "10,1")) { + return "MacBook Air (M1, 2020)"; + } + if (ffStrEquals(version, "9,1")) { + return "MacBook Air (Retina, 13-inch, 2020)"; + } + if (ffStrEquals(version, "8,2")) { + return "MacBook Air (Retina, 13-inch, 2019)"; + } + if (ffStrEquals(version, "8,1")) { + return "MacBook Air (Retina, 13-inch, 2018)"; + } + if (ffStrEquals(version, "7,2")) { + return "MacBook Air (13-inch, Early 2015/2017)"; + } + if (ffStrEquals(version, "7,1")) { + return "MacBook Air (11-inch, Early 2015)"; + } + if (ffStrEquals(version, "6,2")) { + return "MacBook Air (13-inch, Mid 2013/Early 2014)"; + } + if (ffStrEquals(version, "6,1")) { + return "MacBook Air (11-inch, Mid 2013/Early 2014)"; + } + if (ffStrEquals(version, "5,2")) { + return "MacBook Air (13-inch, Mid 2012)"; + } + if (ffStrEquals(version, "5,1")) { + return "MacBook Air (11-inch, Mid 2012)"; + } + if (ffStrEquals(version, "4,2")) { + return "MacBook Air (13-inch, Mid 2011)"; + } + if (ffStrEquals(version, "4,1")) { + return "MacBook Air (11-inch, Mid 2011)"; + } + if (ffStrEquals(version, "3,2")) { + return "MacBook Air (13-inch, Late 2010)"; + } + if (ffStrEquals(version, "3,1")) { + return "MacBook Air (11-inch, Late 2010)"; + } + if (ffStrEquals(version, "2,1")) { + return "MacBook Air (Mid 2009)"; + } + } else if (ffStrbufStartsWithS(hwModel, "Macmini")) { + const char* version = hwModel->chars + strlen("Macmini"); + if (ffStrEquals(version, "9,1")) { + return "Mac mini (M1, 2020)"; + } + if (ffStrEquals(version, "8,1")) { + return "Mac mini (2018)"; + } + if (ffStrEquals(version, "7,1")) { + return "Mac mini (Mid 2014)"; + } + if (ffStrEquals(version, "6,1") || + ffStrEquals(version, "6,2")) { + return "Mac mini (Late 2012)"; + } + if (ffStrEquals(version, "5,1") || + ffStrEquals(version, "5,2")) { + return "Mac mini (Mid 2011)"; + } + if (ffStrEquals(version, "4,1")) { + return "Mac mini (Mid 2010)"; + } + if (ffStrEquals(version, "3,1")) { + return "Mac mini (Early/Late 2009)"; + } + } else if (ffStrbufStartsWithS(hwModel, "MacBook")) { + const char* version = hwModel->chars + strlen("MacBook"); + if (ffStrEquals(version, "10,1")) { + return "MacBook (Retina, 12-inch, 2017)"; + } + if (ffStrEquals(version, "9,1")) { + return "MacBook (Retina, 12-inch, Early 2016)"; + } + if (ffStrEquals(version, "8,1")) { + return "MacBook (Retina, 12-inch, Early 2015)"; + } + if (ffStrEquals(version, "7,1")) { + return "MacBook (13-inch, Mid 2010)"; + } + if (ffStrEquals(version, "6,1")) { + return "MacBook (13-inch, Late 2009)"; + } + if (ffStrEquals(version, "5,2")) { + return "MacBook (13-inch, Early/Mid 2009)"; + } + } else if (ffStrbufStartsWithS(hwModel, "MacPro")) { + const char* version = hwModel->chars + strlen("MacPro"); + if (ffStrEquals(version, "7,1")) { + return "Mac Pro (2019)"; + } + if (ffStrEquals(version, "6,1")) { + return "Mac Pro (Late 2013)"; + } + if (ffStrEquals(version, "5,1")) { + return "Mac Pro (Mid 2010 - Mid 2012)"; + } + if (ffStrEquals(version, "4,1")) { + return "Mac Pro (Early 2009)"; + } + } else if (ffStrbufStartsWithS(hwModel, "Mac")) { + const char* version = hwModel->chars + strlen("Mac"); + if (ffStrEquals(version, "17,9")) { + return "MacBook Pro (14-inch, M5 Pro, 2026)"; + } + if (ffStrEquals(version, "17,8")) { + return "MacBook Pro (16-inch, M5 Pro, 2026)"; + } + if (ffStrEquals(version, "17,7")) { + return "MacBook Pro (14-inch, M5 Max, 2026)"; + } + if (ffStrEquals(version, "17,6")) { + return "MacBook Pro (16-inch, M5 Max, 2026)"; + } + if (ffStrEquals(version, "17,5")) { + return "MacBook Neo (13-inch, A18 Pro, 2026)"; + } + if (ffStrEquals(version, "17,4")) { + return "MacBook Air (15-inch, M5, 2026)"; + } + if (ffStrEquals(version, "17,3")) { + return "MacBook Air (13-inch, M5, 2026)"; + } + if (ffStrEquals(version, "17,2")) { + return "MacBook Pro (14-inch, M5, 2025)"; + } + if (ffStrEquals(version, "16,13")) { + return "MacBook Air (15-inch, M4, 2025)"; + } + if (ffStrEquals(version, "16,12")) { + return "MacBook Air (13-inch, M4, 2025)"; + } + if (ffStrEquals(version, "16,11") || + ffStrEquals(version, "16,10")) { + return "Mac Mini (2024)"; + } + if (ffStrEquals(version, "16,9")) { + return "Mac Studio (M4 Max, 2025)"; + } + if (ffStrEquals(version, "16,3")) { + return "iMac (24-inch, 2024, Four Thunderbolt / USB 4 ports)"; + } + if (ffStrEquals(version, "16,2")) { + return "iMac (24-inch, 2024, Two Thunderbolt / USB 4 ports)"; + } + if (ffStrEquals(version, "16,1")) { + return "MacBook Pro (14-inch, 2024, Three Thunderbolt 4 ports)"; + } + if (ffStrEquals(version, "16,6") || + ffStrEquals(version, "16,8")) { + return "MacBook Pro (14-inch, 2024, Three Thunderbolt 5 ports)"; + } + if (ffStrEquals(version, "16,7") || + ffStrEquals(version, "16,5")) { + return "MacBook Pro (16-inch, 2024, Three Thunderbolt 5 ports)"; + } + if (ffStrEquals(version, "15,14")) { + return "Mac Studio (M3 Ultra, 2025)"; + } + if (ffStrEquals(version, "15,13")) { + return "MacBook Air (15-inch, M3, 2024)"; + } + if (ffStrEquals(version, "15,12")) { + return "MacBook Air (13-inch, M3, 2024)"; + } + if (ffStrEquals(version, "15,3")) { + return "MacBook Pro (14-inch, Nov 2023, Two Thunderbolt / USB 4 ports)"; + } + if (ffStrEquals(version, "15,4")) { + return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports)"; + } + if (ffStrEquals(version, "15,5")) { + return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports, Two USB 3 ports)"; + } + if (ffStrEquals(version, "15,6") || + ffStrEquals(version, "15,8") || + ffStrEquals(version, "15,10")) { + return "MacBook Pro (14-inch, Nov 2023, Three Thunderbolt 4 ports)"; + } + if (ffStrEquals(version, "15,7") || + ffStrEquals(version, "15,9") || + ffStrEquals(version, "15,11")) { + return "MacBook Pro (16-inch, Nov 2023, Three Thunderbolt 4 ports)"; + } + if (ffStrEquals(version, "14,15")) { + return "MacBook Air (15-inch, M2, 2023)"; + } + if (ffStrEquals(version, "14,14")) { + return "Mac Studio (M2 Ultra, 2023, Two Thunderbolt 4 front ports)"; + } + if (ffStrEquals(version, "14,13")) { + return "Mac Studio (M2 Max, 2023, Two USB-C front ports)"; + } + if (ffStrEquals(version, "14,8")) { + return "Mac Pro (2023)"; + } + if (ffStrEquals(version, "14,6") || + ffStrEquals(version, "14,10")) { + return "MacBook Pro (16-inch, 2023)"; + } + if (ffStrEquals(version, "14,5") || + ffStrEquals(version, "14,9")) { + return "MacBook Pro (14-inch, 2023)"; + } + if (ffStrEquals(version, "14,3")) { + return "Mac mini (M2, 2023, Two Thunderbolt 4 ports)"; + } + if (ffStrEquals(version, "14,12")) { + return "Mac mini (M2 Pro, 2023, Four Thunderbolt 4 ports)"; + } + if (ffStrEquals(version, "14,7")) { + return "MacBook Pro (13-inch, M2, 2022)"; + } + if (ffStrEquals(version, "14,2")) { + return "MacBook Air (M2, 2022)"; + } + if (ffStrEquals(version, "13,1")) { + return "Mac Studio (M1 Max, 2022, Two USB-C front ports)"; + } + if (ffStrEquals(version, "13,2")) { + return "Mac Studio (M1 Ultra, 2022, Two Thunderbolt 4 front ports)"; + } + } else if (ffStrbufStartsWithS(hwModel, "iMac")) { + const char* version = hwModel->chars + strlen("iMac"); + if (ffStrEquals(version, "21,1")) { + return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports, Two USB 3 ports)"; + } + if (ffStrEquals(version, "21,2")) { + return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports)"; + } + if (ffStrEquals(version, "20,1") || + ffStrEquals(version, "20,2")) { + return "iMac (Retina 5K, 27-inch, 2020)"; + } + if (ffStrEquals(version, "19,1")) { + return "iMac (Retina 5K, 27-inch, 2019)"; + } + if (ffStrEquals(version, "19,2")) { + return "iMac (Retina 4K, 21.5-inch, 2019)"; + } + if (ffStrEquals(version, "Pro1,1")) { + return "iMac Pro (2017)"; + } + if (ffStrEquals(version, "18,3")) { + return "iMac (Retina 5K, 27-inch, 2017)"; + } + if (ffStrEquals(version, "18,2")) { + return "iMac (Retina 4K, 21.5-inch, 2017)"; + } + if (ffStrEquals(version, "18,1")) { + return "iMac (21.5-inch, 2017)"; + } + if (ffStrEquals(version, "17,1")) { + return "iMac (Retina 5K, 27-inch, Late 2015)"; + } + if (ffStrEquals(version, "16,2")) { + return "iMac (Retina 4K, 21.5-inch, Late 2015)"; + } + if (ffStrEquals(version, "16,1")) { + return "iMac (21.5-inch, Late 2015)"; + } + if (ffStrEquals(version, "15,1")) { + return "iMac (Retina 5K, 27-inch, Late 2014 - Mid 2015)"; + } + if (ffStrEquals(version, "14,4")) { + return "iMac (21.5-inch, Mid 2014)"; + } + if (ffStrEquals(version, "14,2")) { + return "iMac (27-inch, Late 2013)"; + } + if (ffStrEquals(version, "14,1")) { + return "iMac (21.5-inch, Late 2013)"; + } + if (ffStrEquals(version, "13,2")) { + return "iMac (27-inch, Late 2012)"; + } + if (ffStrEquals(version, "13,1")) { + return "iMac (21.5-inch, Late 2012)"; + } + if (ffStrEquals(version, "12,2")) { + return "iMac (27-inch, Mid 2011)"; + } + if (ffStrEquals(version, "12,1")) { + return "iMac (21.5-inch, Mid 2011)"; + } + if (ffStrEquals(version, "11,3")) { + return "iMac (27-inch, Mid 2010)"; + } + if (ffStrEquals(version, "11,2")) { + return "iMac (21.5-inch, Mid 2010)"; + } + if (ffStrEquals(version, "10,1")) { + return "iMac (27/21.5-inch, Late 2009)"; + } + if (ffStrEquals(version, "9,1")) { + return "iMac (24/20-inch, Early 2009)"; + } + } + return NULL; +} + +#ifdef __x86_64__ +bool ffHostDetectMac(FFHostResult* host) { + if (ffStrbufStartsWithS(&host->family, "Mac") && ffStrbufEqualS(&host->vendor, "Apple Inc.")) { + const char* productName = ffHostGetMacProductNameWithHwModel(&host->name); + if (productName) { + ffStrbufDestroy(&host->family); + ffStrbufInitMove(&host->family, &host->name); + ffStrbufSetStatic(&host->name, productName); + return true; + } + } + return false; +} +#endif diff --git a/src/detection/host/host_nbsd.c b/src/detection/host/host_nbsd.c new file mode 100644 index 0000000..a5a29d2 --- /dev/null +++ b/src/detection/host/host_nbsd.c @@ -0,0 +1,25 @@ +#include "host.h" +#include "common/sysctl.h" +#include "common/smbios.h" + +const char* ffDetectHost(FFHostResult* host) { + const char* error = NULL; + if ((error = ffSysctlGetString("machdep.dmi.system-product", &host->name))) { + return error; + } + ffCleanUpSmbiosValue(&host->name); + if (ffSysctlGetString("machdep.dmi.system-vendor", &host->vendor) == NULL) { + ffCleanUpSmbiosValue(&host->vendor); + } + if (ffSysctlGetString("machdep.dmi.system-version", &host->version) == NULL) { + ffCleanUpSmbiosValue(&host->version); + } + if (ffSysctlGetString("machdep.dmi.system-serial", &host->serial) == NULL) { + ffCleanUpSmbiosValue(&host->serial); + } + if (ffSysctlGetString("machdep.dmi.system-uuid", &host->uuid) == NULL) { + ffCleanUpSmbiosValue(&host->uuid); + } + + return NULL; +} diff --git a/src/detection/host/host_nosupport.c b/src/detection/host/host_nosupport.c new file mode 100644 index 0000000..61a7254 --- /dev/null +++ b/src/detection/host/host_nosupport.c @@ -0,0 +1,5 @@ +#include "host.h" + +const char* ffDetectHost(FF_A_UNUSED FFHostResult* host) { + return "Not supported on this platform"; +} diff --git a/src/detection/host/host_obsd.c b/src/detection/host/host_obsd.c new file mode 100644 index 0000000..cb16ecf --- /dev/null +++ b/src/detection/host/host_obsd.c @@ -0,0 +1,22 @@ +#include "host.h" +#include "common/sysctl.h" +#include "common/smbios.h" + +const char* ffDetectHost(FFHostResult* host) { + const char* error = NULL; + if ((error = ffSysctlGetString(CTL_HW, HW_PRODUCT, &host->name))) { + return error; + } + ffCleanUpSmbiosValue(&host->name); + if (ffSysctlGetString(CTL_HW, HW_VENDOR, &host->vendor) == NULL) { + ffCleanUpSmbiosValue(&host->vendor); + } + if (ffSysctlGetString(CTL_HW, HW_VERSION, &host->version) == NULL) { + ffCleanUpSmbiosValue(&host->version); + } + if (ffSysctlGetString(CTL_HW, HW_SERIALNO, &host->serial) == NULL) { + ffCleanUpSmbiosValue(&host->serial); + } + + return NULL; +} diff --git a/src/detection/host/host_windows.c b/src/detection/host/host_windows.c new file mode 100644 index 0000000..9f25829 --- /dev/null +++ b/src/detection/host/host_windows.c @@ -0,0 +1,74 @@ +#include "host.h" +#include "common/smbios.h" + +typedef struct FFSmbiosSystemInfo { + FFSmbiosHeader Header; + + uint8_t Manufacturer; // string + uint8_t ProductName; // string + uint8_t Version; // string + uint8_t SerialNumber; // string + + // 2.1+ + struct { + uint32_t TimeLow; + uint16_t TimeMid; + uint16_t TimeHighAndVersion; + uint8_t ClockSeqHiAndReserved; + uint8_t ClockSeqLow; + uint8_t Node[6]; + } FF_A_PACKED UUID; // varies + uint8_t WakeUpType; // enum + + // 2.4+ + uint8_t SKUNumber; // string + uint8_t Family; // string +} FF_A_PACKED FFSmbiosSystemInfo; + +static_assert(offsetof(FFSmbiosSystemInfo, Family) == 0x1A, + "FFSmbiosSystemInfo: Wrong struct alignment"); + +const char* ffDetectHost(FFHostResult* host) { + const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable(); + if (!smbiosTable) { + return "Failed to get SMBIOS data"; + } + + const FFSmbiosSystemInfo* data = (const FFSmbiosSystemInfo*) (*smbiosTable)[FF_SMBIOS_TYPE_SYSTEM_INFO]; + if (!data) { + return "System information is not found in SMBIOS data"; + } + + const char* strings = (const char*) data + data->Header.Length; + + ffStrbufSetStatic(&host->vendor, ffSmbiosLocateString(strings, data->Manufacturer)); + ffCleanUpSmbiosValue(&host->vendor); + ffStrbufSetStatic(&host->name, ffSmbiosLocateString(strings, data->ProductName)); + ffCleanUpSmbiosValue(&host->name); + ffStrbufSetStatic(&host->version, ffSmbiosLocateString(strings, data->Version)); + ffCleanUpSmbiosValue(&host->version); + ffStrbufSetStatic(&host->serial, ffSmbiosLocateString(strings, data->SerialNumber)); + ffCleanUpSmbiosValue(&host->serial); + + static_assert(offsetof(FFSmbiosSystemInfo, UUID) == 0x08, "FFSmbiosSystemInfo.UUID offset is wrong"); + if (data->Header.Length > offsetof(FFSmbiosSystemInfo, UUID)) { + ffStrbufSetF(&host->uuid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", data->UUID.TimeLow, data->UUID.TimeMid, data->UUID.TimeHighAndVersion, data->UUID.ClockSeqHiAndReserved, data->UUID.ClockSeqLow, data->UUID.Node[0], data->UUID.Node[1], data->UUID.Node[2], data->UUID.Node[3], data->UUID.Node[4], data->UUID.Node[5]); + } + + static_assert(offsetof(FFSmbiosSystemInfo, SKUNumber) == 0x19, "FFSmbiosSystemInfo.SKUNumber offset is wrong"); + if (data->Header.Length > offsetof(FFSmbiosSystemInfo, SKUNumber)) { + ffStrbufSetStatic(&host->sku, ffSmbiosLocateString(strings, data->SKUNumber)); + ffCleanUpSmbiosValue(&host->sku); + } + + if (data->Header.Length > offsetof(FFSmbiosSystemInfo, Family)) { + ffStrbufSetStatic(&host->family, ffSmbiosLocateString(strings, data->Family)); + ffCleanUpSmbiosValue(&host->family); + } + +#if __x86_64__ + ffHostDetectMac(host); +#endif + + return NULL; +} -- cgit v1.2.3