bios: Add a configuration parser for integer attribute

Add a configuration parser for integer attribute
and check the fields for string attribute

Signed-off-by: John Wang <wangzqbj@inspur.com>
Change-Id: I3be56f4a64373fb442ef58ad9d6693ffb8994917
diff --git a/libpldmresponder/bios_parser.cpp b/libpldmresponder/bios_parser.cpp
index 0c39acb..a80771b 100644
--- a/libpldmresponder/bios_parser.cpp
+++ b/libpldmresponder/bios_parser.cpp
@@ -8,6 +8,8 @@
 #include <optional>
 #include <phosphor-logging/log.hpp>
 
+#include "libpldm/bios_table.h"
+
 namespace bios_parser
 {
 
@@ -280,47 +282,52 @@
 
 } // namespace internal
 
-int setup(const Json& entry)
+int setup(const Json& jsonEntry)
 {
 
-    std::string attr = entry.value("attribute_name", "");
+    std::string attr = jsonEntry.value("attribute_name", "");
     // Transfer string type from string to enum
-    std::string strTypeTmp = entry.value("string_type", "Unknown");
+    std::string strTypeTmp = jsonEntry.value("string_type", "Unknown");
     auto iter = strTypeMap.find(strTypeTmp);
     if (iter == strTypeMap.end())
     {
-        log<level::ERR>(
-            "Wrong string type",
-            phosphor::logging::entry("STRING_TYPE=%s", strTypeTmp.c_str()),
-            phosphor::logging::entry("ATTRIBUTE_NAME=%s", attr.c_str()));
+        log<level::ERR>("Wrong string type",
+                        entry("STRING_TYPE=%s", strTypeTmp.c_str()),
+                        entry("ATTRIBUTE_NAME=%s", attr.c_str()));
         return -1;
     }
     uint8_t strType = iter->second;
 
-    uint16_t minStrLen = entry.value("minimum_string_length", 0);
-    uint16_t maxStrLen = entry.value("maximum_string_length", 0);
-    if (maxStrLen - minStrLen < 0)
+    uint16_t minStrLen = jsonEntry.value("minimum_string_length", 0);
+    uint16_t maxStrLen = jsonEntry.value("maximum_string_length", 0);
+    uint16_t defaultStrLen = jsonEntry.value("default_string_length", 0);
+    std::string defaultStr = jsonEntry.value("default_string", "");
+
+    pldm_bios_table_attr_entry_string_info info = {
+        0,     /* name handle */
+        false, /* read only */
+        strType, minStrLen, maxStrLen, defaultStrLen, defaultStr.data(),
+    };
+
+    const char* errmsg;
+    auto rc = pldm_bios_table_attr_entry_string_info_check(&info, &errmsg);
+    if (rc != PLDM_SUCCESS)
     {
-        log<level::ERR>(
-            "Maximum string length is smaller than minimum string length",
-            phosphor::logging::entry("ATTRIBUTE_NAME=%s", attr.c_str()));
-        return -1;
-    }
-    uint16_t defaultStrLen = entry.value("default_string_length", 0);
-    std::string defaultStr = entry.value("default_string", "");
-    if ((defaultStrLen == 0) && (defaultStr.size() > 0))
-    {
-        log<level::ERR>(
-            "Default string length is 0, but default string is existing",
-            phosphor::logging::entry("ATTRIBUTE_NAME=%s", attr.c_str()));
+        log<level::ERR>("Wrong filed for string attribute",
+                        entry("ATTRIBUTE_NAME=%s", attr.c_str()),
+                        entry("ERRMSG=%s", errmsg),
+                        entry("MINIMUM_STRING_LENGTH=%u", minStrLen),
+                        entry("MAXIMUM_STRING_LENGTH=%u", maxStrLen),
+                        entry("DEFAULT_STRING_LENGTH=%u", defaultStrLen),
+                        entry("DEFAULT_STRING=%s", defaultStr.data()));
         return -1;
     }
 
     // Defaulting all the types of attributes to BIOSString
     internal::valueMap.emplace(
         std::move(attr),
-        std::make_tuple(entry.count("dbus") == 0, strType, minStrLen, maxStrLen,
-                        defaultStrLen, std::move(defaultStr)));
+        std::make_tuple(jsonEntry.count("dbus") == 0, strType, minStrLen,
+                        maxStrLen, defaultStrLen, std::move(defaultStr)));
 
     return 0;
 }
@@ -348,6 +355,71 @@
 
 } // namespace bios_string
 
