Backup or restore keyword implementation

This commits implements backup or restore keyword’s value on the
system. Conditions for updating the value,
* System’s primary and backup VPD’s should be on the hardware.
* Record and keyword should be found in the backup and restore config
JSON.

Backup or restore keyword’s value is triggered based on the following,
* Backup - While updating VPD on the primary path, VPD on backup path
gets updated.
* Restore - While updating VPD on the backup path, VPD on primary path
gets updated.

Output:
```
Before updating keyword’s value:
vpd-tool -O /sys/bus/i2c/drivers/at24/7-0050/eeprom -R VSBK -K BR -r -H; vpd-tool -O /system/chassis/motherboard/base_op_panel_blyth -R VSBK -K BR -r; vpd-tool -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R VSYS -K BR -r -H; vpd-tool -O /system/chassis/motherboard -R VSYS -K BR -r

{
    "/sys/bus/i2c/drivers/at24/7-0050/eeprom": {
        "BR": "S0"
    }
}
{
    "/system/chassis/motherboard/base_op_panel_blyth": {
        "BR": "S0"
    }
}

{
    "/sys/bus/i2c/drivers/at24/8-0050/eeprom": {
        "BR": "S0"
    }
}
{
    "/system/chassis/motherboard": {
        "BR": "S0"
    }
}

Update keyword’s value:
root@bonn026bmc:~# vpd-tool -O /system/chassis/motherboard -R VSYS -K BR -w -V 89
Data updated successfully

After updating keyword’s value:
root@bonn026bmc:~# vpd-tool -O /sys/bus/i2c/drivers/at24/7-0050/eeprom -R VSBK -K BR -r -H; vpd-tool -O /system/chassis/motherboard/base_op_panel_blyth -R VSBK -K BR -r; vpd-tool -O /sys/bus/i2c/drivers/at24/8-0050/eeprom -R VSYS -K BR -r -H; vpd-tool -O /system/chassis/motherboard -R VSYS -K BR -r
{
    "/sys/bus/i2c/drivers/at24/7-0050/eeprom": {
        "BR": "89"
    }
}
{
    "/system/chassis/motherboard/base_op_panel_blyth": {
        "BR": "89"
    }
}
{
    "/sys/bus/i2c/drivers/at24/8-0050/eeprom": {
        "BR": "89"
    }
}
{
    "/system/chassis/motherboard": {
        "BR": "89"
    }
}

Note: similarly, tested by updating backup path, observed that both primary and backup keyword’s value got updated with provided new value.
```

