Back up and Restore update

The commit updates the flow of Back up and Restore of system VPD.

Updates:
- Removing call_out_inventory_path tag from the PEL create call
in case there is any issue while backup or restore.
This was done to avoid any calls from phosphor-logging to
VPD-Manager at this stage as Manager service is not up at this
point resulting in a D-Bus call failure.

- Removing dupicate code as and where possible in the flow.

The commit is an extension of following commit:
https://gerrit.openbmc.org/c/openbmc/openpower-vpd-parser/+/62250/

Tests:
PEL was created duringthe flow and confirmed that there was no
call to VPD-Manager from phosphor-logging.

Tested for all te scenarios w.r.t backup and restore of system
VPD.

Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
Change-Id: I92779247438bf50d907fd7f60ed94dda6fadb2a0
diff --git a/ibm_vpd_app.cpp b/ibm_vpd_app.cpp
index 9799982..8acb03a 100644
--- a/ibm_vpd_app.cpp
+++ b/ibm_vpd_app.cpp
@@ -44,6 +44,21 @@
 using namespace openpower::vpd::manager::editor;
 
 /**
+ * @brief API declaration, Populate Dbus.
+ *
+ * This method invokes all the populateInterface functions
+ * and notifies PIM about dbus object.
+ *
+ * @param[in] vpdMap - Either IPZ vpd map or Keyword vpd map based on the
+ * input.
+ * @param[in] js - Inventory json object
+ * @param[in] filePath - Path of the vpd file
+ * @param[in] preIntrStr - Interface string
+ */
+template <typename T>
+static void populateDbus(T& vpdMap, nlohmann::json& js, const string& filePath);
+
+/**
  * @brief Returns the BMC state
  */
 static auto getBMCState()
@@ -859,14 +874,11 @@
  * @brief Parse the given EEPROM file.
  *
  * @param[in] vpdFilePath - Path of EEPROM file
- * @param[in] invPath - Path of inventory object
  * @param[in] js- Reference to vpd inventory json object
- *
  * @return Parsed VPD map
  */
 std::variant<KeywordVpdMap, openpower::vpd::Store>
-    parseVpdFile(const std::string& vpdFilePath, const std::string& invPath,
-                 const nlohmann::json& js)
+    parseVpdFile(const std::string& vpdFilePath, const nlohmann::json& js)
 {
     uint32_t vpdStartOffset = 0;
     for (const auto& item : js["frus"][vpdFilePath])
@@ -874,13 +886,17 @@
         if (item.find("offset") != item.end())
         {
             vpdStartOffset = item["offset"];
+            break;
         }
     }
 
     Binary vpdVector = getVpdDataInVector(js, vpdFilePath);
 
     ParserInterface* parser = ParserFactory::getParser(
-        vpdVector, (pimPath + invPath), vpdFilePath, vpdStartOffset);
+        vpdVector,
+        (pimPath + js["frus"][vpdFilePath][0]["inventoryPath"]
+                       .get_ref<const nlohmann::json::string_t&>()),
+        vpdFilePath, vpdStartOffset);
 
     auto parseResult = parser->parse();
 
@@ -921,13 +937,17 @@
     }
     else
     {
-        auto backupVpdParsedResult = parseVpdFile(systemVpdBackupPath,
-                                                  backupVpdInvPath, js);
+        auto backupVpdParsedResult = parseVpdFile(systemVpdBackupPath, js);
 
         if (auto pVal = get_if<Store>(&backupVpdParsedResult))
         {
             backupVpdMap = pVal->getVpdMap();
         }
+        else
+        {
+            std::cerr << "Invalid format of VPD in back up. Restore aborted."
+                      << std::endl;
+        }
     }
 }
 