+namespace bios_integer
+{
+
+AttrValuesMap valueMap;
+
+int setup(const Json& jsonEntry)
+{
+
+    std::string attr = jsonEntry.value("attribute_name", "");
+    // Transfer string type from string to enum
+
+    uint64_t lowerBound = jsonEntry.value("lower_bound", 0);
+    uint64_t upperBound = jsonEntry.value("upper_bound", 0);
+    uint32_t scalarIncrement = jsonEntry.value("scalar_increment", 1);
+    uint64_t defaultValue = jsonEntry.value("default_value", 0);
+    pldm_bios_table_attr_entry_integer_info info = {
+        0,     /* name handle*/
+        false, /* read only */
+        lowerBound, upperBound, scalarIncrement, defaultValue,
+    };
+    const char* errmsg = nullptr;
+    auto rc = pldm_bios_table_attr_entry_integer_info_check(&info, &errmsg);
+    if (rc != PLDM_SUCCESS)
+    {
+        log<level::ERR>("Wrong filed for integer attribute",
+                        entry("ATTRIBUTE_NAME=%s", attr.c_str()),
+                        entry("ERRMSG=%s", errmsg),
+                        entry("LOWER_BOUND=%llu", lowerBound),
+                        entry("UPPER_BOUND=%llu", upperBound),
+                        entry("DEFAULT_VALUE=%llu", defaultValue),
+                        entry("SCALAR_INCREMENT=%lu", scalarIncrement));
+        return -1;
+    }
+
+    valueMap.emplace(std::move(attr),
+                     std::make_tuple(jsonEntry.count("dbus") == 0, lowerBound,
+                                     upperBound, scalarIncrement,
+                                     defaultValue));
+
+    return 0;
+}
+
+const AttrValuesMap& getValues()
+{
+    return valueMap;
+}
+
+uint64_t getAttrValue(const AttrName& attrName)
+{
+    const auto& dBusMap = BIOSAttrLookup.at(attrName);
+    std::variant<std::string> propValue;
+
+    if (dBusMap == std::nullopt)
+    { // return default string
+        const auto& valueEntry = valueMap.at(attrName);
+        return std::get<AttrDefaultValue>(valueEntry);
+    }
+
+    return pldm::responder::DBusHandler().getDbusProperty<uint64_t>(
+        dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
+        dBusMap->interface.c_str());
+}
+
+} // namespace bios_integer
+
 const std::map<BIOSJsonName, BIOSStringHandler> BIOSStringHandlers = {
     {bIOSEnumJson, bios_enum::setupBIOSStrings},
 };
@@ -355,6 +427,7 @@
 const std::map<BIOSJsonName, typeHandler> BIOSTypeHandlers = {
     {bIOSEnumJson, bios_enum::setup},
     {bIOSStrJson, bios_string::setup},
+    {bIOSIntegerJson, bios_integer::setup},
 };
 
 void setupBIOSStrings(const BIOSJsonName& jsonName, const Json& entry,
@@ -368,14 +441,14 @@
     }
 }
 
-void setupBIOSAttrLookup(const Json& entry, AttrLookup& lookup)
+void setupBIOSAttrLookup(const Json& jsonEntry, AttrLookup& lookup)
 {
     std::optional<DBusMapping> dBusMap;
-    std::string attrName = entry.value("attribute_name", "");
+    std::string attrName = jsonEntry.value("attribute_name", "");
 
-    if (entry.count("dbus") != 0)
+    if (jsonEntry.count("dbus") != 0)
     {
-        auto dBusEntry = entry.value("dbus", emptyJson);
+        auto dBusEntry = jsonEntry.value("dbus", emptyJson);
         std::string objectPath = dBusEntry.value("object_path", "");
         std::string interface = dBusEntry.value("interface", "");
         std::string propertyName = dBusEntry.value("property_name", "");
@@ -388,12 +461,9 @@
         {
             log<level::ERR>(
                 "Invalid dbus config",
-                phosphor::logging::entry("OBJPATH=%s",
-                                         dBusMap->objectPath.c_str()),
-                phosphor::logging::entry("INTERFACE=%s",
-                                         dBusMap->interface.c_str()),
-                phosphor::logging::entry("PROPERTY_NAME=%s",
-                                         dBusMap->propertyName.c_str()));
+                entry("OBJPATH=%s", dBusMap->objectPath.c_str()),
+                entry("INTERFACE=%s", dBusMap->interface.c_str()),
+                entry("PROPERTY_NAME=%s", dBusMap->propertyName.c_str()));
         }
     }
     lookup.emplace(attrName, dBusMap);
@@ -409,7 +479,8 @@
     return 0;
 }
 
