Add a helper function copyRestFRUArea to updateFRUProperty

Refactoring updateFRUProperty function and created a new helper
function copyRestFRUArea. 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: I3a3ac6ff3190f0d91f5806e4824400cca0a590e4
Signed-off-by: Kumar Thangavel <thangavel.k@hcl.com>
diff --git a/include/fru_utils.hpp b/include/fru_utils.hpp
index d1784cd..0a988ef 100644
--- a/include/fru_utils.hpp
+++ b/include/fru_utils.hpp
@@ -68,6 +68,8 @@
     size_t size;           // Fru Area Size
     size_t end;            // Fru Area end offset
     size_t updateFieldLoc; // Fru Area update Field Location
+    size_t restFieldsLoc;  // Starting location of restFRUArea data
+    size_t restFieldsEnd;  // Ending location of restFRUArea data
 };
 
 const std::vector<std::string> fruAreaNames = {"INTERNAL", "CHASSIS", "BOARD",
@@ -170,10 +172,25 @@
 /// properties
 /// \param fruData - vector to store fru data
 /// \param propertyName - fru property Name
-/// \param fruAreaParams - struct to have fru Area paramteters like length,
-/// size. \return true if fru field is found, fruAreaParams are updated with
-/// fruArea and field info.
+/// \param fruAreaParams - struct to have fru Area parameters like length,
+/// size.
+/// \return true if fru field is found, fruAreaParams like updateFieldLoc,
+/// Start, Size, End are updated with fruArea and field info.
 bool findFruAreaLocationAndField(std::vector<uint8_t>& fruData,
                                  const std::string& propertyName,
-                                 struct FruArea& fruAreaParams,
-                                 size_t& fruDataIter);
+                                 struct FruArea& fruAreaParams);
+
+/// \brief Copy the fru Area fields and properties into restFRUAreaFieldsData.
+/// restFRUAreaField is the rest of the fields in FRU area after the field that
+/// is being updated.
+/// \param fruData - vector to store fru data
+/// \param propertyName - fru property Name
+/// \param fruAreaParams - struct to have fru Area parameters like length
+/// \param restFRUAreaFieldsData - vector to store fru Area Fields and
+/// properties.
+/// \return true on success false on failure. restFieldLoc and restFieldEnd
+/// are updated.
+bool copyRestFRUArea(std::vector<uint8_t>& fruData,
+                     const std::string& propertyName,
+                     struct FruArea& fruAreaParams,
+                     std::vector<uint8_t>& restFRUAreaFieldsData);
diff --git a/src/fru_device.cpp b/src/fru_device.cpp
index 446d5c4..1e668ba 100644
--- a/src/fru_device.cpp
+++ b/src/fru_device.cpp
@@ -1107,42 +1107,20 @@
 
     struct FruArea fruAreaParams
     {};
-    size_t fruDataIter = 0;
 
-    if (!findFruAreaLocationAndField(fruData, propertyName, fruAreaParams,
-                                     fruDataIter))
+    if (!findFruAreaLocationAndField(fruData, propertyName, fruAreaParams))
     {
         std::cerr << "findFruAreaLocationAndField failed \n";
         return false;
     }
 
-    ssize_t fieldLength = 0;
-
-    // Push post update fru field bytes to a vector
-    fieldLength = getFieldLength(fruData[fruAreaParams.updateFieldLoc]);
-    if (fieldLength < 0)
+    std::vector<uint8_t> restFRUAreaFieldsData;
+    if (!copyRestFRUArea(fruData, propertyName, fruAreaParams,
+                         restFRUAreaFieldsData))
     {
-        std::cerr << "Property " << propertyName << " not present \n";
+        std::cerr << "copyRestFRUArea failed \n";
         return false;
     }
-    fruDataIter += 1 + fieldLength;
-    size_t restFRUFieldsLoc = fruDataIter;
-    size_t endOfFieldsLoc = 0;
-    while ((fieldLength = getFieldLength(fruData[fruDataIter])) >= 0)
-    {
-        if (fruDataIter >= (fruAreaParams.start + fruAreaParams.size))
-        {
-            fruDataIter = fruAreaParams.start + fruAreaParams.size;
-            break;
-        }
-        fruDataIter += 1 + fieldLength;
-    }
-    endOfFieldsLoc = fruDataIter;
-
-    std::vector<uint8_t> restFRUAreaFieldsData;
-    std::copy_n(fruData.begin() + restFRUFieldsLoc,
-                endOfFieldsLoc - restFRUFieldsLoc + 1,
-                std::back_inserter(restFRUAreaFieldsData));
 
     // Push post update fru areas if any
     unsigned int nextFRUAreaLoc = 0;