@@ -960,135 +980,6 @@
 }
 
 /**
- * @brief Populate base panel object on dbus.
-
- * This method invokes all the populateInterface functions
- * and notifies PIM about base panel dbus object.
-
- * @param[in] vpdMap - Base panel vpd map in IPZ format
- * @param[in] js - Inventory json object
- * @param[in] filePath - Path of the base panel vpd file
- */
-void populateBasePanelObjectOnDBus(const Parsed& vpdMap, nlohmann::json& js,
-                                   const string& filePath)
-{
-    inventory::InterfaceMap interfaces;
-    inventory::ObjectMap objects;
-    inventory::PropertyMap prop;
-
-    string ccinFromVpd = getKwVal(vpdMap, "VINI", "CC");
-    transform(ccinFromVpd.begin(), ccinFromVpd.end(), ccinFromVpd.begin(),
-              ::toupper);
-
-    for (const auto& item : js["frus"][filePath])
-    {
-        const auto& objectPath = item["inventoryPath"];
-        sdbusplus::message::object_path object(objectPath);
-
-        vector<string> ccinList;
-        if (item.find("ccin") != item.end())
-        {
-            for (const auto& cc : item["ccin"])
-            {
-                string ccin = cc;
-                transform(ccin.begin(), ccin.end(), ccin.begin(), ::toupper);
-                ccinList.push_back(ccin);
-            }
-        }
-
-        if (!ccinFromVpd.empty() && !ccinList.empty() &&
-            (find(ccinList.begin(), ccinList.end(), ccinFromVpd) ==
-             ccinList.end()))
-        {
-            continue;
-        }
-
-        if ((item.value("noprime", false)))
-        {
-            // Populate one time properties for non-primeable frus.
-            // For the remaining FRUs, this will get handled as a part of
-            // priming the inventory.
-            setOneTimeProperties(objectPath, interfaces);
-        }
-
-        // Populate the VPD keywords and the common interfaces only if we
-        // are asked to inherit that data from the VPD, else only add the
-        // extraInterfaces.
-        if (item.value("inherit", true))
-        {
-            // Each record in the VPD becomes an interface and all
-            // keyword within the record are properties under that
-            // interface.
-            for (const auto& record : vpdMap)
-            {
-                populateFruSpecificInterfaces(
-                    record.second, ipzVpdInf + record.first, interfaces);
-            }
-
-            if (js.find("commonInterfaces") != js.end())
-            {
-                populateInterfaces(js["commonInterfaces"], interfaces, vpdMap,
-                                   false);
-            }
-        }
-        else
-        {
-            // Check if we have been asked to inherit specific record(s)
-            if (item.find("copyRecords") != item.end())
-            {
-                for (const auto& record : item["copyRecords"])
-                {
-                    const string& recordName = record;
-                    if (vpdMap.find(recordName) != vpdMap.end())
-                    {
-                        populateFruSpecificInterfaces(vpdMap.at(recordName),
-                                                      ipzVpdInf + recordName,
-                                                      interfaces);
-                    }
-                }
-            }
-        }
-
-        // Populate interfaces and properties that are common to every FRU
-        // and additional interface that might be defined on a per-FRU
-        // basis.
-        if (item.find("extraInterfaces") != item.end())
-        {
-            populateInterfaces(item["extraInterfaces"], interfaces, vpdMap,
-                               false);
-        }
-
-        // embedded property(true or false) says whether the subfru is embedded
-        // into the parent fru (or) not. VPD sets Present property only for
-        // embedded frus. If the subfru is not an embedded FRU, the subfru may
-        // or may not be physically present. Those non embedded frus will always
-        // have Present=false irrespective of its physical presence or absence.
-        // Eg: nvme drive in nvme slot is not an embedded FRU. So don't set
-        // Present to true for such sub frus.
-        // Eg: ethernet port is embedded into bmc card. So set Present to true
-        // for such sub frus. Also donot populate present property for embedded
-        // subfru which is synthesized. Currently there is no subfru which are
-        // both embedded and synthesized. But still the case is handled here.
-        if ((item.value("embedded", true)) &&
-            (!item.value("synthesized", false)))
-        {
-            // Check if its required to handle presence for this FRU.
-            if (item.value("handlePresence", true))
-            {
-                inventory::PropertyMap presProp;
-                presProp.emplace("Present", true);
-                insertOrMerge(interfaces, invItemIntf, move(presProp));
-            }
-        }
-
-        objects.emplace(move(object), move(interfaces));
-    }
-
-    // Notify PIM
-    common::utility::callPIM(move(objects));
-}
-
-/**
  * @brief API to check if we need to restore system VPD
  * This functionality is only applicable for IPZ VPD data.
 
@@ -1118,6 +1009,7 @@
 
         if (backupVpdMap.empty())
         {
+            std::cerr << "Backup VPD map is empty" << std::endl;
             return;
         }
     }
@@ -1158,52 +1050,35 @@
                     }
                     else
                     {
-                        auto recItr = backupVpdMap.find(backupVpdRecName);
-                        if (recItr != backupVpdMap.end())
+                        backupValue = getKwVal(backupVpdMap, backupVpdRecName,
+                                               backupVpdKwName);
+
+                        if (backupValue.empty())
                         {
-                            string errorMsg = backupVpdRecName +
-                                              " Record does not exist in "
-                                              "the EEPROM file ";
+                            string errorMsg{};
+                            if (backupVpdMap.find(backupVpdRecName) ==
+                                backupVpdMap.end())
+                            {
+                                errorMsg = backupVpdRecName +
+                                           " Record does not exist in "
+                                           "the EEPROM file ";
+                            }
+                            else
+                            {
+                                errorMsg = backupVpdKwName +
+                                           " Keyword not found or empty.";
+                            }
 
                             errorMsg += systemVpdBackupPath;
 
                             PelAdditionalData additionalData;
                             additionalData.emplace("DESCRIPTION", errorMsg);
 
-                            additionalData.emplace("CALLOUT_INVENTORY_PATH",
-                                                   INVENTORY_PATH +
-                                                       backupVpdInvPath);
-
                             createPEL(additionalData, PelSeverity::ERROR,
                                       errIntfForInvalidVPD, nullptr);
 
                             continue;
                         }
-                        else
-                        {
-                            backupValue = getKwVal(backupVpdMap,
-                                                   backupVpdRecName,
-                                                   backupVpdKwName);
-                            if (backupValue.empty())
-                            {
-                                string errorMsg = backupVpdKwName +
-                                                  " Keyword not found in "
-                                                  "the backup VPD file ";
-
-                                errorMsg += systemVpdBackupPath;
-
-                                PelAdditionalData additionalData;
-                                additionalData.emplace("DESCRIPTION", errorMsg);
-
-                                additionalData.emplace("CALLOUT_INVENTORY_PATH",
-                                                       INVENTORY_PATH +
-                                                           backupVpdInvPath);
-
-                                createPEL(additionalData, PelSeverity::ERROR,
-                                          errIntfForInvalidVPD, nullptr);
-                                continue;
-                            }
-                        }
                     }
 
                     Binary backupDataInBinary(backupValue.begin(),
@@ -1242,9 +1117,6 @@
 
                                 // data mismatch
                                 PelAdditionalData additionalData;
-                                additionalData.emplace("CALLOUT_INVENTORY_PATH",
-                                                       INVENTORY_PATH +
-                                                           objectPath);
 
                                 additionalData.emplace("DESCRIPTION", errMsg);
                                 additionalData.emplace(
@@ -1267,6 +1139,13 @@
                                     continue;
                                 }
                             }
+                            else
+                            {
+                                // both the backup and primary data is
+                                // non-default and same. Nothing needs to be
+                                // done.
+                                continue;
+                            }
                         }
 
                         // If the backup is on the cache we need to copy the
@@ -1299,16 +1178,12 @@
                         errMsg += (*it).first;
                         errMsg += " and keyword: ";
                         errMsg += keywordName;
-                        errMsg += ". SSR need to update primary VPD.";
+                        errMsg += ". Update primary VPD.";
 
                         // mfg default on both backup and primary, log PEL
                         PelAdditionalData additionalData;
-                        additionalData.emplace("CALLOUT_INVENTORY_PATH",
-                                               INVENTORY_PATH + objectPath);
-
                         additionalData.emplace("DESCRIPTION", errMsg);
 
-                        // log PEL TODO: Block IPL
                         createPEL(additionalData, PelSeverity::ERROR,
                                   errIntfForVPDDefault, nullptr);
 
@@ -1332,11 +1207,6 @@
             }
         }
     }
-
-    if (!isBackupOnCache)
-    {
-        populateBasePanelObjectOnDBus(backupVpdMap, js, systemVpdBackupPath);
-    }
 }
 
 /**
@@ -1895,8 +1765,7 @@
         try
         {
             variant<KeywordVpdMap, Store> parseResult;
-
-            parseResult = parseVpdFile(file, baseFruInventoryPath, js);
+            parseResult = parseVpdFile(file, js);
 
             if (isSystemVpd)
             {
@@ -1923,6 +1792,12 @@
         }
         catch (const exception& e)
         {
+            if (!systemVpdBackupPath.empty())
+            {
+                file = systemVpdBackupPath;
+                baseFruInventoryPath = backupVpdInvPath;
+            }
+
             executePostFailAction(js, file);
             throw;
         }
@@ -1938,11 +1813,6 @@
     }
     catch (const VpdEccException& ex)
     {
-        if (!systemVpdBackupPath.empty())
-        {
-            baseFruInventoryPath = backupVpdInvPath;
-        }
-
         additionalData.emplace("DESCRIPTION", "ECC check failed");
         additionalData.emplace("CALLOUT_INVENTORY_PATH",
                                INVENTORY_PATH + baseFruInventoryPath);
@@ -1958,12 +1828,6 @@
     }
     catch (const VpdDataException& ex)
     {
-        if (!systemVpdBackupPath.empty())
-        {
-            file = systemVpdBackupPath;
-            baseFruInventoryPath = backupVpdInvPath;
-        }
-
         if (isThisPcieOnPass1planar(js, file))
         {
             std::cout << "Pcie_device  [" << file
diff --git a/ibm_vpd_utils.cpp b/ibm_vpd_utils.cpp
index cf3a798..d5d280c 100644
--- a/ibm_vpd_utils.cpp
+++ b/ibm_vpd_utils.cpp
@@ -672,6 +672,14 @@
         {
             kwVal = findKwd->second;
         }
+        else
+        {
+            std::cout << "Keyword not found" << std::endl;
+        }
+    }
+    else
+    {
+        std::cerr << "Record not found" << std::endl;
     }
 
     return kwVal;
diff --git a/types.hpp b/types.hpp
index 6efdcfe..70defda 100644
--- a/types.hpp
+++ b/types.hpp
@@ -80,7 +80,6 @@
 using IntfPropMap = std::map<RecordName, GetAllResultType>;
 using RecKwValMap =
     std::unordered_map<RecordName, std::unordered_map<Keyword, Binary>>;
-
 } // namespace inventory
 
 } // namespace vpd