PLDM: System specific BIOS attributes

This commit adds code to populate BIOS attributes
based on the system type that is the platform.

The BIOS Jsons are installed based on the platform/
system type. The system type is populated by entity
manager.

TESTED on hardware across different platform/system type.
On systems where the compatible system interface is not
implemented or entity manager not running, then the BIOS
Jsons with default values are installed.

Signed-off-by: Sagar Srinivas <sagar.srinivas@ibm.com>
Change-Id: I179dad34537ed0d1fb263584d687a1b8cb64c335
diff --git a/libpldmresponder/test/libpldmresponder_bios_config_test.cpp b/libpldmresponder/test/libpldmresponder_bios_config_test.cpp
index 4990f5a..d70a961 100644
--- a/libpldmresponder/test/libpldmresponder_bios_config_test.cpp
+++ b/libpldmresponder/test/libpldmresponder_bios_config_test.cpp
@@ -2,6 +2,7 @@
 #include "common/test/mocked_utils.hpp"
 #include "libpldmresponder/bios_config.hpp"
 #include "libpldmresponder/bios_string_attribute.hpp"
+#include "libpldmresponder/oem_handler.hpp"
 #include "mocked_bios.hpp"
 
 #include <nlohmann/json.hpp>
@@ -18,6 +19,8 @@
 
 using ::testing::_;
 using ::testing::ElementsAreArray;
+using ::testing::Return;
+using ::testing::StrEq;
 using ::testing::Throw;
 
 class TestBIOSConfig : public ::testing::Test
@@ -74,15 +77,28 @@
 fs::path TestBIOSConfig::tableDir;
 std::vector<Json> TestBIOSConfig::jsons;
 
+class MockBiosSystemConfig : public pldm::responder::oem_bios::Handler
+{
+  public:
+    MockBiosSystemConfig(const pldm::utils::DBusHandler* dBusIntf) :
+        pldm::responder::oem_bios::Handler(dBusIntf)
+    {}
+    MOCK_METHOD(void, ibmCompatibleAddedCallback,
+                (sdbusplus::message::message&), ());
+    MOCK_METHOD(std::optional<std::string>, getPlatformName, ());
+};
+
 TEST_F(TestBIOSConfig, buildTablesTest)
 {
     MockdBusHandler dbusHandler;
 
+    MockBiosSystemConfig mockBiosSystemConfig(&dbusHandler);
+
     ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
         .WillByDefault(Throw(std::exception()));
 
     BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
-                          nullptr, nullptr);
+                          nullptr, nullptr, &mockBiosSystemConfig);
     biosConfig.buildTables();
 
     auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
@@ -101,6 +117,7 @@
                                              "Temp",
                                              "InbandCodeUpdate",
                                              "Allowed",
+                                             "Allowed",
                                              "NotAllowed",
                                              "CodeUpdatePolicy",
                                              "Concurrent",
@@ -246,12 +263,87 @@
     }
 }
 