-const std::vector<BIOSJsonName> BIOSConfigFiles = {bIOSEnumJson, bIOSStrJson};
+const std::vector<BIOSJsonName> BIOSConfigFiles = {bIOSEnumJson, bIOSStrJson,
+                                                   bIOSIntegerJson};
 
 int setupConfig(const char* dirPath)
 {
diff --git a/libpldmresponder/bios_parser.hpp b/libpldmresponder/bios_parser.hpp
index 6620ddb..1757fc7 100644
--- a/libpldmresponder/bios_parser.hpp
+++ b/libpldmresponder/bios_parser.hpp
@@ -33,6 +33,7 @@
 using Strings = std::vector<std::string>;
 inline constexpr auto bIOSEnumJson = "enum_attrs.json";
 inline constexpr auto bIOSStrJson = "string_attrs.json";
+inline constexpr auto bIOSIntegerJson = "integer_attrs.json";
 
 /** @brief Get all the preconfigured strings
  *  @return all the preconfigurated strings
@@ -106,4 +107,42 @@
 
 } // namespace bios_string
 
+namespace bios_integer
+{
+
+using AttrName = std::string;
+using IsReadOnly = bool;
+using LowerBound = uint64_t;
+using UpperBound = uint64_t;
+using ScalarIncrement = uint32_t;
+using DefaultValue = uint64_t;
+using AttrValues = std::tuple<IsReadOnly, LowerBound, UpperBound,
+                              ScalarIncrement, DefaultValue>;
+
+constexpr auto AttrIsReadOnly = 0;
+constexpr auto AttrLowerBound = 1;
+constexpr auto AttrUpperBound = 2;
+constexpr auto AttrScalarIncrement = 3;
+constexpr auto AttrDefaultValue = 4;
+
+using AttrValuesMap = std::map<AttrName, AttrValues>;
+
+/** @brief Get the values of all fields for the
+ *         BIOSInteger and BIOSIntegerReadOnly types
+ *
+ *  @return information needed to build the BIOS attribute table specific to
+ *         BIOSInteger and BIOSIntegerReadOnly types
+ */
+const AttrValuesMap& getValues();
+
+/** @brief Get the current values for the BIOS Attribute
+ *
+ *  @param[in] attrName - BIOS attribute name
+ *
+ *  @return BIOS attribute value
+ */
+uint64_t getAttrValue(const AttrName& attrName);
+
+} // namespace bios_integer
+
 } // namespace bios_parser
diff --git a/test/libpldmresponder_bios_test.cpp b/test/libpldmresponder_bios_test.cpp
index f667142..5bfbfb9 100644
--- a/test/libpldmresponder_bios_test.cpp
+++ b/test/libpldmresponder_bios_test.cpp
@@ -19,7 +19,6 @@
 using namespace pldm::responder::bios;
 using namespace pldm::responder::utils;
 using namespace bios_parser;
-using namespace bios_parser::bios_enum;
 
 TEST(epochToBCDTime, testTime)
 {
@@ -56,11 +55,24 @@
 {
     using namespace bios_parser;
     // All the BIOS Strings in the BIOS JSON config files.
-    Strings vec{"HMCManagedState",  "On",           "Off",
-                "FWBootSide",       "Perm",         "Temp",
-                "InbandCodeUpdate", "Allowed",      "NotAllowed",
-                "CodeUpdatePolicy", "Concurrent",   "Disruptive",
-                "str_example1",     "str_example2", "str_example3"};
+    Strings vec{"HMCManagedState",
+                "On",
+                "Off",
+                "FWBootSide",
+                "Perm",
+                "Temp",
+                "InbandCodeUpdate",
+                "Allowed",
+                "NotAllowed",
+                "CodeUpdatePolicy",
+                "Concurrent",
+                "Disruptive",
+                "VDD_AVSBUS_RAIL",
+                "SBE_IMAGE_MINIMUM_VALID_ECS",
+                "INTEGER_INVALID_CASE",
+                "str_example1",
+                "str_example2",
+                "str_example3"};
 
     Strings nullVec{};
 
@@ -78,6 +90,7 @@
 
 TEST(getAttrValue, enumScenarios)
 {
+    using namespace bios_parser::bios_enum;
     // All the BIOS Strings in the BIOS JSON config files.
     AttrValuesMap valueMap{
         {"HMCManagedState", {false, {"On", "Off"}, {"On"}}},
@@ -119,6 +132,21 @@
                  std::out_of_range);
 }
 
+TEST(getAttrValue, integerScenarios)
+{
+    using namespace bios_parser::bios_integer;
+    AttrValuesMap valueMap{
+        {"VDD_AVSBUS_RAIL", {false, 0, 15, 1, 0}},
+        {"SBE_IMAGE_MINIMUM_VALID_ECS", {true, 1, 15, 1, 2}}};
+
+    auto values = getValues();
+    EXPECT_EQ(valueMap, values);
+    auto value = getAttrValue("SBE_IMAGE_MINIMUM_VALID_ECS");
+    EXPECT_EQ(value, 2);
+
+    EXPECT_THROW(getAttrValue("VDM"), std::out_of_range);
+}
+
 TEST(traverseBIOSTable, attrTableScenarios)
 {
     std::vector<uint8_t> enumEntry{
@@ -396,7 +424,7 @@
     req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
 
     std::string attrName("CodeUpdatePolicy");
-    CurrentValues currVals = getAttrValue(attrName);
+    bios_enum::CurrentValues currVals = bios_enum::getAttrValue(attrName);
 
     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);