Click here to Skip to main content
Click here to Skip to main content

Tagged as

SMBIOS Peek

, 27 Mar 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
A second approach to pulling that pesky missing WMI data.

Introduction

Anyone who has used a computer since the IBM PC hit the marketplace back in 1981 has at least heard the term BIOS. It stands for Basic Input / Output System and plays a critical role in the bootstrap process of both x86 and x64 machines. The BIOS is firmware code that runs when the computer is first turned on, and is used to identify and initiate the component hardware that will later get used by the operating system and applications.

If you have ever had the opportunity, (or misfortune depending on the circumstances), of browsing through your PC BIOS, you may well have discovered there is a lot of nice-to-know information there. There are all sorts of useful items, such as what sort of expansion slots are in the chassis, which CPU sockets are populated, even the serial number and manufacturer code for a given RAM chip. (There is also some mostly meaningless information for the majority of us, like whether or not the BIOS supports five and a quarter inch Toshiba brand floppy disks formatted for the Japanese character set.)

While not all of the information applies to everyone, certainly some of it is useful to some of us. Less so if we can only get to the information by waiting for our PC to boot up, then banging frantically on the F2 key, while hoping its not the delete key on this model that interrupts the load of the operating system and brings up the BIOS main menu. Which begs the question, why can't we view all the BIOS information after the operating system boots up?

To WMI or Not to WMI

The answer of course, is that you can. But doing so is not as straight-forward as one might think. In the wild-west days of computing, a system level programmer might just map a pointer directly to the physical start address of the BIOS ROM, and read away. But most of us know those days have come and gone under most modern operating system offerings. Unless you are still running Windows 98 getting access to physical memory addresses, especially from within user application space, is a little tricky. (If you are still running Windows 98 you may find some other things a little tricky, like keeping your PC running for more than a handful of hours without the dreaded blue screen of death paying you a visit!)

In an attempt to simplify systems administration, a few years back Microsoft began to offer IT professionals an initiative called WMI, a subset of the more open DMTF initiative. WMI, which stands for Windows Management Instrumentation, attempts to expose information about hardware by abstracting devices to manageable entities which can then be queried and in some cases controlled via simple scripts. While the information provided is easy to get at it is also often missing the level of detail provided in the BIOS. Take for instance the RAM. According to the WMI documentation, all the same detail level about a physical RAM device that is present in the BIOS is present in the WMI representation. However, the results I get back disagree.

WMI:

 BankLabel: 
 Capacity: 1073741824
 DataWidth: 64
 DeviceLocator: XMM1
 FormFactor: 8
 InterleaveDataDepth: 0
 InterleavePosition: 0
 MemoryType: 0
 Speed: 800
 Tag: Physical Memory 0
 TotalWidth: 64
 TypeDetail: 128

BIOS:

 physical memory array handle:0x37
 memory error information handle:0xfffe
 total width:64
 data width:64
 size:1024 megabytes
 form factor:dimm
 memory type:ddr2
 device set:0x01
 device locator:XMM1
 bank locator:
  additional memory details:
    synchronous
 speed:800 mhz
 manufacturer:JEDEC ID:AD 00 00 00 00 00 00 00
 serial number:28300000
 asset tag:
 part number:HYMP512U64CP8-S6
 rank:8

While the differences may seem subtle, if you are trying to audit your inventory for recalled RAM chips, having the serial number, manufacturer, and part number are an absolute must. Which brings us back to our original question, how does one get at the system management BIOS information from the operating system?

Look Again!

Fortunately, Microsoft gives us two methods for getting at the raw SMBIOS data block. The first is ironically through WMI itself. For reasons unknown to me, the operating system actually loads all the SMBIOS data on start up, but then chooses only to parse and make available portions of it. So while WMI only directly exposes some of the memory components, in fact, by parsing the same data the WMI abstraction objects load to populate themselves, you can successfully retrieve and display all the data. The key to this is the MSSMBios_RawSMBiosTables class inside the root\wmi namespace. If you are using Windows XP or 2000, this is the only way to get this data without writing or accessing a driver lurking in the kernel space. For Windows 2003 and above, there is an API call, GetSystemFirmwareTable, which will retrieve the raw data block.

System Management BIOS Specification

Of course once we have the raw data block itself, there is still the issue of how to parse it. For this you will need to look at the DMTF System Management BIOS Reference Specification. It outlines each and every table from version 1.0 to the current standard (which at the time this document was written is 2.6a). The data structure itself is rather compact, but requires specific knowledge of each table to properly interpret the results. Currently there are forty two defined tables, though only ten of them are required by BIOS vendors to be considered compliant with the specification.

