xref: /openbmc/openpower-vpd-parser/vpd-manager/src/backup_restore.cpp (revision eea9c20de4496258b4dd928be12d88b2448d94ee)
1 #include "backup_restore.hpp"
2 
3 #include "constants.hpp"
4 #include "error_codes.hpp"
5 #include "exceptions.hpp"
6 #include "logger.hpp"
7 #include "parser.hpp"
8 #include "types.hpp"
9 
10 #include <utility/event_logger_utility.hpp>
11 #include <utility/json_utility.hpp>
12 #include <utility/vpd_specific_utility.hpp>
13 
14 namespace vpd
15 {
16 BackupAndRestoreStatus BackupAndRestore::m_backupAndRestoreStatus =
17     BackupAndRestoreStatus::NotStarted;
18 
BackupAndRestore(const nlohmann::json & i_sysCfgJsonObj)19 BackupAndRestore::BackupAndRestore(const nlohmann::json& i_sysCfgJsonObj) :
20     m_sysCfgJsonObj(i_sysCfgJsonObj), m_logger(Logger::getLoggerInstance())
21 {
22     std::string l_backupAndRestoreCfgFilePath =
23         i_sysCfgJsonObj.value("backupRestoreConfigPath", "");
24 
25     uint16_t l_errCode = 0;
26     m_backupAndRestoreCfgJsonObj =
27         jsonUtility::getParsedJson(l_backupAndRestoreCfgFilePath, l_errCode);
28 
29     if (l_errCode)
30     {
31         throw JsonException(
32             "JSON parsing failed for file [" + l_backupAndRestoreCfgFilePath +
33                 "], error : " + commonUtility::getErrCodeMsg(l_errCode),
34             l_backupAndRestoreCfgFilePath);
35     }
36 
37     if (!isJsonValid())
38     {
39         throw JsonException("JSON is not valid.",
40                             l_backupAndRestoreCfgFilePath);
41     }
42 }
43 
isJsonValid()44 bool BackupAndRestore::isJsonValid()
45 {
46     if (m_backupAndRestoreCfgJsonObj.empty() ||
47         !m_backupAndRestoreCfgJsonObj.contains("source") ||
48         !m_backupAndRestoreCfgJsonObj.contains("destination") ||
49         !m_backupAndRestoreCfgJsonObj.contains("type") ||
50         !m_backupAndRestoreCfgJsonObj.contains("backupMap"))
51     {
52         m_logger->logMessage(
53             "Backup restore config JSON is missing necessary tag(s), can't initiate backup and restore.");
54         return false;
55     }
56     return true;
57 }
58 
getFruAndInvPaths(const std::string & i_location) const59 types::EepromInventoryPaths BackupAndRestore::getFruAndInvPaths(
60     const std::string& i_location) const noexcept
61 {
62     if (i_location.empty())
63     {
64         m_logger->logMessage("Empty location received.");
65         return {};
66     }
67 
68     if (!m_backupAndRestoreCfgJsonObj.contains(i_location))
69     {
70         m_logger->logMessage(
71             i_location +
72             " location is missing in the backup and restore config JSON.");
73         return {};
74     }
75 
76     std::string l_fruPath{};
77     std::string l_invObjPath{};
78 
79     if (l_fruPath =
80             m_backupAndRestoreCfgJsonObj[i_location].value("hardwarePath", "");
81         !l_fruPath.empty())
82     {
83         uint16_t l_errCode{0};
84         l_invObjPath = jsonUtility::getInventoryObjPathFromJson(
85             m_sysCfgJsonObj, l_fruPath, l_errCode);
86 
87         if (l_invObjPath.empty())
88         {
89             std::string l_message{
90                 "Failed to get Dbus inventory object path for [" + i_location +
91                 "]."};
92             if (l_errCode)
93             {
94                 l_message.append(
95                     " Error: " + commonUtility::getErrCodeMsg(l_errCode));
96             }
97             m_logger->logMessage(l_message);
98             return {};
99         }
100 
101         return std::make_tuple(l_fruPath, l_invObjPath);
102     }
103     else if (l_invObjPath = m_backupAndRestoreCfgJsonObj[i_location].value(
104                  "inventoryPath", "");
105              !l_invObjPath.empty())
106     {
107         uint16_t l_errCode{0};
108         l_fruPath = jsonUtility::getFruPathFromJson(m_sysCfgJsonObj,
109                                                     l_invObjPath, l_errCode);
110         if (l_fruPath.empty())
111         {
112             std::string l_message{
113                 "Failed to get FRU path for [" + i_location + "]."};
114             if (l_errCode)
115             {
116                 l_message.append(
117                     " Error: " + commonUtility::getErrCodeMsg(l_errCode));
118             }
119             m_logger->logMessage(l_message);
120             return {};
121         }
122 
123         return std::make_tuple(l_fruPath, l_invObjPath);
124     }
125 
126     m_logger->logMessage(
127         "Neither hardwarePath nor inventoryPath is present in the backup and restore config JSON.");
128     return {};
129 }
130 
getSrcAndDstServiceName() const131 std::tuple<std::string, std::string> BackupAndRestore::getSrcAndDstServiceName()
132     const noexcept
133 {
134     uint16_t l_errCode{0};
135 
136     std::string l_srcServiceName =
137         jsonUtility::getServiceName(m_sysCfgJsonObj, m_srcInvPath, l_errCode);
138     if (l_errCode)
139     {
140         m_logger->logMessage("Failed to get source service name, error : " +
141                              commonUtility::getErrCodeMsg(l_errCode));
142 
143         return {};
144     }
145 
146     std::string l_dstServiceName =
147         jsonUtility::getServiceName(m_sysCfgJsonObj, m_dstInvPath, l_errCode);
148     if (l_errCode)
149     {
150         m_logger->logMessage(
151             "Failed to get destination service name, error : " +
152             commonUtility::getErrCodeMsg(l_errCode));
153 
154         return {};
155     }
156 
157     return std::make_tuple(l_srcServiceName, l_dstServiceName);
158 }
159 
extractAndValidateIpzRecordDetails(const auto & i_aRecordKwInfo,types::SrcDstRecordDetails o_srcDstRecordKeywordInfo,const std::optional<types::IPZVpdMap> & i_srcVpdMap,const std::optional<types::IPZVpdMap> & i_dstVpdMap) const160 bool BackupAndRestore::extractAndValidateIpzRecordDetails(
161     const auto& i_aRecordKwInfo,
162     types::SrcDstRecordDetails o_srcDstRecordKeywordInfo,
163     const std::optional<types::IPZVpdMap>& i_srcVpdMap,
164     const std::optional<types::IPZVpdMap>& i_dstVpdMap) const noexcept
165 {
166     try
167     {
168         auto& [l_srcRecordName, l_srcKeywordName, l_dstRecordName,
169                l_dstKeywordName,
170                l_defaultBinaryValue] = o_srcDstRecordKeywordInfo;
171 
172         l_srcRecordName = i_aRecordKwInfo.value("sourceRecord", "");
173         l_srcKeywordName = i_aRecordKwInfo.value("sourceKeyword", "");
174         l_dstRecordName = i_aRecordKwInfo.value("destinationRecord", "");
175         l_dstKeywordName = i_aRecordKwInfo.value("destinationKeyword", "");
176 
177         if (l_srcRecordName.empty() || l_dstRecordName.empty() ||
178             l_srcKeywordName.empty() || l_dstKeywordName.empty())
179         {
180             throw std::runtime_error(
181                 "Record or keyword not found in the backup and restore config JSON.");
182         }
183 
184         if (i_srcVpdMap.has_value() && !i_srcVpdMap->empty() &&
185             i_srcVpdMap->find(l_srcRecordName) == i_srcVpdMap->end())
186         {
187             throw std::runtime_error(
188                 "Record: " + l_srcRecordName + ", is not found in the source " +
189                 m_srcFruPath);
190         }
191 
192         if (i_dstVpdMap.has_value() && !i_dstVpdMap->empty() &&
193             i_dstVpdMap->find(l_dstRecordName) == i_dstVpdMap->end())
194         {
195             throw std::runtime_error(
196                 "Record: " + l_dstRecordName +
197                 ", is not found in the destination " + m_dstFruPath);
198         }
199 
200         if (i_aRecordKwInfo.contains("defaultValue") &&
201             i_aRecordKwInfo["defaultValue"].is_array())
202         {
203             l_defaultBinaryValue = i_aRecordKwInfo["defaultValue"]
204                                        .template get<types::BinaryVector>();
205         }
206         else
207         {
208             throw std::runtime_error(
209                 "Couldn't read default value for record name: " +
210                 l_srcRecordName + ", keyword name: " + l_srcKeywordName +
211                 " from backup and restore config JSON file.");
212         }
213 
214         return true;
215     }
216     catch (const std::exception& l_ex)
217     {
218         m_logger->logMessage(
219             "Failed to extract source and destination record details, error: " +
220             std::string(l_ex.what()));
221         return false;
222     }
223 }
224 
getBinaryAndStrIpzKwValue(const types::IpzType & i_recordKwName,const types::IPZVpdMap & i_vpdMap,const std::string & i_serviceName) const225 types::BinaryStringKwValuePair BackupAndRestore::getBinaryAndStrIpzKwValue(
226     const types::IpzType& i_recordKwName, const types::IPZVpdMap& i_vpdMap,
227     const std::string& i_serviceName) const noexcept
228 {
229     try
230     {
231         std::string l_recordName = std::get<0>(i_recordKwName);
232         std::string l_keywordName = std::get<1>(i_recordKwName);
233 
234         if (l_recordName.empty() || l_keywordName.empty() ||
235             i_serviceName.empty())
236         {
237             throw std::runtime_error("Invalid input received.");
238         }
239 
240         types::BinaryVector l_binaryValue;
241         std::string l_strValue;
242         if (!i_vpdMap.empty())
243         {
244             uint16_t l_errCode{0};
245             l_strValue = vpdSpecificUtility::getKwVal(i_vpdMap.at(l_recordName),
246                                                       l_keywordName, l_errCode);
247 
248             if (l_strValue.empty())
249             {
250                 throw std::runtime_error(
251                     "Keyword value not found in the given VPD map, for [" +
252                     l_recordName + "][" + l_keywordName +
253                     "], reason: " + commonUtility::getErrCodeMsg(l_errCode));
254             }
255 
256             l_binaryValue =
257                 types::BinaryVector(l_strValue.begin(), l_strValue.end());
258         }
259         else
260         {
261             // Read keyword value from DBus
262             const auto l_dbusValue = dbusUtility::readDbusProperty(
263                 i_serviceName, m_srcInvPath,
264                 constants::ipzVpdInf + l_recordName, l_keywordName);
265 
266             if (const auto l_value =
267                     std::get_if<types::BinaryVector>(&l_dbusValue))
268             {
269                 l_binaryValue = *l_value;
270                 l_strValue =
271                     std::string(l_binaryValue.begin(), l_binaryValue.end());
272             }
273             else
274             {
275                 throw std::runtime_error(
276                     "Invalid keyword type found from Dbus, for [" +
277                     l_recordName + "][" + l_keywordName + "]");
278             }
279         }
280 
281         return std::make_tuple(l_binaryValue, l_strValue);
282     }
283     catch (const std::exception& l_ex)
284     {
285         m_logger->logMessage(
286             "Failed to get keyword value, error: " + std::string(l_ex.what()));
287         return {};
288     }
289 }
290 
syncIpzData(const std::string & i_fruPath,const types::IpzType & i_recordKwName,const types::BinaryStringKwValuePair & i_binaryStrValue,types::IPZVpdMap & o_vpdMap) const291 void BackupAndRestore::syncIpzData(
292     const std::string& i_fruPath, const types::IpzType& i_recordKwName,
293     const types::BinaryStringKwValuePair& i_binaryStrValue,
294     types::IPZVpdMap& o_vpdMap) const noexcept
295 {
296     std::string l_recordName = std::get<0>(i_recordKwName);
297     std::string l_keywordName = std::get<1>(i_recordKwName);
298 
299     types::BinaryVector l_binaryValue = std::get<0>(i_binaryStrValue);
300     std::string l_strValue = std::get<1>(i_binaryStrValue);
301 
302     if (i_fruPath.empty() || l_recordName.empty() || l_keywordName.empty() ||
303         l_binaryValue.empty() || l_strValue.empty())
304     {
305         m_logger->logMessage("Invalid input received");
306         return;
307     }
308 
309     // Update keyword's value on hardware
310     auto l_vpdParser = std::make_shared<Parser>(i_fruPath, m_sysCfgJsonObj);
311 
312     const auto l_bytesUpdatedOnHardware = l_vpdParser->updateVpdKeyword(
313         types::IpzData(l_recordName, l_keywordName, l_binaryValue));
314 
315     /* To keep the data in sync between hardware and parsed map
316     updating the o_vpdMap. This should only be done if write
317     on hardware returns success.*/
318     if (!o_vpdMap.empty() && l_bytesUpdatedOnHardware > 0)
319     {
320         o_vpdMap[l_recordName][l_keywordName] = l_strValue;
321     }
322 }
323 
324 std::tuple<types::VPDMapVariant, types::VPDMapVariant>
backupAndRestore()325     BackupAndRestore::backupAndRestore()
326 {
327     auto l_emptyVariantPair =
328         std::make_tuple(std::monostate{}, std::monostate{});
329 
330     try
331     {
332         if (m_backupAndRestoreStatus >= BackupAndRestoreStatus::Invoked)
333         {
334             throw std::runtime_error("Backup and restore invoked already.");
335         }
336 
337         m_backupAndRestoreStatus = BackupAndRestoreStatus::Invoked;
338 
339         std::tie(m_srcFruPath, m_srcInvPath) = getFruAndInvPaths("source");
340         if (m_srcFruPath.empty() || m_srcInvPath.empty())
341         {
342             throw std::runtime_error(
343                 "Failed to initiate backup and restore: unable to extract source FRU or inventory path.");
344         }
345 
346         std::tie(m_dstFruPath, m_dstInvPath) = getFruAndInvPaths("destination");
347         if (m_dstFruPath.empty() || m_dstInvPath.empty())
348         {
349             throw std::runtime_error(
350                 "Failed to initiate backup and restore: unable to extract destination FRU or inventory path.");
351         }
352 
353         types::VPDMapVariant l_srcVpdVariant;
354         if (m_backupAndRestoreCfgJsonObj["source"].contains("hardwarePath"))
355         {
356             std::shared_ptr<Parser> l_vpdParser =
357                 std::make_shared<Parser>(m_srcFruPath, m_sysCfgJsonObj);
358             l_srcVpdVariant = l_vpdParser->parse();
359         }
360 
361         types::VPDMapVariant l_dstVpdVariant;
362         if (m_backupAndRestoreCfgJsonObj["destination"].contains(
363                 "hardwarePath"))
364         {
365             std::shared_ptr<Parser> l_vpdParser =
366                 std::make_shared<Parser>(m_dstFruPath, m_sysCfgJsonObj);
367             l_dstVpdVariant = l_vpdParser->parse();
368         }
369 
370         // Implement backup and restore for IPZ type VPD
371         auto l_backupAndRestoreType =
372             m_backupAndRestoreCfgJsonObj.value("type", "");
373         if (l_backupAndRestoreType.compare("IPZ") == constants::STR_CMP_SUCCESS)
374         {
375             types::IPZVpdMap l_srcVpdMap;
376             if (auto l_srcVpdPtr =
377                     std::get_if<types::IPZVpdMap>(&l_srcVpdVariant))
378             {
379                 l_srcVpdMap = *l_srcVpdPtr;
380             }
381             else if (!std::holds_alternative<std::monostate>(l_srcVpdVariant))
382             {
383                 throw std::runtime_error("Source VPD is not of IPZ type.");
384             }
385 
386             types::IPZVpdMap l_dstVpdMap;
387             if (auto l_dstVpdPtr =
388                     std::get_if<types::IPZVpdMap>(&l_dstVpdVariant))
389             {
390                 l_dstVpdMap = *l_dstVpdPtr;
391             }
392             else if (!std::holds_alternative<std::monostate>(l_dstVpdVariant))
393             {
394                 throw std::runtime_error("Destination VPD is not of IPZ type.");
395             }
396 
397             backupAndRestoreIpzVpd(l_srcVpdMap, l_dstVpdMap);
398             m_backupAndRestoreStatus = BackupAndRestoreStatus::Completed;
399 
400             return std::make_tuple(l_srcVpdMap, l_dstVpdMap);
401         }
402         // Note: add implementation here to support any other VPD type.
403     }
404     catch (const std::exception& l_ex)
405     {
406         m_logger->logMessage("Back up and restore failed with exception: " +
407                              std::string(l_ex.what()));
408     }
409     return l_emptyVariantPair;
410 }
411 
backupAndRestoreIpzVpd(types::IPZVpdMap & io_srcVpdMap,types::IPZVpdMap & io_dstVpdMap)412 void BackupAndRestore::backupAndRestoreIpzVpd(types::IPZVpdMap& io_srcVpdMap,
413                                               types::IPZVpdMap& io_dstVpdMap)
414 {
415     if (!m_backupAndRestoreCfgJsonObj["backupMap"].is_array())
416     {
417         m_logger->logMessage(
418             "Invalid value found for tag backupMap, in backup and restore config JSON.");
419         return;
420     }
421 
422     if (m_srcFruPath.empty() || m_srcInvPath.empty() || m_dstFruPath.empty() ||
423         m_dstInvPath.empty())
424     {
425         m_logger->logMessage(
426             "Couldn't find either source or destination FRU or inventory path.");
427         return;
428     }
429 
430     auto [l_srcServiceName, l_dstServiceName] = getSrcAndDstServiceName();
431     if (l_srcServiceName.empty() || l_dstServiceName.empty())
432     {
433         m_logger->logMessage(
434             "Failed to get Dbus service name; aborting IPZ backup and restore.");
435         return;
436     }
437 
438     for (const auto& l_aRecordKwInfo :
439          m_backupAndRestoreCfgJsonObj["backupMap"])
440     {
441         std::string l_srcRecordName{}, l_srcKeywordName{}, l_dstRecordName{},
442             l_dstKeywordName{};
443         types::BinaryVector l_defaultBinaryValue;
444 
445         if (!extractAndValidateIpzRecordDetails(
446                 l_aRecordKwInfo,
447                 std::tie(l_srcRecordName, l_srcKeywordName, l_dstRecordName,
448                          l_dstKeywordName, l_defaultBinaryValue),
449                 io_srcVpdMap, io_dstVpdMap))
450         {
451             continue;
452         }
453 
454         bool l_isPelRequired = l_aRecordKwInfo.value("isPelRequired", false);
455 
456         const auto [l_srcBinaryValue, l_srcStrValue] =
457             getBinaryAndStrIpzKwValue(
458                 std::make_tuple(l_srcRecordName, l_srcKeywordName),
459                 io_srcVpdMap, l_srcServiceName);
460 
461         if (l_srcBinaryValue.empty() || l_srcStrValue.empty())
462         {
463             m_logger->logMessage(
464                 "Failed to get keyword value for source [" + l_srcRecordName +
465                 "][" + l_srcKeywordName + "]");
466 
467             continue;
468         }
469 
470         const auto [l_dstBinaryValue, l_dstStrValue] =
471             getBinaryAndStrIpzKwValue(
472                 std::make_tuple(l_dstRecordName, l_dstKeywordName),
473                 io_dstVpdMap, l_dstServiceName);
474 
475         if (l_dstBinaryValue.empty() || l_dstStrValue.empty())
476         {
477             m_logger->logMessage(
478                 "Failed to get keyword value for destination [" +
479                 l_dstRecordName + "][" + l_dstKeywordName + "]");
480 
481             continue;
482         }
483 
484         if (l_srcBinaryValue != l_dstBinaryValue)
485         {
486             // ToDo: Handle if there is no valid default value in the backup and
487             // restore config JSON.
488             if (l_dstBinaryValue == l_defaultBinaryValue)
489             {
490                 syncIpzData(m_dstFruPath,
491                             std::make_tuple(l_dstRecordName, l_dstKeywordName),
492                             std::make_tuple(l_srcBinaryValue, l_srcStrValue),
493                             io_dstVpdMap);
494                 continue;
495             }
496 
497             if (l_srcBinaryValue == l_defaultBinaryValue)
498             {
499                 syncIpzData(m_srcFruPath,
500                             std::make_tuple(l_srcRecordName, l_srcKeywordName),
501                             std::make_tuple(l_dstBinaryValue, l_dstStrValue),
502                             io_srcVpdMap);
503             }
504             else
505             {
506                 /**
507                  * Update io_srcVpdMap to publish the same data on DBus, which
508                  * is already present on the DBus. Because after calling
509                  * backupAndRestore API the map value will get published to DBus
510                  * in the worker flow.
511                  */
512                 if (!io_srcVpdMap.empty() && io_dstVpdMap.empty())
513                 {
514                     io_srcVpdMap[l_srcRecordName][l_srcKeywordName] =
515                         l_dstStrValue;
516                 }
517 
518                 std::string l_errorMsg(
519                     "Mismatch found between source and destination VPD for record : " +
520                     l_srcRecordName + " and keyword : " + l_srcKeywordName +
521                     " . Value read from source : " +
522                     commonUtility::convertByteVectorToHex(l_srcBinaryValue) +
523                     " . Value read from destination : " +
524                     commonUtility::convertByteVectorToHex(l_dstBinaryValue));
525 
526                 EventLogger::createSyncPel(
527                     types::ErrorType::VpdMismatch, types::SeverityType::Warning,
528                     __FILE__, __FUNCTION__, 0, l_errorMsg, std::nullopt,
529                     std::nullopt, std::nullopt, std::nullopt);
530             }
531         }
532         else if (l_srcBinaryValue == l_defaultBinaryValue &&
533                  l_dstBinaryValue == l_defaultBinaryValue && l_isPelRequired)
534         {
535             std::string l_errorMsg(
536                 "Default value found on both source and destination VPD, for record: " +
537                 l_srcRecordName + " and keyword: " + l_srcKeywordName);
538 
539             EventLogger::createSyncPel(
540                 types::ErrorType::DefaultValue, types::SeverityType::Error,
541                 __FILE__, __FUNCTION__, 0, l_errorMsg, std::nullopt,
542                 std::nullopt, std::nullopt, std::nullopt);
543         }
544     }
545 }
546 
setBackupAndRestoreStatus(const BackupAndRestoreStatus & i_status)547 void BackupAndRestore::setBackupAndRestoreStatus(
548     const BackupAndRestoreStatus& i_status)
549 {
550     m_backupAndRestoreStatus = i_status;
551 }
552 
updateKeywordOnPrimaryOrBackupPath(const std::string & i_fruPath,const types::WriteVpdParams & i_paramsToWriteData) const553 int BackupAndRestore::updateKeywordOnPrimaryOrBackupPath(
554     const std::string& i_fruPath,
555     const types::WriteVpdParams& i_paramsToWriteData) const noexcept
556 {
557     if (i_fruPath.empty())
558     {
559         m_logger->logMessage("Given FRU path is empty.");
560         return constants::FAILURE;
561     }
562 
563     bool l_inputPathIsSourcePath = false;
564     bool l_inputPathIsDestinationPath = false;
565 
566     if (m_backupAndRestoreCfgJsonObj.contains("source") &&
567         m_backupAndRestoreCfgJsonObj["source"].value("hardwarePath", "") ==
568             i_fruPath &&
569         m_backupAndRestoreCfgJsonObj.contains("destination") &&
570         !m_backupAndRestoreCfgJsonObj["destination"]
571              .value("hardwarePath", "")
572              .empty())
573     {
574         l_inputPathIsSourcePath = true;
575     }
576     else if (m_backupAndRestoreCfgJsonObj.contains("destination") &&
577              m_backupAndRestoreCfgJsonObj["destination"].value(
578                  "hardwarePath", "") == i_fruPath &&
579              m_backupAndRestoreCfgJsonObj.contains("source") &&
580              !m_backupAndRestoreCfgJsonObj["source"]
581                   .value("hardwarePath", "")
582                   .empty())
583     {
584         l_inputPathIsDestinationPath = true;
585     }
586     else
587     {
588         // Input path is neither source or destination path of the
589         // backup&restore JSON or source and destination paths are not hardware
590         // paths in the config JSON.
591         return constants::SUCCESS;
592     }
593 
594     if (m_backupAndRestoreCfgJsonObj["backupMap"].is_array())
595     {
596         std::string l_inpRecordName;
597         std::string l_inpKeywordName;
598         types::BinaryVector l_inpKeywordValue;
599 
600         if (const types::IpzData* l_ipzData =
601                 std::get_if<types::IpzData>(&i_paramsToWriteData))
602         {
603             l_inpRecordName = std::get<0>(*l_ipzData);
604             l_inpKeywordName = std::get<1>(*l_ipzData);
605             l_inpKeywordValue = std::get<2>(*l_ipzData);
606 
607             if (l_inpRecordName.empty() || l_inpKeywordName.empty() ||
608                 l_inpKeywordValue.empty())
609             {
610                 m_logger->logMessage("Invalid input received");
611                 return constants::FAILURE;
612             }
613         }
614         else
615         {
616             // only IPZ type VPD is supported now.
617             return constants::SUCCESS;
618         }
619 
620         for (const auto& l_aRecordKwInfo :
621              m_backupAndRestoreCfgJsonObj["backupMap"])
622         {
623             std::string l_srcRecordName{}, l_srcKeywordName{},
624                 l_dstRecordName{}, l_dstKeywordName{};
625             types::BinaryVector l_defaultBinaryValue;
626 
627             if (!extractAndValidateIpzRecordDetails(
628                     l_aRecordKwInfo,
629                     std::tie(l_srcRecordName, l_srcKeywordName, l_dstRecordName,
630                              l_dstKeywordName, l_defaultBinaryValue),
631                     std::nullopt, std::nullopt))
632             {
633                 continue;
634             }
635 
636             if (l_inputPathIsSourcePath &&
637                 (l_srcRecordName == l_inpRecordName) &&
638                 (l_srcKeywordName == l_inpKeywordName))
639             {
640                 std::string l_fruPath(
641                     m_backupAndRestoreCfgJsonObj["destination"]
642                                                 ["hardwarePath"]);
643                 Parser l_parserObj(l_fruPath, m_sysCfgJsonObj);
644 
645                 return l_parserObj.updateVpdKeyword(std::make_tuple(
646                     l_dstRecordName, l_dstKeywordName, l_inpKeywordValue));
647             }
648             else if (l_inputPathIsDestinationPath &&
649                      (l_dstRecordName == l_inpRecordName) &&
650                      (l_dstKeywordName == l_inpKeywordName))
651             {
652                 std::string l_fruPath(
653                     m_backupAndRestoreCfgJsonObj["source"]["hardwarePath"]);
654                 Parser l_parserObj(l_fruPath, m_sysCfgJsonObj);
655 
656                 return l_parserObj.updateVpdKeyword(std::make_tuple(
657                     l_srcRecordName, l_srcKeywordName, l_inpKeywordValue));
658             }
659         }
660     }
661 
662     // Received property is not part of backup & restore JSON.
663     return constants::SUCCESS;
664 }
665 
666 } // namespace vpd
667