diff --git a/CMakeLists.txt b/CMakeLists.txt index 417a42c68..214938392 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -401,7 +401,7 @@ if(LINUX) src/detection/bluetooth/bluetooth_linux.c src/detection/disk/disk_linux.c src/detection/physicaldisk/physicaldisk_linux.c - src/detection/physicalmemory/physicalmemory_nosupport.c + src/detection/physicalmemory/physicalmemory_linux.c src/detection/diskio/diskio_linux.c src/detection/displayserver/linux/displayserver_linux.c src/detection/displayserver/linux/drm.c @@ -667,7 +667,7 @@ elseif(WIN32) src/detection/gamepad/gamepad_windows.c src/detection/media/media_nosupport.c src/detection/memory/memory_windows.c - src/detection/physicalmemory/physicalmemory_windows.c + src/detection/physicalmemory/physicalmemory_linux.c src/detection/monitor/monitor_windows.c src/detection/netio/netio_windows.c src/detection/opengl/opengl_windows.c diff --git a/src/detection/physicalmemory/physicalmemory_windows.c b/src/detection/physicalmemory/physicalmemory_linux.c similarity index 97% rename from src/detection/physicalmemory/physicalmemory_windows.c rename to src/detection/physicalmemory/physicalmemory_linux.c index 0426d72c7..8b45aa805 100644 --- a/src/detection/physicalmemory/physicalmemory_windows.c +++ b/src/detection/physicalmemory/physicalmemory_linux.c @@ -67,9 +67,13 @@ static_assert(offsetof(FFSmbiosMemoryDevice, RcdRevisionNumber) == 0x62, const char* ffDetectPhysicalMemory(FFlist* result) { - const FFSmbiosMemoryDevice* data = (const FFSmbiosMemoryDevice*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_MEMORY_DEVICE]; + const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable(); + if (!smbiosTable) + return "Failed to get SMBIOS data"; + + const FFSmbiosMemoryDevice* data = (const FFSmbiosMemoryDevice*) (*smbiosTable)[FF_SMBIOS_TYPE_MEMORY_DEVICE]; if (!data) - return "System enclosure is not found in SMBIOS data"; + return "Memory device is not found in SMBIOS data"; for (; data->Header.Type == FF_SMBIOS_TYPE_MEMORY_DEVICE; data = (const FFSmbiosMemoryDevice*) ffSmbiosNextEntry(&data->Header)) diff --git a/src/util/smbiosHelper.c b/src/util/smbiosHelper.c index 29265d03a..4808a1ac8 100644 --- a/src/util/smbiosHelper.c +++ b/src/util/smbiosHelper.c @@ -1,6 +1,7 @@ #include "smbiosHelper.h" #include "common/io/io.h" #include "util/unused.h" +#include "util/mallocHelper.h" bool ffIsSmbiosValueSet(FFstrbuf* value) { @@ -31,7 +32,25 @@ bool ffIsSmbiosValueSet(FFstrbuf* value) ; } +const FFSmbiosHeader* ffSmbiosNextEntry(const FFSmbiosHeader* header) +{ + const char* p = ((const char*) header) + header->Length; + if (*p) + { + do + p += strlen(p) + 1; + while (*p); + } + else // The terminator is always double 0 even if there is no string + p ++; + + return (const FFSmbiosHeader*) (p + 1); +} + #ifdef __linux__ +#include +#include + bool ffGetSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer) { if (ffReadFileBuffer(devicesPath, buffer)) @@ -51,25 +70,50 @@ bool ffGetSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* ffStrbufClear(buffer); return false; } + +const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable() +{ + static FFstrbuf buffer; + static FFSmbiosHeaderTable table; + + if (buffer.chars == NULL) + { + ffStrbufInit(&buffer); + if (!ffAppendFileBuffer("/sys/firmware/dmi/tables/DMI", &buffer)) + return NULL; + + for ( + const FFSmbiosHeader* header = (const FFSmbiosHeader*) buffer.chars; + (const uint8_t*) header < (const uint8_t*) buffer.chars + buffer.length; + header = ffSmbiosNextEntry(header) + ) + { + if (header->Type < FF_SMBIOS_TYPE_END_OF_TABLE) + { + if (!table[header->Type]) + table[header->Type] = header; + } + else if (header->Type == FF_SMBIOS_TYPE_END_OF_TABLE) + break; + } + } + + return &table; +} #elif defined(_WIN32) #include #pragma GCC diagnostic ignored "-Wmultichar" -const FFSmbiosHeader* ffSmbiosNextEntry(const FFSmbiosHeader* header) +typedef struct FFRawSmbiosData { - const char* p = ((const char*) header) + header->Length; - if (*p) - { - do - p += strlen(p) + 1; - while (*p); - } - else // The terminator is always double 0 even if there is no string - p ++; - - return (const FFSmbiosHeader*) (p + 1); -} + uint8_t Used20CallingMethod; + uint8_t SMBIOSMajorVersion; + uint8_t SMBIOSMinorVersion; + uint8_t DmiRevision; + uint32_t Length; + uint8_t SMBIOSTableData[]; +} FFRawSmbiosData; const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable() { @@ -80,7 +124,9 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable() { const DWORD signature = 'RSMB'; uint32_t bufSize = GetSystemFirmwareTable(signature, 0, NULL, 0); - assert(bufSize > sizeof(FFRawSmbiosData)); + if (bufSize <= sizeof(FFRawSmbiosData)) + return NULL; + buffer = (FFRawSmbiosData*) malloc(bufSize); assert(buffer); FF_MAYBE_UNUSED uint32_t resultSize = GetSystemFirmwareTable(signature, 0, buffer, bufSize); diff --git a/src/util/smbiosHelper.h b/src/util/smbiosHelper.h index 81e820be0..7d7a4b18d 100644 --- a/src/util/smbiosHelper.h +++ b/src/util/smbiosHelper.h @@ -12,9 +12,6 @@ static inline void ffCleanUpSmbiosValue(FFstrbuf* value) ffStrbufClear(value); } -#ifdef __linux__ -bool 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 @@ -81,16 +78,6 @@ typedef struct FFSmbiosHeader } __attribute__((__packed__)) 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') @@ -104,6 +91,9 @@ typedef const FFSmbiosHeader* FFSmbiosHeaderTable[FF_SMBIOS_TYPE_END_OF_TABLE]; const FFSmbiosHeader* ffSmbiosNextEntry(const FFSmbiosHeader* header); const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable(); + +#ifdef __linux__ +bool ffGetSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer); #endif #endif