From a macro-view, each table is divided into two sections, the formatted, and the unformatted section. The formatted section consists of a required header, which is defined as 4 bytes.

 0x00  TYPE    BYTE  Specifies the table type of the structure (currently 0 - 41).
 0x01  LENGTH  BYTE  Length of the formatted area including byte 0.
 0x02  HANDLE  WORD  Unique 16-bit handle for correlation to related tables.

After the header, you would read each byte for the specified LENGTH, and match those up against the table in the reference specification for identification. For example, according to the specification, the 4th, 5th, 6th, and 7th bytes of the memory array mapped table (type 19) represent the starting address of the device, to be interpreted as a DWORD. So you can simply pluck those 4 bytes and cast them to an unsigned long, presuming of course you are coding on a little endian processor.

Reading the unformatted section of a table is a little bit trickier. You start by moving to the offset of the table specified by the length parameter. You then can expect each "entry" to be an array of 8-bit ASCII based strings. Each string is null terminated, and the unformatted section of the current table, is separated from the formatted section of the next table, with a double null. This will hopefully be less confusing with an example right out of the DMTF specification.

 BIOS_INFO
 0x00 TYPE             BYTE
 0x02 LENGTH           BYTE
 0x03 HANDLE           WORD
 0x04 VENDOR           BYTE *STRING
 0x05 VERSION          BYTE *STRING
 0x06 START_SEGMENT    WORD
 0x08 RELEASE_DATE     BYTE *STRING
 0x09 ROM_SIZE         BYTE
 0x0A CHARACTERISTICS  QWORD
 0x12 CHARACTERISTICS2 BYTE
 0x14 BIOS_MAJOR       BYTE
 0x15 BIOS_MINOR       BYTE
 0x16 FIRMWARE_MAJOR   BYTE
 0x17 FIRMWARE_MINOR   BYTE

Note the three entries marked "string." These will be the indexes into the unformatted section we use for associating the ASCII text strings with the entry in the table. Let's assume our table contains the following data (the comments to the right are only for clarification and not part of the actual data).

 0                                  ;BIOS structure type
 0x13                               ;length of formatted section
 0x1234                             ;unique handle
 0x01                               ;indexes string 1 in the unformatted section
 0x02                               ;indexes string 2 in the unformatted section
 0xE800                             ;BIOS starting address
 0x03                               ;indexes string 3 in the unformatted section
 0x01                               ;size of BIOS rom 
 0x1C                               ;BIOS characteristics
 0x0                                ;BIOS characteristics extended
 'System BIOS Vendor name',0x0      ;first string in table
 'BIOS version 01.02C',0x0          ;second string in table
 '01/12/2006',0x0                   ;last string in table
 0x0                                ;end of table

(It is worth noting, however, that not all tables have an unformatted section. In that case the LENGTH byte will in fact point to the double nulls which separate the current table from the next table.)

While parsing these tables will for sure make your head spin at first glance, once you get a feel for a few its really not as difficult as it would seem. In truth its mostly tedious and without a doubt the most difficult part of parsing the data from the SMBIOS tables, is simply getting all the table formats into usable header files. Luckily for you, I've already done that in creating my SMBIOS Peek Utility! Drum roll please...

The Source Code

Without further ado I present to you my Smbios Peek Utility. I wrote the application using Visual Studio 2005. It is the most basic of command line programs that simply displays to the console the BIOS information present for the ten mandatory structures for a BIOS to be DMTF compliant. These are based on the May 2nd, 2007 proposed 2.6a specification. The required tables handled are:

 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

You can download the details for these tables here. I did my best to make the code structure itself straight forward and modular. To this extent I frequently chose readability over elegance. Anyone wishing to implement any of the other 42 smbios tables, should be able to do so by copying one of the existing table .h and .cpp files and simply filling in the required support and display methods as defined by the DMTF specification for that table type.

Using the Program

The program gets run from the command line. It can be invoked with a ''-f'' option followed by a file name which will redirect all the console output to the specified file. For example:

 c:\program files\utilities\smbiosp\smbios_p.exe -f "c:\my documents\inventory.txt"

will append all the smbios data gathered silently to the file c:\my documents\inventory.txt. If the file or the directory does not exist, it will be created. If you run the executable without a command line, it simply displays the output on the console. In that case I'd recommend using the |more option to keep the data from scrolling off the display before you have a chance to read it.

Acknowledgments

