oem-meta: Add file IO responder for host bios version

Add handler for write-file command "BIOS_VERSION", which is sent
when host's postcode complete triggered, and update the bios version
to settingsd.

Tested: Verified in yosemite4 platform. The BIOS version was recorded
correctly.

Change-Id: I99580e3593cb417f6e350f5f1e7735fccf6e010b
Signed-off-by: Delphine CC Chiu <Delphine_CC_Chiu@wiwynn.com>
Signed-off-by: Sora Su <baxiche@gmail.com>
diff --git a/oem/meta/libpldmresponder/file_io.cpp b/oem/meta/libpldmresponder/file_io.cpp
index 3aac5a6..0471766 100644
--- a/oem/meta/libpldmresponder/file_io.cpp
+++ b/oem/meta/libpldmresponder/file_io.cpp
@@ -1,5 +1,6 @@
 #include "file_io.hpp"
 
+#include "file_io_type_bios_version.hpp"
 #include "file_io_type_post_code.hpp"
 
 #include <libpldm/oem/meta/file_io.h>
@@ -15,6 +16,9 @@
     {
         case FileIOType::POST_CODE:
             return std::make_unique<PostCodeHandler>(messageTid);
+        case FileIOType::BIOS_VERSION:
+            return std::make_unique<BIOSVersionHandler>(messageTid,
+                                                        dBusHandler);
         default:
             error("Get invalid file io type {FILEIOTYPE}", "FILEIOTYPE",
                   fileIOType);
diff --git a/oem/meta/libpldmresponder/file_io.hpp b/oem/meta/libpldmresponder/file_io.hpp
index 510d650..a5f29b0 100644
--- a/oem/meta/libpldmresponder/file_io.hpp
+++ b/oem/meta/libpldmresponder/file_io.hpp
@@ -16,7 +16,15 @@
 class FileIOHandler : public CmdHandler
 {
   public:
-    FileIOHandler()
+    FileIOHandler() = delete;
+    FileIOHandler(const FileIOHandler&) = delete;
+    FileIOHandler(FileIOHandler&&) = delete;
+    FileIOHandler& operator=(const FileIOHandler&) = delete;
+    FileIOHandler& operator=(FileIOHandler&&) = delete;
+    virtual ~FileIOHandler() = default;
+
+    explicit FileIOHandler(const pldm::utils::DBusHandler* dBusHandler) :
+        dBusHandler(dBusHandler)
     {
         handlers.emplace(
             PLDM_OEM_META_FILE_IO_CMD_WRITE_FILE,
@@ -32,12 +40,6 @@
             });
     }
 
-    FileIOHandler(const FileIOHandler&) = delete;
-    FileIOHandler(FileIOHandler&&) = delete;
-    FileIOHandler& operator=(const FileIOHandler&) = delete;
-    FileIOHandler& operator=(FileIOHandler&&) = delete;
-    virtual ~FileIOHandler() = default;
-
   private:
     /** @brief Handler for writeFileIO command
      *
@@ -63,6 +65,8 @@
 
     std::unique_ptr<FileHandler> getHandlerByType(pldm_tid_t tid,
                                                   FileIOType fileIOType);
+
+    const pldm::utils::DBusHandler* dBusHandler;
 };
 
 } // namespace pldm::responder::oem_meta
diff --git a/oem/meta/libpldmresponder/file_io_by_type.hpp b/oem/meta/libpldmresponder/file_io_by_type.hpp
index af13553..2e0e835 100644
--- a/oem/meta/libpldmresponder/file_io_by_type.hpp
+++ b/oem/meta/libpldmresponder/file_io_by_type.hpp
@@ -12,7 +12,8 @@
 
 enum class FileIOType : uint8_t
 {
-    POST_CODE = 0x00
+    POST_CODE = 0x00,
+    BIOS_VERSION = 0x01
 };
 
 /**
diff --git a/oem/meta/libpldmresponder/file_io_type_bios_version.cpp b/oem/meta/libpldmresponder/file_io_type_bios_version.cpp
new file mode 100644
index 0000000..c03c593
--- /dev/null
+++ b/oem/meta/libpldmresponder/file_io_type_bios_version.cpp
@@ -0,0 +1,69 @@
+#include "file_io_type_bios_version.hpp"
+
+#include "oem/meta/utils.hpp"
+
+#include <phosphor-logging/lg2.hpp>
+
+#include <sstream>
+#include <string>
+
+PHOSPHOR_LOG2_USING;
+namespace pldm::responder::oem_meta
+{
+
+int BIOSVersionHandler::write(const message& data)
+{
+    int completionCode = checkDataIntegrity(data);
+    if (completionCode != PLDM_SUCCESS)
+    {
+        error(
+            "Invalid incoming data for setting BIOS version with completion code {CC}",
+            "CC", completionCode);
+        return completionCode;
+    }
+
+    std::string slotNum = pldm::oem_meta::getSlotNumberStringByTID(tid);
+    pldm::utils::DBusMapping dbusMapping{
+        std::string("/xyz/openbmc_project/software/host") + slotNum +
+            "/Sentinel_Dome_bios",
+        "xyz.openbmc_project.Software.Version", "Version", "string"};
+
+    try
+    {
+        dBusIntf->setDbusProperty(dbusMapping, convertToBIOSVersionStr(data));
+    }
+    catch (const sdbusplus::exception_t& e)
+    {
+        error("Failed to execute Dbus call with error code {ERROR}", "ERROR",
+              e);
+    }
+    catch (const std::exception& e)
+    {
+        error("Failed to set BIOS version with error code {ERROR}", "ERROR", e);
+        return PLDM_ERROR;
+    }
+
+    return PLDM_SUCCESS;
+}
+
+int BIOSVersionHandler::checkDataIntegrity(const message& data)
+{
+    if (data.empty())
+    {
+        return PLDM_ERROR_INVALID_DATA;
+    }
+    else
+    {
+        return PLDM_SUCCESS;
+    }
+}
+
+pldm::utils::PropertyValue BIOSVersionHandler::convertToBIOSVersionStr(
+    const message& data)
+{
+    std::string biosVersion(data.begin(), data.end());
+
+    return pldm::utils::PropertyValue{biosVersion};
+}
+
+} // namespace pldm::responder::oem_meta
diff --git a/oem/meta/libpldmresponder/file_io_type_bios_version.hpp b/oem/meta/libpldmresponder/file_io_type_bios_version.hpp
new file mode 100644
index 0000000..9e2a971
--- /dev/null
+++ b/oem/meta/libpldmresponder/file_io_type_bios_version.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "common/utils.hpp"
+#include "file_io_by_type.hpp"
+#include "oem/meta/utils.hpp"
+
+namespace pldm::responder::oem_meta
+{
+
+/** @class PowerStatusHandler
+ *
+ *  @brief Inherits and implements FileHandler. This class is used
+ *  to set BMC's Host BIOS version based on the incoming request.
+ */
+class BIOSVersionHandler : public FileHandler
+{
+  public:
+    BIOSVersionHandler() = delete;
+    BIOSVersionHandler(const BIOSVersionHandler&) = delete;
+    BIOSVersionHandler(BIOSVersionHandler&&) = delete;
+    BIOSVersionHandler& operator=(const BIOSVersionHandler&) = delete;
+    BIOSVersionHandler& operator=(BIOSVersionHandler&&) = delete;
+
+    explicit BIOSVersionHandler(pldm_tid_t tid,
+                                const pldm::utils::DBusHandler* dBusIntf) :
+        tid(tid), dBusIntf(dBusIntf)
+    {}
+
+    ~BIOSVersionHandler() = default;
+
+    /** @brief Method to set Host's BIOS version.
+     *  @param[in] data - BIOS version raw data.
+     *  @return  PLDM completion code.
+     */
+    int write(const message& data) override;
+
+  private:
+    /** @brief Method to convert raw data to BIOS string Dbus value.
+     *  @param[in] data - Incoming data.
+     *  @return - BIOS version Dbus value
+     */
+    pldm::utils::PropertyValue convertToBIOSVersionStr(const message& data);
+
+    /** @brief Method to check raw data integrity.
+     *  @param[in] data - List of Incoming raw data.
+     *  @return - PLDM completion code.
+     */
+    int checkDataIntegrity(const message& data);
+
+    /** @brief The requester's TID */
+    pldm_tid_t tid = 0;
+
+    /** @brief D-Bus Interface object*/
+    const pldm::utils::DBusHandler* dBusIntf;
+};
+
+} // namespace pldm::responder::oem_meta
diff --git a/oem/meta/libpldmresponder/meson.build b/oem/meta/libpldmresponder/meson.build
index 21d84bc..7dd8eea 100644
--- a/oem/meta/libpldmresponder/meson.build
+++ b/oem/meta/libpldmresponder/meson.build
@@ -1 +1,5 @@
-oem_files += files('file_io.cpp', 'file_io_type_post_code.cpp')
+oem_files += files(
+    'file_io.cpp',
+    'file_io_type_bios_version.cpp',
+    'file_io_type_post_code.cpp',
+)
diff --git a/oem/meta/oem_meta.cpp b/oem/meta/oem_meta.cpp
index 661fa95..4446ba1 100644
--- a/oem/meta/oem_meta.cpp
+++ b/oem/meta/oem_meta.cpp
@@ -7,14 +7,15 @@
 namespace pldm::oem_meta
 {
 
-OemMETA::OemMETA(pldm::responder::Invoker& invoker,
+OemMETA::OemMETA(const pldm::utils::DBusHandler* dbusHandler,
+                 pldm::responder::Invoker& invoker,
                  pldm::responder::platform::Handler* platformHandler)
 {
     oemEventManager = std::make_unique<oem_meta::OemEventManager>();
     registerOemEventHandler(platformHandler);
 
     auto fileIOHandler =
-        std::make_unique<pldm::responder::oem_meta::FileIOHandler>();
+        std::make_unique<pldm::responder::oem_meta::FileIOHandler>(dbusHandler);
     registerOemHandler(invoker, std::move(fileIOHandler));
 }
 
diff --git a/oem/meta/oem_meta.hpp b/oem/meta/oem_meta.hpp
index df67367..7f0d35d 100644
--- a/oem/meta/oem_meta.hpp
+++ b/oem/meta/oem_meta.hpp
@@ -26,10 +26,12 @@
 
   public:
     /** @brief Constucts OemMETA object
+     *  @param[in] dBusIntf - D-Bus handler
      *  @param[in] invoker - invoker handler
      *  @param[in] platformHandler - platformHandler handler
      */
-    explicit OemMETA(pldm::responder::Invoker& invoker,
+    explicit OemMETA(const pldm::utils::DBusHandler* dbusHandler,
+                     pldm::responder::Invoker& invoker,
                      pldm::responder::platform::Handler* platformHandler);
 
   private:
diff --git a/pldmd/pldmd.cpp b/pldmd/pldmd.cpp
index f82a654..52864e8 100644
--- a/pldmd/pldmd.cpp
+++ b/pldmd/pldmd.cpp
@@ -326,7 +326,8 @@
 #endif
 
 #ifdef OEM_META
-    pldm::oem_meta::OemMETA oemMETA(invoker, platformHandler.get());
+    pldm::oem_meta::OemMETA oemMETA(&dbusHandler, invoker,
+                                    platformHandler.get());
 #endif
 
 #ifdef OEM_IBM