FruDevice: parse more than 2 custom fields
The current implementation supports up to two custom fileds for each
FRU Area but there is no such limitation in the specification.
This adds support for unlimited number of custom fields
Tested: tested with FRU which contains three binary BOARD_INFO_AM fields
Change-Id: I6722ff6d98d27badef7a1493d67510596b6cabe9
Signed-off-by: Andrei Kartashev <a.kartashev@yadro.com>
diff --git a/src/FruDevice.cpp b/src/FruDevice.cpp
index 010ee26..7ee7f3b 100644
--- a/src/FruDevice.cpp
+++ b/src/FruDevice.cpp
@@ -107,16 +107,18 @@
auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
auto objServer = sdbusplus::asio::object_server(systemBus);
-static const std::vector<std::string> CHASSIS_FRU_AREAS = {
- "PART_NUMBER", "SERIAL_NUMBER", "INFO_AM1", "INFO_AM2"};
+static const std::vector<std::string> CHASSIS_FRU_AREAS = {"PART_NUMBER",
+ "SERIAL_NUMBER"};
static const std::vector<std::string> BOARD_FRU_AREAS = {
- "MANUFACTURER", "PRODUCT_NAME", "SERIAL_NUMBER", "PART_NUMBER",
- "FRU_VERSION_ID", "INFO_AM1", "INFO_AM2"};
+ "MANUFACTURER", "PRODUCT_NAME", "SERIAL_NUMBER", "PART_NUMBER",
+ "FRU_VERSION_ID"};
static const std::vector<std::string> PRODUCT_FRU_AREAS = {
- "MANUFACTURER", "PRODUCT_NAME", "PART_NUMBER", "VERSION", "SERIAL_NUMBER",
- "ASSET_TAG", "FRU_VERSION_ID", "INFO_AM1", "INFO_AM2"};
+ "MANUFACTURER", "PRODUCT_NAME", "PART_NUMBER", "VERSION",
+ "SERIAL_NUMBER", "ASSET_TAG", "FRU_VERSION_ID"};
+
+static const std::string FRU_CUSTOM_FIELD_NAME = "INFO_AM";
static inline unsigned int getHeaderAreaFieldOffset(fruAreas area)
{
@@ -1047,16 +1049,29 @@
{
continue;
}
- for (auto& field : *fruAreaFieldNames)
+ size_t fieldIndex = 0;
+ DecodeState state = DecodeState::ok;
+ while (state == DecodeState::ok)
{
auto res = decodeFRUData(fruBytesIter, fruBytes.end());
- std::string name = area + "_" + field;
+ std::string name;
+ if (fieldIndex < fruAreaFieldNames->size())
+ {
+ name = area + "_" + fruAreaFieldNames->at(fieldIndex);
+ }
+ else
+ {
+ name = area + "_" + FRU_CUSTOM_FIELD_NAME +
+ std::to_string(fieldIndex -
+ fruAreaFieldNames->size() + 1);
+ }
- if (res.first == DecodeState::end)
+ state = res.first;
+ if (state == DecodeState::end)
{
break;
}
- else if (res.first == DecodeState::err)
+ else if (state == DecodeState::err)
{
std::cerr << "Error while parsing " << name << "\n";
return false;
@@ -1071,6 +1086,7 @@
value.end());
result[name] = std::move(value);
+ ++fieldIndex;
}
}
}
@@ -1611,6 +1627,7 @@
uint8_t fruAreaOffsetFieldValue = 0;
size_t offset = 0;
std::string areaName = propertyName.substr(0, propertyName.find("_"));
+ std::string propertyNamePrefix = areaName + "_";
auto it = std::find(FRU_AREA_NAMES.begin(), FRU_AREA_NAMES.end(), areaName);
if (it == FRU_AREA_NAMES.end())
{
@@ -1657,14 +1674,36 @@
size_t skipToFRUUpdateField = 0;
ssize_t fieldLength;
+ bool found = false;
for (auto& field : *fruAreaFieldNames)
{
skipToFRUUpdateField++;
- if (propertyName.find(field) != std::string::npos)
+ if (propertyName == propertyNamePrefix + field)
{
+ found = true;
break;
}
}
+ if (!found)
+ {
+ std::size_t pos = propertyName.find(FRU_CUSTOM_FIELD_NAME);
+ if (pos == std::string::npos)
+ {
+ std::cerr << "PropertyName doesn't exist in FRU Area Vectors: "
+ << propertyName << "\n";
+ return false;
+ }
+ std::string fieldNumStr =
+ propertyName.substr(pos + FRU_CUSTOM_FIELD_NAME.length());
+ size_t fieldNum = std::stoi(fieldNumStr);
+ if (fieldNum == 0)
+ {
+ std::cerr << "PropertyName not recognized: " << propertyName
+ << "\n";
+ return false;
+ }
+ skipToFRUUpdateField += fieldNum;
+ }
for (size_t i = 1; i < skipToFRUUpdateField; i++)
{