Add a helper function findFruAreaLocationAndField to
updateFRUProperty
Refactoring updateFRUProperty function and created a new helper
function findFruAreaLocationAndField. Moved this function to
fru_utils.cpp as it is common for all fru-device deamons and
avoid code duplication.
This patch is created based on suggestion on the below patch.
https://gerrit.openbmc.org/c/openbmc/entity-manager/+/51555
TESTED : Built Facebook YosemiteV2 images and loaded
on the target hardware. Verified all the fru's read and write.
Signed-off-by: Kumar Thangavel <thangavel.k@hcl.com>
Change-Id: I82265e66ea5db10003e96978979250ea45c2052d
diff --git a/src/fru_utils.cpp b/src/fru_utils.cpp
index bc59af8..e030ac8 100644
--- a/src/fru_utils.cpp
+++ b/src/fru_utils.cpp
@@ -784,3 +784,111 @@
return ret;
}
+
+// Iterate FruArea Names and find start and size of the fru area that contains
+// the propertyName and the field start location for the property. fruAreaParams
+// struct values fruAreaStart, fruAreaSize, fruAreaEnd, fieldLoc values gets
+// updated/returned if successful.
+
+bool findFruAreaLocationAndField(std::vector<uint8_t>& fruData,
+ const std::string& propertyName,
+ struct FruArea& fruAreaParams,
+ size_t& fruDataIter)
+{
+ const std::vector<std::string>* fruAreaFieldNames = nullptr;
+
+ uint8_t fruAreaOffsetFieldValue = 0;
+ size_t offset = 0;
+ std::string areaName = propertyName.substr(0, propertyName.find('_'));
+ std::string propertyNamePrefix = areaName + "_";
+ auto it = std::find(fruAreaNames.begin(), fruAreaNames.end(), areaName);
+ if (it == fruAreaNames.end())
+ {
+ std::cerr << "Can't parse area name for property " << propertyName
+ << " \n";
+ return false;
+ }
+ fruAreas fruAreaToUpdate = static_cast<fruAreas>(it - fruAreaNames.begin());
+ fruAreaOffsetFieldValue =
+ fruData[getHeaderAreaFieldOffset(fruAreaToUpdate)];
+ switch (fruAreaToUpdate)
+ {
+ case fruAreas::fruAreaChassis:
+ offset = 3; // chassis part number offset. Skip fixed first 3 bytes
+ fruAreaFieldNames = &chassisFruAreas;
+ break;
+ case fruAreas::fruAreaBoard:
+ offset = 6; // board manufacturer offset. Skip fixed first 6 bytes
+ fruAreaFieldNames = &boardFruAreas;
+ break;
+ case fruAreas::fruAreaProduct:
+ // Manufacturer name offset. Skip fixed first 3 product fru bytes
+ // i.e. version, area length and language code
+ offset = 3;
+ fruAreaFieldNames = &productFruAreas;
+ break;
+ default:
+ std::cerr << "Invalid PropertyName " << propertyName << " \n";
+ return false;
+ }
+ if (fruAreaOffsetFieldValue == 0)
+ {
+ std::cerr << "FRU Area for " << propertyName << " not present \n";
+ return false;
+ }
+
+ fruAreaParams.start = fruAreaOffsetFieldValue * fruBlockSize;
+ fruAreaParams.size = fruData[fruAreaParams.start + 1] * fruBlockSize;
+ fruAreaParams.end = fruAreaParams.start + fruAreaParams.size;
+ fruDataIter = fruAreaParams.start + offset;
+ size_t skipToFRUUpdateField = 0;
+ ssize_t fieldLength = 0;
+
+ bool found = false;
+ for (const auto& field : *fruAreaFieldNames)
+ {
+ skipToFRUUpdateField++;
+ if (propertyName == propertyNamePrefix + field)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ std::size_t pos = propertyName.find(fruCustomFieldName);
+ 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 + fruCustomFieldName.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++)
+ {
+ if (fruDataIter < fruData.size())
+ {
+ fieldLength = getFieldLength(fruData[fruDataIter]);
+
+ if (fieldLength < 0)
+ {
+ break;
+ }
+ fruDataIter += 1 + fieldLength;
+ }
+ }
+ fruAreaParams.updateFieldLoc = fruDataIter;
+
+ return true;
+}