System Management BIOS: Difference between revisions
[unchecked revision] | [unchecked revision] |
Content deleted Content added
m See also |
m Bot: Replace deprecated source tag with syntaxhighlight |
||
(11 intermediate revisions by 8 users not shown) | |||
Line 1:
SMBIOS (System Management [[BIOS]]
It was first designed for Intel, and released in 1995. Nowadays it supports most desktop architectures, and its last specification was published the 21 of July, 2023.
==
SMBIOS provides a searchable (or querryable) structure called Entry Point Structure (or EPS) that contains a pointer to the SMBIOS Structure Table and some additional information, like its length, version, or number of structures.
=== Format ===
{| align="center" cellspacing="2"
| width="50%" valign="top" |
{| {{wikitable}}
|+ 32-bit Entry Point Structure Format
! Offset
! Name
! Size
|-
| 0x00 || Anchor String || 4 BYTEs
|-
| 0x04 || Entry Point Checksum || BYTE
|-
| 0x05 || Entry Point Lenght || BYTE
|-
| 0x06 || SMBIOS Major Version || BYTE
|-
| 0x07 || SMBIOS Minor Version || BYTE
|-
| 0x08 || SMBIOS Structure Maximum Size || WORD
|-
| 0x0A || Entry Point Revision || BYTE
|-
| 0x0B || Formatted Area || 5 BYTEs
|-
| 0x10 || Intermediate Anchor String || 5 BYTEs
|-
| 0x15 || Intermediate Checksum || BYTE
|-
| 0x16 || Structure Table Length || WORD
|-
| 0x18 || '''Structure Table Address''' || DWORD
|-
| 0x1C || Number of Structures || WORD
|-
| 0x1E || BCD Revision || BYTE
|}
| width="10%" valign="top" |
| width="50%" valign="top" |
{| {{wikitable}}
|+ 64-bit Entry Point Structure Format
! Offset
! Name
! Size
|-
| 0x00 || Anchor String || 5 BYTEs
|-
| 0x05 || Entry Point Checksum || BYTE
|-
| 0x06 || Entry Point Lenght || BYTE
|-
| 0x07 || SMBIOS Major Version || BYTE
|-
| 0x08 || SMBIOS Minor Version || BYTE
|-
| 0x09 || SMBIOS Docrev || BYTE
|-
| 0x0A || Entry Point Revision || BYTE
|-
| 0x0B || Reserved || BYTE
|-
| 0x0C || Structure Table Maximum Size || DWORD
|-
| 0x10 || '''Structure Table Adress''' || QWORD
|}
|}
=== Locating the entry point structure ===
==== Non-UEFI systems ====
Under systems without UEFI, the Entry Point Structure is located somewhere in physical memory from address 0x000F0000 to 0x00FFFFF, with a 16 byte alignment.
* In 32-bit architectures, the SMBIOS EPS first contains (with offset 0) a string with the value "_SM_". This is what will help us search the location of the EPS.
* In 64-bit architectures, as in 32-bit, it first contains a string, but with the value "_SM3_" (The 3 stands for SMBIOS 3, which is the version in 64-bit machines).
This example C code searches the entry point in a 64-bit architecture. All it does is iterate for every 16-byte aligned memory addresses (from 0x000F0000 to 0x000FFFFF) and comparing 4 bytes from that address with the string "_SM3_". To acomplish that, it is needed to verify the checksum value (add all bytes and see if the lowest 8 bits of the result are zero):
<syntaxhighlight lang="c">
/* Start address */
char *eps = 0x000F0000;
int length, i;
while (eps <= (char*) 0x000FFFFF) {
/* Check Anchor String (64-bit version) */
if (!memcmp(eps, "_SM3_", 5)) {
length = eps[5];
checksum = 0;
/* Add all bytes
if (checksum == 0)
/* Done! */
break;
}
/* Next 16-byte-aligned address */
eps += 16;
}
</syntaxhighlight>
Now, ''eps'' contains the address of the Entry Point Structure. Some systems may not have the SMBIOS, so an error check may be a good idea:
<syntaxhighlight lang="c">
if ((unsigned int) eps == 0x00100000) {
/* Error, SMBIOS could not be located */
return -1;
}
</syntaxhighlight>
==== UEFI systems ====
On UEFI systems, the search-for-a-string method is not used to obtain the EPS. Instead, it is located by looking in the EFI Configuration Table for the SMBIOS Version 3 GUID (SMBIOS3_TABLE_GUID), which will contain a pointer to the structure.
This C code shows how that could get implemented using [[GNU-EFI]]:
<syntaxhighlight lang="c">
/* Will contain the address of the Entry Point Structure */
void *SMBIOS_Pointer = NULL;
UINTN status = LibGetSystemConfigurationTable(&SMBIOS3TableGuid, (void **)(&SMBIOS_Pointer));
/* Check all posible errors (maybe is not needed?) */
if (status != EFI_SUCCESS || SMBIOS_Pointer == NULL ||
CompareMem(SMBIOS_Pointer, "_SM3_", 5) ) {
/* Error, SMBIOS could not be located */
return -1;
}
</syntaxhighlight>
== Structure Table ==
Once the EPS is located in memory, information about the SMBIOS table can already be obtained. The most important one is the '''Structure Table Adress''', which is the address of the table that contains all the SMBIOS structures. The structures are located directly adjacent to each other in memory, with a new structure beginning as soon as another one ends. Each structure is composed of a header, a structure specific table, and a string table of variable length.
The first SMBIOS header is located at the '''Structure Table Adress'''. The value of ''type'' indicates what element the structure contains information about. ''length'' indicates the size of '''header + data table'''. The strings are not included in the length.
<syntaxhighlight lang="c">
struct SMBIOSHeader {
uint8_t type;
uint8_t length;
uint16_t handle;
};
</syntaxhighlight>
Immediately after the end of the header, is the data table. At the end of the data table (header address + length), the strings section starts. Each string is NULL terminated and is limited to 64 characters. Strings are referenced within tables by using an index into the string table (index 0 means that the string is effectively a NULL pointer and should be ignored). The first string begins immediately after the data, and the second string begins immediately after that, and so on. The string section itself is terminated by two consecutive zero bytes.
So, the end (and therefore the length) of the SMBIOS structure can be calculated by finding the two [[Null Character]]s in the string section. Your code might look like:
<syntaxhighlight lang="c">
size_t smbios_struct_len(struct SMBIOSHeader *hd)
{
size_t i;
const char *strtab = (char *)hd + hd->len;
// Scan until we find a double zero byte
for (i = 1; strtab[i - 1] != '\0' || strtab[i] != '\0'; i++)
;
return hd->len + i + 1;
}
</syntaxhighlight>
The final table is denoted by a ''type'' field of value 127.
As an example, the BIOS Struct (Type 0) might look like this:
<syntaxhighlight lang="asm">
db 0 ; Indicates BIOS Structure Type |
db 13h ; Length of information in bytes | HEADER
Line 96 ⟶ 205:
db 0 ; End of structure
</syntaxhighlight>
== Header Types ==
{| class="wikitable"
|-
Line 135 ⟶ 241:
|-
| 19
| Memory
|-
| 20
| Memory Device Mapped Address (optional as of SMBIOS 2.5)
|-
| 32
Line 144 ⟶ 253:
==See Also==
===Articles===
* [[ACPI]]
* [[DMI]]
===Forum Threads===
* http://www.osdev.org/phpBB2/viewtopic.php?t=16687 Info (saved here through lack of info)
===External Links===
* [http://www.dmtf.org/standards/smbios/ SMBIOS Specification]
[[Category:X86]]
[[Category:Standards]]
[[Category:Hardware Detection]]
|