@@ -1151,7 +1129,7 @@
     {
         unsigned int fruAreaLoc =
             fruData[getHeaderAreaFieldOffset(nextFRUArea)] * fruBlockSize;
-        if ((fruAreaLoc > endOfFieldsLoc) &&
+        if ((fruAreaLoc > fruAreaParams.restFieldsEnd) &&
             ((nextFRUAreaLoc == 0) || (fruAreaLoc < nextFRUAreaLoc)))
         {
             nextFRUAreaLoc = fruAreaLoc;
@@ -1200,10 +1178,13 @@
               fruData.begin() + fruAreaParams.updateFieldLoc);
 
     // Copy remaining data to main fru area - post updated fru field vector
-    restFRUFieldsLoc = fruAreaParams.updateFieldLoc + updatePropertyReqLen;
-    size_t fruAreaDataEnd = restFRUFieldsLoc + restFRUAreaFieldsData.size();
+    fruAreaParams.restFieldsLoc =
+        fruAreaParams.updateFieldLoc + updatePropertyReqLen;
+    size_t fruAreaDataEnd =
+        fruAreaParams.restFieldsLoc + restFRUAreaFieldsData.size();
+
     std::copy(restFRUAreaFieldsData.begin(), restFRUAreaFieldsData.end(),
-              fruData.begin() + restFRUFieldsLoc);
+              fruData.begin() + fruAreaParams.restFieldsLoc);
 
     // Update final fru with new fru area length and checksum
     unsigned int nextFRUAreaNewLoc = updateFRUAreaLenAndChecksum(
diff --git a/src/fru_utils.cpp b/src/fru_utils.cpp
index 4199439..bfcbdba 100644
--- a/src/fru_utils.cpp
+++ b/src/fru_utils.cpp
@@ -792,8 +792,7 @@
 
 bool findFruAreaLocationAndField(std::vector<uint8_t>& fruData,
                                  const std::string& propertyName,
-                                 struct FruArea& fruAreaParams,
-                                 size_t& fruDataIter)
+                                 struct FruArea& fruAreaParams)
 {
     const std::vector<std::string>* fruAreaFieldNames = nullptr;
 
@@ -840,7 +839,7 @@
     fruAreaParams.start = fruAreaOffsetFieldValue * fruBlockSize;
     fruAreaParams.size = fruData[fruAreaParams.start + 1] * fruBlockSize;
     fruAreaParams.end = fruAreaParams.start + fruAreaParams.size;
-    fruDataIter = fruAreaParams.start + offset;
+    size_t fruDataIter = fruAreaParams.start + offset;
     size_t skipToFRUUpdateField = 0;
     ssize_t fieldLength = 0;
 
@@ -892,3 +891,53 @@
 
     return true;
 }
+
+// Copy the FRU Area fields and properties into restFRUAreaFieldsData vector.
+// Return true for success and false for failure.
+
+bool copyRestFRUArea(std::vector<uint8_t>& fruData,
+                     const std::string& propertyName,
+                     struct FruArea& fruAreaParams,
+                     std::vector<uint8_t>& restFRUAreaFieldsData)
+{
+    size_t fieldLoc = fruAreaParams.updateFieldLoc;
+    size_t start = fruAreaParams.start;
+    size_t fruAreaSize = fruAreaParams.size;
+
+    // Push post update fru field bytes to a vector
+    ssize_t fieldLength = getFieldLength(fruData[fieldLoc]);
+    if (fieldLength < 0)
+    {
+        std::cerr << "Property " << propertyName << " not present \n";
+        return false;
+    }
+
+    size_t fruDataIter = 0;
+    fruDataIter = fieldLoc;
+    fruDataIter += 1 + fieldLength;
+    size_t restFRUFieldsLoc = fruDataIter;
+    size_t endOfFieldsLoc = 0;
+
+    if (fruDataIter < fruData.size())
+    {
+        while ((fieldLength = getFieldLength(fruData[fruDataIter])) >= 0)
+        {
+            if (fruDataIter >= (start + fruAreaSize))
+            {
+                fruDataIter = start + fruAreaSize;
+                break;
+            }
+            fruDataIter += 1 + fieldLength;
+        }
+        endOfFieldsLoc = fruDataIter;
+    }
+
+    std::copy_n(fruData.begin() + restFRUFieldsLoc,
+                endOfFieldsLoc - restFRUFieldsLoc + 1,
+                std::back_inserter(restFRUAreaFieldsData));
+
+    fruAreaParams.restFieldsLoc = restFRUFieldsLoc;
+    fruAreaParams.restFieldsEnd = endOfFieldsLoc;
+
+    return true;
+}