(requires update-workspaces)

add initial SMBIOS implementation for retrieving system information
wacpi -> wfirmware (now also used to retrieve SMBIOS table)

This was SVN commit r9144.
This commit is contained in:
janwas 2011-04-03 15:38:48 +00:00
parent 1a072a3f37
commit 2c72e1f364
7 changed files with 1169 additions and 59 deletions

View File

@ -23,6 +23,7 @@
#include "precompiled.h"
#include "lib/sysdep/acpi.h"
#include "lib/byte_order.h"
#include "lib/sysdep/cpu.h"
#include "lib/module_init.h"
@ -30,7 +31,7 @@
#if ENABLE_MAHAF
# include "lib/sysdep/os/win/mahaf.h"
#else
# include "lib/sysdep/os/win/wacpi.h"
# include "lib/sysdep/os/win/wfirmware.h"
#endif
#pragma pack(1)
@ -307,14 +308,15 @@ static void AllocateAndCopyTables(const AcpiTable**& tables, size_t& numTables)
DeallocateTable(rsdt);
#else
const std::vector<u32> tableIDs = wacpi_TableIDs();
const wfirmware::Provider provider = FOURCC_BE('A','C','P','I');
const wfirmware::TableIds tableIDs = wfirmware::GetTableIDs(provider);
numTables = tableIDs.size();
tables = new const AcpiTable*[numTables];
for(size_t i = 0; i < numTables; i++)
{
std::vector<u8> table = wacpi_GetTable(tableIDs[i]);
wfirmware::Table table = wfirmware::GetTable(provider, tableIDs[i]);
debug_assert(!table.empty());
tables[i] = AllocateTable(table.size());
memcpy((void*)tables[i], &table[0], table.size());

View File

@ -1,48 +0,0 @@
#include "precompiled.h"
#include "lib/sysdep/os/win/wacpi.h"
#include "lib/byte_order.h"
#include "lib/sysdep/os/win/wutil.h"
static const DWORD provider = FOURCC_BE('A','C','P','I');
std::vector<u32> wacpi_TableIDs()
{
std::vector<u32> tableIDs;
WUTIL_FUNC(pEnumSystemFirmwareTables, UINT, (DWORD, PVOID, DWORD));
WUTIL_IMPORT_KERNEL32(EnumSystemFirmwareTables, pEnumSystemFirmwareTables);
if(!pEnumSystemFirmwareTables)
return tableIDs; // empty list
const UINT bufSize = pEnumSystemFirmwareTables(provider, 0, 0);
debug_assert(bufSize != 0);
debug_assert(bufSize % sizeof(DWORD) == 0);
tableIDs.resize(DivideRoundUp((size_t)bufSize, sizeof(DWORD)));
const UINT ret = pEnumSystemFirmwareTables(provider, &tableIDs[0], bufSize);
debug_assert(ret == bufSize);
return tableIDs;
}
std::vector<u8> wacpi_GetTable(u32 id)
{
std::vector<u8> table;
WUTIL_FUNC(pGetSystemFirmwareTable, UINT, (DWORD, DWORD, PVOID, DWORD));
WUTIL_IMPORT_KERNEL32(GetSystemFirmwareTable, pGetSystemFirmwareTable);
if(!pGetSystemFirmwareTable)
return table; // empty table
const UINT bufSize = pGetSystemFirmwareTable(provider, id, 0, 0);
debug_assert(bufSize != 0);
table.resize(bufSize);
const UINT ret = pGetSystemFirmwareTable(provider, id, &table[0], bufSize);
debug_assert(ret == bufSize);
return table;
}

View File

@ -1,8 +0,0 @@
#ifndef INCLUDED_WACPI
#define INCLUDED_WACPI
extern std::vector<u32> wacpi_TableIDs();
extern std::vector<u8> wacpi_GetTable(u32 id);
#endif // #ifndef INCLUDED_WACPI

View File

@ -0,0 +1,48 @@
#include "precompiled.h"
#include "lib/sysdep/os/win/wfirmware.h"
#include "lib/sysdep/os/win/wutil.h"
namespace wfirmware {
TableIds GetTableIDs(Provider provider)
{
WUTIL_FUNC(pEnumSystemFirmwareTables, UINT, (DWORD, PVOID, DWORD));
WUTIL_IMPORT_KERNEL32(EnumSystemFirmwareTables, pEnumSystemFirmwareTables);
if(!pEnumSystemFirmwareTables)
return TableIds();
const size_t tableIdsSize = pEnumSystemFirmwareTables(provider, 0, 0);
debug_assert(tableIdsSize != 0);
debug_assert(tableIdsSize % sizeof(TableId) == 0);
TableIds tableIDs(DivideRoundUp(tableIdsSize, sizeof(TableId)), 0);
const size_t bytesWritten = pEnumSystemFirmwareTables(provider, &tableIDs[0], tableIdsSize);
debug_assert(bytesWritten == tableIdsSize);
return tableIDs;
}
Table GetTable(Provider provider, TableId tableId)
{
WUTIL_FUNC(pGetSystemFirmwareTable, UINT, (DWORD, DWORD, PVOID, DWORD));
WUTIL_IMPORT_KERNEL32(GetSystemFirmwareTable, pGetSystemFirmwareTable);
if(!pGetSystemFirmwareTable)
return Table();
const size_t tableSize = pGetSystemFirmwareTable(provider, tableId, 0, 0);
if(tableSize == 0)
{
debug_assert(0);
return Table();
}
Table table(tableSize, 0);
const size_t bytesWritten = pGetSystemFirmwareTable(provider, tableId, &table[0], tableSize);
debug_assert(bytesWritten == tableSize);
return table;
}
} // namespace wfirmware

View File

@ -0,0 +1,19 @@
#ifndef INCLUDED_WFIRMWARE
#define INCLUDED_WFIRMWARE
namespace wfirmware {
typedef u32 Provider;
typedef u32 TableId;
typedef std::vector<TableId> TableIds;
extern TableIds GetTableIDs(Provider provider);
typedef std::vector<u8> Table;
extern Table GetTable(Provider provider, TableId tableId);
} // namespace wfirmware
#endif // #ifndef INCLUDED_WFIRMWARE

View File

@ -0,0 +1,352 @@
/* Copyright (c) 2011 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "precompiled.h"
#include "smbios.h"
#include "lib/bits.h"
#include "lib/byte_order.h"
#include "lib/module_init.h"
#if OS_WIN
# include "lib/sysdep/os/win/wutil.h"
# include "lib/sysdep/os/win/wfirmware.h"
#endif
namespace SMBIOS {
//-----------------------------------------------------------------------------
#if OS_WIN
static LibError GetTable(wfirmware::Table& table)
{
// (MSDN mentions 'RSMB', but multi-character literals are implementation-defined.)
const DWORD provider = FOURCC_BE('R','S','M','B');
// (MSDN says this will be 0, but we'll retrieve it for 100% correctness.)
wfirmware::TableIds tableIds = wfirmware::GetTableIDs(provider);
if(tableIds.empty())
WARN_RETURN(ERR::_1);
table = wfirmware::GetTable(provider, tableIds[0]);
if(table.empty())
WARN_RETURN(ERR::_2);
// strip the WmiHeader
struct WmiHeader
{
u8 used20CallingMethod;
u8 majorVersion;
u8 minorVersion;
u8 dmiRevision;
u32 length;
};
const WmiHeader* wmiHeader = (const WmiHeader*)&table[0];
debug_assert(table.size() == sizeof(WmiHeader) + wmiHeader->length);
memmove(&table[0], &table[sizeof(WmiHeader)], sizeof(WmiHeader));
return INFO::OK;
}
#endif // OS_WIN
// pointers to the strings (if any) at the end of an SMBIOS structure
typedef std::vector<const char*> Strings;
static Strings ExtractStrings(const Header* header, const char* end, const Header*& next)
{
Strings strings;
const char* pos = ((const char*)header) + header->length;
while(pos <= end-2)
{
if(*pos == '\0')
{
pos++;
if(*pos == 0)
{
pos++;
break;
}
}
strings.push_back(pos);
pos += strlen(pos);
}
next = (const Header*)pos;
return strings;
}
// storage for all structures' strings
static char* stringStorage;
static char* stringStoragePos;
// pointers to dynamically allocated structures
static Structures structures;
static void Cleanup()
{
SAFE_FREE(stringStorage);
stringStoragePos = 0;
// free each allocated structure
#define STRUCTURE(name, id) SAFE_FREE(structures.name##_);
STRUCTURES
#undef STRUCTURE
}
// initialize each of a structure's fields by copying from the SMBIOS data
class FieldInitializer
{
NONCOPYABLE(FieldInitializer); // reference member
public:
FieldInitializer(const Header* header, const Strings& strings)
: data((const u8*)(header+1))
, end(data + header->length)
, strings(strings)
{
}
template<typename T>
void operator()(size_t flags, T& t, const char* UNUSED(name), const char* UNUSED(units))
{
if((flags & F_DERIVED) || data >= end)
{
t = (T)0;
return;
}
if(flags & F_ENUM)
t = (T)*data++;
else
{
memcpy(&t, data, sizeof(t));
data += sizeof(t);
}
}
template<>
void operator()<const char*>(size_t flags, const char*& t, const char* UNUSED(name), const char* UNUSED(units))
{
u8 number;
operator()(flags, number, 0, 0);
if(number == 0)
{
t = "(unspecified)";
return;
}
if(number > strings.size())
{
debug_printf(L"SMBIOS: invalid string number %d (count=%d)\n", number, strings.size());
t = "(unknown)";
return;
}
if(strings[number-1] == 0)
{
t = "(null)";
return;
}
// copy to stringStorage
strcpy(stringStoragePos, strings[number-1]);
t = stringStoragePos;
stringStoragePos += strlen(t)+1;
}
private:
const u8* data;
const u8* end;
const Strings& strings;
};
//-----------------------------------------------------------------------------
// Fixup (e.g. compute derived fields)
template<class Structure>
void Fixup(Structure& UNUSED(structure))
{
// primary template: do nothing
}
template<>
void Fixup<Processor>(Processor& p)
{
// clear "populated" bit that interferes with the interpretation of ProcessorStatus
p.status = (ProcessorStatus)(p.status & ~0x40);
}
template<>
void Fixup<Cache>(Cache& p)
{
struct DecodeSize
{
size_t operator()(u16 size) const
{
const size_t granularity = IsBitSet(size, 15)? 64*KiB : 1*KiB;
return size_t(bits(size, 0, 14)) * granularity;
}
};
p.maxSize = DecodeSize()(p.maxSize16);
p.installedSize = DecodeSize()(p.installedSize16);
p.level = bits(p.configuration, 0, 2)+1;
p.location = (CacheLocation)bits(p.configuration, 5, 6);
p.mode = (CacheMode)bits(p.configuration, 8, 9);
}
template<>
void Fixup<MemoryArray>(MemoryArray& p)
{
if(p.maxCapacity32 != (u32)INT32_MIN)
p.maxCapacity = u64(p.maxCapacity32) * KiB;
}
template<>
void Fixup<MemoryDevice>(MemoryDevice& p)
{
if(p.size16 != INT16_MAX)
p.size = u64(bits(p.size16, 0, 14)) * (IsBitSet(p.size16, 15)? 1*KiB : 1*MiB);
else
p.size = u64(bits(p.size32, 0, 30)) * MiB;
}
template<>
void Fixup<MemoryArrayMappedAddress>(MemoryArrayMappedAddress& p)
{
if(p.startAddress32 != UINT32_MAX)
p.startAddress = u64(p.startAddress32) * KiB;
if(p.endAddress32 != UINT32_MAX)
p.endAddress = u64(p.endAddress32) * KiB;
}
template<>
void Fixup<MemoryDeviceMappedAddress>(MemoryDeviceMappedAddress& p)
{
if(p.startAddress32 != UINT32_MAX)
p.startAddress = u64(p.startAddress32) * KiB;
if(p.endAddress32 != UINT32_MAX)
p.endAddress = u64(p.endAddress32) * KiB;
}
//-----------------------------------------------------------------------------
template<class Structure>
void InitStructure(Structure*& listHead, const Header* header, const Strings& strings)
{
Structure* const p = (Structure*)calloc(1, sizeof(Structure)); // freed in Cleanup
p->header = *header;
if(listHead)
{
// insert at end of list to preserve order of caches/slots
Structure* last = listHead;
while(last->next)
last = last->next;
last->next = p;
}
else
listHead = p;
FieldInitializer fieldInitializer(header, strings);
VisitFields(*p, fieldInitializer);
Fixup(*p);
}
static LibError InitStructures()
{
#if OS_WIN
wfirmware::Table table;
RETURN_ERR(GetTable(table));
#else
std::vector<u8> table;
return ERR::NOT_IMPLEMENTED;
#endif
// workaround for stupid AMIBIOS that repeats the first 8 bytes
if(memcmp(&table[0], &table[8], 8) == 0)
{
memmove(&table[8], &table[16], 8);
table[1] += 8; // the first length field is 8 bytes short, too
}
// (instead of counting the total string size, just use the
// SMBIOS size - typically 1-2 KB - as an upper bound.)
stringStoragePos = stringStorage = (char*)calloc(table.size(), sizeof(char)); // freed in Cleanup
if(!stringStorage)
WARN_RETURN(ERR::NO_MEM);
atexit(Cleanup);
const Header* header = (const Header*)&table[0];
const Header* const end = (const Header*)(&table[0] + table.size());
while(header+1 <= end)
{
if(header->length < sizeof(Header))
WARN_RETURN(ERR::_3);
const Header* next;
const Strings strings = ExtractStrings(header, (const char*)end, next);
switch(header->id)
{
#define STRUCTURE(name, id) case id: InitStructure(structures.name##_, header, strings); break;
STRUCTURES
#undef STRUCTURE
case 126: // inactive
break;
case 127: // end
return INFO::OK;
default:
debug_printf(L"SMBIOS: unknown structure type %d\n", header->id);
break;
}
header = next;
}
debug_printf(L"SMBIOS: table not terminated\n");
return INFO::OK;
}
const Structures* GetStructures()
{
static ModuleInitState initState;
LibError ret = ModuleInit(&initState, InitStructures);
if(ret != INFO::OK)
return 0;
return &structures;
}
} // namespace SMBIOS

745
source/lib/sysdep/smbios.h Normal file
View File

@ -0,0 +1,745 @@
/* Copyright (c) 2011 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef INCLUDED_SMBIOS
#define INCLUDED_SMBIOS
namespace SMBIOS {
// to introduce another structure:
// 1) add its name and ID here
// 2) add a <name>_FIELDS macro defining its fields
// 3) (optional) add a specialization of Fixup
#define STRUCTURES\
STRUCTURE(Bios, 0)\
STRUCTURE(System, 1)\
STRUCTURE(Baseboard, 2)\
STRUCTURE(Chassis, 3)\
STRUCTURE(Processor, 4)\
/* MemoryController (5) and MemoryModule (6) are obsolete */\
STRUCTURE(Cache, 7)\
/* PortConnector (8) is optional */\
STRUCTURE(SystemSlot, 9)\
/* OnBoardDevices (10) is obsolete */\
/* OemStrings (11), SystemConfiguration (12), BiosLanguage (13), GroupAssociations (14), SystemEventLog (15) are optional */\
STRUCTURE(MemoryArray, 16)\
STRUCTURE(MemoryDevice, 17)\
/* MemoryError32 (18) is optional */\
STRUCTURE(MemoryArrayMappedAddress, 19)\
STRUCTURE(MemoryDeviceMappedAddress, 20)\
/* PointingDevice (21), PortableBattery (22), SystemReset (23), HardwareSecurity (24) are optional */\
/* SystemPowerControls (25), VoltageProbe (26), CoolingDevice (27), TemperatureProbe (28) are optional */\
/* ElectricalCurrentProbe (29), OutOfBandRemoteAccess (30), BootIntegrityServices (31) are optional */\
STRUCTURE(SystemBoot, 32)
/* MemoryError64 (33), ManagementDevice (34), ManagementDeviceComponent (35), ManagementDeviceThreshold (36) are optional */\
/* MemoryChannel (37), IpmiDevice (38), SystemPowerSupply (39), Additional (40), OnboardDevices2 (41) are optional */\
/* ManagementControllerHostInterface (42) is optional */
typedef u16 Handle;
// indicates a field (:= member of a structure) is:
enum FieldFlags
{
// computed via other fields (i.e. should not be copied from the SMBIOS data).
F_DERIVED = 0x01,
// not intended for use by applications (usually because it is
// superseded by another - possibly derived - field).
F_INTERNAL = 0x02,
// an enum type; we'll read an SMBIOS byte and cast it to this type.
// (could also be detected via is_enum, but that requires TR1/C++0x)
// (using enum member variables instead of the raw u8 means the debugger
// will display the enumerators)
F_ENUM = 0x04,
// a collection of bit flags and should be displayed as such.
F_FLAGS = 0x08,
// an SMBIOS Handle (allows nicer display of `unknown' handles).
F_HANDLE = 0x10
};
#if MSC_VERSION
# pragma pack(push, 1)
#endif
//-----------------------------------------------------------------------------
// Bios
#define Bios_FIELDS\
FIELD(0, const char*, vendor, "")\
FIELD(0, const char*, version, "")\
FIELD(0, 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 */
//-----------------------------------------------------------------------------
// System
enum SystemWakeUpType
{
SWT_APM_TIMER = 3,
SWT_MODEM_RING,
SWT_LAN_REMOTE,
SWT_POWER_SWITCH,
SWT_PCI_PME,
SWT_AC_POWER_RESTORED
};
#define System_FIELDS\
FIELD(0, const char*, manufacturer, "")\
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_ENUM, SystemWakeUpType, wakeUpType, "")\
FIELD(0, const char*, skuNumber, "")\
FIELD(0, const char*, family, "")
//-----------------------------------------------------------------------------
// Baseboard
enum BaseboardFlags
{
BB_IS_MOTHERBOARD = 0x01,
BB_REQUIRES_DAUGHTER = 0x02,
BB_IS_REMOVEABLE = 0x04,
BB_IS_REPLACEABLE = 0x08,
BB_IS_HOT_SWAPPABLE = 0x10
};
enum BaseboardType
{
BB_BLADE = 3,
BB_SWITCH,
BB_SYSTEM_MANAGEMENT,
BB_PROCESSOR,
BB_IO,
BB_MEMORY,
BB_DAUGHTER,
BB_MOTHERBOARD,
BB_PROCESSOR_MEMORY,
BB_PROCESSOR_IO,
BB_INTERCONNECT,
};
#define Baseboard_FIELDS\
FIELD(0, const char*, manufacturer, "")\
FIELD(0, const char*, product, "")\
FIELD(0, const char*, version, "")\
FIELD(0, const char*, serialNumber, "")\
FIELD(0, const char*, assetTag, "")\
FIELD(F_FLAGS, u8, flags, "")\
FIELD(0, const char*, location, "")\
FIELD(F_HANDLE, Handle, hChassis, "")\
FIELD(F_ENUM, BaseboardType, type, "")\
/* omit subsequent fields because we can't handle the variable-length contained objects */
//-----------------------------------------------------------------------------
// Chassis
enum ChassisType
{
CT_DESKTOP = 3,
CT_LOW_PROFILE_DESKTOP,
CT_PIZZA_BOX,
CT_MINI_TOWER,
CT_TOWER,
CT_PORTABLE,
CT_LAPTOP,
CT_NOTEBOOK,
CT_HANDHELD,
CT_DOCKING_STATION,
CT_ALL_IN_ONE,
CT_SUBNOTEBOOK,
CT_SPACE_SAVING,
CT_LUNCHBOX,
CT_MAIN_SERVER,
CT_EXPANSION,
CT_SUB,
CT_BUS_EXPANSION,
CT_PERIPHERAL,
CT_RAID,
CT_RACK_MOUNT,
CT_SEALED_CASE,
CT_MULTI_SYSTEM,
CT_COMPACT_PCI,
CT_ADVANCED_TCA,
CT_BLADE,
CT_BLADE_ENCLOSURE
};
enum ChassisState
{
CS_SAFE = 3,
CS_WARNING,
CS_CRITICAL,
CS_NON_RECOVERABLE
};
enum ChassisSecurityStatus
{
CSS_NONE = 3,
CSS_EXTERNAL_INTERFACE_LOCKED,
CSS_EXTERNAL_INTERFACE_ENABLED
};
#define Chassis_FIELDS\
FIELD(0, const char*, manufacturer, "")\
FIELD(F_ENUM, ChassisType, type, "")\
FIELD(0, const char*, version, "")\
FIELD(0, const char*, serialNumber, "")\
FIELD(0, const char*, assetTag, "")\
FIELD(F_ENUM, ChassisState, state, "")\
FIELD(F_ENUM, ChassisState, powerState, "")\
FIELD(F_ENUM, ChassisState, thermalState, "")\
FIELD(F_ENUM, ChassisSecurityStatus, securityStatus, "")\
FIELD(0, u32, oemDefined, "")\
FIELD(0, u8, height, "U")\
FIELD(0, u8, numPowerCords, "U")\
/* omit subsequent fields because we can't handle the variable-length contained objects */
//-----------------------------------------------------------------------------
// Processor
enum ProcessorType
{
PT_CENTRAL = 3,
PT_MATH,
PT_DSP,
PT_VIDEO
};
enum ProcessorStatus
{
PS_UNKNOWN = 0,
PS_ENABLED,
PS_USER_DISABLED,
PS_POST_DISABLED,
PS_CPU_IDLE,
PS_OTHER = 7,
// NB: we mask off 0x40 ("populated") for convenience
};
enum ProcessorUpgrade
{
PU_DAUGHTER = 3,
PU_ZIF,
PU_PIGGYBACK,
PU_NONE,
PU_LIF,
PU_SLOT_1,
PU_SLOT_2,
PU_SOCKET_370,
PU_SLOT_A,
PU_SLOT_M,
PU_SOCKET_423,
PU_SOCKET_A,
PU_SOCKET_478,
PU_SOCKET_754,
PU_SOCKET_940,
PU_SOCKET_939,
PU_SOCKET_604,
PU_SOCKET_771,
PU_SOCKET_775,
PU_SOCKET_S1,
PU_SOCKET_AM2,
PU_SOCKET_1207,
PU_SOCKET_1366,
PU_SOCKET_G34,
PU_SOCKET_AM3,
PU_SOCKET_C32,
PU_SOCKET_1156,
PU_SOCKET_1567,
PU_SOCKET_988A,
PU_SOCKET_1288,
PU_SOCKET_988B,
PU_SOCKET_1023,
PU_SOCKET_1224,
PU_SOCKET_1155,
PU_SOCKET_1356,
PU_SOCKET_2011,
PU_SOCKET_FS1,
PU_SOCKET_FS2,
PU_SOCKET_FM1,
PU_SOCKET_FM2
};
enum ProcessorVoltage // bitfield
{
PV_5 = 1,
PV_3_3 = 2,
PV_2_9 = 4
};
enum ProcessorCharacteristics // bitfield
{
PC_UNKNOWN = 0x2,
PC_64_BIT = 0x4,
PC_MULTI_CORE = 0x8, // (indicates cores are present; they might be disabled)
PC_HARDWARE_THREAD = 0x10,
PC_EXECUTE_PROTECTION = 0x20,
PC_ENHANCED_VIRTUALIZATION = 0x40,
PC_POWER_CONTROL = 0x80
};
#define Processor_FIELDS\
FIELD(0, const char*, socket, "")\
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(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(F_ENUM, ProcessorStatus, status, "")\
FIELD(F_ENUM, ProcessorUpgrade, upgrade, "")\
FIELD(F_HANDLE, Handle, hL1, "")\
FIELD(F_HANDLE, Handle, hL2, "")\
FIELD(F_HANDLE, Handle, hL3, "")\
FIELD(0, const char*, serialNumber, "")\
FIELD(0, const char*, assetTag, "")\
FIELD(0, const char*, partNumber, "")\
FIELD(0, u8, coresPerPackage, "")\
FIELD(0, u8, enabledCores, "")\
FIELD(0, u8, logicalPerPackage, "")\
FIELD(F_FLAGS, u16, characteristics, "")\
FIELD(0, u16, family2, "")
//-----------------------------------------------------------------------------
// Cache
enum CacheMode
{
CM_WRITE_THROUGH = 0,
CM_WRITE_BACK,
CM_VARIES,
CM_UNKNOWN
};
enum CacheLocation
{
CL_INTERNAL = 0,
CL_EXTERNAL,
CL_RESERVED,
CL_UNKNOWN
};
enum CacheConfiguration
{
CC_SOCKETED = 0x08,
CC_ENABLED = 0x80
};
enum CacheFlags
{
CF_OTHER = 0x01,
CF_UNKNOWN = 0x02,
CF_NON_BURST = 0x04,
CF_BURST = 0x08,
CF_PIPELINE_BURST = 0x10,
CF_SYNCHRONOUS = 0x20,
CF_ASYNCHRONOUS = 0x40
};
enum CacheECC
{
CE_NONE = 3,
CE_PARITY,
CE_SINGLE_BIT,
CE_MULTIPLE_BIT
};
enum CacheType
{
CT_INSTRUCTION = 3,
CT_DATA,
CT_UNIFIED
};
enum CacheAssociativity
{
CA_DIRECT_MAPPED = 3,
CA_2,
CA_4,
CA_FULL,
CA_8,
CA_16,
CA_12,
CA_24,
CA_32,
CA_48,
CA_64,
CA_20
};
#define Cache_FIELDS\
FIELD(0, const char*, designation, "")\
FIELD(F_FLAGS, u16, configuration, "")\
FIELD(F_INTERNAL, u16, maxSize16, "")\
FIELD(F_INTERNAL, u16, installedSize16, "")\
FIELD(F_FLAGS, u16, supportedFlags, "")\
FIELD(F_FLAGS, u16, currentFlags, "")\
FIELD(0, u8, speed, " ns")\
FIELD(F_ENUM, CacheECC, ecc, "")\
FIELD(F_ENUM, CacheType, type, "")\
FIELD(F_ENUM, CacheAssociativity, associativity, "")\
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")
//-----------------------------------------------------------------------------
// SystemSlot
enum SystemSlotType
{
ST_ISA = 3,
ST_MCA,
ST_EISA,
ST_PCI,
ST_PCMCIA,
ST_VESA,
ST_PROPRIETARY,
ST_PROCESSOR,
ST_MEMORY_CARD,
ST_IO_RISER,
ST_NUBUS,
ST_PCI_66,
ST_AGP,
ST_AGP_2X,
ST_AGP_4X,
ST_PCIX,
ST_AGP_8X,
// (PC98 omitted)
ST_PCIE = 0xA5,
ST_PCIE_X1,
ST_PCIE_X2,
ST_PCIE_X4,
ST_PCIE_X8,
ST_PCIE_X16,
ST_PCIE2,
ST_PCIE2_X1,
ST_PCIE2_X2,
ST_PCIE2_X4,
ST_PCIE2_X8,
ST_PCIE2_X16,
ST_PCIE3,
ST_PCIE3_X1,
ST_PCIE3_X2,
ST_PCIE3_X4,
ST_PCIE3_X8,
ST_PCIE3_X16
};
enum SystemSlotBusWidth
{
SBW_8 = 3,
SBW_16,
SBW_32,
SBW_64,
SBW_128,
SBW_1X,
SBW_2X,
SBW_4X,
SBW_8X,
SBW_12X,
SBW_16X,
SBW_32X,
};
enum SystemSlotUsage
{
SU_AVAILABLE = 3,
SU_IN_USE
};
enum SystemSlotLength
{
SL_SHORT = 3,
SL_LONG
};
enum SystemSlotCharacteristics
{
SC_UNKNOWN = 1,
SC_5_VOLT = 2,
SC_3_3_VOLT = 4,
SC_IS_SHARED = 8
// unused "PC card" bits omitted
};
enum SystemSlotCharacteristics2
{
SC2_SUPPORTS_PME = 1,
SC2_SUPPORTS_HOT_PLUG = 2,
SC2_SUPPORTS_SMBUS = 4
};
#define SystemSlot_FIELDS\
FIELD(0, const char*, designation, "")\
FIELD(F_ENUM, SystemSlotType, type, "")\
FIELD(F_ENUM, SystemSlotBusWidth, busWidth, "")\
FIELD(F_ENUM, SystemSlotUsage, usage, "")\
FIELD(F_ENUM, SystemSlotLength, length, "")\
FIELD(0, u16, id, "")\
FIELD(F_FLAGS, u8, characteristics, "")\
FIELD(F_FLAGS, u8, characteristics2, "")\
FIELD(0, u8, busNumber, "")\
FIELD(0, u8, deviceAndFunctionNumbers, "")
//-----------------------------------------------------------------------------
// MemoryArray
enum MemoryArrayLocation
{
ML_MOTHERBOARD = 3,
ML_ISA_ADDON,
ML_EISA_ADDON,
ML_PCI_ADDON,
ML_MCA_ADDON,
ML_PCMCIA_ADDON,
ML_PROPRIETARY_ADDON,
ML_NUBUS
// (PC98 omitted)
};
enum MemoryArrayUse
{
MU_SYSTEM = 3,
MU_VIDEO,
MU_FLASH,
MU_NVRAM,
MU_CACHE
};
enum MemoryArrayECC
{
ME_NONE = 3,
ME_PARITY,
ME_SINGLE_BIT,
ME_MULTIPLE_BIT,
ME_CRC
};
#define MemoryArray_FIELDS\
FIELD(F_ENUM, MemoryArrayLocation, location, "")\
FIELD(F_ENUM, MemoryArrayUse, use, "")\
FIELD(F_ENUM, MemoryArrayECC, ecc, "")\
FIELD(F_INTERNAL, u32, maxCapacity32, "")\
FIELD(F_HANDLE, Handle, hError, "")\
FIELD(0, u16, numDevices, "")\
FIELD(0, u64, maxCapacity, " bytes")
//-----------------------------------------------------------------------------
// MemoryDevice
enum MemoryDeviceFormFactor
{
MF_SIMM = 3,
MF_SIP,
MF_CHIP,
MF_DIP,
MF_ZIP,
MF_PROPRIETARY_CARD,
MF_DIMM,
MF_TSOP,
MF_ROW_OF_CHIPS,
MF_RIMM,
MF_SODIMM,
MF_SRIMM,
MF_FBDIMM
};
enum MemoryDeviceType
{
MT_DRAM = 3,
MT_EDRAM,
MT_VRAM,
MT_SRAM,
MT_RAM,
MT_ROM,
MT_FLASH,
MT_EEPROM,
MT_FEPROM,
MT_EPROM,
MT_CRRAM,
MT_3DRAM,
MT_SDRAM,
MT_SGRAM,
MT_RDRAM,
MT_DDR,
MT_DDR2,
MT_DDR2_FBDIMM,
MT_DDR3 = 0x18,
MT_FBD2
};
enum MemoryDeviceTypeFlags
{
MTF_OTHER = 0x0002,
MTF_UNKNOWN = 0x0004,
MTF_FAST_PAGED = 0x0008,
MTF_STATIC_COLUMN = 0x0010,
MTF_PSEUDO_STATIC = 0x0020,
MTF_RAMBUS = 0x0040,
MTF_SYNCHRONOUS = 0x0080,
MTF_CMOS = 0x0100,
MTF_EDO = 0x0200,
MTF_WINDOW_DRAM = 0x0400,
MTF_CACHE_DRAM = 0x0800,
MTF_NON_VOLATILE = 0x1000,
MTF_BUFFERED = 0x2000,
MTF_UNBUFFERED = 0x4000,
};
#define MemoryDevice_FIELDS\
FIELD(F_HANDLE, Handle, hMemoryArray, "")\
FIELD(F_HANDLE, Handle, hError, "")\
FIELD(0, u16, totalWidth, " bits")\
FIELD(0, u16, dataWidth, " bits")\
FIELD(F_INTERNAL, u16, size16, "")\
FIELD(F_ENUM, MemoryDeviceFormFactor, formFactor, "")\
FIELD(0, u8, deviceSet, "")\
FIELD(0, const char*, locator, "")\
FIELD(0, const char*, bank, "")\
FIELD(F_ENUM, MemoryDeviceType, type, "")\
FIELD(F_FLAGS, u16, typeFlags, "")\
FIELD(0, u16, speed, " MHz")\
FIELD(0, const char*, manufacturer, "")\
FIELD(0, const char*, serialNumber, "")\
FIELD(0, const char*, assetTag, "")\
FIELD(0, const char*, partNumber, "")\
FIELD(F_FLAGS, u8, attributes, "")\
FIELD(F_INTERNAL, u32, size32, "")\
FIELD(0, u16, configuredSpeed, " MHz")\
FIELD(F_DERIVED, u64, size, " bytes")
//-----------------------------------------------------------------------------
// MemoryArrayMappedAddress
#define MemoryArrayMappedAddress_FIELDS\
FIELD(F_INTERNAL, u32, startAddress32, " bits")\
FIELD(F_INTERNAL, u32, endAddress32, " bits")\
FIELD(F_HANDLE, Handle, hMemoryArray, "")\
FIELD(0, u8, partitionWidth, "")\
FIELD(0, u64, startAddress, "")\
FIELD(0, u64, endAddress, "")\
//-----------------------------------------------------------------------------
// MemoryDeviceMappedAddress
#define MemoryDeviceMappedAddress_FIELDS\
FIELD(F_INTERNAL, u32, startAddress32, " bits")\
FIELD(F_INTERNAL, u32, endAddress32, " bits")\
FIELD(F_HANDLE, Handle, hMemoryDevice, "")\
FIELD(F_HANDLE, Handle, hMemoryArrayMappedAddress, "")\
FIELD(0, u8, partitionRowPosition, "")\
FIELD(0, u8, interleavePosition, "")\
FIELD(0, u8, interleavedDataDepth, "")\
FIELD(0, u64, startAddress, "")\
FIELD(0, u64, endAddress, "")\
//-----------------------------------------------------------------------------
// SystemBoot
enum SystemBootStatus
{
SBS_NO_ERROR = 0,
SBS_NO_BOOTABLE_MEDIA,
SBS_OS_LOAD_FAILED,
SBS_HARDWARE_FAILURE_FIRMWARE,
SBS_HARDWARE_FAILURE_OS,
SBS_USER_REQUESTED_BOOT,
SBS_SECURITY_VIOLATION,
SBS_PREVIOUSLY_REQUESTED_IMAGE,
SBS_WATCHDOG_EXPIRED
};
#define SystemBoot_FIELDS\
FIELD(F_INTERNAL, u32, reserved32, "")\
FIELD(F_INTERNAL, u16, reserved16, "")\
FIELD(F_HANDLE, Handle, hError, "")\
FIELD(0, u16, totalWidth, " bits")\
//-----------------------------------------------------------------------------
struct Header
{
u8 id;
u8 length;
Handle handle;
};
// declare each structure
#define FIELD(flags, type, name, units) type name;
#define STRUCTURE(name, id) struct name { Header header; name* next; name##_FIELDS };
STRUCTURES
#undef STRUCTURE
#undef FIELD
// declare a UDT holding pointers (freed at exit) to each structure
struct Structures
{
#define STRUCTURE(name, id) name* name##_;
STRUCTURES
#undef STRUCTURE
};
#if MSC_VERSION
# pragma pack(pop)
#endif
// define function templates that invoke a Visitor for each of a structure's fields
#define FIELD(flags, type, name, units) visitor(flags, p.name, #name, units);
#define STRUCTURE(name, id) template<class Visitor> void VisitFields(name& p, Visitor& visitor) { name##_FIELDS }
STRUCTURES
#undef STRUCTURE
#undef FIELD
LIB_API const Structures* GetStructures();
} // namespace SMBIOS
#endif // #ifndef INCLUDED_SMBIOS