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_device.cpp b/src/fru_device.cpp
index ed55e4a..50f1e4b 100644
--- a/src/fru_device.cpp
+++ b/src/fru_device.cpp
@@ -1108,100 +1108,20 @@
return false;
}
- const std::vector<std::string>* fruAreaFieldNames = nullptr;
+ struct FruArea fruAreaParams{};
+ size_t fruDataIter = 0;
- 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())
+ if (!findFruAreaLocationAndField(fruData, propertyName, fruAreaParams,
+ fruDataIter))
{
- 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 << "Don't know how to handle property " << propertyName
- << " \n";
- return false;
- }
- if (fruAreaOffsetFieldValue == 0)
- {
- std::cerr << "FRU Area for " << propertyName << " not present \n";
+ std::cerr << "findFruAreaLocationAndField failed \n";
return false;
}
- size_t fruAreaStart = fruAreaOffsetFieldValue * fruBlockSize;
- size_t fruAreaSize = fruData[fruAreaStart + 1] * fruBlockSize;
- size_t fruAreaEnd = fruAreaStart + fruAreaSize;
- size_t fruDataIter = fruAreaStart + 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++)
- {
- fieldLength = getFieldLength(fruData[fruDataIter]);
- if (fieldLength < 0)
- {
- break;
- }
- fruDataIter += 1 + fieldLength;
- }
- size_t fruUpdateFieldLoc = fruDataIter;
-
// Push post update fru field bytes to a vector
- fieldLength = getFieldLength(fruData[fruUpdateFieldLoc]);
+ fieldLength = getFieldLength(fruData[fruAreaParams.updateFieldLoc]);
if (fieldLength < 0)
{
std::cerr << "Property " << propertyName << " not present \n";
@@ -1212,9 +1132,9 @@
size_t endOfFieldsLoc = 0;
while ((fieldLength = getFieldLength(fruData[fruDataIter])) >= 0)
{
- if (fruDataIter >= (fruAreaStart + fruAreaSize))
+ if (fruDataIter >= (fruAreaParams.start + fruAreaParams.size))
{
- fruDataIter = fruAreaStart + fruAreaSize;
+ fruDataIter = fruAreaParams.start + fruAreaParams.size;
break;
}
fruDataIter += 1 + fieldLength;
@@ -1249,8 +1169,9 @@
// check FRU area size
size_t fruAreaDataSize =
- ((fruUpdateFieldLoc - fruAreaStart + 1) + restFRUAreaFieldsData.size());
- size_t fruAreaAvailableSize = fruAreaSize - fruAreaDataSize;
+ ((fruAreaParams.updateFieldLoc - fruAreaParams.start + 1) +
+ restFRUAreaFieldsData.size());
+ size_t fruAreaAvailableSize = fruAreaParams.size - fruAreaDataSize;
if ((updatePropertyReqLen + 1) > fruAreaAvailableSize)
{
@@ -1259,10 +1180,11 @@
// round size to 8-byte blocks
newFRUAreaSize =
((newFRUAreaSize - 1) / fruBlockSize + 1) * fruBlockSize;
- size_t newFRUDataSize = fruData.size() + newFRUAreaSize - fruAreaSize;
+ size_t newFRUDataSize =
+ fruData.size() + newFRUAreaSize - fruAreaParams.size;
fruData.resize(newFRUDataSize);
- fruAreaSize = newFRUAreaSize;
- fruAreaEnd = fruAreaStart + fruAreaSize;
+ fruAreaParams.size = newFRUAreaSize;
+ fruAreaParams.end = fruAreaParams.start + fruAreaParams.size;
#else
std::cerr << "FRU field length: " << updatePropertyReqLen + 1
<< " should not be greater than available FRU area size: "
@@ -1273,21 +1195,21 @@
// write new requested property field length and data
constexpr uint8_t newTypeLenMask = 0xC0;
- fruData[fruUpdateFieldLoc] =
+ fruData[fruAreaParams.updateFieldLoc] =
static_cast<uint8_t>(updatePropertyReqLen | newTypeLenMask);
- fruUpdateFieldLoc++;
+ fruAreaParams.updateFieldLoc++;
std::copy(updatePropertyReq.begin(), updatePropertyReq.end(),
- fruData.begin() + fruUpdateFieldLoc);
+ fruData.begin() + fruAreaParams.updateFieldLoc);
// Copy remaining data to main fru area - post updated fru field vector
- restFRUFieldsLoc = fruUpdateFieldLoc + updatePropertyReqLen;
+ restFRUFieldsLoc = fruAreaParams.updateFieldLoc + updatePropertyReqLen;
size_t fruAreaDataEnd = restFRUFieldsLoc + restFRUAreaFieldsData.size();
std::copy(restFRUAreaFieldsData.begin(), restFRUAreaFieldsData.end(),
fruData.begin() + restFRUFieldsLoc);
// Update final fru with new fru area length and checksum
unsigned int nextFRUAreaNewLoc = updateFRUAreaLenAndChecksum(
- fruData, fruAreaStart, fruAreaDataEnd, fruAreaEnd);
+ fruData, fruAreaParams.start, fruAreaDataEnd, fruAreaParams.end);
#ifdef ENABLE_FRU_AREA_RESIZE
++nextFRUAreaNewLoc;