Add HSC version support for get OEMdevice info cmd

Added HSC version support for get OEM device info IPMI command.
With this patch able to populate HSC 1, 2, 3 inventory item versions to
get OEM device info command.

Tested:
Verified using IPMI command
Command : ipmitool raw 0x30 0x27 1 //Get OEM device info command
Response:  0a 00 87 02 01 02 01 06 02 00 00

Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
Change-Id: I8efffa774c73da00ec4b5df9f3480bca3c35dfd3
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index deecca7..aa99fed 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -316,6 +316,68 @@
     return IPMI_CC_OK;
 }
 
+bool getActiveHSCSoftwareVersionInfo(std::string& hscVersion, size_t hscNumber)
+{
+    std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+    try
+    {
+        std::string hsbpObjPath =
+            "/xyz/openbmc_project/software/HSBP_" + std::to_string(hscNumber);
+        auto service = getService(*dbus, biosVersionIntf, hsbpObjPath);
+        Value hscVersionValue =
+            getDbusProperty(*dbus, "xyz.openbmc_project.HsbpManager",
+                            hsbpObjPath, biosVersionIntf, "Version");
+        hscVersion = std::get<std::string>(hscVersionValue);
+    }
+    catch (const sdbusplus::exception::exception& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "Failed to retrieve HSBP version information",
+            phosphor::logging::entry("HSBP Number=%d", hscNumber));
+        return false;
+    }
+    return true;
+}
+
+bool getHscVerInfo(ipmi::Context::ptr ctx, uint8_t& hsc0Major,
+                   uint8_t& hsc0Minor, uint8_t& hsc1Major, uint8_t& hsc1Minor,
+                   uint8_t& hsc2Major, uint8_t& hsc2Minor)
+{
+    std::string hscVersion;
+    std::array<uint8_t, 6> hscVersions{0};
+
+    for (size_t hscNumber = 1; hscNumber <= 3; hscNumber++)
+    {
+        if (!getActiveHSCSoftwareVersionInfo(hscVersion, hscNumber))
+        {
+            continue;
+        }
+        std::regex pattern1("(\\d+?).(\\d+?).(\\d+?)");
+        constexpr size_t matchedPhosphor = 4;
+        std::smatch results;
+        // hscVersion = BOOT_VER.FPGA_VER.SECURITY_REVISION (Example: 00.02.01)
+        if (std::regex_match(hscVersion, results, pattern1))
+        {
+            // Major version is FPGA_VER and Minor version is SECURITY_REV
+            if (results.size() == matchedPhosphor)
+            {
+                int index = (hscNumber - 1) * 2;
+                hscVersions[index] =
+                    static_cast<uint8_t>(std::stoi(results[2]));
+                hscVersions[index + 1] =
+                    static_cast<uint8_t>(std::stoi(results[3]));
+            }
+        }
+    }
+    hsc0Major = hscVersions[0];
+    hsc0Minor = hscVersions[1];
+    hsc1Major = hscVersions[2];
+    hsc1Minor = hscVersions[3];
+    hsc2Major = hscVersions[4];
+    hsc2Minor = hscVersions[5];
+    return true;
+}
+
 bool getSwVerInfo(ipmi::Context::ptr ctx, uint8_t& bmcMajor, uint8_t& bmcMinor,
                   uint8_t& meMajor, uint8_t& meMinor)
 {
@@ -435,11 +497,15 @@
             std::array<uint8_t, verLen> meBuf = {0xff, 0xff};
             std::array<uint8_t, verLen> hsc2Buf = {0xff, 0xff};
             // data0/1: BMC version number; data6/7: ME version number
-            // the others: HSC0/1/2 version number, not avaible.
             if (!getSwVerInfo(ctx, bmcBuf[0], bmcBuf[1], meBuf[0], meBuf[1]))
             {
                 return ipmi::responseUnspecifiedError();
             }
+            if (!getHscVerInfo(ctx, hsc0Buf[0], hsc0Buf[1], hsc1Buf[0],
+                               hsc1Buf[1], hsc2Buf[0], hsc2Buf[1]))
+            {
+                return ipmi::responseUnspecifiedError();
+            }
             return ipmi::responseSuccess(
                 std::tuple<
                     uint8_t, std::array<uint8_t, verLen>,