mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Host / Chassis (Windows): parse SMBIOS data directly
This commit is contained in:
+2
-2
@@ -621,7 +621,7 @@ elseif(WIN32)
|
||||
src/detection/bluetooth/bluetooth_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
src/detection/brightness/brightness_windows.cpp
|
||||
src/detection/chassis/chassis_windows.cpp
|
||||
src/detection/chassis/chassis_windows.c
|
||||
src/detection/cpu/cpu_windows.c
|
||||
src/detection/cpuusage/cpuusage_windows.c
|
||||
src/detection/cursor/cursor_windows.c
|
||||
@@ -631,7 +631,7 @@ elseif(WIN32)
|
||||
src/detection/displayserver/displayserver_windows.c
|
||||
src/detection/font/font_windows.c
|
||||
src/detection/gpu/gpu_windows.c
|
||||
src/detection/host/host_windows.cpp
|
||||
src/detection/host/host_windows.c
|
||||
src/detection/icons/icons_windows.c
|
||||
src/detection/libc/libc_windows.cpp
|
||||
src/detection/lm/lm_nosupport.c
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
const char* ffChassisTypeToString(uint32_t type)
|
||||
{
|
||||
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.2.0.pdf
|
||||
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.7.0.pdf
|
||||
// 7.4.1 System Enclosure or Chassis Types
|
||||
switch (type)
|
||||
switch (type & 0b01111111)
|
||||
{
|
||||
case 0x01: return "Other";
|
||||
case 0x02: return "Unknown";
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "chassis.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
// 7.4
|
||||
typedef struct FFSmbiosSystemEnclosure
|
||||
{
|
||||
uint8_t Manufacturer;
|
||||
uint8_t Type;
|
||||
uint8_t Version;
|
||||
uint8_t SerialNumber;
|
||||
uint8_t AssetTagNumber;
|
||||
uint8_t BootupState;
|
||||
uint8_t PowerSupplyState;
|
||||
uint8_t ThermalState;
|
||||
uint8_t SecurityStatus;
|
||||
uint32_t OEMDefined;
|
||||
uint8_t Height;
|
||||
uint8_t NumberOfPowerCords;
|
||||
} FFSmbiosSystemEnclosure;
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options)
|
||||
{
|
||||
const FFRawSmbiosData* data = ffGetSmbiosData();
|
||||
|
||||
for (
|
||||
const FFSmbiosHeader* header = (const FFSmbiosHeader*) data->SMBIOSTableData;
|
||||
(const uint8_t*) header < data->SMBIOSTableData + data->Length && header->Type < FF_SMBIOS_TYPE_LAST;
|
||||
header = ffSmbiosSkipLastStr(header)
|
||||
)
|
||||
{
|
||||
if (header->Type != FF_SMBIOS_TYPE_SYSTEM_ENCLOSURE)
|
||||
continue;
|
||||
|
||||
const FFSmbiosSystemEnclosure* data = (const FFSmbiosSystemEnclosure*) header->Data;
|
||||
const char* strings = (const char*) header + header->Length;
|
||||
|
||||
ffStrbufSetStatic(&result->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
|
||||
ffCleanUpSmbiosValue(&result->vendor);
|
||||
ffStrbufSetStatic(&result->version, ffSmbiosLocateString(strings, data->Version));
|
||||
ffCleanUpSmbiosValue(&result->version);
|
||||
ffStrbufSetStatic(&result->type, ffChassisTypeToString(data->Type));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "System enclosure is not found in SMBIOS data";
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
extern "C" {
|
||||
#include "chassis.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
}
|
||||
#include "util/windows/unicode.hpp"
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
static const char* detectWithRegistry(FFChassisResult* result)
|
||||
{
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL)) // SMBIOS
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed";
|
||||
|
||||
uint32_t type = 0;
|
||||
if(!ffRegReadUint(hKey, L"EnclosureType", &type, NULL))
|
||||
return "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\EnclosureType\" doesn't exist";
|
||||
|
||||
const char* typeStr = ffChassisTypeToString(type);
|
||||
if(!typeStr)
|
||||
return "Unknown chassis type";
|
||||
|
||||
ffStrbufAppendS(&result->type, typeStr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
|
||||
{
|
||||
FFWmiQuery query(L"SELECT Version, ChassisTypes, Manufacturer FROM Win32_SystemEnclosure");
|
||||
if (!query)
|
||||
return "Query WMI service failed";
|
||||
|
||||
if (FFWmiRecord record = query.next())
|
||||
{
|
||||
if (auto vtProp = record.get(L"ChassisTypes"))
|
||||
{
|
||||
auto [arr, len] = vtProp.get<std::pair<const int32_t*, uint32_t>>();
|
||||
if(len == 0)
|
||||
return "ChassisTypes contain no data";
|
||||
for (uint32_t i = 0; i < len; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
ffStrbufAppendS(&result->type, ", ");
|
||||
ffStrbufAppendS(&result->type, ffChassisTypeToString((uint32_t) arr[i]));
|
||||
}
|
||||
}
|
||||
else
|
||||
return "Get ChassisTypes failed";
|
||||
|
||||
if (auto vtProp = record.get(L"Version"))
|
||||
{
|
||||
ffStrbufSetWSV(&result->version, vtProp.get<std::wstring_view>());
|
||||
ffCleanUpSmbiosValue(&result->version);
|
||||
}
|
||||
|
||||
if (auto vtProp = record.get(L"Manufacturer"))
|
||||
{
|
||||
ffStrbufSetWSV(&result->vendor, vtProp.get<std::wstring_view>());
|
||||
ffCleanUpSmbiosValue(&result->vendor);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
return "No WMI result returned";
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options)
|
||||
{
|
||||
if (options->useWmi)
|
||||
return detectWithWmi(result);
|
||||
return detectWithRegistry(result);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#include "host.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
typedef struct FFSmbiosSystemInfo
|
||||
{
|
||||
uint8_t Manufacturer;
|
||||
uint8_t ProductName;
|
||||
uint8_t Version;
|
||||
uint8_t SerialNumber;
|
||||
struct {
|
||||
uint32_t TimeLow;
|
||||
uint16_t TimeMid;
|
||||
uint16_t TimeHighAndVersion;
|
||||
uint8_t ClockSeqHiAndReserved;
|
||||
uint8_t ClockSeqLow;
|
||||
uint8_t Node[6];
|
||||
} UUID;
|
||||
uint8_t WakeUpType;
|
||||
uint8_t SKUNumber;
|
||||
uint8_t Family;
|
||||
} FFSmbiosSystemInfo;
|
||||
|
||||
const char* ffDetectHost(FFHostResult* host, FFHostOptions* options)
|
||||
{
|
||||
const FFRawSmbiosData* fullData = ffGetSmbiosData();
|
||||
|
||||
for (
|
||||
const FFSmbiosHeader* header = (const FFSmbiosHeader*) fullData->SMBIOSTableData;
|
||||
(const uint8_t*) header < fullData->SMBIOSTableData + fullData->Length && header->Type < FF_SMBIOS_TYPE_LAST;
|
||||
header = ffSmbiosSkipLastStr(header)
|
||||
)
|
||||
{
|
||||
if (header->Type != FF_SMBIOS_TYPE_SYSTEM_INFO)
|
||||
continue;
|
||||
|
||||
const FFSmbiosSystemInfo* data = (const FFSmbiosSystemInfo*) header->Data;
|
||||
const char* strings = (const char*) header + 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);
|
||||
|
||||
if (header->Length > 0x08)
|
||||
{
|
||||
// Order?
|
||||
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]);
|
||||
}
|
||||
if (header->Length > 0x19)
|
||||
{
|
||||
ffStrbufSetStatic(&host->family, ffSmbiosLocateString(strings, data->Family));
|
||||
ffCleanUpSmbiosValue(&host->family);
|
||||
ffStrbufSetStatic(&host->sku, ffSmbiosLocateString(strings, data->SKUNumber));
|
||||
ffCleanUpSmbiosValue(&host->sku);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "System information is not found in SMBIOS data";
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
extern "C"
|
||||
{
|
||||
#include "host.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
#include "util/windows/unicode.hpp"
|
||||
|
||||
const char* detectWithWmi(FFHostResult* host)
|
||||
{
|
||||
FFWmiQuery query(L"SELECT IdentifyingNumber, UUID FROM Win32_ComputerSystemProduct", nullptr, FFWmiNamespace::CIMV2);
|
||||
if(!query)
|
||||
return "Query WMI service failed";
|
||||
|
||||
if (FFWmiRecord record = query.next())
|
||||
{
|
||||
if (auto identifyingNumber = record.get(L"IdentifyingNumber"))
|
||||
ffStrbufSetWSV(&host->serial, identifyingNumber.get<std::wstring_view>());
|
||||
if (auto uuid = record.get(L"UUID"))
|
||||
ffStrbufSetWSV(&host->uuid, uuid.get<std::wstring_view>());
|
||||
return NULL;
|
||||
}
|
||||
return "No WMI result returned";
|
||||
}
|
||||
|
||||
const char* ffDetectHost(FFHostResult* host, FFHostOptions* options)
|
||||
{
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL))
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed";
|
||||
|
||||
ffRegReadStrbuf(hKey, L"SystemProductName", &host->name, NULL);
|
||||
ffCleanUpSmbiosValue(&host->name);
|
||||
ffRegReadStrbuf(hKey, L"SystemFamily", &host->family, NULL);
|
||||
ffCleanUpSmbiosValue(&host->family);
|
||||
ffRegReadStrbuf(hKey, L"SystemVersion", &host->version, NULL);
|
||||
ffCleanUpSmbiosValue(&host->version);
|
||||
ffRegReadStrbuf(hKey, L"SystemSKU", &host->sku, NULL);
|
||||
ffCleanUpSmbiosValue(&host->sku);
|
||||
ffRegReadStrbuf(hKey, L"SystemManufacturer", &host->vendor, NULL);
|
||||
ffCleanUpSmbiosValue(&host->vendor);
|
||||
|
||||
if (options->useWmi)
|
||||
detectWithWmi(host);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -47,4 +47,22 @@ void ffGetSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf*
|
||||
|
||||
ffStrbufClear(buffer);
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wmultichar"
|
||||
|
||||
const FFRawSmbiosData* ffGetSmbiosData()
|
||||
{
|
||||
static FFRawSmbiosData* buffer;
|
||||
if (!buffer)
|
||||
{
|
||||
const DWORD signature = 'RSMB';
|
||||
uint32_t bufSize = GetSystemFirmwareTable(signature, 0, NULL, 0);
|
||||
assert(bufSize > sizeof(FFRawSmbiosData));
|
||||
buffer = (FFRawSmbiosData*) malloc(bufSize);
|
||||
GetSystemFirmwareTable(signature, 0, buffer, bufSize);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,66 @@ static inline void ffCleanUpSmbiosValue(FFstrbuf* value)
|
||||
|
||||
#ifdef __linux__
|
||||
void ffGetSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer);
|
||||
#elif defined(_WIN32)
|
||||
// https://github.com/KunYi/DumpSMBIOS
|
||||
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.7.0.pdf
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFSmbiosType // : uint8_t
|
||||
{
|
||||
FF_SMBIOS_TYPE_BIOS = 0,
|
||||
FF_SMBIOS_TYPE_SYSTEM_INFO = 1,
|
||||
FF_SMBIOS_TYPE_BASEBOARD_INFO = 2,
|
||||
FF_SMBIOS_TYPE_SYSTEM_ENCLOSURE = 3,
|
||||
FF_SMBIOS_TYPE_PROCESSOR_INFO = 4,
|
||||
FF_SMBIOS_TYPE_MEMORY_MODULE_INFO = 6,
|
||||
FF_SMBIOS_TYPE_CACHE_INFO = 7,
|
||||
FF_SMBIOS_TYPE_OEM_STRING = 11,
|
||||
FF_SMBIOS_TYPE_MEMORY_DEVICE = 17,
|
||||
FF_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS = 19,
|
||||
FF_SMBIOS_TYPE_BUILTIN_POINT_DEVICE = 21,
|
||||
FF_SMBIOS_TYPE_PORTABLE_BATTERY = 22,
|
||||
FF_SMBIOS_TYPE_LAST = 127,
|
||||
} FFSmbiosType;
|
||||
static_assert(sizeof(FFSmbiosType) == 1, "FFSmbiosType should be 1 byte");
|
||||
|
||||
typedef struct FFSmbiosHeader
|
||||
{
|
||||
FFSmbiosType Type;
|
||||
uint8_t Length;
|
||||
uint16_t Handle;
|
||||
uint8_t Data[];
|
||||
} FFSmbiosHeader;
|
||||
static_assert(sizeof(FFSmbiosHeader) == 4, "FFSmbiosHeader should be 4 bytes");
|
||||
|
||||
typedef struct FFRawSmbiosData
|
||||
{
|
||||
uint8_t Used20CallingMethod;
|
||||
uint8_t SMBIOSMajorVersion;
|
||||
uint8_t SMBIOSMinorVersion;
|
||||
uint8_t DmiRevision;
|
||||
uint32_t Length;
|
||||
uint8_t SMBIOSTableData[];
|
||||
} FFRawSmbiosData;
|
||||
|
||||
static inline const char* ffSmbiosLocateString(const char* start, uint8_t index /* start from 1 */)
|
||||
{
|
||||
if (index == 0 || *start == '\0')
|
||||
return NULL;
|
||||
while (--index)
|
||||
start += strlen(start) + 1;
|
||||
return start;
|
||||
}
|
||||
|
||||
static inline const FFSmbiosHeader* ffSmbiosSkipLastStr(const FFSmbiosHeader* header)
|
||||
{
|
||||
const char* p = ((const char*) header) + header->Length;
|
||||
while (*p)
|
||||
p += strlen(p) + 1;
|
||||
|
||||
return (const FFSmbiosHeader*) (p + 1);
|
||||
}
|
||||
|
||||
const FFRawSmbiosData* ffGetSmbiosData();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user