bios: Initialise the bios attributes from bios-settings-manager

The bios-settings-manager is persisting the current value for the PLDM
BIOS attributes. The PLDM daemon will lookup the bios-settings-manager
for the current value and create the BIOS attribute value table.

Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
Change-Id: I6a7a9ff9c3766189e6a64ab88c5c5e438881151f
diff --git a/libpldmresponder/bios_attribute.hpp b/libpldmresponder/bios_attribute.hpp
index d712429..ebdf1dc 100644
--- a/libpldmresponder/bios_attribute.hpp
+++ b/libpldmresponder/bios_attribute.hpp
@@ -57,9 +57,13 @@
      *  @param[in] stringTable - The string Table
      *  @param[in,out] attrTable - The attribute table
      *  @param[in,out] attrValueTable - The attribute value table
+     *  @param[in,out] optAttributeValue - init value of the attribute
      */
-    virtual void constructEntry(const BIOSStringTable& stringTable,
-                                Table& attrTable, Table& attrValueTable) = 0;
+    virtual void constructEntry(
+        const BIOSStringTable& stringTable, Table& attrTable,
+        Table& attrValueTable,
+        std::optional<std::variant<int64_t, std::string>> optAttributeValue =
+            std::nullopt) = 0;
 
     /** @brief Method to update the value for an attribute
      *  @param[in,out] newValue - An attribute value table row with the new
diff --git a/libpldmresponder/bios_config.cpp b/libpldmresponder/bios_config.cpp
index 5497ac6..b61b3b6 100644
--- a/libpldmresponder/bios_config.cpp
+++ b/libpldmresponder/bios_config.cpp
@@ -476,13 +476,51 @@
         return;
     }
 
+    BaseBIOSTable biosTable{};
+    constexpr auto biosObjPath = "/xyz/openbmc_project/bios_config/manager";
+    constexpr auto biosInterface = "xyz.openbmc_project.BIOSConfig.Manager";
+
+    try
+    {
+        auto& bus = dbusHandler->getBus();
+        auto service = dbusHandler->getService(biosObjPath, biosInterface);
+        auto method =
+            bus.new_method_call(service.c_str(), biosObjPath,
+                                "org.freedesktop.DBus.Properties", "Get");
+        method.append(biosInterface, "BaseBIOSTable");
+        auto reply = bus.call(method);
+        std::variant<BaseBIOSTable> varBiosTable{};
+        reply.read(varBiosTable);
+        biosTable = std::get<BaseBIOSTable>(varBiosTable);
+    }
+    // Failed to read the BaseBIOSTable, so update the BaseBIOSTable with the
+    // default values populated from the BIOS JSONs to keep PLDM and
+    // bios-settings-manager in sync
+    catch (const std::exception& e)
+    {
+        std::cerr << "Failed to read BaseBIOSTable property, ERROR=" << e.what()
+                  << "\n";
+    }
+
     Table attrTable, attrValueTable;
 
     for (auto& attr : biosAttributes)
     {
         try
         {
-            attr->constructEntry(biosStringTable, attrTable, attrValueTable);
+            auto iter = biosTable.find(attr->name);
+            if (iter == biosTable.end())
+            {
+                attr->constructEntry(biosStringTable, attrTable, attrValueTable,
+                                     std::nullopt);
+            }
+            else
+            {
+                attr->constructEntry(
+                    biosStringTable, attrTable, attrValueTable,
+                    std::get<static_cast<uint8_t>(Index::currentValue)>(
+                        iter->second));
+            }
         }
         catch (const std::exception& e)
         {
diff --git a/libpldmresponder/bios_config.hpp b/libpldmresponder/bios_config.hpp
index 4cfa582..287633c 100644
--- a/libpldmresponder/bios_config.hpp
+++ b/libpldmresponder/bios_config.hpp
@@ -112,6 +112,20 @@
                      bool updateBaseBIOSTable = true);
 
   private:
+    /** @enum Index into the fields in the BaseBIOSTable
+     */
+    enum class Index : uint8_t
+    {
+        attributeType = 0,
+        readOnly,
+        displayName,
+        description,
+        menuPath,
+        currentValue,
+        defaultValue,
+        options,
+    };
+
     const fs::path jsonDir;
     const fs::path tableDir;
     DBusHandler* const dbusHandler;
