summaryrefslogtreecommitdiffstats
path: root/src/detection/chassis
diff options
context:
space:
mode:
authorsumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
committersumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
commit76424950e373d3b04ac3dd13019151bfba3e8423 (patch)
tree4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/chassis
Add the files
Diffstat (limited to 'src/detection/chassis')
-rw-r--r--src/detection/chassis/chassis.c81
-rw-r--r--src/detection/chassis/chassis.h14
-rw-r--r--src/detection/chassis/chassis_apple.c40
-rw-r--r--src/detection/chassis/chassis_bsd.c16
-rw-r--r--src/detection/chassis/chassis_linux.c39
-rw-r--r--src/detection/chassis/chassis_nbsd.c20
-rw-r--r--src/detection/chassis/chassis_nosupport.c5
-rw-r--r--src/detection/chassis/chassis_windows.c54
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;
+}