Parse BIOS version

Signed-off-by: Lei YU <yulei.sh@bytedance.com>
Change-Id: I419c91e62f1960612ad356f6a3b7a88b5e82a5a8
diff --git a/src/inspur_oem.cpp b/src/inspur_oem.cpp
index 4f8d724..e427af8 100644
--- a/src/inspur_oem.cpp
+++ b/src/inspur_oem.cpp
@@ -7,12 +7,28 @@
 
 #include <optional>
 
+namespace
+{
+constexpr auto FIRMWARE_TYPE_OFFSET = 0;
+constexpr auto FIRMWARE_TYPE_SIZE = 1;
+constexpr auto FIRMWARE_VERSION_OFFSET =
+    FIRMWARE_TYPE_OFFSET + FIRMWARE_TYPE_SIZE;
+constexpr auto FIRMWARE_VERSION_SIZE = 15;
+constexpr auto FIRMWARE_BUILDTIME_OFFSET =
+    FIRMWARE_VERSION_OFFSET + FIRMWARE_VERSION_SIZE;
+constexpr auto FIRMWARE_BUILDTIME_SIZE = 20;
+
+static_assert(FIRMWARE_VERSION_OFFSET == 1);
+static_assert(FIRMWARE_BUILDTIME_OFFSET == 16);
+} // namespace
+
 namespace ipmi
 {
 
 #define UNUSED(x) (void)(x)
 
 using namespace phosphor::logging;
+using namespace inspur;
 
 static void registerOEMFunctions() __attribute__((constructor));
 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
@@ -94,10 +110,28 @@
     info.data.resize(dataLen);
     memcpy(info.data.data(), p, dataLen);
 
-    dumpAssetInfo(info);
+    //    dumpAssetInfo(info);
     return info;
 }
 
+void parseBIOSInfo(const std::vector<uint8_t>& data)
+{
+    bios_version_devname dev = static_cast<bios_version_devname>(data[0]);
+    std::string version{data.data() + FIRMWARE_VERSION_OFFSET,
+                        data.data() + FIRMWARE_VERSION_SIZE};
+    std::string buildTime;
+    if (dev == bios_version_devname::BIOS)
+    {
+        buildTime.assign(reinterpret_cast<const char*>(
+                             data.data() + FIRMWARE_BUILDTIME_OFFSET),
+                         FIRMWARE_BUILDTIME_SIZE);
+    }
+
+    printf("Dev %s, version %s, build time %s\n",
+           bios_devname[static_cast<int>(dev)].data(), version.c_str(),
+           buildTime.c_str());
+}
+
 ipmi_ret_t ipmiOemInspurAssetInfo(ipmi_netfn_t /* netfn */,
                                   ipmi_cmd_t /* cmd */, ipmi_request_t request,
                                   ipmi_response_t response,
@@ -117,9 +151,9 @@
     }
 
     // For now we only support BIOS type
-    printf("%s: Received BIOS info\n", __func__);
+    parseBIOSInfo(info->data);
 
-    return IPMI_CC_UNSPECIFIED_ERROR;
+    return IPMI_CC_OK;
 }
 
 void registerOEMFunctions(void)
diff --git a/src/inspur_oem.hpp b/src/inspur_oem.hpp
index c1d0440..8c47e8d 100644
--- a/src/inspur_oem.hpp
+++ b/src/inspur_oem.hpp
@@ -1,5 +1,10 @@
 #pragma once
+#include <array>
 #include <cstdint>
+#include <string_view>
+
+namespace inspur
+{
 
 enum ipmi_inspur_net_fns
 {
@@ -23,3 +28,21 @@
     uint8_t allInfoDone;
     uint16_t totalMessageLen;
 } __attribute__((packed));
+
+enum class bios_version_devname
+{
+    BIOS = 0,
+    ME = 1,
+    IE = 2,
+    PCH = 3,
+    BOARD = 4,
+    MRC = 5,
+    CUSTOM_ID = 6,
+    PCH_STEPPING = 7,
+};
+
+constexpr std::array<std::string_view, 8> bios_devname{
+    "BIOS", "ME", "IE", "PCH", "BOARD", "MRC", "CUSTOM_ID", "PCH_STEPPING",
+};
+
+} // namespace inspur