@@ -202,7 +216,10 @@
      */
     std::optional<Table> buildAndStoreStringTable();
 
-    /** @brief Build attr table and attr value table and persist them
+    /** @brief Build attribute table and attribute value table and persist them
+     *         Read the BaseBIOSTable from the bios-settings-manager and update
+     *         attribute table and attribute value table.
+     *
      *  @param[in] stringTable - The string Table
      */
     void buildAndStoreAttrTables(const Table& stringTable);
diff --git a/libpldmresponder/bios_enum_attribute.cpp b/libpldmresponder/bios_enum_attribute.cpp
index a5c7ee4..0808898 100644
--- a/libpldmresponder/bios_enum_attribute.cpp
+++ b/libpldmresponder/bios_enum_attribute.cpp
@@ -195,8 +195,9 @@
     dbusHandler->setDbusProperty(*dBusMap, it->first);
 }
 
-void BIOSEnumAttribute::constructEntry(const BIOSStringTable& stringTable,
-                                       Table& attrTable, Table& attrValueTable)
+void BIOSEnumAttribute::constructEntry(
+    const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
+    std::optional<std::variant<int64_t, std::string>> optAttributeValue)
 {
     auto possibleValuesHandle =
         getPossibleValuesHandle(stringTable, possibleValues);
@@ -215,7 +216,24 @@
         table::attribute::decodeHeader(attrTableEntry);
 
     std::vector<uint8_t> currValueIndices(1, 0);
-    currValueIndices[0] = getAttrValueIndex();
+
+    if (optAttributeValue.has_value())
+    {
+        auto attributeValue = optAttributeValue.value();
+        if (attributeValue.index() == 1)
+        {
+            auto currValue = std::get<std::string>(attributeValue);
+            currValueIndices[0] = getValueIndex(currValue, possibleValues);
+        }
+        else
+        {
+            currValueIndices[0] = getAttrValueIndex();
+        }
+    }
+    else
+    {
+        currValueIndices[0] = getAttrValueIndex();
+    }
 
     table::attribute_value::constructEnumEntry(attrValueTable, attrHandle,
                                                attrType, currValueIndices);
diff --git a/libpldmresponder/bios_enum_attribute.hpp b/libpldmresponder/bios_enum_attribute.hpp
index e69d76d..48492cc 100644
--- a/libpldmresponder/bios_enum_attribute.hpp
+++ b/libpldmresponder/bios_enum_attribute.hpp
@@ -47,9 +47,12 @@
      *  @param[in] stringTable - The string Table
      *  @param[in,out] attrTable - The attribute table
      *  @param[in,out] attrValueTable - The attribute value table
+     *  @param[in,out] optAttributeValue - init value of the attribute
      */
     void constructEntry(const BIOSStringTable& stringTable, Table& attrTable,
-                        Table& attrValueTable) override;
+                        Table& attrValueTable,
+                        std::optional<std::variant<int64_t, std::string>>
+                            optAttributeValue = std::nullopt) override;
 
     /** @brief Generate attribute entry by the spec DSP0247_1.0.0 Table 14
      *  @param[in] attributevalue - attribute value(Enumeration, String and
diff --git a/libpldmresponder/bios_integer_attribute.cpp b/libpldmresponder/bios_integer_attribute.cpp
index 4a23ace..9753ef8 100644
--- a/libpldmresponder/bios_integer_attribute.cpp
+++ b/libpldmresponder/bios_integer_attribute.cpp
@@ -98,9 +98,9 @@
     throw std::invalid_argument("dbus type error");
 }
 
-void BIOSIntegerAttribute::constructEntry(const BIOSStringTable& stringTable,
-                                          Table& attrTable,
-                                          Table& attrValueTable)
+void BIOSIntegerAttribute::constructEntry(
+    const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
+    std::optional<std::variant<int64_t, std::string>> optAttributeValue)
 {
 
     pldm_bios_table_attr_entry_integer_info info = {
@@ -115,7 +115,24 @@
     auto [attrHandle, attrType, _] =
         table::attribute::decodeHeader(attrTableEntry);
 
-    auto currentValue = getAttrValue();
+    int64_t currentValue{};
+    if (optAttributeValue.has_value())
+    {
+        auto attributeValue = optAttributeValue.value();
+        if (attributeValue.index() == 0)
+        {
+            currentValue = std::get<int64_t>(attributeValue);
+        }
+        else
+        {
+            currentValue = getAttrValue();
+        }
+    }
+    else
+    {
+        currentValue = getAttrValue();
+    }
+
     table::attribute_value::constructIntegerEntry(attrValueTable, attrHandle,
                                                   attrType, currentValue);
 }
diff --git a/libpldmresponder/bios_integer_attribute.hpp b/libpldmresponder/bios_integer_attribute.hpp
index 5f2773a..033c18f 100644
--- a/libpldmresponder/bios_integer_attribute.hpp
+++ b/libpldmresponder/bios_integer_attribute.hpp
@@ -43,9 +43,12 @@
      *  @param[in] stringTable - The string Table
      *  @param[in,out] attrTable - The attribute table
      *  @param[in,out] attrValueTable - The attribute value table
+     *  @param[in,out] optAttributeValue - init value of the attribute
      */
     void constructEntry(const BIOSStringTable& stringTable, Table& attrTable,
-                        Table& attrValueTable) override;
+                        Table& attrValueTable,
+                        std::optional<std::variant<int64_t, std::string>>
+                            optAttributeValue = std::nullopt) override;
 
     /** @brief Generate attribute entry by the spec DSP0247_1.0.0 Table 14
      *  @param[in] attributevalue - attribute value(Enumeration, String and
diff --git a/libpldmresponder/bios_string_attribute.cpp b/libpldmresponder/bios_string_attribute.cpp
index 41538b6..4f9bc4f 100644
--- a/libpldmresponder/bios_string_attribute.cpp
+++ b/libpldmresponder/bios_string_attribute.cpp
@@ -90,9 +90,9 @@
     }
 }
 
-void BIOSStringAttribute::constructEntry(const BIOSStringTable& stringTable,
-                                         Table& attrTable,
-                                         Table& attrValueTable)
+void BIOSStringAttribute::constructEntry(
+    const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
+    std::optional<std::variant<int64_t, std::string>> optAttributeValue)
 {
     pldm_bios_table_attr_entry_string_info info = {
         stringTable.findHandle(name), readOnly,
@@ -105,7 +105,25 @@
         table::attribute::constructStringEntry(attrTable, &info);
     auto [attrHandle, attrType, _] =
         table::attribute::decodeHeader(attrTableEntry);
-    auto currStr = getAttrValue();
+
+    std::string currStr{};
+    if (optAttributeValue.has_value())
+    {
+        auto attributeValue = optAttributeValue.value();
+        if (attributeValue.index() == 1)
+        {
+            currStr = std::get<std::string>(attributeValue);
+        }
+        else
+        {
+            currStr = getAttrValue();
+        }
+    }
+    else
+    {
+        currStr = getAttrValue();
+    }
+
     table::attribute_value::constructStringEntry(attrValueTable, attrHandle,
                                                  attrType, currStr);
 }
diff --git a/libpldmresponder/bios_string_attribute.hpp b/libpldmresponder/bios_string_attribute.hpp
index b079401..ff364ec 100644
--- a/libpldmresponder/bios_string_attribute.hpp
+++ b/libpldmresponder/bios_string_attribute.hpp
@@ -66,9 +66,12 @@
      *  @param[in] stringTable - The string Table
      *  @param[in,out] attrTable - The attribute table
      *  @param[in,out] attrValueTable - The attribute value table
+     *  @param[in,out] optAttributeValue - init value of the attribute
      */
     void constructEntry(const BIOSStringTable& stringTable, Table& attrTable,
-                        Table& attrValueTable) override;
+                        Table& attrValueTable,
+                        std::optional<std::variant<int64_t, std::string>>
+                            optAttributeValue = std::nullopt) override;
 
     /** @brief Generate attribute entry by the spec DSP0247_1.0.0 Table 14
      *  @param[in] attributevalue - attribute value(Enumeration, String and