oem-ibm: Maintain bootside Mapping and Set bios attribute

This commit adds code to maintain a mapping between running,
non-running and Temp, Perm side which would help the bmc
and remote PLDM terminus determine at any point in time if the
code update was successful and that remote PLDM terminus knows
exactly which side it is running on.

In the event the code update failed, then for that case
the new added bios attribute "fw_boot_side", which will
be set in the event. If BMC tries to boot from the new
"Temp" side (other side), and if it fails, then BMC must
update fw_boot_side to "Perm".

Change-Id: I9f1edad1e36850742aba88d93f8cf0fc8b9d8c8d
Signed-off-by: Archana Kakani <archana.kakani@ibm.com>
diff --git a/common/utils.hpp b/common/utils.hpp
index 23db119..c031af1 100644
--- a/common/utils.hpp
+++ b/common/utils.hpp
@@ -12,7 +12,9 @@
 #include <unistd.h>
 
 #include <nlohmann/json.hpp>
+#include <phosphor-logging/lg2.hpp>
 #include <sdbusplus/server.hpp>
+#include <xyz/openbmc_project/BIOSConfig/Manager/common.hpp>
 #include <xyz/openbmc_project/Inventory/Manager/client.hpp>
 #include <xyz/openbmc_project/Logging/Entry/server.hpp>
 #include <xyz/openbmc_project/ObjectMapper/client.hpp>
@@ -32,6 +34,8 @@
         std::chrono::seconds(DBUS_TIMEOUT))
         .count();
 
+PHOSPHOR_LOG2_USING;
+
 namespace pldm
 {
 namespace utils
@@ -202,12 +206,20 @@
 using PropertyMap = std::map<std::string, PropertyValue>;
 using InterfaceMap = std::map<std::string, PropertyMap>;
 using ObjectValueTree = std::map<sdbusplus::message::object_path, InterfaceMap>;
+using AttributeName = std::string;
+using AttributeType = std::string;
+using AttributeValue = std::variant<std::string, int64_t>;
+using PendingAttributesList = std::vector<
+    std::pair<AttributeName, std::tuple<AttributeType, AttributeValue>>>;
 
 using SensorPDR = std::vector<uint8_t>;
 using SensorPDRs = std::vector<SensorPDR>;
 using EffecterPDR = std::vector<uint8_t>;
 using EffecterPDRs = std::vector<EffecterPDR>;
 
+constexpr auto EnumAttribute =
+    "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration";
+
 /**
  * @brief The interface for DBusHandler
  */
@@ -687,5 +699,53 @@
 std::optional<uint32_t> fruFieldParserU32(const uint8_t* value,
                                           const uint8_t& length);
 
+/** @brief Method to get the value from a bios attribute
+ *
+ *  @param[in] dbusAttrName - the bios attribute name from
+ *             which the value must be retrieved
+ *
+ *  @return the attribute value
+ */
+template <typename T>
+std::optional<T> getBiosAttrValue(const std::string& dbusAttrName)
+{
+    constexpr auto biosConfigPath = "/xyz/openbmc_project/bios_config/manager";
+    constexpr auto biosConfigIntf = sdbusplus::common::xyz::openbmc_project::
+        bios_config::Manager::interface;
+
+    std::string var1;
+    std::variant<std::string, int64_t> var2, var3;
+    auto& bus = DBusHandler::getBus();
+    try
+    {
+        auto service = pldm::utils::DBusHandler().getService(biosConfigPath,
+                                                             biosConfigIntf);
+        auto method = bus.new_method_call(service.c_str(), biosConfigPath,
+                                          biosConfigIntf, "GetAttribute");
+        method.append(dbusAttrName);
+        auto reply = bus.call(method, dbusTimeout);
+        reply.read(var1, var2, var3);
+        if (auto ptr = std::get_if<T>(&var2))
+        {
+            return *ptr;
+        }
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        info("Error getting the bios attribute {BIOS_ATTR}: {ERR_EXCEP}",
+             "BIOS_ATTR", dbusAttrName, "ERR_EXCEP", e);
+    }
+
+    return std::nullopt;
+}
+
+/** @brief Method to set the specified bios attribute with
+ *         specified value
+ *
+ *  @param[in] PendingAttributesList - the list of bios attribute and values
+ *             to be set
+ */
+void setBiosAttr(const PendingAttributesList& biosAttrList);
+
 } // namespace utils
 } // namespace pldm