From 68bc0a56510ad201aecf2034a20d10c389592c84 Mon Sep 17 00:00:00 2001 From: janwas Date: Mon, 4 Apr 2011 16:50:02 +0000 Subject: [PATCH] smbios: add support for stringizing the structures This was SVN commit r9162. --- source/lib/sysdep/smbios.cpp | 127 +++++++++++++++++++++++++++++++---- source/lib/sysdep/smbios.h | 69 +++++++++---------- 2 files changed, 149 insertions(+), 47 deletions(-) diff --git a/source/lib/sysdep/smbios.cpp b/source/lib/sysdep/smbios.cpp index 2b2e8caa01..716e8369e3 100644 --- a/source/lib/sysdep/smbios.cpp +++ b/source/lib/sysdep/smbios.cpp @@ -200,11 +200,30 @@ void Fixup(Structure& UNUSED(structure)) // primary template: do nothing } +template<> +void Fixup(Bios& p) +{ + p.size = u64(p.encodedSize+1) * 64*KiB; +} + template<> void Fixup(Processor& p) { - // clear "populated" bit that interferes with the interpretation of ProcessorStatus - p.status = (ProcessorStatus)(p.status & ~0x40); + p.isPopulated = (p.status & 0x40) != 0; + p.status = (ProcessorStatus)bits((size_t)p.status, 0, 2); + + if(p.voltage & 0x80) + p.voltage &= ~0x80; + else + { + // (arbitrarily) report the lowest supported value + if(IsBitSet(p.voltage, 0)) + p.voltage = 50; + if(IsBitSet(p.voltage, 1)) + p.voltage = 33; + if(IsBitSet(p.voltage, 2)) + p.voltage = 29; + } } template<> @@ -229,7 +248,7 @@ template<> void Fixup(OnBoardDevices& p) { p.isEnabled = (p.type & 0x80) != 0; - p.type = (OnBoardDeviceType)(p.type & 0x7F); + p.type = (OnBoardDeviceType)(p.type & ~0x80); } template<> @@ -291,7 +310,7 @@ void Fixup(TemperatureProbe& p) //----------------------------------------------------------------------------- template -void InitStructure(Structure*& listHead, const Header* header, const Strings& strings) +void AddStructure(const Header* header, const Strings& strings, Structure*& listHead) { Structure* const p = (Structure*)calloc(1, sizeof(Structure)); // freed in Cleanup p->header = *header; @@ -334,8 +353,15 @@ static LibError InitStructures() const Header* header = (const Header*)&table[0]; const Header* const end = (const Header*)(&table[0] + table.size()); - while(header+1 <= end) + for(;;) { + if(header+1 > end) + { + debug_printf(L"SMBIOS: table not terminated\n"); + break; + } + if(header->id == 127) // end + break; if(header->length < sizeof(Header)) WARN_RETURN(ERR::_3); @@ -344,17 +370,12 @@ static LibError InitStructures() switch(header->id) { -#define STRUCTURE(name, id) case id: InitStructure(structures.name##_, header, strings); break; +#define STRUCTURE(name, id) case id: AddStructure(header, strings, structures.name##_); break; STRUCTURES #undef STRUCTURE - case 126: // inactive - break; - case 127: // end - return INFO::OK; - default: - if(32 < header->id && header->id < 128) // only mention non-proprietary structures of which we are not aware + if(32 < header->id && header->id < 126) // only mention non-proprietary structures of which we are not aware debug_printf(L"SMBIOS: unknown structure type %d\n", header->id); break; } @@ -362,7 +383,6 @@ static LibError InitStructures() header = next; } - debug_printf(L"SMBIOS: table not terminated\n"); return INFO::OK; } @@ -376,4 +396,85 @@ const Structures* GetStructures() return &structures; } + +//----------------------------------------------------------------------------- + +class FieldStringizer +{ + NONCOPYABLE(FieldStringizer); // reference member +public: + FieldStringizer(std::stringstream& ss) + : ss(ss) + { + } + + template + void operator()(size_t flags, T& t, const char* name, const char* units) + { + if(flags & F_INTERNAL) + return; + + ss << name << ": "; + if(flags & (F_HEX|F_FLAGS)) + ss << std::hex << std::uppercase; + else + ss << std::dec; + + if(flags & F_HANDLE) + { + if(u64(t) == 0xFFFE || u64(t) == 0xFFFF) + ss << "(N/A)"; + else + ss << t; + } + else if(flags & F_SIZE) + { + u64 value = (u64)t; + if(value > GiB) + ss << value/GiB << " GiB"; + else if(value > MiB) + ss << value/MiB << " MiB"; + else if(value > KiB) + ss << value/KiB << " KiB"; + else + ss << value << " bytes"; + } + else if(sizeof(t) == 1) + ss << (unsigned)t; + else + ss << t; + + ss << units << "\n"; + } + +private: + std::stringstream& ss; +}; + + +template +void StringizeStructure(const char* name, Structure* p, std::stringstream& ss) +{ + for(; p; p = p->next) + { + ss << "\n[" << name << "]\n"; + FieldStringizer fieldStringizer(ss); + VisitFields(*p, fieldStringizer); + } +} + + +std::string StringizeStructures(const Structures* structures) +{ + if(!structures) + return "(null)"; + + std::stringstream ss; +#define STRUCTURE(name, id) StringizeStructure(#name, structures->name##_, ss); + STRUCTURES +#undef STRUCTURE + + return ss.str(); +} + } // namespace SMBIOS diff --git a/source/lib/sysdep/smbios.h b/source/lib/sysdep/smbios.h index 3c0b08e88a..b81ea6b68e 100644 --- a/source/lib/sysdep/smbios.h +++ b/source/lib/sysdep/smbios.h @@ -76,11 +76,16 @@ enum FieldFlags // will display the enumerators) F_ENUM = 0x04, - // a collection of bit flags and should be displayed as such. + // a collection of bit flags. F_FLAGS = 0x08, // an SMBIOS Handle (allows nicer display of `unknown' handles). - F_HANDLE = 0x10 + F_HANDLE = 0x10, + + // a number that should be displayed in hexadecimal form. + F_HEX = 0x20, + + F_SIZE = 0x40 }; #if MSC_VERSION @@ -94,11 +99,12 @@ enum FieldFlags #define Bios_FIELDS\ FIELD(0, const char*, vendor, "")\ FIELD(0, const char*, version, "")\ - FIELD(0, u16, startSegment, "")\ + FIELD(F_HEX, u16, startSegment, "")\ FIELD(0, const char*, releaseDate, "")\ - FIELD(0, u8, size, " +1*64KB")\ - FIELD(0, u64, characteristics, "")\ - /* omit subsequent fields because we can't handle the variable-length characteristics extension */ + FIELD(F_INTERNAL, u8, encodedSize, "")\ + FIELD(F_HEX, u64, characteristics, "")\ + /* omit subsequent fields because we can't handle the variable-length characteristics extension */\ + FIELD(F_DERIVED|F_SIZE, u64, size, "") //----------------------------------------------------------------------------- @@ -119,8 +125,8 @@ enum SystemWakeUpType FIELD(0, const char*, productName, "")\ FIELD(0, const char*, version, "")\ FIELD(0, const char*, serialNumber, "")\ - FIELD(0, u64, uuid0, "")\ - FIELD(0, u64, uuid1, "")\ + FIELD(F_HEX, u64, uuid0, "")\ + FIELD(F_HEX, u64, uuid1, "")\ FIELD(F_ENUM, SystemWakeUpType, wakeUpType, "")\ FIELD(0, const char*, skuNumber, "")\ FIELD(0, const char*, family, "") @@ -228,7 +234,7 @@ enum ChassisSecurityStatus FIELD(F_ENUM, ChassisSecurityStatus, securityStatus, "")\ FIELD(0, u32, oemDefined, "")\ FIELD(0, u8, height, "U")\ - FIELD(0, u8, numPowerCords, "U")\ + FIELD(0, u8, numPowerCords, "")\ /* omit subsequent fields because we can't handle the variable-length contained objects */ @@ -299,13 +305,6 @@ enum ProcessorUpgrade PU_SOCKET_FM2 }; -enum ProcessorVoltage // bitfield -{ - PV_5 = 1, - PV_3_3 = 2, - PV_2_9 = 4 -}; - enum ProcessorCharacteristics // bitfield { PC_UNKNOWN = 0x2, @@ -322,12 +321,12 @@ enum ProcessorCharacteristics // bitfield FIELD(F_ENUM, ProcessorType, type, "")\ FIELD(0, u8, family, "") /* we don't bother providing enumerators for > 200 families */\ FIELD(0, const char*, manufacturer, "")\ - FIELD(0, u64, id, "")\ + FIELD(F_HEX, u64, id, "")\ FIELD(0, const char*, version, "")\ - FIELD(F_FLAGS, u8, voltage, "")\ - FIELD(0, u16, externalClockFrequency, " Mhz")\ - FIELD(0, u16, maxFrequency, " Mhz")\ - FIELD(0, u16, bootFrequency, " Mhz")\ + FIELD(0, u8, voltage, " dV")\ + FIELD(0, u16, externalClockFrequency, " MHz")\ + FIELD(0, u16, maxFrequency, " MHz")\ + FIELD(0, u16, bootFrequency, " MHz")\ FIELD(F_ENUM, ProcessorStatus, status, "")\ FIELD(F_ENUM, ProcessorUpgrade, upgrade, "")\ FIELD(F_HANDLE, Handle, hL1, "")\ @@ -340,7 +339,8 @@ enum ProcessorCharacteristics // bitfield FIELD(0, u8, enabledCores, "")\ FIELD(0, u8, logicalPerPackage, "")\ FIELD(F_FLAGS, u16, characteristics, "")\ - FIELD(0, u16, family2, "") + FIELD(0, u16, family2, "")\ + FIELD(F_DERIVED, u8, isPopulated, "") //----------------------------------------------------------------------------- @@ -424,8 +424,8 @@ enum CacheAssociativity FIELD(F_DERIVED, size_t, level, "") /* 1..8 */\ FIELD(F_DERIVED|F_ENUM, CacheLocation, location, "")\ FIELD(F_DERIVED|F_ENUM, CacheMode, mode, "")\ - FIELD(F_DERIVED, size_t, maxSize, " bytes")\ - FIELD(F_DERIVED, size_t, installedSize, " bytes") + FIELD(F_DERIVED|F_SIZE, size_t, maxSize, "")\ + FIELD(F_DERIVED|F_SIZE, size_t, installedSize, "") //----------------------------------------------------------------------------- @@ -685,7 +685,7 @@ enum MemoryArrayECC FIELD(F_INTERNAL, u32, maxCapacity32, "")\ FIELD(F_HANDLE, Handle, hError, "")\ FIELD(0, u16, numDevices, "")\ - FIELD(0, u64, maxCapacity, " bytes") + FIELD(F_SIZE, u64, maxCapacity, "") //----------------------------------------------------------------------------- @@ -770,7 +770,7 @@ enum MemoryDeviceTypeFlags FIELD(F_FLAGS, u8, attributes, "")\ FIELD(F_INTERNAL, u32, size32, "")\ FIELD(0, u16, configuredSpeed, " MHz")\ - FIELD(F_DERIVED, u64, size, " bytes") + FIELD(F_DERIVED|F_SIZE, u64, size, "") //----------------------------------------------------------------------------- @@ -781,8 +781,8 @@ enum MemoryDeviceTypeFlags FIELD(F_INTERNAL, u32, endAddress32, " bits")\ FIELD(F_HANDLE, Handle, hMemoryArray, "")\ FIELD(0, u8, partitionWidth, "")\ - FIELD(0, u64, startAddress, "")\ - FIELD(0, u64, endAddress, "")\ + FIELD(F_HEX, u64, startAddress, "")\ + FIELD(F_HEX, u64, endAddress, "")\ //----------------------------------------------------------------------------- @@ -796,8 +796,8 @@ enum MemoryDeviceTypeFlags FIELD(0, u8, partitionRowPosition, "")\ FIELD(0, u8, interleavePosition, "")\ FIELD(0, u8, interleavedDataDepth, "")\ - FIELD(0, u64, startAddress, "")\ - FIELD(0, u64, endAddress, "")\ + FIELD(F_HEX, u64, startAddress, "")\ + FIELD(F_HEX, u64, endAddress, "")\ //---------------------------------------------------------------------------- @@ -864,7 +864,7 @@ enum VoltageProbeLocation FIELD(0, u16, tolerance, " mV")\ FIELD(0, u16, accuracy, " x 100 ppm")\ FIELD(0, u32, oemDefined, "")\ - FIELD(0, u16, nominalValue, " dDegC")\ + FIELD(0, u16, nominalValue, " mv")\ FIELD(F_DERIVED, VoltageProbeLocation, location, "")\ FIELD(F_DERIVED, Status, status, "") @@ -919,13 +919,13 @@ enum TemperatureProbeLocation #define TemperatureProbe_FIELDS\ FIELD(0, const char*, description, "")\ FIELD(F_INTERNAL, u8, locationAndStatus, "")\ - FIELD(0, u16, maxValue, " dDegC")\ - FIELD(0, u16, minValue, " dDegC")\ + FIELD(0, i16, maxValue, " dDegC")\ + FIELD(0, i16, minValue, " dDegC")\ FIELD(0, u16, resolution, " mDegC")\ FIELD(0, u16, tolerance, " dDegC")\ FIELD(0, u16, accuracy, " x 100 ppm")\ FIELD(0, u32, oemDefined, "")\ - FIELD(0, u16, nominalValue, " dDegC")\ + FIELD(0, i16, nominalValue, " dDegC")\ FIELD(F_DERIVED, TemperatureProbeLocation, location, "")\ FIELD(F_DERIVED, Status, status, "") @@ -989,6 +989,7 @@ STRUCTURES #undef FIELD LIB_API const Structures* GetStructures(); +LIB_API std::string StringizeStructures(const Structures*); } // namespace SMBIOS