+TEST_F(TestBIOSConfig, buildTablesSystemSpecificTest)
+{
+    MockdBusHandler dbusHandler;
+
+    MockBiosSystemConfig mockBiosSystemConfig(&dbusHandler);
+
+    ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
+        .WillByDefault(Throw(std::exception()));
+
+    BIOSConfig biosConfig("./system_type1/bios_jsons", tableDir.c_str(),
+                          &dbusHandler, 0, 0, nullptr, nullptr,
+                          &mockBiosSystemConfig);
+
+    biosConfig.buildTables();
+
+    auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
+    auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
+    auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
+
+    EXPECT_TRUE(stringTable);
+    EXPECT_TRUE(attrTable);
+    EXPECT_TRUE(attrValueTable);
+
+    BIOSStringTable biosStringTable(*stringTable);
+
+    for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
+                                                          attrTable->size()))
+    {
+        auto header = table::attribute::decodeHeader(entry);
+        auto attrName = biosStringTable.findString(header.stringHandle);
+        auto jsonEntry = findJsonEntry(attrName);
+        EXPECT_TRUE(jsonEntry);
+        switch (header.attrType)
+        {
+            case PLDM_BIOS_STRING:
+            case PLDM_BIOS_STRING_READ_ONLY:
+            {
+                if (attrName == "str_example2")
+                {
+                    auto stringField =
+                        table::attribute::decodeStringEntry(entry);
+                    EXPECT_EQ(stringField.maxLength, 200);
+                }
+
+                break;
+            }
+            case PLDM_BIOS_INTEGER:
+            case PLDM_BIOS_INTEGER_READ_ONLY:
+            {
+                if (attrName == "SBE_IMAGE_MINIMUM_VALID_ECS")
+                {
+                    auto integerField =
+                        table::attribute::decodeIntegerEntry(entry);
+                    EXPECT_EQ(integerField.upperBound, 30);
+                }
+                break;
+            }
+            case PLDM_BIOS_ENUMERATION:
+            case PLDM_BIOS_ENUMERATION_READ_ONLY:
+            {
+                if (attrName == "FWBootSide")
+                {
+                    auto [pvHdls,
+                          defInds] = table::attribute::decodeEnumEntry(entry);
+                    auto defValue =
+                        biosStringTable.findString(pvHdls[defInds[0]]);
+                    EXPECT_EQ(defValue, "Temp");
+                }
+            }
+        }
+    }
+}
+
 TEST_F(TestBIOSConfig, setAttrValue)
 {
     MockdBusHandler dbusHandler;
 
+    MockBiosSystemConfig mockBiosSystemConfig(&dbusHandler);
+
     BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
-                          nullptr, nullptr);
+                          nullptr, nullptr, &mockBiosSystemConfig);
     biosConfig.removeTables();
     biosConfig.buildTables();
 