When I first began this project, I was specifically hunting for the serial number on the RAM chips. I had a number of very frustrating false starts and misinformation. Not to push the Microsoft Kool-Aid, but as often is the case I got my first real clue from the Microsoft News Groups. I owe many thanks to "Ben Voigt", "Jeff Henkels", and the mysterious but dead-on-the-money "m". I am always amazed at the number of people willing to help out a fellow hacker at microsoft.public.win32.programmer.kernel. I also owe a debt of gratitude to "kirants" and his 2006 article appropriately titled: ''SMBIOS Demystified''.

Unfortunately...

After running this utility on several different motherboards, I came across a PC where the BIOS manufacturer was not loading all of the data, even when more in-depth probing of the device EEPROMs themselves show the data is present. This is unfortunate and surprising since in my case at least, the BIOS core was the latest and greatest version from one of the BIOS developers who chair the standard committee that advocates SMBIOS data. In such cases the only way to get the data is to purchase a third party application, or write an SMBUS mini-port client driver. Who knows, I may try my hand at this as well. If so, you can bet I'll be posting a version 2 of this article!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

wjfrancis
Software Developer (Senior)
United States United States
I began coding at the ripe old age of eleven (yep, I've always been a nerd). Back then every 8-bit computer on the market had its own flavor of BASIC burned into the EPROM and I was adept at most of them. Somewhere in my bedroom there was an actual bed, but you'd be hard pressed to find it surrounded as it was. My collection included a C64, VIC20, TRS80, APPLE II+, TI-99/4A, and even one of those silver Timex Sinclair "computers" with the chicklet keys.
 
Eventually I taught myself 6502 assembler, and later Pascal and C. While I spent the majority of my professional career doing a mixture of C++, C#, and dabbling in ARM Assembler, for the last year I've been focusing on JAVA and the Android Platform. While I am a Windows guy at heart lately I'm finding some love for UBUNTU as well.
 
When I am not at the computer I am hanging out with my 12 year old son. He just finished coding a javascript implementation of Conway's Game of Life. Oh yeah, I guess that means we were in front of the computer. Go figure!

Comments and Discussions

 
Questionhow save raw data of bios as a .rom file ? PinmemberDominoBoy24-Nov-14 12:04 
QuestionBios Boot order sequence display Pinmembervinayagashiva1237-Oct-14 21:54 
QuestionNice ,thank you man PinmemberMember 111323926-Oct-14 2:36 
QuestionWindows 2000 - Failed to initialize raw smb bios data PinmemberFarzan Doroodgar31-Jul-14 7:14 
GeneralMy vote of 5 PinmemberMember 1024188829-Aug-13 22:12 
GeneralMy vote of 1 [modified] PinmemberElmue24-Jun-13 13:30 
NewsMessage Automatically Removed PinmemberElmue20-Jun-13 7:57 
GeneralMessage Removed Pinmemberwjfrancis20-Jun-13 11:22 
GeneralMessage Automatically Removed PinmemberElmue21-Jun-13 10:03 
NewsMessage Automatically Removed PinmemberElmue20-Jun-13 7:54 
BugBugfixes [modified] Pinmembermatelich5-Jan-12 12:32 
QuestionSome Bios values missing PinmemberFletch5714-Jul-11 7:37 
QuestionWake on Lan (WOL) check possible? Pinmembertunafish248-Jul-10 17:57 
GeneralVery interesting article PinmemberLloyd Atkinson27-Jun-10 6:07 
GeneralMy vote of 5 PinmemberTom The Cat26-Jun-10 22:07 
GeneralThanks. PinmemberV570200923-Apr-09 6:29 
GeneralRidiculous Pinmemberkilt27-Nov-08 4:22 
QuestionLimitations PinmemberMember 18925187-Nov-08 6:34 
GeneralThankyou PinmemberDogby20-Jul-08 23:36 
GeneralWrite to areas of BIOS NVRAM Pinmemberndavis1-Apr-08 19:56 
GeneralRe: Write to areas of BIOS NVRAM Pinmemberwjfrancis1-Apr-08 20:15 
GeneralJust an Update Pinmemberwjfrancis31-Mar-08 10:34 
QuestionRe: Just an Update PinmemberLeonMc31-Mar-08 22:42 
GeneralGreat, thank you man! Pinmembermbow7529-Mar-08 1:37 
GeneralNice, but zip file of source is too big Pinmemberkmlch28-Mar-08 17:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 27 Mar 2008
Article Copyright 2008 by wjfrancis
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid