Note: Dump SMBIOS Entry Pointer Structure

// DumpSMBIOS.cpp : Defines the entry point for the console
application.
//

#include “stdafx.h"
#include “.SysInfoISysInfo.h"
#include
“.SysInfoItemID.h"

typedef ISysInfo* (*_CreateSysInfo) (DWORD);
typedef void
(*_DestroySysInfo) (ISysInfo*);
typedef ULONG    (*_MemReadBlock) (ULONG
address, UCHAR* data, ULONG count, ULONG unitsize);
_MemReadBlock
pfMemReadBlock = NULL;

#pragma pack(push)
#pragma pack(1)

typedef struct {
UCHAR    Signature[4];
UCHAR    Chksum;

UCHAR    Length;
UCHAR    VerMajor;
UCHAR    VerMinor;

UINT16    MaxSize;
UCHAR    EPSRevision;
UCHAR
Formatter[5];
UCHAR    DMISignature[5];
UCHAR    DMIChksum;

UINT16    StructLength;
ULONG    StructAddress;
UINT16
NumStruct;
UCHAR    BCDRevision;
} SMBIOS_EPS, *PSMBIOS_EPS;

// ref. section 3.1.2 in spec.
typedef struct {
UCHAR
Type;
UCHAR    Length;
UINT16    Handle;
}
SMBIOS_STRUCT_HEADER, *PSMBIOS_STRUCT_HEADER;

typedef struct _TYPE_0_ {
SMBIOS_STRUCT_HEADER    Header;

UCHAR    Vendor;
UCHAR    Version;
UINT16    StartingAddrSeg;
}
BIOSInfo, *PBIOSInfo;

#pragma pack(pop)

UCHAR* toString(const UCHAR* src, int len)
{
static UCHAR
buff[256];
memcpy(buff, src, len);
buff[len] = 0;
return
buff;
}

