PhysicalMemory (Linux): add support

Note: this module requires root permission to work in Linux
This commit is contained in:
李通洲 2024-05-11 08:14:56 +00:00
parent 41f0971570
commit d28907ee9d
4 changed files with 71 additions and 31 deletions

View File

@ -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

View File

@ -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))

View File

@ -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 <fcntl.h>
#include <sys/stat.h>
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 <windows.h>
#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);

View File

@ -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