xref: /reactos/sdk/lib/dmilib/dmilib.c (revision cc439606)
1 /*
2  * PROJECT:     ReactOS DMI/SMBIOS Library
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        dmilib.c
5  * PURPOSE:     SMBIOS table parsing functions
6  * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7  * REFERENCES:  http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
8  */
9 
10 #include "precomp.h"
11 
12 static
13 PCHAR
14 GetDmiString(
15     _In_ PDMI_HEADER Header,
16     _In_ ULONG FieldOffset)
17 {
18     ULONG StringIndex;
19     PCHAR String;
20 
21     StringIndex = ((PUCHAR)Header)[FieldOffset];
22     if (StringIndex == 0)
23     {
24         return NULL;
25     }
26 
27     String = (PCHAR)Header + Header->Length;
28 
29     while (--StringIndex != 0)
30     {
31         while (*String != 0)
32             String++;
33 
34         String++;
35     }
36 
37     return String;
38 }
39 
40 VOID
41 ParseSMBiosTables(
42     _In_reads_bytes_(TableSize) PVOID SMBiosTables,
43     _In_ ULONG TableSize,
44     _Inout_updates_(ID_STRINGS_MAX) PCHAR * Strings)
45 {
46     PMSSmBios_RawSMBiosTables BiosTablesHeader = SMBiosTables;
47     PDMI_HEADER Header;
48     ULONG Remaining;
49     PCHAR Data;
50 
51     Header = (PDMI_HEADER)(&BiosTablesHeader->SMBiosData);
52     Remaining = BiosTablesHeader->Size;
53 
54     while (Remaining >= sizeof(*Header))
55     {
56         if (Header->Type == DMI_ENTRY_END_OF_TABLE)
57             break;
58 
59         switch (Header->Type)
60         {
61         case DMI_ENTRY_BIOS:
62             if (Remaining < DMI_BIOS_SIZE)
63                 return;
64             Strings[BIOS_VENDOR] = GetDmiString(Header, DMI_BIOS_VENDOR);
65             Strings[BIOS_VERSION] = GetDmiString(Header, DMI_BIOS_VERSION);
66             Strings[BIOS_DATE] = GetDmiString(Header, DMI_BIOS_DATE);
67             break;
68 
69         case DMI_ENTRY_SYSTEM:
70             if (Remaining < DMI_SYS_SIZE)
71                 return;
72             Strings[SYS_VENDOR] = GetDmiString(Header, DMI_SYS_VENDOR);
73             Strings[SYS_PRODUCT] = GetDmiString(Header, DMI_SYS_PRODUCT);
74             Strings[SYS_VERSION] = GetDmiString(Header, DMI_SYS_VERSION);
75             Strings[SYS_SERIAL] = GetDmiString(Header, DMI_SYS_SERIAL);
76             Strings[SYS_SKU] = GetDmiString(Header, DMI_SYS_SKU);
77             Strings[SYS_FAMILY] = GetDmiString(Header, DMI_SYS_FAMILY);
78             break;
79 
80         case DMI_ENTRY_BASEBOARD:
81             if (Remaining < DMI_BOARD_SIZE)
82                 return;
83             Strings[BOARD_VENDOR] = GetDmiString(Header, DMI_BOARD_VENDOR);
84             Strings[BOARD_NAME] = GetDmiString(Header, DMI_BOARD_NAME);
85             Strings[BOARD_VERSION] = GetDmiString(Header, DMI_BOARD_VERSION);
86             Strings[BOARD_SERIAL] = GetDmiString(Header, DMI_BOARD_SERIAL);
87             Strings[BOARD_ASSET_TAG] = GetDmiString(Header, DMI_BOARD_ASSET_TAG);
88             break;
89 
90         case DMI_ENTRY_CHASSIS:
91         case DMI_ENTRY_ONBOARD_DEVICE:
92         case DMI_ENTRY_OEMSTRINGS:
93         // DMI_ENTRY_IPMI_DEV?
94         // DMI_ENTRY_ONBOARD_DEV_EXT?
95             break;
96         }
97 
98         Remaining -= Header->Length;
99         Data = (PCHAR)Header + Header->Length;
100 
101         /* Now loop until we find 2 zeroes */
102         while ((Remaining >= 2) && ((Data[0] != 0) || (Data[1] != 0)))
103         {
104             Data++;
105             Remaining--;
106         }
107 
108         if (Remaining < 2)
109             break;
110 
111         /* Go to the next header */
112         Remaining -= 2;
113         Header = (PDMI_HEADER)((PUCHAR)Data + 2);
114     }
115 }
116