void printSMBIOSEPS(SMBIOS_EPS& eps, ULONG addr)
{

printf(“SMBIOS Signature: %s, at 0x%Xn", toString(eps.Signature, 4),
addr);
printf(“Checksum: 0x%Xn", eps.Chksum);
printf(“Length:
%d(0x%X)n", eps.Length, eps.Length);
printf(“Version: %d.%dn",
eps.VerMajor, eps.VerMinor);
printf(“Maximum Structure Size: %d(0x%X)n",
eps.MaxSize, eps.MaxSize);
printf(“Entry Point Structure Revision: %dn",
eps.EPSRevision);
printf(“Formatter Area:
0x%02X,0x%02X,0x%02X,0x%02X,0x%02Xn",

eps.Formatter[0],eps.Formatter[1],eps.Formatter[2],

eps.Formatter[3],eps.Formatter[4]);
printf(“Intermediate anchor string:
%sn", toString(eps.DMISignature, 5));
printf(“Intermediate Checksum:
0x%Xn", eps.DMIChksum);
printf(“Structure Table Length: %dn",
eps.StructLength);
printf(“Structure Table Address: 0x%08Xn",
eps.StructAddress);
printf(“Number of SMBIOS Structures: %dn",
eps.NumStruct);
printf(“BCD Revision: 0x%02Xn", eps.BCDRevision);
}

bool LoadSysInfo(HMODULE &hSysInfoLib, ISysInfo* pISysInfo)
{

hSysInfoLib = LoadLibrary(_T(“SysInfo.dll"));

if (NULL != hSysInfoLib)
{
_CreateSysInfo
pCreateSysInfo = (_CreateSysInfo)GetProcAddress(hSysInfoLib, “CreateSysInfo");

if (NULL != pCreateSysInfo)
{
pISysInfo =
pCreateSysInfo(MODE_PCI); // request access memory spaces, MODE_PCI

}
else
{
printf(“ERR: Failed in
GetProcAddress(“CreateSysInfo")n");
exit(-1);

return false;
}
}
else
{

printf(“Can’t find Sysinfo.dlln");
exit(-1);
return
false;
}
return true;
}

bool UnloadSysInfo(HMODULE hSysInfoLib, ISysInfo* pISysInfo)
{

_DestroySysInfo pDestroySysInfo = (_DestroySysInfo)GetProcAddress(hSysInfoLib,
“DestroySysInfo");
if (pDestroySysInfo)
{

pDestroySysInfo(pISysInfo);
pISysInfo = NULL;
}

else
{
printf(“ERR: Failed in
GetProcAddress(“DestroySysInfo")n");
exit(-1);
return
false;
}

FreeLibrary(hSysInfoLib);
hSysInfoLib = NULL;
return
true;
}

bool FindSMBIOS(PSMBIOS_EPS& eps, UCHAR* buff, UINT size)
{

UCHAR *p = buff;

for (UINT i = 0; i < size; i+=16)
{
if (0 ==
memcmp(p, “_SM_", 4))
{
PSMBIOS_EPS psm =
(PSMBIOS_EPS)p;

if (0 == memcmp(psm->DMISignature, “_DMI_",5))

{
UCHAR chk = 0;

// verify checksum
for(UINT i=0; i <
psm->Length; i++)
{

chk+=*(p+i);
}

if (0 == chk)
{
eps
= psm;
return true;
}

}
}
p+=16;
}
return false;
}

void DumpSMBIOSStruct(ULONG Addr,UINT Len, UINT Num)
{
UCHAR
*pData;
UCHAR *p = NULL;
pData = (UCHAR*)malloc(Len);
if
(NULL != pData)
{
pfMemReadBlock(Addr, pData, Len,
1);
p = pData;
}
PSMBIOS_STRUCT_HEADER
pHeader;
for (UINT i = 0; i < Num; i++) {
pHeader =
(PSMBIOS_STRUCT_HEADER)p;
switch(pHeader->Type) {
case
0: {
PBIOSInfo pBIOSinfo = (PBIOSInfo)p;

printf(“BIOS Starting Segment: 0x%X",
pBIOSinfo->StartingAddrSeg);
}

break;
case 1:
break;
}
UCHAR
*nt = p + pHeader->Length; // point to struct end
while (0 != (*nt
| *(nt+1))) nt++;
nt+=2;
if (nt > pData+Len) break; //
over?
p = nt;
}

free(pData);
}

int _tmain(int argc, _TCHAR* argv[])
{
ISysInfo* pISysInfo =
NULL;
HMODULE hSysInfoLib = NULL;
const ULONG MEM_RANGE = 64*1024;
// 0xF0000 ~ 0xFFFFF, 64K
const ULONG MEM_START = 0xF0000;
UCHAR
buff[MEM_RANGE];
PSMBIOS_EPS pSMBIOS = NULL;

if (false == LoadSysInfo(hSysInfoLib, pISysInfo))
return -1;

pfMemReadBlock = (_MemReadBlock) GetProcAddress(hSysInfoLib,
“_MemReadBlock");
if (pfMemReadBlock)
{

pfMemReadBlock(MEM_START, buff, MEM_RANGE, 1);
FindSMBIOS(pSMBIOS,
buff, MEM_RANGE);
}
else
{
printf(“ERR: failed
in GetProcAddress(“_MemReadBlock")n");
}

if (pSMBIOS)
{
printf(“Find out the SMBIOS Entry Point
Structure n");
printSMBIOSEPS(*pSMBIOS, ((UCHAR*)pSMBIOS – buff) +
0xF0000);
DumpSMBIOSStruct(pSMBIOS->StructAddress,
pSMBIOS->StructLength, pSMBIOS->NumStruct);
}

UnloadSysInfo(hSysInfoLib, pISysInfo);
return 0;
}

Result is run the program on Lenovo X60

Find out the SMBIOS Entry Point Structure
SMBIOS Signature: _SM_, at
0xF6730
Checksum: 0x27
Length: 31(0x1F)
Version: 2.4
Maximum
Structure Size: 86(0x56)
Entry Point Structure Revision: 0
Formatter Area:
0x00,0x00,0x00,0x00,0x00
Intermediate anchor string: _DMI_
Intermediate
Checksum: 0x3E
Structure Table Length: 2241
Structure Table Address:
0x000E0010
Number of SMBIOS Structures: 67
BCD Revision: 0x00

這個執行結果SMBIOS Entry Point Structure 在 0F6730h, 而一共有 67個數據體, 頭一個在 0E0010h
的位址

解析 SMBIOS 數據體麻煩的地方是, 在數據體後面還有可能接數個字串(C string). 所以不能直接使用數據體 本身的
length來跳到下一個數據體. 看了 Spec. 的Example 還是有點模糊.需要在花點時間想想怎樣Dump才好!

把數據體與數據體定位搞定了!

廣告

4 回應 to “Note: Dump SMBIOS Entry Pointer Structure”

  1. 結果要怎麼把數據體與數據體定位 呢?
    因為最近也在摸這個smbios

  2. 對於EFI base system,如win8,該方式貌似不有效,其SMBIOS EPS不在F0000h~FFFFFh範圍內,怎麼辦?

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

%d 位部落客按了讚: