Add SMBIOS 3.0 compatibility to version check

As per SMBIOS specification (DSP0134 Section 5.2.2) SMBIOS 3.0 requires
a different Entry Point Structure, including a different Anchor String
check.

Tested:
After appending the Entry Point Structure to the end of the SMBIOS
table, this code started working. We will most likely want to document
this somewhere as it's not industry standard to have the entry point
structure appended to the back like this.

Jan 01 00:01:03 smbiosmdrv2app[902]: SMBIOS 2.1 Anchor String not found. Looking for SMBIOS 3.0
Jan 01 00:03:05 smbiosmdrv2app[1680]: SMBIOS VERSION - 3.2
Jan 01 00:03:06 smbiosmdrv2app[1680]: VERSION INFO - BIOS - 99.99.99.99

Resolves: openbmc/smbios-mdr#3
Signed-off-by: Brandon Kim <brandonkim@google.com>
Change-Id: Ied5e0df545ec046cc1e0823d9f48317881493325
diff --git a/include/smbios_mdrv2.hpp b/include/smbios_mdrv2.hpp
index ed3cf34..3ebe8ab 100644
--- a/include/smbios_mdrv2.hpp
+++ b/include/smbios_mdrv2.hpp
@@ -125,7 +125,7 @@
     uint8_t minorVersion;
 } SMBIOSVersion;
 
-struct EntryPointStructure
+struct EntryPointStructure21
 {
     uint32_t anchorString;
     uint8_t epChecksum;
@@ -142,6 +142,19 @@
     uint8_t smbiosBDCRevision;
 } __attribute__((packed));
 
+struct EntryPointStructure30
+{
+    uint8_t anchorString[5];
+    uint8_t epChecksum;
+    uint8_t epLength;
+    SMBIOSVersion smbiosVersion;
+    uint8_t smbiosDocRev;
+    uint8_t epRevision;
+    uint8_t reserved;
+    uint32_t structTableMaxSize;
+    uint64_t structTableAddr;
+} __attribute__((packed));
+
 static constexpr const char* cpuPath =
     "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu";
 
diff --git a/src/mdrv2.cpp b/src/mdrv2.cpp
index 8e5883b..f7f428b 100644
--- a/src/mdrv2.cpp
+++ b/src/mdrv2.cpp
@@ -583,40 +583,68 @@
 
 bool MDR_V2::checkSMBIOSVersion(uint8_t* dataIn)
 {
-    const std::string anchorString = "_SM_";
+    const std::string anchorString21 = "_SM_";
+    const std::string anchorString30 = "_SM3_";
     std::string buffer(dataIn, dataIn + smbiosTableStorageSize);
 
     auto it = std::search(std::begin(buffer), std::end(buffer),
-                          std::begin(anchorString), std::end(anchorString));
-    if (it == std::end(buffer))
+                          std::begin(anchorString21), std::end(anchorString21));
+    bool smbios21Found = it != std::end(buffer);
+    if (!smbios21Found)
     {
-        phosphor::logging::log<phosphor::logging::level::ERR>(
-            "Anchor String not found");
-        return false;
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "SMBIOS 2.1 Anchor String not found. Looking for SMBIOS 3.0");
+        it = std::search(std::begin(buffer), std::end(buffer),
+                         std::begin(anchorString30), std::end(anchorString30));
+        if (it == std::end(buffer))
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "SMBIOS 2.1 and 3.0 Anchor Strings not found");
+            return false;
+        }
     }
 
     auto pos = std::distance(std::begin(buffer), it);
     auto length = smbiosTableStorageSize - pos;
-    if (length < sizeof(EntryPointStructure))
-    {
-        phosphor::logging::log<phosphor::logging::level::ERR>(
-            "Invalid entry point structure");
-        return false;
-    }
+    uint8_t foundMajorVersion;
+    uint8_t foundMinorVersion;
 
-    auto epStructure =
-        reinterpret_cast<const EntryPointStructure*>(&dataIn[pos]);
-    lg2::info("SMBIOS VERSION - {MAJOR}.{MINOR}", "MAJOR",
-              epStructure->smbiosVersion.majorVersion, "MINOR",
-              epStructure->smbiosVersion.minorVersion);
+    if (smbios21Found)
+    {
+        if (length < sizeof(EntryPointStructure21))
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Invalid entry point structure for SMBIOS 2.1");
+            return false;
+        }
+
+        auto epStructure =
+            reinterpret_cast<const EntryPointStructure21*>(&dataIn[pos]);
+        foundMajorVersion = epStructure->smbiosVersion.majorVersion;
+        foundMinorVersion = epStructure->smbiosVersion.minorVersion;
+    }
+    else
+    {
+        if (length < sizeof(EntryPointStructure30))
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Invalid entry point structure for SMBIOS 3.0");
+            return false;
+        }
+
+        auto epStructure =
+            reinterpret_cast<const EntryPointStructure30*>(&dataIn[pos]);
+        foundMajorVersion = epStructure->smbiosVersion.majorVersion;
+        foundMinorVersion = epStructure->smbiosVersion.minorVersion;
+    }
+    lg2::info("SMBIOS VERSION - {MAJOR}.{MINOR}", "MAJOR", foundMajorVersion,
+              "MINOR", foundMinorVersion);
 
     auto itr = std::find_if(
         std::begin(supportedSMBIOSVersions), std::end(supportedSMBIOSVersions),
         [&](SMBIOSVersion versionItr) {
-            return versionItr.majorVersion ==
-                       epStructure->smbiosVersion.majorVersion &&
-                   versionItr.minorVersion ==
-                       epStructure->smbiosVersion.minorVersion;
+            return versionItr.majorVersion == foundMajorVersion &&
+                   versionItr.minorVersion == foundMinorVersion;
         });
     if (itr == std::end(supportedSMBIOSVersions))
     {