Host / Chassis (Windows): parse SMBIOS data directly

This commit is contained in:
李通洲
2024-01-06 00:41:02 +08:00
parent 21f3875c4f
commit 33f3199383
8 changed files with 197 additions and 126 deletions
+2 -2
View File
@@ -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 -2
View File
@@ -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";
+47
View File
@@ -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";
}
-73
View File
@@ -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);
}
+68
View File
@@ -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";
}
-49
View File
@@ -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;
}
+18
View File
@@ -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
+60
View File
@@ -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