UPDATE : If you want access the SMBIOS using Delphi or Free Pascal try the TSMBIOS project.
The system management BIOS (SMBIOS) is a specification of how the system vendors present management information about their products in a standard format, so you can use the SMBIOS to discover information about the hardware platform, such as the system manufacturer, the system BIOS version, processor installed characteristics and so on. From windows you can acceess the SMBIOS tables using the WMI or the WinApi. In this article I will show how you can gain access to the SMBios tables using the WMI and Delphi.
The SMBIOS Tables
The tables are located directly adjacent to each other in memory. Each table is composed of a 4-byte header, a specific structure , and an optional string table.
Header
This is the header description of each table
The type field present in the header define how each table must be interpreted, this is a list of a few table types
- BIOS Information (Type 0)
- System Information (Type 1)
- System Enclosure (Type 3)
- Processor Information (Type 4)
- Cache Information (Type 7)
- System Slots (Type 9)
- Physical Memory Array (Type 16)
- Memory Device (Type 17)
- Memory Array Mapped Address (Type 19)
- System Boot Information (Type 32)
Text Strings
The text strings associated with a given SMBIOS table are appended directly after the formatted portion of the structure. Each string is terminated with a null (00h) BYTE and the set of strings is terminated with an additional null (00h) BYTE. When the formatted portion of a SMBIOS structure references a string, it does so by specifying a non-zero string number within the structure’s string-set. For example, if a string field contains 02h, it references the second string following the formatted portion of the SMBIOS structure. If a string field references no string, a null (0) is placed in that string field.
Check the next representation of a BIOS Table (Type
db 0 ; Indicates BIOS Structure Type | db 13h ; Length of information in bytes | Header of the table dw ? ; Reserved for handle | db 01h ; String 1 is the Vendor Name | db 02h ; String 2 is the BIOS version | dw 0E800h ; BIOS Starting Address | db 03h ; String 3 is the BIOS Build Date | formatted portion db 1 ; Size of BIOS ROM is 128K (64K * (1 + 1)) | dq BIOS_Char ; BIOS Characteristics | db 0 ; BIOS Characteristics Extension Byte 1 | db ‘System BIOS Vendor Name’,0 ; | db ‘4.04’,0 ; | Text Strings (unformatted portion) db ‘00/00/0000’,0 ; | db 0 ; End of structure
WMI
Now which you know the basics about the SMBios table structures, you need a way to retrieve such tables. the WMI provides a way to get the raw SMBIOS data in a single buffer using the class MSSmBios_RawSMBiosTables this class is in the root\WMI namespace and is available since Windows XP.
Check this small snippet to retrieve the SMBios tables buffer contained in the SMBiosData property
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
vArray : variant;
Value : integer;
i : integer;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
//connect to the Wmi service
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\WMI', '', '');
//execute the WQL sentence
FWbemObjectSet := FWMIService.ExecQuery('SELECT * FROM MSSmBios_RawSMBiosTables', 'WQL', wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumvariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
//store the size of the buffer
FSize := FWbemObject.Size;
GetMem(FBuffer, FSize);
//get the addtional properties like the SMBIos version
FDmiRevision:= FWbemObject.DmiRevision;
FSmbiosMajorVersion :=FWbemObject.SmbiosMajorVersion;
FSmbiosMinorVersion :=FWbemObject.SmbiosMinorVersion;
//get the buffer of the SMBios tables
vArray := FWbemObject.SMBiosData;
FWbemObject := Unassigned;
end;
end;
Delphi
From the Delphi side we need to create a few structures to hold the data of the tables and write some helper functions to parse the information.
type
// http://www.dmtf.org/standards/smbios
SMBiosTables = (
BIOSInformation = 0,
SystemInformation = 1,
BaseBoardInformation = 2,
EnclosureInformation = 3,
ProcessorInformation = 4,
MemoryControllerInformation = 5,
MemoryModuleInformation = 6,
CacheInformation = 7,
PortConnectorInformation = 8,
SystemSlotsInformation = 9,
OnBoardDevicesInformation = 10,
OEMStrings = 11,
SystemConfigurationOptions = 12,
BIOSLanguageInformation = 13,
GroupAssociations = 14,
SystemEventLog = 15,
PhysicalMemoryArray = 16,
MemoryDevice = 17,
MemoryErrorInformation = 18,
MemoryArrayMappedAddress = 19,
MemoryDeviceMappedAddress = 20,
EndofTable = 127); //for more tables check the official specifications http://www.dmtf.org/standards/smbios
//the header of each SMBios table
TSmBiosTableHeader = packed record
TableType: Byte;
Length: Byte;
Handle: Word;
end;
//this is a helper record to store the header and index of each table stored in the buffer
TSMBiosTableEntry = record
Header: TSmBiosTableHeader;
Index : Integer;
end;
//this is the record to store Bios information about the table Type 0
TBiosInfo = packed record
Header: TSmBiosTableHeader;
Vendor: Byte;
Version: Byte;
StartingSegment: Word;
ReleaseDate: Byte;
BiosRomSize: Byte;
Characteristics: Int64;
ExtensionBytes : array [0..1] of Byte;
end;
The next code show how you can parse the buffer with the raw data and fill a Generic TList of TSMBiosTableEntry records.
function GetSMBiosTablesList(Buffer : PByteArray): TList;
Var
Index : integer;
Header: TSmBiosTableHeader;
Entry : TSMBiosTableEntry;
begin
Result := TList.Create;
Index := 0;
repeat
//read the header
Move(Buffer[Index], Header, SizeOf(Header));
Entry.Header:=Header;
Entry.Index:=Index;
//add to the list
Result.Add(Entry);
//check if the tale type is 127 (end of tables)
if Header.TableType=Ord(SMBiosTables.EndofTable) then break;
//increase the Index in the length of the formatted data
inc(Index, Header.Length);
//Text strings zone
//check for the boundaries of the buffer
if Index+1>FSize then
Break;
//check for $00 $00 -> table termination
while not((Buffer[Index] = 0) and (Buffer[Index + 1] = 0)) do
if Index+1>FSize then
Break
else
inc(Index);
inc(Index, 2);
until (Index>FSize);
end;
Now to retrieve a text string from a SMBios table
//the Entry Parameter is the buffer to the unformatted data
//The index is the number of the text string to retrieve
function GetSMBiosString(Entry, Index: integer): AnsiString;
var
i: integer;
p: PAnsiChar;
begin
Result := '';
for i := 1 to Index do
begin
p := PAnsiChar(@Buffer[Entry]);
if i = Index then
begin
Result := p;
break;
end
else
inc(Entry, StrLen(p) + 1);
end;
end;
A unit to retrieve the Smbios tables
Here I leave a unit to retrieve and parse the SMBios tables, the unit does not cover all the tables types (you can read the official specification)
//Author Rodrigo Ruz V.
//2011-08-01
unit uSMBIOS;
interface
uses
SysUtils,
Windows,
Generics.Collections,
Classes;
type
// http://www.dmtf.org/standards/smbios
SMBiosTables = (
BIOSInformation = 0,
SystemInformation = 1,
BaseBoardInformation = 2,
EnclosureInformation = 3,
ProcessorInformation = 4,
MemoryControllerInformation = 5,
MemoryModuleInformation = 6,
CacheInformation = 7,
PortConnectorInformation = 8,
SystemSlotsInformation = 9,
OnBoardDevicesInformation = 10,
OEMStrings = 11,
SystemConfigurationOptions = 12,
BIOSLanguageInformation = 13,
GroupAssociations = 14,
SystemEventLog = 15,
PhysicalMemoryArray = 16,
MemoryDevice = 17,
MemoryErrorInformation = 18,
MemoryArrayMappedAddress = 19,
MemoryDeviceMappedAddress = 20,
EndofTable = 127);
TSmBiosTableHeader = packed record
TableType: Byte;
Length: Byte;
Handle: Word;
end;
TBiosInfo = packed record
Header: TSmBiosTableHeader;
Vendor: Byte;
Version: Byte;
StartingSegment: Word;
ReleaseDate: Byte;
BiosRomSize: Byte;
Characteristics: Int64;
ExtensionBytes : array [0..1] of Byte;
end;
TSysInfo = packed record
Header: TSmBiosTableHeader;
Manufacturer: Byte;
ProductName: Byte;
Version: Byte;
SerialNumber: Byte;
UUID: array [0 .. 15] of Byte;
WakeUpType: Byte;
end;
TBaseBoardInfo = packed record
Header: TSmBiosTableHeader;
Manufacturer: Byte;
Product: Byte;
Version: Byte;
SerialNumber: Byte;
end;
TEnclosureInfo = packed record
Header: TSmBiosTableHeader;
Manufacturer: Byte;
&Type: Byte;
Version: Byte;
SerialNumber: Byte;
AssetTagNumber: Byte;
BootUpState: Byte;
PowerSupplyState: Byte;
ThermalState: Byte;
SecurityStatus: Byte;
OEM_Defined: DWORD;
end;
TProcessorInfo = packed record
Header: TSmBiosTableHeader;
SocketDesignation: Byte;
ProcessorType: Byte;
ProcessorFamily: Byte;
ProcessorManufacturer: Byte;
ProcessorID: Int64; // QWORD;
ProcessorVersion: Byte;
Voltaje: Byte;
ExternalClock: Word;
MaxSpeed: Word;
CurrentSpeed: Word;
Status: Byte;
ProcessorUpgrade: Byte;
L1CacheHandler: Word;
L2CacheHandler: Word;
L3CacheHandler: Word;
SerialNumber: Byte;
AssetTag: Byte;
PartNumber: Byte;
end;
TCacheInfo = packed record
Header: TSmBiosTableHeader;
SocketDesignation: Byte;
CacheConfiguration: DWORD;
MaximumCacheSize: Word;
InstalledSize: Word;
SupportedSRAMType: Word;
CurrentSRAMType: Word;
CacheSpeed: Byte;
ErrorCorrectionType: Byte;
SystemCacheType: Byte;
Associativity: Byte;
end;
TSMBiosTableEntry = record
Header: TSmBiosTableHeader;
Index : Integer;
end;
TSMBios = class
private
FSize: integer;
FBuffer: PByteArray;
FDataString: AnsiString;
FBiosInfo: TBiosInfo;
FSysInfo: TSysInfo;
FBaseBoardInfo: TBaseBoardInfo;
FEnclosureInfo: TEnclosureInfo;
FProcessorInfo: TProcessorInfo;
FBiosInfoIndex: Integer;
FSysInfoIndex: Integer;
FBaseBoardInfoIndex: Integer;
FEnclosureInfoIndex: Integer;
FProcessorInfoIndex: Integer;
FDmiRevision: Integer;
FSmbiosMajorVersion: Integer;
FSmbiosMinorVersion: Integer;
FSMBiosTablesList: TList;
procedure LoadSMBIOS;
procedure ReadSMBiosTables;
function GetHasBiosInfo: Boolean;
function GetHasSysInfo: Boolean;
function GetHasBaseBoardInfo: Boolean;
function GetHasEnclosureInfo: Boolean;
function GetHasProcessorInfo: Boolean;
function GetSMBiosTablesList:TList;
public
constructor Create;
destructor Destroy; override;
function SearchSMBiosTable(TableType: SMBiosTables): integer;
function GetSMBiosTableIndex(TableType: SMBiosTables): integer;
function GetSMBiosString(Entry, Index: integer): AnsiString;
property Size: integer read FSize;
property Buffer: PByteArray read FBuffer;
property DataString: AnsiString read FDataString;
property DmiRevision: Integer read FDmiRevision;
property SmbiosMajorVersion : Integer read FSmbiosMajorVersion;
property SmbiosMinorVersion : Integer read FSmbiosMinorVersion;
property SMBiosTablesList : TList read FSMBiosTablesList;
property BiosInfo: TBiosInfo read FBiosInfo Write FBiosInfo;
property BiosInfoIndex: Integer read FBiosInfoIndex Write FBiosInfoIndex;
property HasBiosInfo : Boolean read GetHasBiosInfo;
property SysInfo: TSysInfo read FSysInfo Write FSysInfo;
property SysInfoIndex: Integer read FSysInfoIndex Write FSysInfoIndex;
property HasSysInfo : Boolean read GetHasSysInfo;
property BaseBoardInfo: TBaseBoardInfo read FBaseBoardInfo write FBaseBoardInfo;
property BaseBoardInfoIndex: Integer read FBaseBoardInfoIndex Write FBaseBoardInfoIndex;
property HasBaseBoardInfo : Boolean read GetHasBaseBoardInfo;
property EnclosureInfo: TEnclosureInfo read FEnclosureInfo write FEnclosureInfo;
property EnclosureInfoIndex: Integer read FEnclosureInfoIndex Write FEnclosureInfoIndex;
property HasEnclosureInfo : Boolean read GetHasEnclosureInfo;
property ProcessorInfo: TProcessorInfo read FProcessorInfo write FProcessorInfo;
property ProcessorInfoIndex: Integer read FProcessorInfoIndex Write FProcessorInfoIndex;
property HasProcessorInfo : Boolean read GetHasProcessorInfo;
end;
implementation
uses
ComObj,
ActiveX,
Variants;
{ TSMBios }
constructor TSMBios.Create;
begin
Inherited;
FBuffer := nil;
FSMBiosTablesList:=nil;
LoadSMBIOS;
ReadSMBiosTables;
end;
destructor TSMBios.Destroy;
begin
if Assigned(FBuffer) and (FSize > 0) then
FreeMem(FBuffer);
if Assigned(FSMBiosTablesList) then
FSMBiosTablesList.Free;
Inherited;
end;
function TSMBios.GetHasBaseBoardInfo: Boolean;
begin
Result:=FBaseBoardInfoIndex>=0;
end;
function TSMBios.GetHasBiosInfo: Boolean;
begin
Result:=FBiosInfoIndex>=0;
end;
function TSMBios.GetHasEnclosureInfo: Boolean;
begin
Result:=FEnclosureInfoIndex>=0;
end;
function TSMBios.GetHasProcessorInfo: Boolean;
begin
Result:=FProcessorInfoIndex>=0;
end;
function TSMBios.GetHasSysInfo: Boolean;
begin
Result:=FSysInfoIndex>=0;
end;
function TSMBios.SearchSMBiosTable(TableType: SMBiosTables): integer;
Var
Index : integer;
Header : TSmBiosTableHeader;
begin
Index := 0;
repeat
Move(Buffer[Index], Header, SizeOf(Header));
if Header.TableType = Ord(TableType) then
break
else
begin
inc(Index, Header.Length);
if Index+1>FSize then
begin
Index:=-1;
Break;
end;
while not((Buffer[Index] = 0) and (Buffer[Index + 1] = 0)) do
if Index+1>FSize then
begin
Index:=-1;
Break;
end
else
inc(Index);
inc(Index, 2);
end;
until (Index>FSize);
Result := Index;
end;
function TSMBios.GetSMBiosString(Entry, Index: integer): AnsiString;
var
i: integer;
p: PAnsiChar;
begin
Result := '';
for i := 1 to Index do
begin
p := PAnsiChar(@Buffer[Entry]);
if i = Index then
begin
Result := p;
break;
end
else
inc(Entry, StrLen(p) + 1);
end;
end;
function TSMBios.GetSMBiosTableIndex(TableType: SMBiosTables): integer;
Var
Entry : TSMBiosTableEntry;
begin
Result:=-1;
for Entry in FSMBiosTablesList do
if Entry.Header.TableType=Ord(TableType) then
begin
Result:=Entry.Index;
Break;
end;
end;
function TSMBios.GetSMBiosTablesList: TList;
Var
Index : integer;
Header: TSmBiosTableHeader;
Entry : TSMBiosTableEntry;
begin
Result := TList.Create;
Index := 0;
repeat
Move(Buffer[Index], Header, SizeOf(Header));
Entry.Header:=Header;
Entry.Index:=Index;
Result.Add(Entry);
if Header.TableType=Ord(SMBiosTables.EndofTable) then break;
inc(Index, Header.Length);// + 1);
if Index+1>FSize then
Break;
while not((Buffer[Index] = 0) and (Buffer[Index + 1] = 0)) do
if Index+1>FSize then
Break
else
inc(Index);
inc(Index, 2);
until (Index>FSize);
end;
procedure TSMBios.LoadSMBIOS;
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator: OLEVariant;
FWMIService: OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject: OLEVariant;
oEnum: IEnumvariant;
iValue: LongWord;
vArray: variant;
Value: integer;
i: integer;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\WMI', '', '');
FWbemObjectSet := FWMIService.ExecQuery('SELECT * FROM MSSmBios_RawSMBiosTables', 'WQL', wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumvariant;
if oEnum.Next(1, FWbemObject, iValue) = 0 then
begin
FSize := FWbemObject.Size;
GetMem(FBuffer, FSize);
FDmiRevision:= FWbemObject.DmiRevision;
FSmbiosMajorVersion :=FWbemObject.SmbiosMajorVersion;
FSmbiosMinorVersion :=FWbemObject.SmbiosMinorVersion;
vArray := FWbemObject.SMBiosData;
if (VarType(vArray) and VarArray) <> 0 then
for i := VarArrayLowBound(vArray, 1) to VarArrayHighBound(vArray, 1) do
begin
Value := vArray[i];
Buffer[i] := Value;
if Value in [$20..$7E] then
FDataString := FDataString + AnsiString(Chr(Value))
else
FDataString := FDataString + '.';
end;
FSMBiosTablesList:=GetSMBiosTablesList;
FWbemObject := Unassigned;
end;
end;
procedure TSMBios.ReadSMBiosTables;
begin
FBiosInfoIndex := GetSMBiosTableIndex(BIOSInformation);
if FBiosInfoIndex >= 0 then
Move(Buffer[FBiosInfoIndex], FBiosInfo, SizeOf(FBiosInfo));
FSysInfoIndex := GetSMBiosTableIndex(SystemInformation);
if FSysInfoIndex >= 0 then
Move(Buffer[FSysInfoIndex], FSysInfo, SizeOf(FSysInfo));
FBaseBoardInfoIndex := GetSMBiosTableIndex(BaseBoardInformation);
if FBaseBoardInfoIndex >= 0 then
Move(Buffer[FBaseBoardInfoIndex], FBaseBoardInfo, SizeOf(FBaseBoardInfo));
FEnclosureInfoIndex := GetSMBiosTableIndex(EnclosureInformation);
if FEnclosureInfoIndex >= 0 then
Move(Buffer[FEnclosureInfoIndex], FEnclosureInfo, SizeOf(FEnclosureInfo));
FProcessorInfoIndex := GetSMBiosTableIndex(ProcessorInformation);
if FProcessorInfoIndex >= 0 then
Move(Buffer[FProcessorInfoIndex], FProcessorInfo, SizeOf(FProcessorInfo));
end;
end.
Sample project
This console application show how use this unit
{$APPTYPE CONSOLE}
uses
Classes,
SysUtils,
ActiveX,
ComObj,
uSMBIOS in 'uSMBIOS.pas';
procedure GetMSSmBios_RawSMBiosTablesInfo;
Var
SMBios : TSMBios;
UUID : Array[0..31] of Char;
Entry : TSMBiosTableEntry;
begin
SMBios:=TSMBios.Create;
try
With SMBios do
begin
Writeln(Format('%d SMBios tables found',[SMBiosTablesList.Count]));
Writeln('');
Writeln('Type Handle Length Index');
for Entry in SMBiosTablesList do
Writeln(Format('%3d %4x %3d %4d',[Entry.Header.TableType, Entry.Header.Handle, Entry.Header.Length, Entry.Index]));
Readln;
if HasBiosInfo then
begin
WriteLn('Bios Information');
WriteLn('Vendor '+GetSMBiosString(BiosInfoIndex + BiosInfo.Header.Length, BiosInfo.Vendor));
WriteLn('Version '+GetSMBiosString(BiosInfoIndex + BiosInfo.Header.Length, BiosInfo.Version));
WriteLn('Start Segment '+IntToHex(BiosInfo.StartingSegment,4));
WriteLn('ReleaseDate '+GetSMBiosString(BiosInfoIndex + BiosInfo.Header.Length, BiosInfo.ReleaseDate));
WriteLn(Format('Bios Rom Size %d k',[64*(BiosInfo.BiosRomSize+1)]));
WriteLn('');
end;
if HasSysInfo then
begin
WriteLn('System Information');
WriteLn('Manufacter '+GetSMBiosString(SysInfoIndex + SysInfo.Header.Length, SysInfo.Manufacturer));
WriteLn('Product Name '+GetSMBiosString(SysInfoIndex + SysInfo.Header.Length, SysInfo.ProductName));
WriteLn('Version '+GetSMBiosString(SysInfoIndex + SysInfo.Header.Length, SysInfo.Version));
WriteLn('Serial Number '+GetSMBiosString(SysInfoIndex + SysInfo.Header.Length, SysInfo.SerialNumber));
BinToHex(@SysInfo.UUID,UUID,SizeOf(SysInfo.UUID));
WriteLn('UUID '+UUID);
WriteLn('');
end;
if HasBaseBoardInfo then
begin
WriteLn('BaseBoard Information');
WriteLn('Manufacter '+GetSMBiosString(BaseBoardInfoIndex + BaseBoardInfo.Header.Length, BaseBoardInfo.Manufacturer));
WriteLn('Product '+GetSMBiosString(BaseBoardInfoIndex + BaseBoardInfo.Header.Length, BaseBoardInfo.Product));
WriteLn('Version '+GetSMBiosString(BaseBoardInfoIndex + BaseBoardInfo.Header.Length, BaseBoardInfo.Version));
WriteLn('Serial Number '+GetSMBiosString(BaseBoardInfoIndex + BaseBoardInfo.Header.Length, BaseBoardInfo.SerialNumber));
WriteLn('');
end;
if HasEnclosureInfo then
begin
WriteLn('Enclosure Information');
WriteLn('Manufacter '+GetSMBiosString(EnclosureInfoIndex + EnclosureInfo.Header.Length, EnclosureInfo.Manufacturer));
WriteLn('Version '+GetSMBiosString(EnclosureInfoIndex + EnclosureInfo.Header.Length, EnclosureInfo.Version));
WriteLn('Serial Number '+GetSMBiosString(EnclosureInfoIndex + EnclosureInfo.Header.Length, EnclosureInfo.SerialNumber));
WriteLn('Asset Tag Number '+GetSMBiosString(EnclosureInfoIndex + EnclosureInfo.Header.Length, EnclosureInfo.AssetTagNumber));
WriteLn('');
end;
if HasProcessorInfo then
begin
WriteLn('Processor Information');
WriteLn('Socket Designation '+GetSMBiosString(ProcessorInfoIndex + ProcessorInfo.Header.Length, ProcessorInfo.SocketDesignation));
WriteLn('Processor Manufacturer '+GetSMBiosString(ProcessorInfoIndex + ProcessorInfo.Header.Length, ProcessorInfo.ProcessorManufacturer));
WriteLn('Serial Number '+GetSMBiosString(ProcessorInfoIndex + ProcessorInfo.Header.Length, ProcessorInfo.SerialNumber));
WriteLn('Asset Tag '+GetSMBiosString(ProcessorInfoIndex + ProcessorInfo.Header.Length, ProcessorInfo.AssetTag));
WriteLn('Part Number '+GetSMBiosString(ProcessorInfoIndex + ProcessorInfo.Header.Length, ProcessorInfo.PartNumber));
WriteLn('');
end;
end;
finally
SMBios.Free;
end;
end;
begin
try
CoInitialize(nil);
try
GetMSSmBios_RawSMBiosTablesInfo;
finally
CoUninitialize;
end;
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
Check these samples images of the console App.
Additional Information
Check the next resources to get more info about the SMBios
- System Management BIOS DMTF Specification
- SMBIOS Demystified (C++ article to parse and show the raw data of the SMBios tables)
- SMBIOS Support in Windows
- GetSystemFirmwareTable
- EnumSystemFirmwareTables



August 3, 2011 at 12:11 am
Very nice. I haven’t been fiddling with hardware for a long time. Reminds me of DOS era :)
August 3, 2011 at 12:21 am
François, while I wrote this article had the same memories..like reading the Bios and CMOS memory using Turbo Pascal – those were good times :)
August 3, 2011 at 2:59 am
Hi. This is just something for me right now. Unfortunately I have great difficulties reading grey characters on black background. Hope what is written there are just examples on output.
August 3, 2011 at 3:09 am
Sorry for that, the images only shows the output of the app, so don’t worry. for that.
August 4, 2011 at 7:35 pm
wow THIS VERY AWESOME!!! thanks Rodrigo, really love ur article.
August 7, 2011 at 8:48 am
Rodrigo: I give you 5* thumbs, all of your tutorial article are very clear and detail. Thanks a lot. God bless you.
regards
August 18, 2011 at 8:17 am
Great article, old solution with whole bios dump not working anymore.
Delphi 7 is not support generic (Generics.Collections). Is it there a workaround for delphi 7.
Thank you.
August 18, 2011 at 9:25 am
In Delphi 7, you can replace the generics with a TList or an dynamic array,
August 20, 2011 at 2:18 pm
I am successfully modified unit “uSMBIOS” for Delphi 7 using dynamic array like you suggested.
Thank you once more.
August 20, 2011 at 2:26 pm
You are welcome, glad to help you
June 30, 2012 at 4:11 am
ivica,
I also have Delphi 7. I really don’t understand Generics.Collections and stuff like that.
Could you be so kind as to share your Delphi 7 version of this code?
I am sure I am not alone :)
August 9, 2012 at 12:09 pm
Leave your email and i will send you working example for D7.
August 17, 2012 at 8:21 am
ivica, could you share modified code for delphi7… (oztruva@gmail.com)
August 20, 2011 at 4:12 am
Thank you for this posting, i am currently using your code to write a reader for all the tables, hopefully i can share it with you when it’s complete
September 16, 2011 at 4:38 pm
It was failed to compiled using Lazarus.. :(
Would you mind to make it works to compile using Lazarus too??
I’m newbie.. But I want to use your Unit for my knowledge..
Thank You,
Onix Tan.
January 8, 2012 at 10:40 pm
Thanks very much for sharing your knowledge and Delphi code, it saved me alot of work.
Pingback: SMBios: BiosHelp geht nicht - Delphi-PRAXiS
July 9, 2012 at 7:13 am
Thanks for this excellent example. I’ve been trying to get some of the numeric values out of SMBIOS, like L1 Cache Handle which is a WORD value. In my tests L1, L2 and L3 contain 770, 772 and 771 respectively. I think this might be pointing to these values in a similar way to the way strings are handled in SMBIOS because clearly these aren’t proper values. This is different to CoreCount which has the correct value when I load the the buffer into the ProcessorInfo. Try as I might, I cannot seem to get it to reference correctly and return decent values. Could I ask if you have found a way to do this? I’m wondering if you might have a GetSMBIOSWord equivalent?
July 9, 2012 at 10:32 am
Riichard, these fileds store the handles of the cache structure table (type 7), you must decode this table using the SMBIOS spec http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf and then compare the handle values.
Pingback: SMBios Ungenauigkeiten? - Delphi-PRAXiS