diff options
Diffstat (limited to 'src/detection/chassis')
| -rw-r--r-- | src/detection/chassis/chassis.c | 81 | ||||
| -rw-r--r-- | src/detection/chassis/chassis.h | 14 | ||||
| -rw-r--r-- | src/detection/chassis/chassis_apple.c | 40 | ||||
| -rw-r--r-- | src/detection/chassis/chassis_bsd.c | 16 | ||||
| -rw-r--r-- | src/detection/chassis/chassis_linux.c | 39 | ||||
| -rw-r--r-- | src/detection/chassis/chassis_nbsd.c | 20 | ||||
| -rw-r--r-- | src/detection/chassis/chassis_nosupport.c | 5 | ||||
| -rw-r--r-- | src/detection/chassis/chassis_windows.c | 54 |
8 files changed, 269 insertions, 0 deletions
diff --git a/src/detection/chassis/chassis.c b/src/detection/chassis/chassis.c new file mode 100644 index 0000000..d4d1fd3 --- /dev/null +++ b/src/detection/chassis/chassis.c @@ -0,0 +1,81 @@ +#include "chassis.h" + +const char* ffChassisTypeToString(uint32_t type) { + // 7.4.1 System Enclosure or Chassis Types + switch (type & 0b01111111) { + case 0x01: + return "Other"; + case 0x02: + return "Unknown"; + case 0x03: + return "Desktop"; + case 0x04: + return "Low Profile Desktop"; + case 0x05: + return "Pizza Box"; + case 0x06: + return "Mini Tower"; + case 0x07: + return "Tower"; + case 0x08: + return "Portable"; + case 0x09: + return "Laptop"; + case 0x0A: + return "Notebook"; + case 0x0B: + return "Hand Held"; + case 0x0C: + return "Docking Station"; + case 0x0D: + return "All in One"; + case 0x0E: + return "Sub Notebook"; + case 0x0F: + return "Space-saving"; + case 0x10: + return "Lunch Box"; + case 0x11: + return "Main Server Chassis"; + case 0x12: + return "Expansion Chassis"; + case 0x13: + return "SubChassis"; + case 0x14: + return "Bus Expansion Chassis"; + case 0x15: + return "Peripheral Chassis"; + case 0x16: + return "RAID Chassis"; + case 0x17: + return "Rack Mount Chassis"; + case 0x18: + return "Sealed-case PC"; + case 0x19: + return "Multi-system chassis"; + case 0x1A: + return "Compact PCI"; + case 0x1B: + return "Advanced TCA"; + case 0x1C: + return "Blade"; + case 0x1D: + return "Blade Enclosure"; + case 0x1E: + return "Tablet"; + case 0x1F: + return "Convertible"; + case 0x20: + return "Detachable"; + case 0x21: + return "IoT Gateway"; + case 0x22: + return "Embedded PC"; + case 0x23: + return "Mini PC"; + case 0x24: + return "Stick PC"; + default: + return NULL; + } +} diff --git a/src/detection/chassis/chassis.h b/src/detection/chassis/chassis.h new file mode 100644 index 0000000..4e57ad0 --- /dev/null +++ b/src/detection/chassis/chassis.h @@ -0,0 +1,14 @@ +#pragma once + +#include "fastfetch.h" +#include "modules/chassis/option.h" + +typedef struct FFChassisResult { + FFstrbuf type; + FFstrbuf serial; + FFstrbuf vendor; + FFstrbuf version; +} FFChassisResult; + +const char* ffDetectChassis(FFChassisResult* result); +const char* ffChassisTypeToString(uint32_t type); diff --git a/src/detection/chassis/chassis_apple.c b/src/detection/chassis/chassis_apple.c new file mode 100644 index 0000000..1ff4fee --- /dev/null +++ b/src/detection/chassis/chassis_apple.c @@ -0,0 +1,40 @@ +#include "chassis.h" +#include "detection/host/host.h" + +const char* ffDetectChassis(FFChassisResult* result) { + FFHostResult host = { + .family = ffStrbufCreate(), + .name = ffStrbufCreate(), + .version = ffStrbufCreate(), + .sku = ffStrbufCreate(), + .serial = ffStrbufCreate(), + .uuid = ffStrbufCreate(), + .vendor = ffStrbufCreate(), + }; + if (ffDetectHost(&host) != NULL) { + return "Failed to detect host"; + } + + if (ffStrbufStartsWithS(&host.name, "MacBook ")) { + ffStrbufSetStatic(&result->type, "Laptop"); + } else if (ffStrbufStartsWithS(&host.name, "Mac mini ") || + ffStrbufStartsWithS(&host.name, "Mac Studio ")) { + ffStrbufSetStatic(&result->type, "Mini PC"); + } else if (ffStrbufStartsWithS(&host.name, "iMac ")) { + ffStrbufSetStatic(&result->type, "All in One"); + } else { + ffStrbufSetStatic(&result->type, "Desktop"); + } + + ffStrbufSet(&result->vendor, &host.vendor); + + ffStrbufDestroy(&host.family); + ffStrbufDestroy(&host.name); + ffStrbufDestroy(&host.version); + ffStrbufDestroy(&host.sku); + ffStrbufDestroy(&host.serial); + ffStrbufDestroy(&host.uuid); + ffStrbufDestroy(&host.vendor); + + return NULL; +} diff --git a/src/detection/chassis/chassis_bsd.c b/src/detection/chassis/chassis_bsd.c new file mode 100644 index 0000000..fa13718 --- /dev/null +++ b/src/detection/chassis/chassis_bsd.c @@ -0,0 +1,16 @@ +#include "chassis.h" +#include "common/settings.h" +#include "common/smbios.h" + +const char* ffDetectChassis(FFChassisResult* result) { + // Unlike other platforms, `smbios.chassis.type` return display string directly on my machine + ffSettingsGetFreeBSDKenv("smbios.chassis.type", &result->type); + ffCleanUpSmbiosValue(&result->type); + ffSettingsGetFreeBSDKenv("smbios.chassis.maker", &result->vendor); + ffCleanUpSmbiosValue(&result->vendor); + ffSettingsGetFreeBSDKenv("smbios.chassis.serial", &result->serial); + ffCleanUpSmbiosValue(&result->serial); + ffSettingsGetFreeBSDKenv("smbios.chassis.version", &result->version); + ffCleanUpSmbiosValue(&result->version); + return NULL; +} diff --git a/src/detection/chassis/chassis_linux.c b/src/detection/chassis/chassis_linux.c new file mode 100644 index 0000000..af7ed0a --- /dev/null +++ b/src/detection/chassis/chassis_linux.c @@ -0,0 +1,39 @@ +#include "chassis.h" +#include "common/io.h" +#include "common/smbios.h" + +#include <ctype.h> + +const char* ffDetectChassis(FFChassisResult* result) { + if (ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type)) { + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_serial", "/sys/class/dmi/id/chassis_serial", &result->serial); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->version); + + if (result->type.length) { + const char* typeStr = ffChassisTypeToString((uint32_t) ffStrbufToUInt(&result->type, 9999)); + if (typeStr) { + ffStrbufSetStatic(&result->type, typeStr); + } + } + } else { + // Available on Asahi Linux + uint32_t chassisType = 0; + if (ffReadFileData("/sys/firmware/devicetree/base/smbios/smbios/chassis/chassis-type", sizeof(chassisType), &chassisType)) // big endian + { + chassisType = __builtin_bswap32(chassisType); + const char* typeStr = ffChassisTypeToString(chassisType); + if (typeStr) { + ffStrbufSetStatic(&result->type, typeStr); + } + + if (ffReadFileBuffer("/sys/firmware/devicetree/base/smbios/smbios/chassis/manufacturer", &result->vendor) && result->vendor.length > 0) { + ffStrbufTrimRight(&result->vendor, '\0'); + } + } else if (ffReadFileBuffer("/sys/firmware/devicetree/base/chassis-type", &result->type) && result->type.length > 0) { + ffStrbufTrimRight(&result->type, '\0'); + result->type.chars[0] = (char) toupper(result->type.chars[0]); + } + } + return NULL; +} diff --git a/src/detection/chassis/chassis_nbsd.c b/src/detection/chassis/chassis_nbsd.c new file mode 100644 index 0000000..5644798 --- /dev/null +++ b/src/detection/chassis/chassis_nbsd.c @@ -0,0 +1,20 @@ +#include "chassis.h" +#include "common/sysctl.h" +#include "common/smbios.h" + +const char* ffDetectChassis(FFChassisResult* chassis) { + if (ffSysctlGetString("machdep.dmi.chassis-type", &chassis->type) == NULL) { + ffCleanUpSmbiosValue(&chassis->type); + } + if (ffSysctlGetString("machdep.dmi.chassis-version", &chassis->version) == NULL) { + ffCleanUpSmbiosValue(&chassis->version); + } + if (ffSysctlGetString("machdep.dmi.chassis-vendor", &chassis->vendor) == NULL) { + ffCleanUpSmbiosValue(&chassis->vendor); + } + if (ffSysctlGetString("machdep.dmi.chassis-serial", &chassis->serial) == NULL) { + ffCleanUpSmbiosValue(&chassis->serial); + } + + return NULL; +} diff --git a/src/detection/chassis/chassis_nosupport.c b/src/detection/chassis/chassis_nosupport.c new file mode 100644 index 0000000..0fc4dd9 --- /dev/null +++ b/src/detection/chassis/chassis_nosupport.c @@ -0,0 +1,5 @@ +#include "chassis.h" + +const char* ffDetectChassis(FF_A_UNUSED FFChassisResult* result) { + return "Not supported on this platform"; +} diff --git a/src/detection/chassis/chassis_windows.c b/src/detection/chassis/chassis_windows.c new file mode 100644 index 0000000..51a4c6c --- /dev/null +++ b/src/detection/chassis/chassis_windows.c @@ -0,0 +1,54 @@ +#include "chassis.h" +#include "common/smbios.h" + +// 7.4 +typedef struct FFSmbiosSystemEnclosure { + FFSmbiosHeader Header; + + uint8_t Manufacturer; // string + uint8_t Type; // varies + uint8_t Version; // string + uint8_t SerialNumber; // string + uint8_t AssetTagNumber; // string + + // 2.1+ + uint8_t BootupState; // enum + uint8_t PowerSupplyState; // enum + uint8_t ThermalState; // enum + uint8_t SecurityStatus; // enum + + // 2.3+ + uint32_t OEMDefined; // varies + uint8_t Height; // varies + uint8_t NumberOfPowerCords; // varies + uint8_t ContainedElementCount; // varies + uint8_t ContainedRecordLength; // varies + uint8_t ContainedElements[]; // varies +} FF_A_PACKED FFSmbiosSystemEnclosure; + +static_assert(offsetof(FFSmbiosSystemEnclosure, ContainedElements) == 0x15, + "FFSmbiosSystemEnclosure: Wrong struct alignment"); + +const char* ffDetectChassis(FFChassisResult* result) { + const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable(); + if (!smbiosTable) { + return "Failed to get SMBIOS data"; + } + + const FFSmbiosSystemEnclosure* data = (const FFSmbiosSystemEnclosure*) (*smbiosTable)[FF_SMBIOS_TYPE_SYSTEM_ENCLOSURE]; + if (!data) { + return "System enclosure is not found in SMBIOS data"; + } + + const char* strings = (const char*) data + data->Header.Length; + + ffStrbufSetStatic(&result->vendor, ffSmbiosLocateString(strings, data->Manufacturer)); + ffCleanUpSmbiosValue(&result->vendor); + ffStrbufSetStatic(&result->serial, ffSmbiosLocateString(strings, data->SerialNumber)); + ffCleanUpSmbiosValue(&result->serial); + ffStrbufSetStatic(&result->version, ffSmbiosLocateString(strings, data->Version)); + ffCleanUpSmbiosValue(&result->version); + ffStrbufSetStatic(&result->type, ffChassisTypeToString(data->Type)); + + return NULL; +} |