BIOS: Implement attribute value table with type string
Construct attribute value table with type string based on string table
and attribute table.
Change-Id: I40c782ae8753340c964cf067e53e7947b18e9e35
Signed-off-by: Carol Wang <wangkair@cn.ibm.com>
diff --git a/libpldmresponder/bios.cpp b/libpldmresponder/bios.cpp
index 90d86c8..6454052 100644
--- a/libpldmresponder/bios.cpp
+++ b/libpldmresponder/bios.cpp
@@ -479,13 +479,13 @@
*
* @param[in] BIOSAttributeTable - the attribute table
* @param[in] BIOSStringTable - the string table
+ * @param[in, out] attributeValueTable - the attribute value table
*
- * @return - Table - the attribute value table
*/
-Table constructAttrValueTable(const BIOSTable& BIOSAttributeTable,
- const BIOSTable& BIOSStringTable)
+void constructAttrValueTable(const BIOSTable& BIOSAttributeTable,
+ const BIOSTable& BIOSStringTable,
+ Table& attributeValueTable)
{
- Table attributeValueTable;
Response response;
BIOSAttributeTable.load(response);
@@ -518,7 +518,7 @@
{
log<level::ERR>("Did not find string name for handle",
entry("STRING_HANDLE=%d", stringHdl));
- return attributeValueTable;
+ return;
}
attrPtr =
reinterpret_cast<struct pldm_bios_attr_table_entry*>(tableData);
@@ -538,7 +538,7 @@
if (std::distance(tableData, response.data() + tableLen) <=
padChksumMax)
{
- return attributeValueTable;
+ return;
}
attrPtr =
@@ -583,8 +583,6 @@
attrPtr =
reinterpret_cast<struct pldm_bios_attr_table_entry*>(tableData);
}
-
- return attributeValueTable;
}
} // end namespace bios_type_enum
@@ -659,6 +657,101 @@
stringAttrTable.end());
}
}
+
+/** @brief Construct the attibute value table for BIOS type String and
+ * String ReadOnly
+ *
+ * @param[in] BIOSAttributeTable - the attribute table
+ * @param[in] BIOSStringTable - the string table
+ * @param[in, out] attributeValueTable - the attribute value table
+ *
+ */
+void constructAttrValueTable(const BIOSTable& BIOSAttributeTable,
+ const BIOSTable& BIOSStringTable,
+ Table& attributeValueTable)
+{
+ Response response;
+ BIOSAttributeTable.load(response);
+
+ auto dataPtr = response.data();
+ size_t tableLen = response.size();
+
+ while (true)
+ {
+ auto attrPtr =
+ reinterpret_cast<struct pldm_bios_attr_table_entry*>(dataPtr);
+ uint16_t attrHdl = attrPtr->attr_handle;
+ uint8_t attrType = attrPtr->attr_type;
+ uint16_t stringHdl = attrPtr->string_handle;
+ dataPtr += (sizeof(struct pldm_bios_attr_table_entry) - 1);
+ // pass number of StringType, MinimumStringLength, MaximumStringLength
+ dataPtr += sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint16_t);
+ auto sizeDefaultStr = *(reinterpret_cast<uint16_t*>(dataPtr));
+ // pass number of DefaultStringLength, DefaultString
+ dataPtr += sizeof(uint16_t) + sizeDefaultStr;
+
+ auto attrName = findStringName(stringHdl, BIOSStringTable);
+ if (attrName.empty())
+ {
+ if (std::distance(dataPtr, response.data() + tableLen) <=
+ padChksumMax)
+ {
+ log<level::ERR>("Did not find string name for handle",
+ entry("STRING_HANDLE=%d", stringHdl));
+ return;
+ }
+ continue;
+ }
+
+ uint16_t currStrLen = 0;
+ std::string currStr;
+ try
+ {
+ currStr = getAttrValue(attrName);
+ currStrLen = currStr.size();
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>("getAttrValue returned error for attribute",
+ entry("NAME=%s", attrName.c_str()),
+ entry("ERROR=%s", e.what()));
+ if (std::distance(dataPtr, response.data() + tableLen) <=
+ padChksumMax)
+ {
+ return;
+ }
+ continue;
+ }
+
+ BIOSTableRow strAttrValTable(
+ bios_parser::bios_string::attrValueTableSize + currStrLen, 0);
+ BIOSTableRow::iterator it = strAttrValTable.begin();
+ auto attrValPtr =
+ reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+ strAttrValTable.data());
+ attrValPtr->attr_handle = attrHdl;
+ attrValPtr->attr_type = attrType;
+ std::advance(it, (sizeof(pldm_bios_attr_val_table_entry) - 1));
+ std::copy_n(reinterpret_cast<uint8_t*>(&currStrLen), sizeof(uint16_t),
+ it);
+ std::advance(it, sizeof(uint16_t));
+ if (currStrLen)
+ {
+ std::copy_n(currStr.cbegin(), currStrLen, it);
+ std::advance(it, currStrLen);
+ }
+
+ attributeValueTable.insert(attributeValueTable.end(),
+ strAttrValTable.begin(),
+ strAttrValTable.end());
+
+ if (std::distance(dataPtr, response.data() + tableLen) <= padChksumMax)
+ {
+ break;
+ }
+ }
+}
+
} // end namespace bios_type_string
using typeHandler =
@@ -668,6 +761,16 @@
{bios_parser::bIOSEnumJson, bios_type_enum::constructAttrTable},
{bios_parser::bIOSStrJson, bios_type_string::constructAttrTable}};
+using valueHandler = void (*)(const BIOSTable& BIOSAttributeTable,
+
+ const BIOSTable& BIOSStringTable,
+
+ Table& attributeTable);
+
+std::map<std::string, valueHandler> attrValueHandlers{
+ {bios_parser::bIOSEnumJson, bios_type_enum::constructAttrValueTable},
+ {bios_parser::bIOSStrJson, bios_type_string::constructAttrValueTable}};
+
/** @brief Construct the BIOS attribute table
*
* @param[in] BIOSAttributeTable - the attribute table
@@ -768,8 +871,7 @@
const BIOSTable& BIOSStringTable,
uint32_t& /*transferHandle*/,
uint8_t& /*transferOpFlag*/,
- uint8_t instanceID,
- const char* /*biosJsonDir*/)
+ uint8_t instanceID, const char* biosJsonDir)
{
Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
0);
@@ -780,8 +882,27 @@
if (BIOSAttributeValueTable.isEmpty())
{ // no persisted table, constructing fresh table and data
- Table attributeValueTable = bios_type_enum::constructAttrValueTable(
- BIOSAttributeTable, BIOSStringTable);
+ Table attributeValueTable;
+ fs::path dir(biosJsonDir);
+
+ for (auto it = attrValueHandlers.begin(); it != attrValueHandlers.end();
+ it++)
+ {
+ fs::path file = dir / it->first;
+ if (fs::exists(file))
+ {
+ it->second(BIOSAttributeTable, BIOSStringTable,
+ attributeValueTable);
+ }
+ }
+
+ if (attributeValueTable.empty())
+ { // no available json file is found
+ encode_get_bios_table_resp(instanceID, PLDM_BIOS_TABLE_UNAVAILABLE,
+ nxtTransferHandle, transferFlag, nullptr,
+ response.size(), responsePtr);
+ return response;
+ }
// calculate pad
uint8_t padSize = utils::getNumPadBytes(attributeValueTable.size());
std::vector<uint8_t> pad(padSize, 0);
diff --git a/libpldmresponder/bios_parser.cpp b/libpldmresponder/bios_parser.cpp
index a6f07d8..99c1149 100644
--- a/libpldmresponder/bios_parser.cpp
+++ b/libpldmresponder/bios_parser.cpp
@@ -433,6 +433,31 @@
{
return internal::valueMap;
}
+
+std::string getAttrValue(const AttrName& attrName)
+{
+ const auto& dBusMap = internal::attrLookup.at(attrName);
+ std::variant<std::string> propValue;
+
+ if (dBusMap == std::nullopt)
+ { // return default string
+ const auto& valueEntry = internal::valueMap.at(attrName);
+ return std::get<DefaultStr>(valueEntry);
+ }
+
+ auto bus = sdbusplus::bus::new_default();
+ auto service = pldm::responder::getService(bus, dBusMap->objectPath,
+ dBusMap->interface);
+ auto method =
+ bus.new_method_call(service.c_str(), dBusMap->objectPath.c_str(),
+ "org.freedesktop.DBus.Properties", "Get");
+ method.append(dBusMap->interface, dBusMap->propertyName);
+ auto reply = bus.call(method);
+ reply.read(propValue);
+
+ return std::get<std::string>(propValue);
+}
+
} // namespace bios_string
Strings getStrings(const char* dirPath)
diff --git a/libpldmresponder/bios_parser.hpp b/libpldmresponder/bios_parser.hpp
index 2edbc95..8b0c46e 100644
--- a/libpldmresponder/bios_parser.hpp
+++ b/libpldmresponder/bios_parser.hpp
@@ -124,6 +124,12 @@
sizeof(uint16_t) + sizeof(uint8_t) +
sizeof(uint16_t) + sizeof(uint16_t) +
sizeof(uint16_t));
+/* attrValueTableSize is the sum of fixed length of members which construct a
+ * string attribute value table, including attr_handle(uint16_t),
+ * attr_type(uint8_t), CurrentStringLength(uint16_t)*/
+constexpr auto attrValueTableSize = 5;
+static_assert(attrValueTableSize ==
+ sizeof(uint16_t) + sizeof(uint8_t) + sizeof(uint16_t));
/** @brief Get the string related values and the default values for the
* BIOSString and BIOSStringReadOnly types
@@ -133,6 +139,14 @@
*/
const AttrValuesMap& getValues();
+/** @brief Get the current values for the BIOS Attribute
+ *
+ * @param[in] attrName - BIOS attribute name
+ *
+ * @return BIOS attribute value
+ */
+std::string getAttrValue(const AttrName& attrName);
+
} // namespace bios_string
} // namespace bios_parser