Handle file mode for system VPD collection

This commit adds changes to read system VPD from designated file
location in case VPD collection mode is 'file mode' for the system.

In non-field mode, VPD collection mode is determined by reading u-boot
variable "vpdmode".

```
Test:
Good path:
1. Updated u-boot vpdmode to file mode.
2. Copied the system VPD to designated location for file mode.
3. After system reboot, observed that system VPD is collected successfully.

Bad path:
1. Updated u-boot vpdmode to file mode.
2. Skipped copying system VPD to designated file location.
3. After system reboot, observed that vpd-manger logged a critical PEL as system VPD parsing is failed.

Part of info from PEL:
"User Data 1": {
    "Section Version": "1",
    "Sub-section type": "1",
    "Created by": "bmc error logging",
    "DESCRIPTION": "Standard runtime exception. Reason: System VPD parsing failed, from path [/var/lib/vpd/file/sys/bus/i2c/drivers/at24/8-0050/eeprom]. Either file doesn't exist or error occurred while parsing the file.",
    "FileName": "/usr/src/debug/openpower-fru-vpd/1.0+git/vpd-manager/oem-handler/ibm_handler.cpp",
    "FunctionName": "performInitialSetup",
    "InteranlRc": "0",
    "UserData1": "",
    "UserData2": ""
}
```

Change-Id: Iae4eb64fe91e608f9ae61ab7f88ae41d36bc1007
Signed-off-by: Anupama B R <anupama.b.r1@ibm.com>
diff --git a/vpd-manager/include/constants.hpp b/vpd-manager/include/constants.hpp
index d7ada0a..f7ebff9 100644
--- a/vpd-manager/include/constants.hpp
+++ b/vpd-manager/include/constants.hpp
@@ -245,5 +245,7 @@
     "xyz.openbmc_project.Inventory.Decorator.Position";
 static std::vector<uint8_t> rbmcPrototypeSystemImValue{
     55, 54, 48, 48, 50, 48, 48, 48};
+
+static constexpr auto fileModeDirectoryPath = "/var/lib/vpd/file";
 } // namespace constants
 } // namespace vpd
diff --git a/vpd-manager/include/utility/common_utility.hpp b/vpd-manager/include/utility/common_utility.hpp
index dfb194f..d2dcbfa 100644
--- a/vpd-manager/include/utility/common_utility.hpp
+++ b/vpd-manager/include/utility/common_utility.hpp
@@ -383,5 +383,42 @@
     return l_result;
 }
 
+/**
+ * @brief API to get effective FRU path
+ *
+ * API to get effective VPD path for a FRU based on the VPD collection mode.
+ *
+ * @param[in] i_vpdCollectionMode - VPD collection mode.
+ * @param[in,out] io_fruPath - Path to the EEPROM file.
+ * @param[out] o_errCode - To set error code in case of error.
+ *
+ */
+inline void getEffectiveFruPath(
+    const types::VpdCollectionMode& i_vpdCollectionMode,
+    std::string& io_fruPath, uint16_t& o_errCode) noexcept
+{
+    try
+    {
+        o_errCode = 0;
+        if (types::VpdCollectionMode::FILE_MODE == i_vpdCollectionMode)
+        {
+            io_fruPath.insert(0, constants::fileModeDirectoryPath);
+        }
+
+        // For Hardware mode and mixed mode FRU path is considered as EEPROM
+        // path. No change is needed.
+
+        // ToDo: Need to handle path for mixed mode, when mixed mode is fully
+        // implemented.
+    }
+    catch (std::exception& l_ex)
+    {
+        o_errCode = error_code::STANDARD_EXCEPTION;
+        Logger::getLoggerInstance()->logMessage(
+            "Error while getting effective path, reason: " +
+            std::string(l_ex.what()));
+    }
+}
+
 } // namespace commonUtility
 } // namespace vpd
diff --git a/vpd-manager/oem-handler/ibm_handler.cpp b/vpd-manager/oem-handler/ibm_handler.cpp
index dcb0ddd..bd06a7f 100644
--- a/vpd-manager/oem-handler/ibm_handler.cpp
+++ b/vpd-manager/oem-handler/ibm_handler.cpp
@@ -755,8 +755,26 @@
         throw JsonException("System config JSON is empty", m_sysCfgJsonObj);
     }
 
+    uint16_t l_errCode = 0;
+    std::string l_systemVpdPath{SYSTEM_VPD_FILE_PATH};
+    commonUtility::getEffectiveFruPath(m_vpdCollectionMode, l_systemVpdPath,
+                                       l_errCode);
+
+    if (l_errCode)
+    {
+        throw std::runtime_error(
+            "Failed to get effective System VPD path, for [" + l_systemVpdPath +
+            "], reason: " + commonUtility::getErrCodeMsg(l_errCode));
+    }
+
     // parse system VPD
-    auto l_parsedVpdMap = m_worker->parseVpdFile(SYSTEM_VPD_FILE_PATH);
+    auto l_parsedVpdMap = m_worker->parseVpdFile(l_systemVpdPath);
+    if (std::holds_alternative<std::monostate>(l_parsedVpdMap))
+    {
+        throw std::runtime_error(
+            "System VPD parsing failed, from path [" + l_systemVpdPath +
+            "]. Either file doesn't exist or error occurred while parsing the file.");
+    }
 
     // Implies it is default JSON.
     std::string l_systemJson{JSON_ABSOLUTE_PATH_PREFIX};
@@ -770,7 +788,6 @@
             "No system JSON found corresponding to IM read from VPD.");
     }
 
-    uint16_t l_errCode = 0;
     // re-parse the JSON once appropriate JSON has been selected.
     m_sysCfgJsonObj = jsonUtility::getParsedJson(l_systemJson, l_errCode);