Add OEM get BMC Version String command

Change-Id: If8704427844eee4f54173425a2b74787f939a9cf
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index 4f8166f..49b66cd 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -29,6 +29,7 @@
 
 namespace general
 {
+static constexpr Cmd cmdGetBmcVersionString = 0x01;
 static constexpr Cmd cmdRestoreConfiguration = 0x02;
 static constexpr Cmd cmdGetSmSignal = 0x14;
 static constexpr Cmd cmdSetSmSignal = 0x15;
diff --git a/ipmi-allowlist.conf b/ipmi-allowlist.conf
index 792e38f..af82e2f 100644
--- a/ipmi-allowlist.conf
+++ b/ipmi-allowlist.conf
@@ -182,6 +182,7 @@
 0x2e:0xF0:0x7f7f   //<Intel OEM>:<Set HW Protection Coefficient>
 0x2e:0xF1:0xff7f   //<Intel OEM>:<Get HW Protection Coefficient>
 0x2e:0xF2:0xff7f   //<Intel OEM>:<Get Limiting Policy ID>
+0x30:0x01:0x7f7f   //<Intel General Application>:<Get FW Version String>
 0x30:0x02:0x7f7f   //<Intel General Application>:<Restore Configuration>
 0x30:0x03:0x7f7f   //<Intel General Application>:<Restore SDR>
 0x30:0x04:0xff7f   //<Intel General Application>:<Get NW Switch MIB>
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index 390e112..4e3b7a5 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -274,6 +274,43 @@
 
 } // namespace mailbox
 
+ipmi::RspType<std::string> ipmiOEMGetBmcVersionString()
+{
+    static std::string version{};
+    if (version.empty())
+    {
+        std::regex expr{"^VERSION_ID=(.*)$"};
+        static constexpr auto osReleasePath{"/etc/os-release"};
+        std::ifstream ifs(osReleasePath);
+        if (!ifs.is_open())
+        {
+            version = "os-release not present";
+        }
+        std::string line{};
+        while (std::getline(ifs, line))
+        {
+            std::smatch sm;
+            if (regex_match(line, sm, expr))
+            {
+                if (sm.size() == 2)
+                {
+                    std::string v = sm[1].str();
+                    // remove the quotes
+                    v.erase(std::remove(v.begin(), v.end(), '\"'), v.end());
+                    version = v;
+                    break;
+                }
+            }
+        }
+        ifs.close();
+        if (version.empty())
+        {
+            version = "VERSION_ID not present";
+        }
+    }
+    return ipmi::responseSuccess(version);
+}
+
 // Returns the Chassis Identifier (serial #)
 ipmi_ret_t ipmiOEMGetChassisIdentifier(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                                        ipmi_request_t request,
@@ -3963,6 +4000,10 @@
 {
     phosphor::logging::log<phosphor::logging::level::INFO>(
         "Registering OEM commands");
+    registerHandler(prioOemBase, intel::netFnGeneral,
+                    intel::general::cmdGetBmcVersionString, Privilege::User,
+                    ipmiOEMGetBmcVersionString);
+
     ipmiPrintAndRegister(intel::netFnGeneral,
                          intel::general::cmdGetChassisIdentifier, NULL,
                          ipmiOEMGetChassisIdentifier,