diff --git a/libpldmresponder/test/system_type1/bios_jsons/enum_attrs.json b/libpldmresponder/test/system_type1/bios_jsons/enum_attrs.json
new file mode 100644
index 0000000..18c221b
--- /dev/null
+++ b/libpldmresponder/test/system_type1/bios_jsons/enum_attrs.json
@@ -0,0 +1,60 @@
+{
+    "entries": [
+        {
+            "attribute_name": "HMCManagedState",
+            "possible_values": ["On", "Off"],
+            "default_values": ["On"],
+            "readOnly": false,
+            "helpText": "HMCManagedState HelpText",
+            "displayName": "HMCManagedState DisplayName",
+            "dbus": {
+                "object_path": "/xyz/abc/def",
+                "interface": "xyz.openbmc_project.HMCManaged.State",
+                "property_name": "State",
+                "property_type": "string",
+                "property_values": [
+                    "xyz.openbmc_project.State.On",
+                    "xyz.openbmc_project.State.Off"
+                ]
+            }
+        },
+        {
+            "attribute_name": "FWBootSide",
+            "possible_values": ["Perm", "Temp"],
+            "default_values": ["Temp"],
+            "readOnly": false,
+            "helpText": "FWBootSide HelpText",
+            "displayName": "FWBootSide DisplayName",
+            "dbus": {
+                "object_path": "/xyz/abc/def",
+                "interface": "xyz.openbmc.FWBoot.Side",
+                "property_name": "Side",
+                "property_type": "bool",
+                "property_values": [true, false]
+            }
+        },
+        {
+            "attribute_name": "InbandCodeUpdate",
+            "possible_values": ["Allowed", "NotAllowed"],
+            "default_values": ["Allowed"],
+            "readOnly": false,
+            "helpText": "InbandCodeUpdate HelpText",
+            "displayName": "InbandCodeUpdate DisplayName",
+            "dbus": {
+                "object_path": "/xyz/abc/def",
+                "interface": "xyz.openbmc.InBandCodeUpdate",
+                "property_name": "Policy",
+                "property_type": "uint8_t",
+                "property_values": [0, 1]
+            }
+        },
+        {
+            "attribute_name": "CodeUpdatePolicy",
+            "possible_values": ["Concurrent", "Disruptive"],
+            "default_values": ["Concurrent"],
+            "readOnly": true,
+            "helpText": "CodeUpdatePolicy HelpText",
+            "displayName": "CodeUpdatePolicy DisplayName"
+        }
+    ]
+}
diff --git a/libpldmresponder/test/system_type1/bios_jsons/integer_attrs.json b/libpldmresponder/test/system_type1/bios_jsons/integer_attrs.json
new file mode 100644
index 0000000..b735630
--- /dev/null
+++ b/libpldmresponder/test/system_type1/bios_jsons/integer_attrs.json
@@ -0,0 +1,40 @@
+{
+    "entries": [
+        {
+            "attribute_name": "VDD_AVSBUS_RAIL",
+            "lower_bound": 0,
+            "upper_bound": 15,
+            "scalar_increment": 1,
+            "default_value": 0,
+            "readOnly": false,
+            "helpText": "VDD_AVSBUS_RAIL HelpText",
+            "displayName": "VDD_AVSBUS_RAIL DisplayName",
+            "dbus": {
+                "object_path": "/xyz/openbmc_project/avsbus",
+                "interface": "xyz.openbmc.AvsBus.Manager",
+                "property_type": "uint8_t",
+                "property_name": "Rail"
+            }
+        },
+        {
+            "attribute_name": "SBE_IMAGE_MINIMUM_VALID_ECS",
+            "lower_bound": 1,
+            "upper_bound": 30,
+            "scalar_increment": 1,
+            "default_value": 2,
+            "readOnly": true,
+            "helpText": "SBE_IMAGE_MINIMUM_VALID_ECS HelpText",
+            "displayName": "SBE_IMAGE_MINIMUM_VALID_ECS DisplayName"
+        },
+        {
+            "attribute_name": "INTEGER_INVALID_CASE",
+            "lower_bound": 1,
+            "upper_bound": 15,
+            "scalar_increment": 2,
+            "default_value": 3,
+            "readOnly": true,
+            "helpText": "INTEGER_INVALID_CASE HelpText",
+            "displayName": "INTEGER_INVALID_CASE DisplayName"
+        }
+    ]
+}
diff --git a/libpldmresponder/test/system_type1/bios_jsons/string_attrs.json b/libpldmresponder/test/system_type1/bios_jsons/string_attrs.json
new file mode 100644
index 0000000..7e3b8f4
--- /dev/null
+++ b/libpldmresponder/test/system_type1/bios_jsons/string_attrs.json
@@ -0,0 +1,49 @@
+{
+    "entries": [
+        {
+            "attribute_name": "str_example1",
+            "string_type": "ASCII",
+            "minimum_string_length": 1,
+            "maximum_string_length": 100,
+            "default_string_length": 3,
+            "default_string": "abc",
+            "readOnly": false,
+            "helpText": "str_example1 HelpText",
+            "displayName": "str_example1 DisplayName",
+            "dbus": {
+                "object_path": "/xyz/abc/def",
+                "interface": "xyz.openbmc_project.str_example1.value",
+                "property_name": "Str_example1",
+                "property_type": "string"
+            }
+        },
+        {
+            "attribute_name": "str_example2",
+            "string_type": "Hex",
+            "minimum_string_length": 0,
+            "maximum_string_length": 200,
+            "default_string_length": 0,
+            "default_string": "",
+            "readOnly": false,
+            "helpText": "str_example2 HelpText",
+            "displayName": "str_example2 DisplayName",
+            "dbus": {
+                "object_path": "/xyz/abc/def",
+                "interface": "xyz.openbmc_project.str_example2.value",
+                "property_name": "Str_example2",
+                "property_type": "string"
+            }
+        },
+        {
+            "attribute_name": "str_example3",
+            "string_type": "Unknown",
+            "minimum_string_length": 1,
+            "maximum_string_length": 100,
+            "default_string_length": 2,
+            "default_string": "ef",
+            "readOnly": true,
+            "helpText": "str_example3 HelpText",
+            "displayName": "str_example3 DisplayName"
+        }
+    ]
+}