+/*
+ * PROJECT: ReactOS DMI/SMBIOS Library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: dmilib.c
+ * PURPOSE: SMBIOS table parsing functions
+ * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
+ * REFERENCES: http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
+ */
+
+#include "precomp.h"
+
+static
+PCHAR
+GetDmiString(
+ _In_ PDMI_HEADER Header,
+ _In_ ULONG FieldOffset)
+{
+ ULONG StringIndex;
+ PCHAR String;
+
+ StringIndex = ((PUCHAR)Header)[FieldOffset];
+ if (StringIndex == 0)
+ {
+ return NULL;
+ }
+
+ String = (PCHAR)Header + Header->Length;
+
+ while (--StringIndex != 0)
+ {
+ while (*String != 0)
+ String++;
+
+ String++;
+ }
+
+ return String;
+}
+
+VOID
+ParseSMBiosTables(
+ _In_reads_bytes_(TableSize) PVOID SMBiosTables,
+ _In_ ULONG TableSize,
+ _Inout_updates_(ID_STRINGS_MAX) PCHAR * Strings)
+{
+ PMSSmBios_RawSMBiosTables BiosTablesHeader = SMBiosTables;
+ PDMI_HEADER Header;
+ ULONG Remaining;
+ PCHAR Data;
+
+ Header = (PDMI_HEADER)(&BiosTablesHeader->SMBiosData);
+ Remaining = BiosTablesHeader->Size;
+
+ while (Remaining >= sizeof(*Header))
+ {
+ if (Header->Type == DMI_ENTRY_END_OF_TABLE)
+ break;
+
+ switch (Header->Type)
+ {
+ case DMI_ENTRY_BIOS:
+ if (Remaining < DMI_BIOS_SIZE)
+ return;
+ Strings[BIOS_VENDOR] = GetDmiString(Header, DMI_BIOS_VENDOR);
+ Strings[BIOS_VERSION] = GetDmiString(Header, DMI_BIOS_VERSION);
+ Strings[BIOS_DATE] = GetDmiString(Header, DMI_BIOS_DATE);
+ break;
+
+ case DMI_ENTRY_SYSTEM:
+ if (Remaining < DMI_SYS_SIZE)
+ return;
+ Strings[SYS_VENDOR] = GetDmiString(Header, DMI_SYS_VENDOR);
+ Strings[SYS_PRODUCT] = GetDmiString(Header, DMI_SYS_PRODUCT);
+ Strings[SYS_VERSION] = GetDmiString(Header, DMI_SYS_VERSION);
+ Strings[SYS_SERIAL] = GetDmiString(Header, DMI_SYS_SERIAL);
+ break;
+
+ case DMI_ENTRY_BASEBOARD:
+ if (Remaining < DMI_BOARD_SIZE)
+ return;
+ Strings[BOARD_VENDOR] = GetDmiString(Header, DMI_BOARD_VENDOR);
+ Strings[BOARD_NAME] = GetDmiString(Header, DMI_BOARD_NAME);
+ Strings[BOARD_VERSION] = GetDmiString(Header, DMI_BOARD_VERSION);
+ Strings[BOARD_SERIAL] = GetDmiString(Header, DMI_BOARD_SERIAL);
+ Strings[BOARD_ASSET_TAG] = GetDmiString(Header, DMI_BOARD_ASSET_TAG);
+ break;
+
+ case DMI_ENTRY_CHASSIS:
+ case DMI_ENTRY_ONBOARD_DEVICE:
+ case DMI_ENTRY_OEMSTRINGS:
+ // DMI_ENTRY_IPMI_DEV?
+ // DMI_ENTRY_ONBOARD_DEV_EXT?
+ break;
+ }
+
+ Remaining -= Header->Length;
+ Data = (PCHAR)Header + Header->Length;
+
+ /* Now loop until we find 2 zeroes */
+ while ((Remaining >= 2) && ((Data[0] != 0) || (Data[1] != 0)))
+ {
+ Data++;
+ Remaining--;
+ }
+
+ if (Remaining < 2)
+ break;
+
+ /* Go to the next header */
+ Remaining -= 2;
+ Header = (PDMI_HEADER)((PUCHAR)Data + 2);
+ }
+}