mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 10:22:12 +02:00
Smbios: add verbose debug logs
This commit is contained in:
+169
-26
@@ -2,6 +2,7 @@
|
||||
#include "common/io/io.h"
|
||||
#include "util/unused.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/debug.h"
|
||||
|
||||
bool ffIsSmbiosValueSet(FFstrbuf* value)
|
||||
{
|
||||
@@ -138,55 +139,112 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
|
||||
if (buffer.chars == NULL)
|
||||
{
|
||||
FF_DEBUG("Initializing SMBIOS buffer");
|
||||
ffStrbufInit(&buffer);
|
||||
#if !__HAIKU__ && !__OpenBSD__
|
||||
#ifdef __linux__
|
||||
FF_DEBUG("Using Linux implementation - trying /sys/firmware/dmi/tables/DMI");
|
||||
if (!ffAppendFileBuffer("/sys/firmware/dmi/tables/DMI", &buffer))
|
||||
#endif
|
||||
{
|
||||
#if !defined(__sun) && !defined(__NetBSD__)
|
||||
FF_DEBUG("Using memory-mapped implementation");
|
||||
FF_STRBUF_AUTO_DESTROY strEntryAddress = ffStrbufCreate();
|
||||
#ifdef __FreeBSD__
|
||||
if (!ffSettingsGetFreeBSDKenv("hint.smbios.0.mem", &strEntryAddress))
|
||||
FF_DEBUG("Using FreeBSD kenv implementation");
|
||||
if (!ffSettingsGetFreeBSDKenv("hint.smbios.0.mem", &strEntryAddress)) {
|
||||
FF_DEBUG("Failed to get SMBIOS address from FreeBSD kenv");
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Got SMBIOS address from kenv: %s", strEntryAddress.chars);
|
||||
#elif defined(__linux__)
|
||||
{
|
||||
FF_DEBUG("Using Linux EFI systab implementation");
|
||||
FF_STRBUF_AUTO_DESTROY systab = ffStrbufCreate();
|
||||
if (!ffAppendFileBuffer("/sys/firmware/efi/systab", &systab))
|
||||
if (!ffAppendFileBuffer("/sys/firmware/efi/systab", &systab)) {
|
||||
FF_DEBUG("Failed to read /sys/firmware/efi/systab");
|
||||
return NULL;
|
||||
}
|
||||
if (!ffParsePropLines(systab.chars, "SMBIOS3=", &strEntryAddress) &&
|
||||
!ffParsePropLines(systab.chars, "SMBIOS=", &strEntryAddress))
|
||||
!ffParsePropLines(systab.chars, "SMBIOS=", &strEntryAddress)) {
|
||||
FF_DEBUG("Failed to find SMBIOS entry in systab");
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Found SMBIOS entry in systab: %s", strEntryAddress.chars);
|
||||
}
|
||||
#endif
|
||||
|
||||
loff_t entryAddress = (loff_t) strtol(strEntryAddress.chars, NULL, 16);
|
||||
if (entryAddress == 0) return NULL;
|
||||
if (entryAddress == 0) {
|
||||
FF_DEBUG("Invalid SMBIOS entry address: 0");
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Parsed SMBIOS entry address: 0x%lx", (unsigned long)entryAddress);
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/mem", O_RDONLY);
|
||||
if (fd < 0) return NULL;
|
||||
if (fd < 0) {
|
||||
FF_DEBUG("Failed to open /dev/mem: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("/dev/mem opened successfully with fd=%d", fd);
|
||||
|
||||
FFSmbiosEntryPoint entryPoint;
|
||||
FF_DEBUG("Attempting to read %zu bytes from physical address 0x%lx",
|
||||
sizeof(entryPoint), (unsigned long)entryAddress);
|
||||
if (pread(fd, &entryPoint, sizeof(entryPoint), entryAddress) < 0x10)
|
||||
{
|
||||
FF_DEBUG("pread failed, trying mmap");
|
||||
// `pread /dev/mem` returns EFAULT in FreeBSD
|
||||
// https://stackoverflow.com/questions/69372330/how-to-read-dev-mem-using-read
|
||||
void* p = mmap(NULL, sizeof(entryPoint), PROT_READ, MAP_SHARED, fd, entryAddress);
|
||||
if (p == MAP_FAILED) return NULL;
|
||||
if (p == MAP_FAILED) {
|
||||
FF_DEBUG("mmap failed: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
memcpy(&entryPoint, p, sizeof(entryPoint));
|
||||
munmap(p, sizeof(entryPoint));
|
||||
FF_DEBUG("Successfully read entry point data via mmap");
|
||||
} else {
|
||||
FF_DEBUG("Successfully read entry point data via pread");
|
||||
}
|
||||
#else
|
||||
// Sun or NetBSD
|
||||
FF_DEBUG("Using %s specific implementation",
|
||||
#ifdef __NetBSD__
|
||||
"NetBSD"
|
||||
#else
|
||||
"SunOS"
|
||||
#endif
|
||||
);
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/smbios", O_RDONLY);
|
||||
if (fd < 0) return NULL;
|
||||
if (fd < 0) {
|
||||
FF_DEBUG("Failed to open /dev/smbios: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("/dev/smbios opened successfully with fd=%d", fd);
|
||||
|
||||
FFSmbiosEntryPoint entryPoint;
|
||||
#ifdef __NetBSD__
|
||||
off_t addr = (off_t) ffSysctlGetInt64("machdep.smbios", 0);
|
||||
if (addr == 0) return NULL;
|
||||
if (pread(fd, &entryPoint, sizeof(entryPoint), addr) < 1) return NULL;
|
||||
if (addr == 0) {
|
||||
FF_DEBUG("Failed to get SMBIOS address from sysctl");
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Got SMBIOS address from sysctl: 0x%lx", (unsigned long)addr);
|
||||
|
||||
if (pread(fd, &entryPoint, sizeof(entryPoint), addr) < 1) {
|
||||
FF_DEBUG("Failed to read SMBIOS entry point: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Successfully read SMBIOS entry point");
|
||||
#else
|
||||
if (ffReadFDData(fd, sizeof(entryPoint), &entryPoint) < 1) return NULL;
|
||||
FF_DEBUG("Reading SMBIOS entry point from /dev/smbios");
|
||||
if (ffReadFDData(fd, sizeof(entryPoint), &entryPoint) < 1) {
|
||||
FF_DEBUG("Failed to read SMBIOS entry point: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Successfully read SMBIOS entry point");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -194,95 +252,152 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
loff_t tableAddress = 0;
|
||||
if (memcmp(entryPoint.Smbios20.AnchorString, "_SM_", sizeof(entryPoint.Smbios20.AnchorString)) == 0)
|
||||
{
|
||||
if (entryPoint.Smbios20.EntryPointLength != sizeof(entryPoint.Smbios20))
|
||||
FF_DEBUG("Found SMBIOS 2.0 entry point");
|
||||
if (entryPoint.Smbios20.EntryPointLength != sizeof(entryPoint.Smbios20)) {
|
||||
FF_DEBUG("Invalid SMBIOS 2.0 entry point length: %u (expected %zu)",
|
||||
entryPoint.Smbios20.EntryPointLength, sizeof(entryPoint.Smbios20));
|
||||
return NULL;
|
||||
}
|
||||
tableLength = entryPoint.Smbios20.StructureTableLength;
|
||||
tableAddress = (loff_t) entryPoint.Smbios20.StructureTableAddress;
|
||||
FF_DEBUG("SMBIOS 2.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u",
|
||||
tableLength, (unsigned long)tableAddress,
|
||||
entryPoint.Smbios20.SmbiosMajorVersion, entryPoint.Smbios20.SmbiosMinorVersion);
|
||||
}
|
||||
else if (memcmp(entryPoint.Smbios30.AnchorString, "_SM3_", sizeof(entryPoint.Smbios30.AnchorString)) == 0)
|
||||
{
|
||||
if (entryPoint.Smbios30.EntryPointLength != sizeof(entryPoint.Smbios30))
|
||||
FF_DEBUG("Found SMBIOS 3.0 entry point");
|
||||
if (entryPoint.Smbios30.EntryPointLength != sizeof(entryPoint.Smbios30)) {
|
||||
FF_DEBUG("Invalid SMBIOS 3.0 entry point length: %u (expected %zu)",
|
||||
entryPoint.Smbios30.EntryPointLength, sizeof(entryPoint.Smbios30));
|
||||
return NULL;
|
||||
}
|
||||
tableLength = entryPoint.Smbios30.StructureTableMaximumSize;
|
||||
tableAddress = (loff_t) entryPoint.Smbios30.StructureTableAddress;
|
||||
FF_DEBUG("SMBIOS 3.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u.%u",
|
||||
tableLength, (unsigned long)tableAddress,
|
||||
entryPoint.Smbios30.SmbiosMajorVersion, entryPoint.Smbios30.SmbiosMinorVersion, entryPoint.Smbios30.SmbiosDocrev);
|
||||
}
|
||||
else
|
||||
else {
|
||||
FF_DEBUG("Unknown SMBIOS entry point format");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ffStrbufEnsureFixedLengthFree(&buffer, tableLength);
|
||||
FF_DEBUG("Attempting to read SMBIOS table data: %u bytes at 0x%lx", tableLength, (unsigned long)tableAddress);
|
||||
if (pread(fd, buffer.chars, tableLength, tableAddress) == (ssize_t) tableLength)
|
||||
{
|
||||
buffer.length = tableLength;
|
||||
buffer.chars[buffer.length] = '\0';
|
||||
FF_DEBUG("Successfully read SMBIOS table data: %u bytes", tableLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("pread failed, trying mmap");
|
||||
// entryPoint.StructureTableAddress must be page aligned.
|
||||
// Unaligned physical memory access results in all kinds of crashes.
|
||||
void* p = mmap(NULL, tableLength, PROT_READ, MAP_SHARED, fd, tableAddress);
|
||||
if (p == MAP_FAILED)
|
||||
{
|
||||
FF_DEBUG("mmap failed: %s", strerror(errno));
|
||||
ffStrbufDestroy(&buffer); // free buffer and reset state
|
||||
return NULL;
|
||||
}
|
||||
ffStrbufSetNS(&buffer, tableLength, (char*) p);
|
||||
munmap(p, tableLength);
|
||||
FF_DEBUG("Successfully read SMBIOS table data via mmap: %u bytes", tableLength);
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
FF_DEBUG("Using %s implementation",
|
||||
#if __HAIKU__
|
||||
"Haiku"
|
||||
#else
|
||||
"OpenBSD"
|
||||
#endif
|
||||
);
|
||||
|
||||
uint32_t tableLength = 0;
|
||||
off_t tableAddress = 0;
|
||||
FF_AUTO_CLOSE_FD int fd = open(
|
||||
#if __HAIKU__
|
||||
"/dev/misc/mem"
|
||||
#else
|
||||
"/dev/mem"
|
||||
"/dev/mem" // kern.securelevel must be -1
|
||||
#endif
|
||||
, O_RDONLY);
|
||||
if (fd < 0)
|
||||
if (fd < 0) {
|
||||
FF_DEBUG("Failed to open memory device: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Memory device opened successfully with fd=%d", fd);
|
||||
|
||||
// Works on legacy BIOS only
|
||||
// See: https://wiki.osdev.org/System_Management_BIOS#UEFI_systems
|
||||
FF_AUTO_FREE uint8_t* smBiosBase = malloc(0x10000);
|
||||
if (pread(fd, smBiosBase, 0x10000, 0xF0000) != 0x10000)
|
||||
if (pread(fd, smBiosBase, 0x10000, 0xF0000) != 0x10000) {
|
||||
FF_DEBUG("Failed to read SMBIOS memory region: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Successfully read 0x10000 bytes from physical address 0xF0000");
|
||||
|
||||
for (off_t offset = 0; offset <= 0xffe0; offset += 0x10)
|
||||
{
|
||||
FFSmbiosEntryPoint* p = (void*)(smBiosBase + offset);
|
||||
if (memcmp(p, "_SM3_", sizeof(p->Smbios30.AnchorString)) == 0)
|
||||
{
|
||||
if (p->Smbios30.EntryPointLength != sizeof(p->Smbios30))
|
||||
FF_DEBUG("Found SMBIOS 3.0 entry point at offset 0x%lx", (unsigned long)offset);
|
||||
if (p->Smbios30.EntryPointLength != sizeof(p->Smbios30)) {
|
||||
FF_DEBUG("Invalid SMBIOS 3.0 entry point length: %u (expected %zu)",
|
||||
p->Smbios30.EntryPointLength, sizeof(p->Smbios30));
|
||||
return NULL;
|
||||
}
|
||||
tableLength = p->Smbios30.StructureTableMaximumSize;
|
||||
tableAddress = (off_t) p->Smbios30.StructureTableAddress;
|
||||
FF_DEBUG("SMBIOS 3.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u.%u",
|
||||
tableLength, (unsigned long)tableAddress,
|
||||
p->Smbios30.SmbiosMajorVersion, p->Smbios30.SmbiosMinorVersion, p->Smbios30.SmbiosDocrev);
|
||||
break;
|
||||
}
|
||||
else if (memcmp(p, "_SM_", sizeof(p->Smbios20.AnchorString)) == 0)
|
||||
{
|
||||
if (p->Smbios20.EntryPointLength != sizeof(p->Smbios20))
|
||||
FF_DEBUG("Found SMBIOS 2.0 entry point at offset 0x%lx", (unsigned long)offset);
|
||||
if (p->Smbios20.EntryPointLength != sizeof(p->Smbios20)) {
|
||||
FF_DEBUG("Invalid SMBIOS 2.0 entry point length: %u (expected %zu)",
|
||||
p->Smbios20.EntryPointLength, sizeof(p->Smbios20));
|
||||
return NULL;
|
||||
}
|
||||
tableLength = p->Smbios20.StructureTableLength;
|
||||
tableAddress = (off_t) p->Smbios20.StructureTableAddress;
|
||||
FF_DEBUG("SMBIOS 2.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u",
|
||||
tableLength, (unsigned long)tableAddress,
|
||||
p->Smbios20.SmbiosMajorVersion, p->Smbios20.SmbiosMinorVersion);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tableLength == 0)
|
||||
if (tableLength == 0) {
|
||||
FF_DEBUG("No valid SMBIOS entry point found in memory region");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ffStrbufEnsureFixedLengthFree(&buffer, tableLength);
|
||||
FF_DEBUG("Attempting to read SMBIOS table data: %u bytes at 0x%lx", tableLength, (unsigned long)tableAddress);
|
||||
if (pread(fd, buffer.chars, tableLength, tableAddress) == tableLength)
|
||||
{
|
||||
buffer.length = tableLength;
|
||||
buffer.chars[buffer.length] = '\0';
|
||||
FF_DEBUG("Successfully read SMBIOS table data: %u bytes", tableLength);
|
||||
}
|
||||
else
|
||||
else {
|
||||
FF_DEBUG("Failed to read SMBIOS table data: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
FF_DEBUG("Parsing SMBIOS table structures");
|
||||
int structureCount = 0;
|
||||
for (
|
||||
const FFSmbiosHeader* header = (const FFSmbiosHeader*) buffer.chars;
|
||||
(const uint8_t*) header < (const uint8_t*) buffer.chars + buffer.length;
|
||||
@@ -291,16 +406,25 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
{
|
||||
if (header->Type < FF_SMBIOS_TYPE_END_OF_TABLE)
|
||||
{
|
||||
if (!table[header->Type])
|
||||
if (!table[header->Type]) {
|
||||
table[header->Type] = header;
|
||||
FF_DEBUG("Found SMBIOS structure type %u, handle 0x%04X, length %u",
|
||||
header->Type, header->Handle, header->Length);
|
||||
structureCount++;
|
||||
}
|
||||
}
|
||||
else if (header->Type == FF_SMBIOS_TYPE_END_OF_TABLE)
|
||||
else if (header->Type == FF_SMBIOS_TYPE_END_OF_TABLE) {
|
||||
FF_DEBUG("Reached end-of-table marker");
|
||||
break;
|
||||
}
|
||||
}
|
||||
FF_DEBUG("Parsed %d SMBIOS structures", structureCount);
|
||||
}
|
||||
|
||||
if (buffer.length == 0)
|
||||
if (buffer.length == 0) {
|
||||
FF_DEBUG("No valid SMBIOS data available");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &table;
|
||||
}
|
||||
@@ -326,16 +450,28 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
FF_DEBUG("Initializing Windows SMBIOS buffer");
|
||||
const DWORD signature = 'RSMB';
|
||||
FF_DEBUG("Querying system firmware table size with signature 'RSMB'");
|
||||
uint32_t bufSize = GetSystemFirmwareTable(signature, 0, NULL, 0);
|
||||
if (bufSize <= sizeof(FFRawSmbiosData))
|
||||
if (bufSize <= sizeof(FFRawSmbiosData)) {
|
||||
FF_DEBUG("Invalid firmware table size: %u (must be > %zu)",
|
||||
bufSize, sizeof(FFRawSmbiosData));
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Firmware table size: %u bytes", bufSize);
|
||||
|
||||
buffer = (FFRawSmbiosData*) malloc(bufSize);
|
||||
assert(buffer);
|
||||
FF_DEBUG("Allocated buffer for SMBIOS data");
|
||||
|
||||
FF_MAYBE_UNUSED uint32_t resultSize = GetSystemFirmwareTable(signature, 0, buffer, bufSize);
|
||||
assert(resultSize == bufSize);
|
||||
FF_DEBUG("Successfully retrieved SMBIOS data: version %u.%u, length %u bytes",
|
||||
buffer->SMBIOSMajorVersion, buffer->SMBIOSMinorVersion, buffer->Length);
|
||||
|
||||
FF_DEBUG("Parsing SMBIOS table structures");
|
||||
int structureCount = 0;
|
||||
for (
|
||||
const FFSmbiosHeader* header = (const FFSmbiosHeader*) buffer->SMBIOSTableData;
|
||||
(const uint8_t*) header < buffer->SMBIOSTableData + buffer->Length;
|
||||
@@ -344,12 +480,19 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
{
|
||||
if (header->Type < FF_SMBIOS_TYPE_END_OF_TABLE)
|
||||
{
|
||||
if (!table[header->Type])
|
||||
if (!table[header->Type]) {
|
||||
table[header->Type] = header;
|
||||
FF_DEBUG("Found SMBIOS structure type %u, handle 0x%04X, length %u",
|
||||
header->Type, header->Handle, header->Length);
|
||||
structureCount++;
|
||||
}
|
||||
}
|
||||
else if (header->Type == FF_SMBIOS_TYPE_END_OF_TABLE)
|
||||
else if (header->Type == FF_SMBIOS_TYPE_END_OF_TABLE) {
|
||||
FF_DEBUG("Reached end-of-table marker");
|
||||
break;
|
||||
}
|
||||
}
|
||||
FF_DEBUG("Parsed %d SMBIOS structures", structureCount);
|
||||
}
|
||||
|
||||
return &table;
|
||||
|
||||
Reference in New Issue
Block a user