bios: Implement BIOSEnumAttribute
Implement BIOSEnumAttribute, most of the code is copied from
bios/bios_parser.cpp.
Implement SetAttrValueOnDbus and constructEntry for enum attribute
Signed-off-by: John Wang <wangzqbj@inspur.com>
Change-Id: Ia6230485fd2d6d05f9f2ddb3a80b81f6556aee9f
diff --git a/libpldmresponder/bios_config.cpp b/libpldmresponder/bios_config.cpp
index 90b2ad2..e742ee6 100644
--- a/libpldmresponder/bios_config.cpp
+++ b/libpldmresponder/bios_config.cpp
@@ -1,5 +1,6 @@
#include "bios_config.hpp"
+#include "bios_enum_attribute.hpp"
#include "bios_integer_attribute.hpp"
#include "bios_string_attribute.hpp"
@@ -66,9 +67,12 @@
load(jsonDir / stringJsonFile, [this](const Json& entry) {
constructAttribute<BIOSStringAttribute>(entry);
});
- load(jsonDir / stringJsonFile, [this](const Json& entry) {
+ load(jsonDir / integerJsonFile, [this](const Json& entry) {
constructAttribute<BIOSIntegerAttribute>(entry);
});
+ load(jsonDir / enumJsonFile, [this](const Json& entry) {
+ constructAttribute<BIOSEnumAttribute>(entry);
+ });
}
void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
diff --git a/libpldmresponder/bios_enum_attribute.cpp b/libpldmresponder/bios_enum_attribute.cpp
new file mode 100644
index 0000000..7d7cba4
--- /dev/null
+++ b/libpldmresponder/bios_enum_attribute.cpp
@@ -0,0 +1,204 @@
+#include "bios_enum_attribute.hpp"
+
+#include "utils.hpp"
+
+#include <iostream>
+
+namespace pldm
+{
+namespace responder
+{
+namespace bios
+{
+
+BIOSEnumAttribute::BIOSEnumAttribute(const Json& entry,
+ DBusHandler* const dbusHandler) :
+ BIOSAttribute(entry, dbusHandler)
+{
+ std::string attrName = entry.at("attribute_name");
+ Json pv = entry.at("possible_values");
+ for (auto& val : pv)
+ {
+ possibleValues.emplace_back(val);
+ }
+
+ std::vector<std::string> defaultValues;
+ Json dv = entry.at("default_values");
+ for (auto& val : dv)
+ {
+ defaultValues.emplace_back(val);
+ }
+ assert(defaultValues.size() == 1);
+ defaultValue = defaultValues[0];
+ if (!readOnly)
+ {
+ auto dbusValues = entry.at("dbus").at("property_values");
+ buildValMap(dbusValues);
+ }
+}
+
+uint8_t BIOSEnumAttribute::getValueIndex(const std::string& value,
+ const std::vector<std::string>& pVs)
+{
+ auto iter = std::find_if(pVs.begin(), pVs.end(),
+ [&value](const auto& v) { return v == value; });
+ if (iter == pVs.end())
+ {
+ throw std::invalid_argument("value must be one of possible value");
+ }
+ return iter - pVs.begin();
+}
+
+std::vector<uint16_t> BIOSEnumAttribute::getPossibleValuesHandle(
+ const BIOSStringTable& stringTable, const std::vector<std::string>& pVs)
+{
+ std::vector<uint16_t> possibleValuesHandle;
+ for (const auto& pv : pVs)
+ {
+ auto handle = stringTable.findHandle(pv);
+ possibleValuesHandle.push_back(handle);
+ }
+
+ return possibleValuesHandle;
+}
+
+void BIOSEnumAttribute::buildValMap(const Json& dbusVals)
+{
+ PropertyValue value;
+ size_t pos = 0;
+ for (auto it = dbusVals.begin(); it != dbusVals.end(); ++it, ++pos)
+ {
+ if (dBusMap->propertyType == "uint8_t")
+ {
+ value = static_cast<uint8_t>(it.value());
+ }
+ else if (dBusMap->propertyType == "uint16_t")
+ {
+ value = static_cast<uint16_t>(it.value());
+ }
+ else if (dBusMap->propertyType == "uint32_t")
+ {
+ value = static_cast<uint32_t>(it.value());
+ }
+ else if (dBusMap->propertyType == "uint64_t")
+ {
+ value = static_cast<uint64_t>(it.value());
+ }
+ else if (dBusMap->propertyType == "int16_t")
+ {
+ value = static_cast<int16_t>(it.value());
+ }
+ else if (dBusMap->propertyType == "int32_t")
+ {
+ value = static_cast<int32_t>(it.value());
+ }
+ else if (dBusMap->propertyType == "int64_t")
+ {
+ value = static_cast<int64_t>(it.value());
+ }
+ else if (dBusMap->propertyType == "bool")
+ {
+ value = static_cast<bool>(it.value());
+ }
+ else if (dBusMap->propertyType == "double")
+ {
+ value = static_cast<double>(it.value());
+ }
+ else if (dBusMap->propertyType == "string")
+ {
+ value = static_cast<std::string>(it.value());
+ }
+ else
+ {
+ std::cerr << "Unknown D-Bus property type, TYPE="
+ << dBusMap->propertyType << "\n";
+ throw std::invalid_argument("Unknown D-BUS property type");
+ }
+ valMap.emplace(value, possibleValues[pos]);
+ }
+}
+
+uint8_t BIOSEnumAttribute::getAttrValueIndex()
+{
+ auto defaultValueIndex = getValueIndex(defaultValue, possibleValues);
+ if (readOnly)
+ {
+ return defaultValueIndex;
+ }
+
+ try
+ {
+ auto propValue = dbusHandler->getDbusPropertyVariant(
+ dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
+ dBusMap->interface.c_str());
+ auto iter = valMap.find(propValue);
+ if (iter == valMap.end())
+ {
+ return defaultValueIndex;
+ }
+ auto currentValue = iter->second;
+ return getValueIndex(currentValue, possibleValues);
+ }
+ catch (const std::exception& e)
+ {
+ return defaultValueIndex;
+ }
+}
+
+void BIOSEnumAttribute::setAttrValueOnDbus(
+ const pldm_bios_attr_val_table_entry* attrValueEntry,
+ const pldm_bios_attr_table_entry* attrEntry,
+ const BIOSStringTable& stringTable)
+{
+ if (readOnly)
+ {
+ return;
+ }
+ auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry);
+ auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry);
+
+ assert(currHdls.size() == 1);
+
+ auto valueString = stringTable.findString(pvHdls[currHdls[0]]);
+
+ auto it = std::find_if(valMap.begin(), valMap.end(),
+ [&valueString](const auto& typePair) {
+ return typePair.second == valueString;
+ });
+ if (it == valMap.end())
+ {
+ return;
+ }
+
+ dbusHandler->setDbusProperty(*dBusMap, it->first);
+}
+
+void BIOSEnumAttribute::constructEntry(const BIOSStringTable& stringTable,
+ Table& attrTable, Table& attrValueTable)
+{
+ auto possibleValuesHandle =
+ getPossibleValuesHandle(stringTable, possibleValues);
+ std::vector<uint8_t> defaultIndices(1, 0);
+ defaultIndices[0] = getValueIndex(defaultValue, possibleValues);
+
+ pldm_bios_table_attr_entry_enum_info info = {
+ stringTable.findHandle(name), readOnly,
+ (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(),
+ (uint8_t)defaultIndices.size(), defaultIndices.data(),
+ };
+
+ auto attrTableEntry =
+ table::attribute::constructEnumEntry(attrTable, &info);
+ auto [attrHandle, attrType, _] =
+ table::attribute::decodeHeader(attrTableEntry);
+
+ std::vector<uint8_t> currValueIndices(1, 0);
+ currValueIndices[0] = getAttrValueIndex();
+
+ table::attribute_value::constructEnumEntry(attrValueTable, attrHandle,
+ attrType, currValueIndices);
+}
+
+} // namespace bios
+} // namespace responder
+} // namespace pldm
\ No newline at end of file
diff --git a/libpldmresponder/bios_enum_attribute.hpp b/libpldmresponder/bios_enum_attribute.hpp
new file mode 100644
index 0000000..2d8667a
--- /dev/null
+++ b/libpldmresponder/bios_enum_attribute.hpp
@@ -0,0 +1,93 @@
+#pragma once
+
+#include "bios_attribute.hpp"
+
+#include <map>
+#include <set>
+#include <string>
+#include <variant>
+
+class TestBIOSEnumAttribute;
+
+namespace pldm
+{
+namespace responder
+{
+namespace bios
+{
+
+/** @class BIOSEnumAttribute
+ * @brief Associate enum entry(attr table and attribute value table) and
+ * dbus attribute
+ */
+class BIOSEnumAttribute : public BIOSAttribute
+{
+ public:
+ friend class ::TestBIOSEnumAttribute;
+ /** @brief Construct a bios enum attribute
+ * @param[in] entry - Json Object
+ * @param[in] dbusHandler - Dbus Handler
+ */
+ BIOSEnumAttribute(const Json& entry, DBusHandler* const dbusHandler);
+
+ /** @brief Set Attribute value On Dbus according to the attribute value
+ * entry
+ * @param[in] attrValueEntry - The attribute value entry
+ * @param[in] attrEntry - The attribute entry corresponding to the
+ * attribute value entry
+ * @param[in] stringTable - The string table
+ */
+ void
+ setAttrValueOnDbus(const pldm_bios_attr_val_table_entry* attrValueEntry,
+ const pldm_bios_attr_table_entry* attrEntry,
+ const BIOSStringTable& stringTable) override;
+
+ /** @brief Construct corresponding entries at the end of the attribute table
+ * and attribute value tables
+ * @param[in] stringTable - The string Table
+ * @param[in,out] attrTable - The attribute table
+ * @param[in,out] attrValueTable - The attribute value table
+ */
+ void constructEntry(const BIOSStringTable& stringTable, Table& attrTable,
+ Table& attrValueTable) override;
+
+ private:
+ std::vector<std::string> possibleValues;
+ std::string defaultValue;
+
+ /** @brief Get index of the given value in possible values
+ * @param[in] value - The given value
+ * @param[in] pVs - The possible values
+ * @return Index of the given value in possible values
+ */
+ uint8_t getValueIndex(const std::string& value,
+ const std::vector<std::string>& pVs);
+
+ /** @brief Get handles of possible values
+ * @param[in] stringTable - The bios string table
+ * @param[in] pVs - The possible values
+ * @return The handles
+ */
+ std::vector<uint16_t>
+ getPossibleValuesHandle(const BIOSStringTable& stringTable,
+ const std::vector<std::string>& pVs);
+
+ using ValMap = std::map<PropertyValue, std::string>;
+
+ /** @brief Map of value on dbus and pldm */
+ ValMap valMap;
+
+ /** @brief Build the map of dbus value to pldm enum value
+ * @param[in] dbusVals - The dbus values in the json's dbus section
+ */
+ void buildValMap(const Json& dbusVals);
+
+ /** @brief Get index of the current value in possible values
+ * @return The index of the current value in possible values
+ */
+ uint8_t getAttrValueIndex();
+};
+
+} // namespace bios
+} // namespace responder
+} // namespace pldm
\ No newline at end of file
diff --git a/libpldmresponder/bios_table.cpp b/libpldmresponder/bios_table.cpp
index 67dfb0e..3f5d532 100644
--- a/libpldmresponder/bios_table.cpp
+++ b/libpldmresponder/bios_table.cpp
@@ -193,6 +193,33 @@
return {lower, upper, scalar, def};
}
+const pldm_bios_attr_table_entry*
+ constructEnumEntry(Table& table, pldm_bios_table_attr_entry_enum_info* info)
+{
+ auto entryLength = pldm_bios_table_attr_entry_enum_encode_length(
+ info->pv_num, info->def_num);
+
+ auto tableSize = table.size();
+ table.resize(tableSize + entryLength, 0);
+ pldm_bios_table_attr_entry_enum_encode(table.data() + tableSize,
+ entryLength, info);
+
+ return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
+ tableSize);
+}
+
+EnumField decodeEnumEntry(const pldm_bios_attr_table_entry* entry)
+{
+ uint8_t pvNum = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
+ std::vector<uint16_t> pvHdls(pvNum, 0);
+ pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, pvHdls.data(), pvNum);
+ auto defNum = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
+ std::vector<uint8_t> defIndices(defNum, 0);
+ pldm_bios_table_attr_entry_enum_decode_def_indices(entry, defIndices.data(),
+ defIndices.size());
+ return {pvHdls, defIndices};
+}
+
} // namespace attribute
namespace attribute_value
@@ -220,6 +247,16 @@
return pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
}
+std::vector<uint8_t>
+ decodeEnumEntry(const pldm_bios_attr_val_table_entry* entry)
+{
+ auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
+ std::vector<uint8_t> currHdls(number, 0);
+ pldm_bios_table_attr_value_entry_enum_decode_handles(entry, currHdls.data(),
+ currHdls.size());
+ return currHdls;
+}
+
const pldm_bios_attr_val_table_entry*
constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
const std::string& str)
@@ -251,6 +288,21 @@
tableSize);
}
+const pldm_bios_attr_val_table_entry*
+ constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
+ const std::vector<uint8_t>& handleIndices)
+{
+ auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
+ handleIndices.size());
+ auto tableSize = table.size();
+ table.resize(tableSize + entryLength);
+ pldm_bios_table_attr_value_entry_encode_enum(
+ table.data() + tableSize, entryLength, attrHandle, attrType,
+ handleIndices.size(), handleIndices.data());
+ return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
+ tableSize);
+}
+
std::optional<Table> updateTable(const Table& table, const void* entry,
size_t size)
{
diff --git a/libpldmresponder/bios_table.hpp b/libpldmresponder/bios_table.hpp
index aab6f53..cb1873c 100644
--- a/libpldmresponder/bios_table.hpp
+++ b/libpldmresponder/bios_table.hpp
@@ -252,6 +252,31 @@
*/
IntegerField decodeIntegerEntry(const pldm_bios_attr_table_entry* entry);
+/** @struct EnumField
+ * @brief Enum field of attribute table
+ */
+struct EnumField
+{
+ std::vector<uint16_t> possibleValueStringHandle;
+ std::vector<uint8_t> defaultValueIndex;
+};
+
+/** @brief decode enum entry of attribute table
+ * @param[in] entry - Pointer to an attribute table entry
+ * @return Enum field of the entry
+ */
+EnumField decodeEnumEntry(const pldm_bios_attr_table_entry* entry);
+
+/** @brief construct enum entry of attribute table at the end of the
+ * given table
+ * @param[in,out] table - The given table
+ * @param[in] info - enum info
+ * @return pointer to the constructed entry
+ */
+const pldm_bios_attr_table_entry*
+ constructEnumEntry(Table& table,
+ pldm_bios_table_attr_entry_enum_info* info);
+
} // namespace attribute
namespace attribute_value
@@ -284,6 +309,13 @@
*/
uint64_t decodeIntegerEntry(const pldm_bios_attr_val_table_entry* entry);
+/** @brief Decode enum entry of attribute value table
+ * @param[in] entry - Pointer to an attribute value table entry
+ * @return Current value string handle indices
+ */
+std::vector<uint8_t>
+ decodeEnumEntry(const pldm_bios_attr_val_table_entry* entry);
+
/** @brief Construct string entry of attribute value table at the end of the
* given table
* @param[in] table - The given table
@@ -309,6 +341,18 @@
uint8_t attrType,
uint64_t value);
+/** @brief Construct enum entry of attribute value table at the end of
+ * the given table
+ * @param[in] table - The given table
+ * @param[in] attrHandle - attribute handle
+ * @param[in] attrType - attribute type
+ * @param[in] handleIndices - handle indices
+ * @return Pointer to the constructed entry
+ */
+const pldm_bios_attr_val_table_entry*
+ constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
+ const std::vector<uint8_t>& handleIndices);
+
/** @brief construct a table with an new entry
* @param[in] table - the table need to be updated
* @param[in] entry - the new attribute value entry
diff --git a/libpldmresponder/meson.build b/libpldmresponder/meson.build
index 9e073eb..88dfdab 100644
--- a/libpldmresponder/meson.build
+++ b/libpldmresponder/meson.build
@@ -13,6 +13,7 @@
'bios_attribute.cpp',
'bios_string_attribute.cpp',
'bios_integer_attribute.cpp',
+ 'bios_enum_attribute.cpp',
'bios_config.cpp',
'pdr_utils.cpp',
'pdr.cpp',