Change-Id: I175e55305d103b1833d07bbd14b3e76dd7d02cc9
Signed-off-by: Anupama B R <anupama.b.r1@ibm.com>
diff --git a/vpd-manager/src/backup_restore.cpp b/vpd-manager/src/backup_restore.cpp
index e06f2e8..87cbdc2 100644
--- a/vpd-manager/src/backup_restore.cpp
+++ b/vpd-manager/src/backup_restore.cpp
@@ -399,8 +399,7 @@
 
 int BackupAndRestore::updateKeywordOnPrimaryOrBackupPath(
     const std::string& i_fruPath,
-    [[maybe_unused]] const types::WriteVpdParams& i_paramsToWriteData)
-    const noexcept
+    const types::WriteVpdParams& i_paramsToWriteData) const noexcept
 {
     if (i_fruPath.empty())
     {
@@ -408,6 +407,10 @@
         return constants::FAILURE;
     }
 
+    bool l_isInputPathIsSourcePath = false;
+    bool l_isInputPathIsDestinationPath = false;
+    types::IpzData l_paramsToWrite;
+
     if (m_backupAndRestoreCfgJsonObj.contains("source") &&
         m_backupAndRestoreCfgJsonObj["source"].value("hardwarePath", "") ==
             i_fruPath &&
@@ -416,7 +419,7 @@
              .value("hardwarePath", "")
              .empty())
     {
-        // ToDo implementation needs to be added
+        l_isInputPathIsSourcePath = true;
     }
     else if (m_backupAndRestoreCfgJsonObj.contains("destination") &&
              m_backupAndRestoreCfgJsonObj["destination"].value(
@@ -426,9 +429,94 @@
                   .value("hardwarePath", "")
                   .empty())
     {
-        // ToDo implementation needs to be added
+        l_isInputPathIsDestinationPath = true;
+    }
+    else
+    {
+        // Input path is neither source or destination path of the
+        // backup&restore JSON.
+        return constants::SUCCESS;
     }
 
+    if (m_backupAndRestoreCfgJsonObj.contains("backupMap") &&
+        m_backupAndRestoreCfgJsonObj["backupMap"].is_array())
+    {
+        std::string l_inpRecordName;
+        std::string l_inpKeywordName;
+        types::BinaryVector l_keywordValue;
+
+        if (const types::IpzData* l_ipzData =
+                std::get_if<types::IpzData>(&i_paramsToWriteData))
+        {
+            l_inpRecordName = std::get<0>(*l_ipzData);
+            l_inpKeywordName = std::get<1>(*l_ipzData);
+            l_keywordValue = std::get<2>(*l_ipzData);
+
+            if (l_inpRecordName.empty() || l_inpKeywordName.empty() ||
+                l_keywordValue.empty())
+            {
+                logging::logMessage("Invalid input received");
+                return constants::FAILURE;
+            }
+        }
+        else
+        {
+            // only IPZ type VPD is supported now.
+            return constants::SUCCESS;
+        }
+
+        for (const auto& l_aRecordKwInfo :
+             m_backupAndRestoreCfgJsonObj["backupMap"])
+        {
+            if (l_aRecordKwInfo.value("sourceRecord", "").empty() ||
+                l_aRecordKwInfo.value("sourceKeyword", "").empty() ||
+                l_aRecordKwInfo.value("destinationRecord", "").empty() ||
+                l_aRecordKwInfo.value("destinationKeyword", "").empty())
+            {
+                // invalid backup map found
+                logging::logMessage(
+                    "Invalid backup map found, one or more field(s) found empty or not present in the config JSON: sourceRecord: " +
+                    l_aRecordKwInfo.value("sourceRecord", "") +
+                    ", sourceKeyword: " +
+                    l_aRecordKwInfo.value("sourceKeyword", "") +
+                    ", destinationRecord: " +
+                    l_aRecordKwInfo.value("destinationRecord", "") +
+                    ", destinationKeyword: " +
+                    l_aRecordKwInfo.value("destinationKeyword", ""));
+                continue;
+            }
+
+            if (l_isInputPathIsSourcePath &&
+                (l_aRecordKwInfo["sourceRecord"] == l_inpRecordName) &&
+                (l_aRecordKwInfo["sourceKeyword"] == l_inpKeywordName))
+            {
+                std::string l_fruPath(
+                    m_backupAndRestoreCfgJsonObj["destination"]
+                                                ["hardwarePath"]);
+                Parser l_parserObj(l_fruPath, m_sysCfgJsonObj);
+
+                return l_parserObj.updateVpdKeyword(std::make_tuple(
+                    l_aRecordKwInfo["destinationRecord"],
+                    l_aRecordKwInfo["destinationKeyword"], l_keywordValue));
+            }
+            else if (l_isInputPathIsDestinationPath &&
+                     (l_aRecordKwInfo["destinationRecord"] ==
+                      l_inpRecordName) &&
+                     (l_aRecordKwInfo["destinationKeyword"] ==
+                      l_inpKeywordName))
+            {
+                std::string l_fruPath(
+                    m_backupAndRestoreCfgJsonObj["source"]["hardwarePath"]);
+                Parser l_parserObj(l_fruPath, m_sysCfgJsonObj);
+
+                return l_parserObj.updateVpdKeyword(std::make_tuple(
+                    l_aRecordKwInfo["sourceRecord"],
+                    l_aRecordKwInfo["sourceKeyword"], l_keywordValue));
+            }
+        }
+    }
+
+    // Received property is not part of backup & restore JSON.
     return constants::SUCCESS;
 }