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