blob: 9a0529492fcacac9f524f412f5f3b9df3e983bb9 [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#include "config.h"
2
3#include "worker.hpp"
4
5#include "backup_restore.hpp"
6#include "configuration.hpp"
7#include "constants.hpp"
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05008#include "exceptions.hpp"
9#include "logger.hpp"
10#include "parser.hpp"
11#include "parser_factory.hpp"
12#include "parser_interface.hpp"
13
Rekha Aparnac6159a22025-10-09 12:20:20 +053014#include <utility/common_utility.hpp>
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050015#include <utility/dbus_utility.hpp>
Rekha Aparnaa39aafa2025-11-04 00:06:12 -060016#include <utility/event_logger_utility.hpp>
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050017#include <utility/json_utility.hpp>
18#include <utility/vpd_specific_utility.hpp>
19
20#include <filesystem>
21#include <fstream>
22#include <future>
23#include <typeindex>
24#include <unordered_set>
25
26namespace vpd
27{
28
Souvik Roy31548842025-10-22 07:03:12 +000029Worker::Worker(std::string pathToConfigJson, uint8_t i_maxThreadCount,
30 types::VpdCollectionMode i_vpdCollectionMode) :
31 m_configJsonPath(pathToConfigJson), m_semaphore(i_maxThreadCount),
32 m_vpdCollectionMode(i_vpdCollectionMode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050033{
34 // Implies the processing is based on some config JSON
35 if (!m_configJsonPath.empty())
36 {
37 // Check if symlink is already there to confirm fresh boot/factory
38 // reset.
39 if (std::filesystem::exists(INVENTORY_JSON_SYM_LINK))
40 {
41 logging::logMessage("Sym Link already present");
42 m_configJsonPath = INVENTORY_JSON_SYM_LINK;
43 m_isSymlinkPresent = true;
44 }
45
46 try
47 {
Rekha Aparnaca9a0862025-08-29 04:08:33 -050048 uint16_t l_errCode = 0;
49 m_parsedJson =
50 jsonUtility::getParsedJson(m_configJsonPath, l_errCode);
51
52 if (l_errCode)
53 {
54 throw std::runtime_error(
55 "JSON parsing failed for file [ " + m_configJsonPath +
Rekha Aparnac6159a22025-10-09 12:20:20 +053056 " ], error : " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparnaca9a0862025-08-29 04:08:33 -050057 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050058
59 // check for mandatory fields at this point itself.
60 if (!m_parsedJson.contains("frus"))
61 {
62 throw std::runtime_error("Mandatory tag(s) missing from JSON");
63 }
64 }
65 catch (const std::exception& ex)
66 {
67 throw(JsonException(ex.what(), m_configJsonPath));
68 }
69 }
70 else
71 {
72 logging::logMessage("Processing in not based on any config JSON");
73 }
74}
75
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050076static std::string readFitConfigValue()
77{
78 std::vector<std::string> output =
79 commonUtility::executeCmd("/sbin/fw_printenv");
80 std::string fitConfigValue;
81
82 for (const auto& entry : output)
83 {
84 auto pos = entry.find("=");
85 auto key = entry.substr(0, pos);
86 if (key != "fitconfig")
87 {
88 continue;
89 }
90
91 if (pos + 1 < entry.size())
92 {
93 fitConfigValue = entry.substr(pos + 1);
94 }
95 }
96
97 return fitConfigValue;
98}
99
100bool Worker::isSystemVPDOnDBus() const
101{
102 const std::string& mboardPath =
103 m_parsedJson["frus"][SYSTEM_VPD_FILE_PATH].at(0).value(
104 "inventoryPath", "");
105
106 if (mboardPath.empty())
107 {
108 throw JsonException("System vpd file path missing in JSON",
109 INVENTORY_JSON_SYM_LINK);
110 }
111
Anupama B R68a70432025-09-25 02:09:37 -0500112 std::vector<std::string> interfaces = {
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500113 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
114
115 const types::MapperGetObject& objectMap =
116 dbusUtility::getObjectMap(mboardPath, interfaces);
117
118 if (objectMap.empty())
119 {
120 return false;
121 }
122 return true;
123}
124
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500125void Worker::fillVPDMap(const std::string& vpdFilePath,
126 types::VPDMapVariant& vpdMap)
127{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500128 if (vpdFilePath.empty())
129 {
130 throw std::runtime_error("Invalid file path passed to fillVPDMap API.");
131 }
132
133 if (!std::filesystem::exists(vpdFilePath))
134 {
135 throw std::runtime_error("Can't Find physical file");
136 }
137
Sunny Srivastava043955d2025-01-21 18:04:49 +0530138 std::shared_ptr<Parser> vpdParser =
139 std::make_shared<Parser>(vpdFilePath, m_parsedJson);
140 vpdMap = vpdParser->parse();
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500141}
142
143void Worker::getSystemJson(std::string& systemJson,
144 const types::VPDMapVariant& parsedVpdMap)
145{
146 if (auto pVal = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
147 {
Sunny Srivastava2e30cb82025-11-17 21:01:33 +0530148 uint16_t l_errCode = 0;
149 std::string hwKWdValue =
150 vpdSpecificUtility::getHWVersion(*pVal, l_errCode);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500151 if (hwKWdValue.empty())
152 {
Sunny Srivastava2e30cb82025-11-17 21:01:33 +0530153 if (l_errCode)
154 {
155 throw DataException("Failed to fetch HW value. Reason: " +
156 commonUtility::getErrCodeMsg(l_errCode));
157 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500158 throw DataException("HW value fetched is empty.");
159 }
160
Sunny Srivastava2e30cb82025-11-17 21:01:33 +0530161 const std::string& imKwdValue =
162 vpdSpecificUtility::getIMValue(*pVal, l_errCode);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500163 if (imKwdValue.empty())
164 {
Sunny Srivastava2e30cb82025-11-17 21:01:33 +0530165 if (l_errCode)
166 {
167 throw DataException("Failed to fetch IM value. Reason: " +
168 commonUtility::getErrCodeMsg(l_errCode));
169 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500170 throw DataException("IM value fetched is empty.");
171 }
172
173 auto itrToIM = config::systemType.find(imKwdValue);
174 if (itrToIM == config::systemType.end())
175 {
176 throw DataException("IM keyword does not map to any system type");
177 }
178
179 const types::HWVerList hwVersionList = itrToIM->second.second;
180 if (!hwVersionList.empty())
181 {
182 transform(hwKWdValue.begin(), hwKWdValue.end(), hwKWdValue.begin(),
183 ::toupper);
184
185 auto itrToHW =
186 std::find_if(hwVersionList.begin(), hwVersionList.end(),
187 [&hwKWdValue](const auto& aPair) {
188 return aPair.first == hwKWdValue;
189 });
190
191 if (itrToHW != hwVersionList.end())
192 {
193 if (!(*itrToHW).second.empty())
194 {
195 systemJson += (*itrToIM).first + "_" + (*itrToHW).second +
196 ".json";
197 }
198 else
199 {
200 systemJson += (*itrToIM).first + ".json";
201 }
202 return;
203 }
204 }
205 systemJson += itrToIM->second.first + ".json";
206 return;
207 }
208
Sunny Srivastava043955d2025-01-21 18:04:49 +0530209 throw DataException(
210 "Invalid VPD type returned from Parser. Can't get system JSON.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500211}
212
213static void setEnvAndReboot(const std::string& key, const std::string& value)
214{
215 // set env and reboot and break.
216 commonUtility::executeCmd("/sbin/fw_setenv", key, value);
217 logging::logMessage("Rebooting BMC to pick up new device tree");
218
219 // make dbus call to reboot
220 auto bus = sdbusplus::bus::new_default_system();
221 auto method = bus.new_method_call(
222 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
223 "org.freedesktop.systemd1.Manager", "Reboot");
224 bus.call_noreply(method);
225}
226
227void Worker::setJsonSymbolicLink(const std::string& i_systemJson)
228{
229 std::error_code l_ec;
230 l_ec.clear();
Sunny Srivastavaadff7882025-03-13 11:41:05 +0530231
232 // Check if symlink file path exists and if the JSON at this location is a
233 // symlink.
234 if (m_isSymlinkPresent &&
235 std::filesystem::is_symlink(INVENTORY_JSON_SYM_LINK, l_ec))
236 { // Don't care about exception in "is_symlink". Will continue with creation
237 // of symlink.
238
239 const auto& l_symlinkFilePth =
240 std::filesystem::read_symlink(INVENTORY_JSON_SYM_LINK, l_ec);
241
242 if (l_ec)
243 {
244 logging::logMessage(
245 "Can't read existing symlink. Error =" + l_ec.message() +
246 "Trying removal of symlink and creation of new symlink.");
247 }
248
249 // If currently set JSON is the required one. No further processing
250 // required.
251 if (i_systemJson == l_symlinkFilePth)
252 {
253 // Correct symlink already set.
254 return;
255 }
256
257 if (!std::filesystem::remove(INVENTORY_JSON_SYM_LINK, l_ec))
258 {
259 // No point going further. If removal fails for existing symlink,
260 // create will anyways throw.
261 throw std::runtime_error(
262 "Removal of symlink failed with Error = " + l_ec.message() +
263 ". Can't proceed with create_symlink.");
264 }
265 }
266
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500267 if (!std::filesystem::exists(VPD_SYMLIMK_PATH, l_ec))
268 {
269 if (l_ec)
270 {
271 throw std::runtime_error(
272 "File system call to exist failed with error = " +
273 l_ec.message());
274 }
275
276 // implies it is a fresh boot/factory reset.
277 // Create the directory for hosting the symlink
278 if (!std::filesystem::create_directories(VPD_SYMLIMK_PATH, l_ec))
279 {
280 if (l_ec)
281 {
282 throw std::runtime_error(
283 "File system call to create directory failed with error = " +
284 l_ec.message());
285 }
286 }
287 }
288
289 // create a new symlink based on the system
290 std::filesystem::create_symlink(i_systemJson, INVENTORY_JSON_SYM_LINK,
291 l_ec);
292
293 if (l_ec)
294 {
295 throw std::runtime_error(
296 "create_symlink system call failed with error: " + l_ec.message());
297 }
298
299 // If the flow is at this point implies the symlink was not present there.
300 // Considering this as factory reset.
301 m_isFactoryResetDone = true;
302}
303
304void Worker::setDeviceTreeAndJson()
305{
306 // JSON is madatory for processing of this API.
307 if (m_parsedJson.empty())
308 {
Sunny Srivastava043955d2025-01-21 18:04:49 +0530309 throw JsonException("System config JSON is empty", m_configJsonPath);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500310 }
311
312 types::VPDMapVariant parsedVpdMap;
313 fillVPDMap(SYSTEM_VPD_FILE_PATH, parsedVpdMap);
314
315 // Implies it is default JSON.
316 std::string systemJson{JSON_ABSOLUTE_PATH_PREFIX};
317
318 // ToDo: Need to check if INVENTORY_JSON_SYM_LINK pointing to correct system
319 // This is required to support movement from rainier to Blue Ridge on the
320 // fly.
321
Sunny Srivastavaadff7882025-03-13 11:41:05 +0530322 getSystemJson(systemJson, parsedVpdMap);
323
324 if (!systemJson.compare(JSON_ABSOLUTE_PATH_PREFIX))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500325 {
Sunny Srivastava043955d2025-01-21 18:04:49 +0530326 throw DataException(
327 "No system JSON found corresponding to IM read from VPD.");
Sunny Srivastavaadff7882025-03-13 11:41:05 +0530328 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500329
Rekha Aparnaca9a0862025-08-29 04:08:33 -0500330 uint16_t l_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500331
Rekha Aparnaca9a0862025-08-29 04:08:33 -0500332 // re-parse the JSON once appropriate JSON has been selected.
333 m_parsedJson = jsonUtility::getParsedJson(systemJson, l_errCode);
334
335 if (l_errCode)
Sunny Srivastavaadff7882025-03-13 11:41:05 +0530336 {
Rekha Aparnaca9a0862025-08-29 04:08:33 -0500337 throw(JsonException(
338 "JSON parsing failed for file [ " + systemJson +
Rekha Aparnac6159a22025-10-09 12:20:20 +0530339 " ], error : " + commonUtility::getErrCodeMsg(l_errCode),
Rekha Aparnaca9a0862025-08-29 04:08:33 -0500340 systemJson));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500341 }
342
Jinu Thomas5dcee082025-11-14 09:35:20 +0530343 setCollectionStatusProperty(SYSTEM_VPD_FILE_PATH,
344 constants::vpdCollectionInProgress);
345
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500346 std::string devTreeFromJson;
347 if (m_parsedJson.contains("devTree"))
348 {
349 devTreeFromJson = m_parsedJson["devTree"];
350
351 if (devTreeFromJson.empty())
352 {
Sunny Srivastava043955d2025-01-21 18:04:49 +0530353 EventLogger::createSyncPel(
354 types::ErrorType::JsonFailure, types::SeverityType::Error,
355 __FILE__, __FUNCTION__, 0,
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500356 "Mandatory value for device tree missing from JSON[" +
Sunny Srivastava043955d2025-01-21 18:04:49 +0530357 systemJson + "]",
358 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500359 }
360 }
361
362 auto fitConfigVal = readFitConfigValue();
363
364 if (devTreeFromJson.empty() ||
365 fitConfigVal.find(devTreeFromJson) != std::string::npos)
366 { // Skipping setting device tree as either devtree info is missing from
367 // Json or it is rightly set.
368
Sunny Srivastavaadff7882025-03-13 11:41:05 +0530369 setJsonSymbolicLink(systemJson);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500370
Rekha Aparna196e3082025-09-08 20:40:35 -0500371 if (isSystemVPDOnDBus())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500372 {
Rekha Aparna196e3082025-09-08 20:40:35 -0500373 uint16_t l_errCode = 0;
374 if (jsonUtility::isBackupAndRestoreRequired(m_parsedJson,
375 l_errCode))
376 {
377 performBackupAndRestore(parsedVpdMap);
378 }
379 else if (l_errCode)
380 {
381 logging::logMessage(
382 "Failed to check if backup and restore required. Reason : " +
Rekha Aparnac6159a22025-10-09 12:20:20 +0530383 commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna196e3082025-09-08 20:40:35 -0500384 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500385 }
386
387 // proceed to publish system VPD.
388 publishSystemVPD(parsedVpdMap);
Anupama B R4c65fcd2025-09-01 08:09:00 -0500389 setCollectionStatusProperty(SYSTEM_VPD_FILE_PATH,
390 constants::vpdCollectionCompleted);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500391 return;
392 }
393
394 setEnvAndReboot("fitconfig", devTreeFromJson);
395 exit(EXIT_SUCCESS);
396}
397
398void Worker::populateIPZVPDpropertyMap(
399 types::InterfaceMap& interfacePropMap,
400 const types::IPZKwdValueMap& keyordValueMap,
401 const std::string& interfaceName)
402{
403 types::PropertyMap propertyValueMap;
404 for (const auto& kwdVal : keyordValueMap)
405 {
406 auto kwd = kwdVal.first;
407
408 if (kwd[0] == '#')
409 {
410 kwd = std::string("PD_") + kwd[1];
411 }
412 else if (isdigit(kwd[0]))
413 {
414 kwd = std::string("N_") + kwd;
415 }
416
417 types::BinaryVector value(kwdVal.second.begin(), kwdVal.second.end());
418 propertyValueMap.emplace(move(kwd), move(value));
419 }
420
421 if (!propertyValueMap.empty())
422 {
423 interfacePropMap.emplace(interfaceName, propertyValueMap);
424 }
425}
426
427void Worker::populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap,
428 types::InterfaceMap& interfaceMap)
429{
430 for (const auto& kwdValMap : keyordVPDMap)
431 {
432 types::PropertyMap propertyValueMap;
433 auto kwd = kwdValMap.first;
434
435 if (kwd[0] == '#')
436 {
437 kwd = std::string("PD_") + kwd[1];
438 }
439 else if (isdigit(kwd[0]))
440 {
441 kwd = std::string("N_") + kwd;
442 }
443
444 if (auto keywordValue = get_if<types::BinaryVector>(&kwdValMap.second))
445 {
446 types::BinaryVector value((*keywordValue).begin(),
447 (*keywordValue).end());
448 propertyValueMap.emplace(move(kwd), move(value));
449 }
450 else if (auto keywordValue = get_if<std::string>(&kwdValMap.second))
451 {
452 types::BinaryVector value((*keywordValue).begin(),
453 (*keywordValue).end());
454 propertyValueMap.emplace(move(kwd), move(value));
455 }
456 else if (auto keywordValue = get_if<size_t>(&kwdValMap.second))
457 {
458 if (kwd == "MemorySizeInKB")
459 {
460 types::PropertyMap memProp;
461 memProp.emplace(move(kwd), ((*keywordValue)));
462 interfaceMap.emplace("xyz.openbmc_project.Inventory.Item.Dimm",
463 move(memProp));
464 continue;
465 }
466 else
467 {
468 logging::logMessage(
469 "Unknown Keyword =" + kwd + " found in keyword VPD map");
470 continue;
471 }
472 }
473 else
474 {
475 logging::logMessage(
476 "Unknown variant type found in keyword VPD map.");
477 continue;
478 }
479
480 if (!propertyValueMap.empty())
481 {
Rekha Aparnad3662222025-10-14 10:33:17 -0500482 uint16_t l_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500483 vpdSpecificUtility::insertOrMerge(
Rekha Aparnad3662222025-10-14 10:33:17 -0500484 interfaceMap, constants::kwdVpdInf, move(propertyValueMap),
485 l_errCode);
486
487 if (l_errCode)
488 {
489 logging::logMessage(
490 "Failed to insert value into map, error : " +
491 commonUtility::getErrCodeMsg(l_errCode));
492 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500493 }
494 }
495}
496
497void Worker::populateInterfaces(const nlohmann::json& interfaceJson,
498 types::InterfaceMap& interfaceMap,
499 const types::VPDMapVariant& parsedVpdMap)
500{
501 for (const auto& interfacesPropPair : interfaceJson.items())
502 {
503 const std::string& interface = interfacesPropPair.key();
504 types::PropertyMap propertyMap;
Rekha Aparna6256db92025-10-17 09:58:49 -0500505 uint16_t l_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500506
507 for (const auto& propValuePair : interfacesPropPair.value().items())
508 {
509 const std::string property = propValuePair.key();
510
511 if (propValuePair.value().is_boolean())
512 {
513 propertyMap.emplace(property,
514 propValuePair.value().get<bool>());
515 }
516 else if (propValuePair.value().is_string())
517 {
518 if (property.compare("LocationCode") == 0 &&
519 interface.compare("com.ibm.ipzvpd.Location") == 0)
520 {
521 std::string value =
522 vpdSpecificUtility::getExpandedLocationCode(
523 propValuePair.value().get<std::string>(),
Rekha Aparna6256db92025-10-17 09:58:49 -0500524 parsedVpdMap, l_errCode);
525
526 if (l_errCode)
527 {
528 logging::logMessage(
529 "Failed to get expanded location code for location code - " +
530 propValuePair.value().get<std::string>() +
531 " ,error : " +
532 commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna6256db92025-10-17 09:58:49 -0500533 }
534
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500535 propertyMap.emplace(property, value);
536
537 auto l_locCodeProperty = propertyMap;
538 vpdSpecificUtility::insertOrMerge(
539 interfaceMap,
540 std::string(constants::xyzLocationCodeInf),
Rekha Aparnad3662222025-10-14 10:33:17 -0500541 move(l_locCodeProperty), l_errCode);
542
543 if (l_errCode)
544 {
545 logging::logMessage(
546 "Failed to insert value into map, error : " +
547 commonUtility::getErrCodeMsg(l_errCode));
548 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500549 }
550 else
551 {
552 propertyMap.emplace(
553 property, propValuePair.value().get<std::string>());
554 }
555 }
556 else if (propValuePair.value().is_array())
557 {
558 try
559 {
560 propertyMap.emplace(
561 property,
562 propValuePair.value().get<types::BinaryVector>());
563 }
564 catch (const nlohmann::detail::type_error& e)
565 {
566 std::cerr << "Type exception: " << e.what() << "\n";
567 }
568 }
569 else if (propValuePair.value().is_number())
570 {
571 // For now assume the value is a size_t. In the future it would
572 // be nice to come up with a way to get the type from the JSON.
573 propertyMap.emplace(property,
574 propValuePair.value().get<size_t>());
575 }
576 else if (propValuePair.value().is_object())
577 {
578 const std::string& record =
579 propValuePair.value().value("recordName", "");
580 const std::string& keyword =
581 propValuePair.value().value("keywordName", "");
582 const std::string& encoding =
583 propValuePair.value().value("encoding", "");
584
585 if (auto ipzVpdMap =
586 std::get_if<types::IPZVpdMap>(&parsedVpdMap))
587 {
588 if (!record.empty() && !keyword.empty() &&
589 (*ipzVpdMap).count(record) &&
590 (*ipzVpdMap).at(record).count(keyword))
591 {
592 auto encoded = vpdSpecificUtility::encodeKeyword(
Rekha Aparna17ddfb52025-10-09 20:45:53 -0500593 ((*ipzVpdMap).at(record).at(keyword)), encoding,
594 l_errCode);
595
596 if (l_errCode)
597 {
598 logging::logMessage(
599 std::string(
600 "Failed to get encoded keyword value for : ") +
601 keyword + std::string(", error : ") +
602 commonUtility::getErrCodeMsg(l_errCode));
603 }
604
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500605 propertyMap.emplace(property, encoded);
606 }
607 }
608 else if (auto kwdVpdMap =
609 std::get_if<types::KeywordVpdMap>(&parsedVpdMap))
610 {
611 if (!keyword.empty() && (*kwdVpdMap).count(keyword))
612 {
613 if (auto kwValue = std::get_if<types::BinaryVector>(
614 &(*kwdVpdMap).at(keyword)))
615 {
616 auto encodedValue =
617 vpdSpecificUtility::encodeKeyword(
618 std::string((*kwValue).begin(),
619 (*kwValue).end()),
Rekha Aparna17ddfb52025-10-09 20:45:53 -0500620 encoding, l_errCode);
621
622 if (l_errCode)
623 {
624 logging::logMessage(
625 std::string(
626 "Failed to get encoded keyword value for : ") +
627 keyword + std::string(", error : ") +
628 commonUtility::getErrCodeMsg(l_errCode));
629 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500630
631 propertyMap.emplace(property, encodedValue);
632 }
633 else if (auto kwValue = std::get_if<std::string>(
634 &(*kwdVpdMap).at(keyword)))
635 {
636 auto encodedValue =
637 vpdSpecificUtility::encodeKeyword(
638 std::string((*kwValue).begin(),
639 (*kwValue).end()),
Rekha Aparna17ddfb52025-10-09 20:45:53 -0500640 encoding, l_errCode);
641
642 if (l_errCode)
643 {
644 logging::logMessage(
645 "Failed to get encoded keyword value for : " +
646 keyword + ", error : " +
647 commonUtility::getErrCodeMsg(l_errCode));
648 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500649
650 propertyMap.emplace(property, encodedValue);
651 }
652 else if (auto uintValue = std::get_if<size_t>(
653 &(*kwdVpdMap).at(keyword)))
654 {
655 propertyMap.emplace(property, *uintValue);
656 }
657 else
658 {
659 logging::logMessage(
660 "Unknown keyword found, Keywrod = " + keyword);
661 }
662 }
663 }
664 }
665 }
666 vpdSpecificUtility::insertOrMerge(interfaceMap, interface,
Rekha Aparnad3662222025-10-14 10:33:17 -0500667 move(propertyMap), l_errCode);
668
669 if (l_errCode)
670 {
671 logging::logMessage("Failed to insert value into map, error : " +
672 commonUtility::getErrCodeMsg(l_errCode));
673 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500674 }
675}
676
677bool Worker::isCPUIOGoodOnly(const std::string& i_pgKeyword)
678{
679 const unsigned char l_io[] = {
680 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF,
681 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF};
682
683 // EQ0 index (in PG keyword) starts at 97 (with offset starting from 0).
684 // Each EQ carries 3 bytes of data. Totally there are 8 EQs. If all EQs'
685 // value equals 0xE7F9FF, then the cpu has no good cores and its treated as
686 // IO.
687 if (memcmp(l_io, i_pgKeyword.data() + constants::INDEX_OF_EQ0_IN_PG,
688 constants::SIZE_OF_8EQ_IN_PG) == 0)
689 {
690 return true;
691 }
692
693 // The CPU is not an IO
694 return false;
695}
696
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500697void Worker::processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru,
698 types::InterfaceMap& interfaces)
699{
700 // embedded property(true or false) says whether the subfru is embedded
701 // into the parent fru (or) not. VPD sets Present property only for
702 // embedded frus. If the subfru is not an embedded FRU, the subfru may
703 // or may not be physically present. Those non embedded frus will always
704 // have Present=false irrespective of its physical presence or absence.
705 // Eg: nvme drive in nvme slot is not an embedded FRU. So don't set
706 // Present to true for such sub frus.
707 // Eg: ethernet port is embedded into bmc card. So set Present to true
708 // for such sub frus. Also donot populate present property for embedded
709 // subfru which is synthesized. Currently there is no subfru which are
710 // both embedded and synthesized. But still the case is handled here.
711
712 // Check if its required to handle presence for this FRU.
713 if (singleFru.value("handlePresence", true))
714 {
Rekha Aparnad3662222025-10-14 10:33:17 -0500715 uint16_t l_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500716 types::PropertyMap presProp;
717 presProp.emplace("Present", true);
Rekha Aparnad3662222025-10-14 10:33:17 -0500718 vpdSpecificUtility::insertOrMerge(interfaces,
719 "xyz.openbmc_project.Inventory.Item",
720 move(presProp), l_errCode);
721
722 if (l_errCode)
723 {
724 logging::logMessage("Failed to insert value into map, error : " +
725 commonUtility::getErrCodeMsg(l_errCode));
726 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500727 }
728}
729
730void Worker::processExtraInterfaces(const nlohmann::json& singleFru,
731 types::InterfaceMap& interfaces,
732 const types::VPDMapVariant& parsedVpdMap)
733{
734 populateInterfaces(singleFru["extraInterfaces"], interfaces, parsedVpdMap);
735 if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
736 {
737 if (singleFru["extraInterfaces"].contains(
738 "xyz.openbmc_project.Inventory.Item.Cpu"))
739 {
740 auto itrToRec = (*ipzVpdMap).find("CP00");
741 if (itrToRec == (*ipzVpdMap).end())
742 {
743 return;
744 }
745
Rekha Aparna7d9a7062025-10-07 04:14:42 -0500746 uint16_t l_errCode = 0;
747 const std::string pgKeywordValue{vpdSpecificUtility::getKwVal(
748 itrToRec->second, "PG", l_errCode)};
Souvik Roya55fcca2025-02-19 01:33:58 -0600749
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500750 if (!pgKeywordValue.empty())
751 {
752 if (isCPUIOGoodOnly(pgKeywordValue))
753 {
754 interfaces["xyz.openbmc_project.Inventory.Item"]
755 ["PrettyName"] = "IO Module";
756 }
757 }
Souvik Roya55fcca2025-02-19 01:33:58 -0600758 else
759 {
Rekha Aparna7d9a7062025-10-07 04:14:42 -0500760 throw DataException(
761 std::string(__FUNCTION__) +
762 "Failed to get value for keyword PG, error : " +
763 commonUtility::getErrCodeMsg(l_errCode));
Souvik Roya55fcca2025-02-19 01:33:58 -0600764 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500765 }
766 }
767}
768
769void Worker::processCopyRecordFlag(const nlohmann::json& singleFru,
770 const types::VPDMapVariant& parsedVpdMap,
771 types::InterfaceMap& interfaces)
772{
773 if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
774 {
775 for (const auto& record : singleFru["copyRecords"])
776 {
777 const std::string& recordName = record;
778 if ((*ipzVpdMap).find(recordName) != (*ipzVpdMap).end())
779 {
780 populateIPZVPDpropertyMap(interfaces,
781 (*ipzVpdMap).at(recordName),
782 constants::ipzVpdInf + recordName);
783 }
784 }
785 }
786}
787
788void Worker::processInheritFlag(const types::VPDMapVariant& parsedVpdMap,
789 types::InterfaceMap& interfaces)
790{
791 if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
792 {
793 for (const auto& [recordName, kwdValueMap] : *ipzVpdMap)
794 {
795 populateIPZVPDpropertyMap(interfaces, kwdValueMap,
796 constants::ipzVpdInf + recordName);
797 }
798 }
799 else if (auto kwdVpdMap = std::get_if<types::KeywordVpdMap>(&parsedVpdMap))
800 {
801 populateKwdVPDpropertyMap(*kwdVpdMap, interfaces);
802 }
803
804 if (m_parsedJson.contains("commonInterfaces"))
805 {
806 populateInterfaces(m_parsedJson["commonInterfaces"], interfaces,
807 parsedVpdMap);
808 }
809}
810
811bool Worker::processFruWithCCIN(const nlohmann::json& singleFru,
812 const types::VPDMapVariant& parsedVpdMap)
813{
814 if (auto ipzVPDMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
815 {
816 auto itrToRec = (*ipzVPDMap).find("VINI");
817 if (itrToRec == (*ipzVPDMap).end())
818 {
819 return false;
820 }
821
Rekha Aparna7d9a7062025-10-07 04:14:42 -0500822 uint16_t l_errCode = 0;
Souvik Roya55fcca2025-02-19 01:33:58 -0600823 std::string ccinFromVpd{
Rekha Aparna7d9a7062025-10-07 04:14:42 -0500824 vpdSpecificUtility::getKwVal(itrToRec->second, "CC", l_errCode)};
Souvik Roya55fcca2025-02-19 01:33:58 -0600825
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500826 if (ccinFromVpd.empty())
827 {
Rekha Aparna7d9a7062025-10-07 04:14:42 -0500828 logging::logMessage("Failed to get CCIN kwd value, error : " +
829 commonUtility::getErrCodeMsg(l_errCode));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500830 return false;
831 }
832
833 transform(ccinFromVpd.begin(), ccinFromVpd.end(), ccinFromVpd.begin(),
834 ::toupper);
835
836 std::vector<std::string> ccinList;
837 for (std::string ccin : singleFru["ccin"])
838 {
839 transform(ccin.begin(), ccin.end(), ccin.begin(), ::toupper);
840 ccinList.push_back(ccin);
841 }
842
843 if (ccinList.empty())
844 {
845 return false;
846 }
847
848 if (find(ccinList.begin(), ccinList.end(), ccinFromVpd) ==
849 ccinList.end())
850 {
851 return false;
852 }
853 }
854 return true;
855}
856
857void Worker::processFunctionalProperty(const std::string& i_inventoryObjPath,
858 types::InterfaceMap& io_interfaces)
859{
860 if (!dbusUtility::isChassisPowerOn())
861 {
Anupama B R68a70432025-09-25 02:09:37 -0500862 std::vector<std::string> l_operationalStatusInf = {
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500863 constants::operationalStatusInf};
864
865 auto mapperObjectMap = dbusUtility::getObjectMap(
866 i_inventoryObjPath, l_operationalStatusInf);
867
868 // If the object has been found. Check if it is under PIM.
869 if (mapperObjectMap.size() != 0)
870 {
871 for (const auto& [l_serviceName, l_interfaceLsit] : mapperObjectMap)
872 {
873 if (l_serviceName == constants::pimServiceName)
874 {
875 // The object is already under PIM. No need to process
876 // again. Retain the old value.
877 return;
878 }
879 }
880 }
881
882 // Implies value is not there in D-Bus. Populate it with default
883 // value "true".
Rekha Aparnad3662222025-10-14 10:33:17 -0500884 uint16_t l_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500885 types::PropertyMap l_functionalProp;
886 l_functionalProp.emplace("Functional", true);
887 vpdSpecificUtility::insertOrMerge(io_interfaces,
888 constants::operationalStatusInf,
Rekha Aparnad3662222025-10-14 10:33:17 -0500889 move(l_functionalProp), l_errCode);
890
891 if (l_errCode)
892 {
893 logging::logMessage(
894 "Failed to insert interface into map, error : " +
895 commonUtility::getErrCodeMsg(l_errCode));
896 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500897 }
898
899 // if chassis is power on. Functional property should be there on D-Bus.
900 // Don't process.
901 return;
902}
903
904void Worker::processEnabledProperty(const std::string& i_inventoryObjPath,
905 types::InterfaceMap& io_interfaces)
906{
907 if (!dbusUtility::isChassisPowerOn())
908 {
Anupama B R68a70432025-09-25 02:09:37 -0500909 std::vector<std::string> l_enableInf = {constants::enableInf};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500910
911 auto mapperObjectMap =
912 dbusUtility::getObjectMap(i_inventoryObjPath, l_enableInf);
913
914 // If the object has been found. Check if it is under PIM.
915 if (mapperObjectMap.size() != 0)
916 {
917 for (const auto& [l_serviceName, l_interfaceLsit] : mapperObjectMap)
918 {
919 if (l_serviceName == constants::pimServiceName)
920 {
921 // The object is already under PIM. No need to process
922 // again. Retain the old value.
923 return;
924 }
925 }
926 }
927
928 // Implies value is not there in D-Bus. Populate it with default
929 // value "true".
Rekha Aparnad3662222025-10-14 10:33:17 -0500930 uint16_t l_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500931 types::PropertyMap l_enabledProp;
932 l_enabledProp.emplace("Enabled", true);
933 vpdSpecificUtility::insertOrMerge(io_interfaces, constants::enableInf,
Rekha Aparnad3662222025-10-14 10:33:17 -0500934 move(l_enabledProp), l_errCode);
935
936 if (l_errCode)
937 {
938 logging::logMessage(
939 "Failed to insert interface into map, error : " +
940 commonUtility::getErrCodeMsg(l_errCode));
941 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500942 }
943
944 // if chassis is power on. Enabled property should be there on D-Bus.
945 // Don't process.
946 return;
947}
948
949void Worker::populateDbus(const types::VPDMapVariant& parsedVpdMap,
950 types::ObjectMap& objectInterfaceMap,
951 const std::string& vpdFilePath)
952{
953 if (vpdFilePath.empty())
954 {
955 throw std::runtime_error(
Sunny Srivastava4c509c22025-03-25 12:43:40 +0530956 std::string(__FUNCTION__) +
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500957 "Invalid parameter passed to populateDbus API.");
958 }
959
960 // JSON config is mandatory for processing of "if". Add "else" for any
961 // processing without config JSON.
962 if (!m_parsedJson.empty())
963 {
964 types::InterfaceMap interfaces;
965
966 for (const auto& aFru : m_parsedJson["frus"][vpdFilePath])
967 {
968 const auto& inventoryPath = aFru["inventoryPath"];
969 sdbusplus::message::object_path fruObjectPath(inventoryPath);
970 if (aFru.contains("ccin"))
971 {
972 if (!processFruWithCCIN(aFru, parsedVpdMap))
973 {
974 continue;
975 }
976 }
977
978 if (aFru.value("inherit", true))
979 {
980 processInheritFlag(parsedVpdMap, interfaces);
981 }
982
983 // If specific record needs to be copied.
984 if (aFru.contains("copyRecords"))
985 {
986 processCopyRecordFlag(aFru, parsedVpdMap, interfaces);
987 }
988
989 if (aFru.contains("extraInterfaces"))
990 {
991 // Process extra interfaces w.r.t a FRU.
992 processExtraInterfaces(aFru, interfaces, parsedVpdMap);
993 }
994
995 // Process FRUS which are embedded in the parent FRU and whose VPD
996 // will be synthesized.
997 if ((aFru.value("embedded", true)) &&
998 (!aFru.value("synthesized", false)))
999 {
1000 processEmbeddedAndSynthesizedFrus(aFru, interfaces);
1001 }
1002
1003 processFunctionalProperty(inventoryPath, interfaces);
1004 processEnabledProperty(inventoryPath, interfaces);
1005
1006 objectInterfaceMap.emplace(std::move(fruObjectPath),
1007 std::move(interfaces));
1008 }
1009 }
1010}
1011
Patrick Williams43fedab2025-02-03 14:28:05 -05001012std::string Worker::createAssetTagString(
1013 const types::VPDMapVariant& i_parsedVpdMap)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001014{
1015 std::string l_assetTag;
1016
1017 // system VPD will be in IPZ format.
1018 if (auto l_parsedVpdMap = std::get_if<types::IPZVpdMap>(&i_parsedVpdMap))
1019 {
1020 auto l_itrToVsys = (*l_parsedVpdMap).find(constants::recVSYS);
1021 if (l_itrToVsys != (*l_parsedVpdMap).end())
1022 {
Rekha Aparna7d9a7062025-10-07 04:14:42 -05001023 uint16_t l_errCode = 0;
Souvik Roya55fcca2025-02-19 01:33:58 -06001024 const std::string l_tmKwdValue{vpdSpecificUtility::getKwVal(
Rekha Aparna7d9a7062025-10-07 04:14:42 -05001025 l_itrToVsys->second, constants::kwdTM, l_errCode)};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001026
Souvik Roya55fcca2025-02-19 01:33:58 -06001027 if (l_tmKwdValue.empty())
1028 {
1029 throw std::runtime_error(
1030 std::string("Failed to get value for keyword [") +
1031 constants::kwdTM +
Rekha Aparna7d9a7062025-10-07 04:14:42 -05001032 std::string("] while creating Asset tag. Error : " +
1033 commonUtility::getErrCodeMsg(l_errCode)));
Souvik Roya55fcca2025-02-19 01:33:58 -06001034 }
1035
1036 const std::string l_seKwdValue{vpdSpecificUtility::getKwVal(
Rekha Aparna7d9a7062025-10-07 04:14:42 -05001037 l_itrToVsys->second, constants::kwdSE, l_errCode)};
Souvik Roya55fcca2025-02-19 01:33:58 -06001038
1039 if (l_seKwdValue.empty())
1040 {
1041 throw std::runtime_error(
1042 std::string("Failed to get value for keyword [") +
1043 constants::kwdSE +
Rekha Aparna7d9a7062025-10-07 04:14:42 -05001044 std::string("] while creating Asset tag. Error : " +
1045 commonUtility::getErrCodeMsg(l_errCode)));
Souvik Roya55fcca2025-02-19 01:33:58 -06001046 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001047
1048 l_assetTag = std::string{"Server-"} + l_tmKwdValue +
1049 std::string{"-"} + l_seKwdValue;
1050 }
1051 else
1052 {
1053 throw std::runtime_error(
1054 "VSYS record not found in parsed VPD map to create Asset tag.");
1055 }
1056 }
1057 else
1058 {
1059 throw std::runtime_error(
1060 "Invalid VPD type recieved to create Asset tag.");
1061 }
1062
1063 return l_assetTag;
1064}
1065
1066void Worker::publishSystemVPD(const types::VPDMapVariant& parsedVpdMap)
1067{
1068 types::ObjectMap objectInterfaceMap;
1069
1070 if (std::get_if<types::IPZVpdMap>(&parsedVpdMap))
1071 {
1072 populateDbus(parsedVpdMap, objectInterfaceMap, SYSTEM_VPD_FILE_PATH);
1073
1074 try
1075 {
1076 if (m_isFactoryResetDone)
1077 {
1078 const auto& l_assetTag = createAssetTagString(parsedVpdMap);
1079
1080 auto l_itrToSystemPath = objectInterfaceMap.find(
1081 sdbusplus::message::object_path(constants::systemInvPath));
1082 if (l_itrToSystemPath == objectInterfaceMap.end())
1083 {
1084 throw std::runtime_error(
Sunny Srivastava043955d2025-01-21 18:04:49 +05301085 "Asset tag update failed. System Path not found in object map.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001086 }
1087
1088 types::PropertyMap l_assetTagProperty;
1089 l_assetTagProperty.emplace("AssetTag", l_assetTag);
1090
1091 (l_itrToSystemPath->second)
1092 .emplace(constants::assetTagInf,
1093 std::move(l_assetTagProperty));
1094 }
1095 }
1096 catch (const std::exception& l_ex)
1097 {
1098 EventLogger::createSyncPel(
Sunny Srivastava043955d2025-01-21 18:04:49 +05301099 EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
1100 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001101 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
1102 }
1103
1104 // Notify PIM
1105 if (!dbusUtility::callPIM(move(objectInterfaceMap)))
1106 {
1107 throw std::runtime_error("Call to PIM failed for system VPD");
1108 }
1109 }
1110 else
1111 {
1112 throw DataException("Invalid format of parsed VPD map.");
1113 }
1114}
1115
1116bool Worker::processPreAction(const std::string& i_vpdFilePath,
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001117 const std::string& i_flagToProcess,
1118 uint16_t& i_errCode)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001119{
Sunny Srivastavab5fab802025-11-05 21:42:26 +05301120 i_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001121 if (i_vpdFilePath.empty() || i_flagToProcess.empty())
1122 {
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001123 i_errCode = error_code::INVALID_INPUT_PARAMETER;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001124 return false;
1125 }
1126
1127 if ((!jsonUtility::executeBaseAction(m_parsedJson, "preAction",
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001128 i_vpdFilePath, i_flagToProcess,
1129 i_errCode)) &&
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001130 (i_flagToProcess.compare("collection") == constants::STR_CMP_SUCCESS))
1131 {
1132 // TODO: Need a way to delete inventory object from Dbus and persisted
1133 // data section in case any FRU is not present or there is any
1134 // problem in collecting it. Once it has been deleted, it can be
1135 // re-created in the flow of priming the inventory. This needs to be
1136 // done either here or in the exception section of "parseAndPublishVPD"
1137 // API. Any failure in the process of collecting FRU will land up in the
1138 // excpetion of "parseAndPublishVPD".
1139
1140 // If the FRU is not there, clear the VINI/CCIN data.
1141 // Enity manager probes for this keyword to look for this
1142 // FRU, now if the data is persistent on BMC and FRU is
1143 // removed this can lead to ambiguity. Hence clearing this
1144 // Keyword if FRU is absent.
1145 const auto& inventoryPath =
1146 m_parsedJson["frus"][i_vpdFilePath].at(0).value("inventoryPath",
1147 "");
1148
1149 if (!inventoryPath.empty())
1150 {
1151 types::ObjectMap l_pimObjMap{
1152 {inventoryPath,
1153 {{constants::kwdVpdInf,
1154 {{constants::kwdCCIN, types::BinaryVector{}}}}}}};
1155
1156 if (!dbusUtility::callPIM(std::move(l_pimObjMap)))
1157 {
1158 logging::logMessage(
1159 "Call to PIM failed for file " + i_vpdFilePath);
1160 }
1161 }
1162 else
1163 {
1164 logging::logMessage(
1165 "Inventory path is empty in Json for file " + i_vpdFilePath);
1166 }
1167
1168 return false;
1169 }
1170 return true;
1171}
1172
1173bool Worker::processPostAction(
1174 const std::string& i_vpdFruPath, const std::string& i_flagToProcess,
1175 const std::optional<types::VPDMapVariant> i_parsedVpd)
1176{
1177 if (i_vpdFruPath.empty() || i_flagToProcess.empty())
1178 {
1179 logging::logMessage(
1180 "Invalid input parameter. Abort processing post action");
1181 return false;
1182 }
1183
1184 // Check if post action tag is to be triggered in the flow of collection
1185 // based on some CCIN value?
Rekha Aparna1d8ec012025-10-22 12:37:01 -05001186 uint16_t l_errCode = 0;
1187
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001188 if (m_parsedJson["frus"][i_vpdFruPath]
1189 .at(0)["postAction"][i_flagToProcess]
1190 .contains("ccin"))
1191 {
1192 if (!i_parsedVpd.has_value())
1193 {
1194 logging::logMessage("Empty VPD Map");
1195 return false;
1196 }
1197
1198 // CCIN match is required to process post action for this FRU as it
1199 // contains the flag.
1200 if (!vpdSpecificUtility::findCcinInVpd(
1201 m_parsedJson["frus"][i_vpdFruPath].at(
1202 0)["postAction"]["collection"],
Rekha Aparna1d8ec012025-10-22 12:37:01 -05001203 i_parsedVpd.value(), l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001204 {
Rekha Aparna1d8ec012025-10-22 12:37:01 -05001205 if (l_errCode)
1206 {
1207 // ToDo - Check if PEL is required in case of RECORD_NOT_FOUND
1208 // and KEYWORD_NOT_FOUND error codes.
1209 logging::logMessage("Failed to find CCIN in VPD, error : " +
1210 commonUtility::getErrCodeMsg(l_errCode));
1211 }
1212
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001213 // If CCIN is not found, implies post action processing is not
1214 // required for this FRU. Let the flow continue.
1215 return true;
1216 }
1217 }
1218
1219 if (!jsonUtility::executeBaseAction(m_parsedJson, "postAction",
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001220 i_vpdFruPath, i_flagToProcess,
1221 l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001222 {
1223 logging::logMessage(
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001224 "Execution of post action failed for path: " + i_vpdFruPath +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301225 " . Reason: " + commonUtility::getErrCodeMsg(l_errCode));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001226
1227 // If post action was required and failed only in that case return
1228 // false. In all other case post action is considered passed.
1229 return false;
1230 }
1231
1232 return true;
1233}
1234
1235types::VPDMapVariant Worker::parseVpdFile(const std::string& i_vpdFilePath)
1236{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001237 try
1238 {
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001239 uint16_t l_errCode = 0;
1240
Sunny Srivastava4c509c22025-03-25 12:43:40 +05301241 if (i_vpdFilePath.empty())
1242 {
1243 throw std::runtime_error(
1244 std::string(__FUNCTION__) +
Sunny Srivastava0a5fce12025-04-09 11:09:51 +05301245 " Empty VPD file path passed. Abort processing");
Sunny Srivastava4c509c22025-03-25 12:43:40 +05301246 }
1247
Sunny Srivastava0a5fce12025-04-09 11:09:51 +05301248 bool isPreActionRequired = false;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001249 if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001250 "preAction", "collection", l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001251 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +05301252 isPreActionRequired = true;
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001253 if (!processPreAction(i_vpdFilePath, "collection", l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001254 {
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001255 if (l_errCode == error_code::DEVICE_NOT_PRESENT)
1256 {
1257 logging::logMessage(
Rekha Aparnac6159a22025-10-09 12:20:20 +05301258 commonUtility::getErrCodeMsg(l_errCode) +
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001259 i_vpdFilePath);
1260 // Presence pin has been read successfully and has been read
1261 // as false, so this is not a failure case, hence returning
1262 // empty variant so that pre action is not marked as failed.
1263 return types::VPDMapVariant{};
1264 }
Sunny Srivastava4c509c22025-03-25 12:43:40 +05301265 throw std::runtime_error(
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001266 std::string(__FUNCTION__) +
1267 " Pre-Action failed with error: " +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301268 commonUtility::getErrCodeMsg(l_errCode));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001269 }
1270 }
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001271 else if (l_errCode)
1272 {
1273 logging::logMessage(
1274 "Failed to check if pre action required for FRU [" +
1275 i_vpdFilePath +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301276 "], error : " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001277 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001278
1279 if (!std::filesystem::exists(i_vpdFilePath))
1280 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +05301281 if (isPreActionRequired)
1282 {
1283 throw std::runtime_error(
1284 std::string(__FUNCTION__) + " Could not find file path " +
1285 i_vpdFilePath + "Skipping parser trigger for the EEPROM");
1286 }
1287 return types::VPDMapVariant{};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001288 }
1289
1290 std::shared_ptr<Parser> vpdParser =
1291 std::make_shared<Parser>(i_vpdFilePath, m_parsedJson);
1292
1293 types::VPDMapVariant l_parsedVpd = vpdParser->parse();
1294
1295 // Before returning, as collection is over, check if FRU qualifies for
1296 // any post action in the flow of collection.
1297 // Note: Don't change the order, post action needs to be processed only
1298 // after collection for FRU is successfully done.
1299 if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001300 "postAction", "collection",
1301 l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001302 {
1303 if (!processPostAction(i_vpdFilePath, "collection", l_parsedVpd))
1304 {
Sunny Srivastava4c509c22025-03-25 12:43:40 +05301305 // Post action was required but failed while executing.
1306 // Behaviour can be undefined.
1307 EventLogger::createSyncPel(
1308 types::ErrorType::InternalFailure,
1309 types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
1310 std::string("Required post action failed for path [" +
1311 i_vpdFilePath + "]"),
1312 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001313 }
1314 }
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001315 else if (l_errCode)
1316 {
1317 logging::logMessage(
1318 "Error while checking if post action required for FRU [" +
1319 i_vpdFilePath +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301320 "], error : " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001321 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001322
1323 return l_parsedVpd;
1324 }
1325 catch (std::exception& l_ex)
1326 {
Rekha Aparnaff7d7992025-09-01 11:08:53 -05001327 uint16_t l_errCode = 0;
Souvik Roy37c6bef2025-07-17 00:55:59 -05001328 std::string l_exMsg{
1329 std::string(__FUNCTION__) + " : VPD parsing failed for " +
1330 i_vpdFilePath + " due to error: " + l_ex.what()};
1331
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001332 // If post fail action is required, execute it.
1333 if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001334 "postFailAction", "collection",
1335 l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001336 {
1337 if (!jsonUtility::executePostFailAction(m_parsedJson, i_vpdFilePath,
Rekha Aparnaff7d7992025-09-01 11:08:53 -05001338 "collection", l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001339 {
Rekha Aparnaff7d7992025-09-01 11:08:53 -05001340 l_exMsg += ". Post fail action also failed. Error : " +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301341 commonUtility::getErrCodeMsg(l_errCode) +
Rekha Aparnaff7d7992025-09-01 11:08:53 -05001342 " Aborting collection for this FRU.";
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001343 }
1344 }
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001345 else if (l_errCode)
1346 {
1347 l_exMsg +=
1348 ". Failed to check if post fail action required, error : " +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301349 commonUtility::getErrCodeMsg(l_errCode);
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001350 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001351
Souvik Roy37c6bef2025-07-17 00:55:59 -05001352 if (typeid(l_ex) == typeid(DataException))
1353 {
1354 throw DataException(l_exMsg);
1355 }
1356 else if (typeid(l_ex) == typeid(EccException))
1357 {
1358 throw EccException(l_exMsg);
1359 }
1360 throw std::runtime_error(l_exMsg);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001361 }
1362}
1363
Patrick Williams43fedab2025-02-03 14:28:05 -05001364std::tuple<bool, std::string> Worker::parseAndPublishVPD(
1365 const std::string& i_vpdFilePath)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001366{
Priyanga Ramasamy1aad7832024-12-12 22:13:52 -06001367 std::string l_inventoryPath{};
1368
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001369 try
1370 {
1371 m_semaphore.acquire();
1372
1373 // Thread launched.
1374 m_mutex.lock();
1375 m_activeCollectionThreadCount++;
1376 m_mutex.unlock();
1377
Anupama B R4c65fcd2025-09-01 08:09:00 -05001378 setCollectionStatusProperty(i_vpdFilePath,
1379 constants::vpdCollectionInProgress);
Priyanga Ramasamy1aad7832024-12-12 22:13:52 -06001380
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001381 const types::VPDMapVariant& parsedVpdMap = parseVpdFile(i_vpdFilePath);
Sunny Srivastava0a5fce12025-04-09 11:09:51 +05301382 if (!std::holds_alternative<std::monostate>(parsedVpdMap))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001383 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +05301384 types::ObjectMap objectInterfaceMap;
1385 populateDbus(parsedVpdMap, objectInterfaceMap, i_vpdFilePath);
1386
1387 // Notify PIM
1388 if (!dbusUtility::callPIM(move(objectInterfaceMap)))
1389 {
1390 throw std::runtime_error(
1391 std::string(__FUNCTION__) +
1392 "Call to PIM failed while publishing VPD.");
1393 }
1394 }
1395 else
1396 {
1397 logging::logMessage("Empty parsedVpdMap recieved for path [" +
1398 i_vpdFilePath + "]. Check PEL for reason.");
Anupama B R4c65fcd2025-09-01 08:09:00 -05001399
1400 // As empty parsedVpdMap recieved for some reason, but still
1401 // considered VPD collection is completed. Hence FRU collection
1402 // Status will be set as completed.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001403 }
1404 }
1405 catch (const std::exception& ex)
1406 {
Anupama B R24691d22025-05-21 08:14:15 -05001407 setCollectionStatusProperty(i_vpdFilePath,
Anupama B R5cd1b2d2025-08-05 04:57:40 -05001408 constants::vpdCollectionFailed);
Priyanga Ramasamy1aad7832024-12-12 22:13:52 -06001409
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001410 // handle all the exceptions internally. Return only true/false
1411 // based on status of execution.
1412 if (typeid(ex) == std::type_index(typeid(DataException)))
1413 {
Rekha Aparna017567a2025-08-13 02:07:06 -05001414 uint16_t l_errCode = 0;
Sunny Srivastava78c91072025-02-05 14:09:50 +05301415 // In case of pass1 planar, VPD can be corrupted on PCIe cards. Skip
1416 // logging error for these cases.
Rekha Aparna715eaff2025-10-23 02:06:50 -05001417 if (vpdSpecificUtility::isPass1Planar(l_errCode))
Sunny Srivastava78c91072025-02-05 14:09:50 +05301418 {
Rekha Aparna017567a2025-08-13 02:07:06 -05001419 std::string l_invPath =
1420 jsonUtility::getInventoryObjPathFromJson(
1421 m_parsedJson, i_vpdFilePath, l_errCode);
1422
1423 if (l_errCode != 0)
1424 {
1425 logging::logMessage(
1426 "Failed to get inventory object path from JSON for FRU [" +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301427 i_vpdFilePath +
1428 "], error: " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna017567a2025-08-13 02:07:06 -05001429 }
1430
RekhaAparna011ef21002025-02-18 23:47:36 -06001431 const std::string& l_invPathLeafValue =
Rekha Aparna017567a2025-08-13 02:07:06 -05001432 sdbusplus::message::object_path(l_invPath).filename();
Sunny Srivastava78c91072025-02-05 14:09:50 +05301433
RekhaAparna011ef21002025-02-18 23:47:36 -06001434 if ((l_invPathLeafValue.find("pcie_card", 0) !=
1435 std::string::npos))
Sunny Srivastava78c91072025-02-05 14:09:50 +05301436 {
1437 // skip logging any PEL for PCIe cards on pass 1 planar.
1438 return std::make_tuple(false, i_vpdFilePath);
1439 }
1440 }
Rekha Aparna715eaff2025-10-23 02:06:50 -05001441 else if (l_errCode)
1442 {
1443 logging::logMessage(
1444 "Failed to check if system is Pass 1 Planar, error : " +
1445 commonUtility::getErrCodeMsg(l_errCode));
1446 }
Sunny Srivastava4c509c22025-03-25 12:43:40 +05301447 }
Sunny Srivastava78c91072025-02-05 14:09:50 +05301448
Sunny Srivastava4c509c22025-03-25 12:43:40 +05301449 EventLogger::createSyncPel(
Souvik Roy37c6bef2025-07-17 00:55:59 -05001450 EventLogger::getErrorType(ex),
1451 (typeid(ex) == typeid(DataException)) ||
1452 (typeid(ex) == typeid(EccException))
1453 ? types::SeverityType::Warning
1454 : types::SeverityType::Informational,
Sunny Srivastava4c509c22025-03-25 12:43:40 +05301455 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(ex),
1456 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001457
1458 // TODO: Figure out a way to clear data in case of any failure at
1459 // runtime.
Sunny Srivastavad159bb42025-01-09 11:13:50 +05301460
1461 // set present property to false for any error case. In future this will
1462 // be replaced by presence logic.
Souvik Roy6a9553c2025-02-07 01:16:32 -06001463 // Update Present property for this FRU only if we handle Present
1464 // property for the FRU.
1465 if (isPresentPropertyHandlingRequired(
1466 m_parsedJson["frus"][i_vpdFilePath].at(0)))
1467 {
1468 setPresentProperty(i_vpdFilePath, false);
1469 }
Sunny Srivastavad159bb42025-01-09 11:13:50 +05301470
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001471 m_semaphore.release();
1472 return std::make_tuple(false, i_vpdFilePath);
1473 }
Anupama B R4c65fcd2025-09-01 08:09:00 -05001474
1475 setCollectionStatusProperty(i_vpdFilePath,
1476 constants::vpdCollectionCompleted);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001477 m_semaphore.release();
1478 return std::make_tuple(true, i_vpdFilePath);
1479}
1480
Sunny Srivastava61611752025-02-04 00:29:33 -06001481bool Worker::skipPathForCollection(const std::string& i_vpdFilePath)
1482{
1483 if (i_vpdFilePath.empty())
1484 {
1485 return true;
1486 }
1487
1488 // skip processing of system VPD again as it has been already collected.
1489 if (i_vpdFilePath == SYSTEM_VPD_FILE_PATH)
1490 {
1491 return true;
1492 }
1493
1494 if (dbusUtility::isChassisPowerOn())
1495 {
1496 // If chassis is powered on, skip collecting FRUs which are
1497 // powerOffOnly.
Rekha Aparna52041882025-09-01 20:48:07 -05001498
1499 uint16_t l_errCode = 0;
1500 if (jsonUtility::isFruPowerOffOnly(m_parsedJson, i_vpdFilePath,
1501 l_errCode))
Sunny Srivastava61611752025-02-04 00:29:33 -06001502 {
1503 return true;
1504 }
Rekha Aparna52041882025-09-01 20:48:07 -05001505 else if (l_errCode)
1506 {
1507 logging::logMessage(
1508 "Failed to check if FRU is power off only for FRU [" +
1509 i_vpdFilePath +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301510 "], error : " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna52041882025-09-01 20:48:07 -05001511 }
Sunny Srivastava61611752025-02-04 00:29:33 -06001512
Rekha Aparna017567a2025-08-13 02:07:06 -05001513 std::string l_invPath = jsonUtility::getInventoryObjPathFromJson(
1514 m_parsedJson, i_vpdFilePath, l_errCode);
1515
1516 if (l_errCode)
1517 {
1518 logging::logMessage(
1519 "Failed to get inventory path from JSON for FRU [" +
1520 i_vpdFilePath +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301521 "], error : " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna017567a2025-08-13 02:07:06 -05001522
1523 return false;
1524 }
1525
Sunny Srivastava61611752025-02-04 00:29:33 -06001526 const std::string& l_invPathLeafValue =
Rekha Aparna017567a2025-08-13 02:07:06 -05001527 sdbusplus::message::object_path(l_invPath).filename();
Sunny Srivastava61611752025-02-04 00:29:33 -06001528
1529 if ((l_invPathLeafValue.find("pcie_card", 0) != std::string::npos))
1530 {
1531 return true;
1532 }
1533 }
1534
1535 return false;
1536}
1537
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001538void Worker::collectFrusFromJson()
1539{
1540 // A parsed JSON file should be present to pick FRUs EEPROM paths
1541 if (m_parsedJson.empty())
1542 {
Sunny Srivastava4c509c22025-03-25 12:43:40 +05301543 throw JsonException(
1544 std::string(__FUNCTION__) +
1545 ": Config JSON is mandatory for processing of FRUs through this API.",
1546 m_configJsonPath);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001547 }
1548
1549 const nlohmann::json& listOfFrus =
1550 m_parsedJson["frus"].get_ref<const nlohmann::json::object_t&>();
1551
1552 for (const auto& itemFRUS : listOfFrus.items())
1553 {
1554 const std::string& vpdFilePath = itemFRUS.key();
1555
Sunny Srivastava61611752025-02-04 00:29:33 -06001556 if (skipPathForCollection(vpdFilePath))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001557 {
1558 continue;
1559 }
1560
Souvik Roy1f4c8f82025-01-23 00:37:43 -06001561 try
1562 {
1563 std::thread{[vpdFilePath, this]() {
1564 const auto& l_parseResult = parseAndPublishVPD(vpdFilePath);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001565
Souvik Roy1f4c8f82025-01-23 00:37:43 -06001566 m_mutex.lock();
1567 m_activeCollectionThreadCount--;
1568 m_mutex.unlock();
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001569
Souvik Roy1f4c8f82025-01-23 00:37:43 -06001570 if (!m_activeCollectionThreadCount)
1571 {
1572 m_isAllFruCollected = true;
1573 }
1574 }}.detach();
1575 }
1576 catch (const std::exception& l_ex)
1577 {
1578 // add vpdFilePath(EEPROM path) to failed list
1579 m_failedEepromPaths.push_front(vpdFilePath);
1580 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001581 }
1582}
1583
1584// ToDo: Move the API under IBM_SYSTEM
1585void Worker::performBackupAndRestore(types::VPDMapVariant& io_srcVpdMap)
1586{
1587 try
1588 {
Rekha Aparnaca9a0862025-08-29 04:08:33 -05001589 uint16_t l_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001590 std::string l_backupAndRestoreCfgFilePath =
1591 m_parsedJson.value("backupRestoreConfigPath", "");
1592
1593 nlohmann::json l_backupAndRestoreCfgJsonObj =
Rekha Aparnaca9a0862025-08-29 04:08:33 -05001594 jsonUtility::getParsedJson(l_backupAndRestoreCfgFilePath,
1595 l_errCode);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001596
Rekha Aparnaca9a0862025-08-29 04:08:33 -05001597 if (l_errCode)
RekhaAparna011ef21002025-02-18 23:47:36 -06001598 {
Rekha Aparnaca9a0862025-08-29 04:08:33 -05001599 throw JsonException(
1600 "JSON parsing failed for file [ " +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301601 l_backupAndRestoreCfgFilePath +
1602 " ], error : " + commonUtility::getErrCodeMsg(l_errCode),
Rekha Aparnaca9a0862025-08-29 04:08:33 -05001603 l_backupAndRestoreCfgFilePath);
RekhaAparna011ef21002025-02-18 23:47:36 -06001604 }
1605
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001606 // check if either of "source" or "destination" has inventory path.
1607 // this indicates that this sytem has System VPD on hardware
1608 // and other copy on D-Bus (BMC cache).
1609 if (!l_backupAndRestoreCfgJsonObj.empty() &&
1610 ((l_backupAndRestoreCfgJsonObj.contains("source") &&
1611 l_backupAndRestoreCfgJsonObj["source"].contains(
1612 "inventoryPath")) ||
1613 (l_backupAndRestoreCfgJsonObj.contains("destination") &&
1614 l_backupAndRestoreCfgJsonObj["destination"].contains(
1615 "inventoryPath"))))
1616 {
1617 BackupAndRestore l_backupAndRestoreObj(m_parsedJson);
1618 auto [l_srcVpdVariant,
1619 l_dstVpdVariant] = l_backupAndRestoreObj.backupAndRestore();
1620
1621 // ToDo: Revisit is this check is required or not.
1622 if (auto l_srcVpdMap =
1623 std::get_if<types::IPZVpdMap>(&l_srcVpdVariant);
1624 l_srcVpdMap && !(*l_srcVpdMap).empty())
1625 {
1626 io_srcVpdMap = std::move(l_srcVpdVariant);
1627 }
1628 }
1629 }
1630 catch (const std::exception& l_ex)
1631 {
1632 EventLogger::createSyncPel(
Sunny Srivastava043955d2025-01-21 18:04:49 +05301633 EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
Sunny Srivastava15a189a2025-02-26 16:53:19 +05301634 __FILE__, __FUNCTION__, 0,
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001635 std::string(
1636 "Exception caught while backup and restore VPD keyword's.") +
Sunny Srivastava15a189a2025-02-26 16:53:19 +05301637 EventLogger::getErrorMsg(l_ex),
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001638 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
1639 }
1640}
1641
1642void Worker::deleteFruVpd(const std::string& i_dbusObjPath)
1643{
1644 if (i_dbusObjPath.empty())
1645 {
1646 throw std::runtime_error("Given DBus object path is empty.");
1647 }
1648
Rekha Aparna0578dd22025-09-02 08:20:21 -05001649 uint16_t l_errCode = 0;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001650 const std::string& l_fruPath =
Rekha Aparna0578dd22025-09-02 08:20:21 -05001651 jsonUtility::getFruPathFromJson(m_parsedJson, i_dbusObjPath, l_errCode);
1652
1653 if (l_errCode)
1654 {
1655 logging::logMessage(
1656 "Failed to get FRU path for inventory path [" + i_dbusObjPath +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301657 "], error : " + commonUtility::getErrCodeMsg(l_errCode) +
Rekha Aparna0578dd22025-09-02 08:20:21 -05001658 " Aborting FRU VPD deletion.");
1659 return;
1660 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001661
1662 try
1663 {
1664 auto l_presentPropValue = dbusUtility::readDbusProperty(
1665 constants::pimServiceName, i_dbusObjPath,
1666 constants::inventoryItemInf, "Present");
1667
1668 if (auto l_value = std::get_if<bool>(&l_presentPropValue))
1669 {
Rekha Aparnaa1187a52025-09-01 12:42:19 -05001670 uint16_t l_errCode = 0;
Souvik Roye9120152025-07-02 08:24:38 -05001671 // check if FRU's Present property is handled by vpd-manager
1672 const auto& l_isFruPresenceHandled =
Rekha Aparnaa1187a52025-09-01 12:42:19 -05001673 jsonUtility::isFruPresenceHandled(m_parsedJson, l_fruPath,
1674 l_errCode);
1675
1676 if (l_errCode)
1677 {
1678 throw std::runtime_error(
1679 "Failed to check if FRU's presence is handled, reason: " +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301680 commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparnaa1187a52025-09-01 12:42:19 -05001681 }
Souvik Roye9120152025-07-02 08:24:38 -05001682
1683 if (!(*l_value) && l_isFruPresenceHandled)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001684 {
1685 throw std::runtime_error("Given FRU is not present");
1686 }
Souvik Roye9120152025-07-02 08:24:38 -05001687 else if (*l_value && !l_isFruPresenceHandled)
1688 {
1689 throw std::runtime_error(
1690 "Given FRU is present and its presence is not handled by vpd-manager.");
1691 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001692 else
1693 {
1694 if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001695 "preAction", "deletion",
1696 l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001697 {
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001698 if (!processPreAction(l_fruPath, "deletion", l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001699 {
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001700 std::string l_msg = "Pre action failed";
1701 if (l_errCode)
1702 {
Rekha Aparnac6159a22025-10-09 12:20:20 +05301703 l_msg += " Reason: " +
1704 commonUtility::getErrCodeMsg(l_errCode);
Sunny Srivastava4f053df2025-09-03 02:27:37 -05001705 }
1706 throw std::runtime_error(l_msg);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001707 }
1708 }
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001709 else if (l_errCode)
1710 {
1711 logging::logMessage(
1712 "Failed to check if pre action required for FRU [" +
1713 l_fruPath + "], error : " +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301714 commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001715 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001716
1717 std::vector<std::string> l_interfaceList{
1718 constants::operationalStatusInf};
1719
1720 types::MapperGetSubTree l_subTreeMap =
1721 dbusUtility::getObjectSubTree(i_dbusObjPath, 0,
1722 l_interfaceList);
1723
1724 types::ObjectMap l_objectMap;
1725
1726 // Updates VPD specific interfaces property value under PIM for
1727 // sub FRUs.
1728 for (const auto& [l_objectPath, l_serviceInterfaceMap] :
1729 l_subTreeMap)
1730 {
1731 types::InterfaceMap l_interfaceMap;
Rekha Aparna2c04eeb2025-10-22 22:15:07 -05001732 vpdSpecificUtility::resetDataUnderPIM(
1733 l_objectPath, l_interfaceMap, l_errCode);
1734
1735 if (l_errCode)
1736 {
1737 throw std::runtime_error(
1738 "Failed to reset data under PIM for sub FRU [" +
1739 l_objectPath + "], error : " +
1740 commonUtility::getErrCodeMsg(l_errCode));
1741 }
1742
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001743 l_objectMap.emplace(l_objectPath,
1744 std::move(l_interfaceMap));
1745 }
1746
1747 types::InterfaceMap l_interfaceMap;
Rekha Aparna2c04eeb2025-10-22 22:15:07 -05001748 vpdSpecificUtility::resetDataUnderPIM(
1749 i_dbusObjPath, l_interfaceMap, l_errCode);
1750
1751 if (l_errCode)
1752 {
1753 throw std::runtime_error(
1754 "Failed to reset data under PIM, error : " +
1755 commonUtility::getErrCodeMsg(l_errCode));
1756 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001757
1758 l_objectMap.emplace(i_dbusObjPath, std::move(l_interfaceMap));
1759
1760 if (!dbusUtility::callPIM(std::move(l_objectMap)))
1761 {
1762 throw std::runtime_error("Call to PIM failed.");
1763 }
1764
1765 if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001766 "postAction", "deletion",
1767 l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001768 {
1769 if (!processPostAction(l_fruPath, "deletion"))
1770 {
1771 throw std::runtime_error("Post action failed");
1772 }
1773 }
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001774 else if (l_errCode)
1775 {
1776 logging::logMessage(
1777 "Failed to check if post action required during deletion for FRU [" +
1778 l_fruPath + "], error : " +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301779 commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001780 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001781 }
1782 }
1783 else
1784 {
1785 logging::logMessage(
1786 "Can't process delete VPD for FRU [" + i_dbusObjPath +
1787 "] as unable to read present property");
1788 return;
1789 }
1790
1791 logging::logMessage(
1792 "Successfully completed deletion of FRU VPD for " + i_dbusObjPath);
1793 }
1794 catch (const std::exception& l_ex)
1795 {
Rekha Aparnaff7d7992025-09-01 11:08:53 -05001796 uint16_t l_errCode = 0;
1797 std::string l_errMsg =
1798 "Failed to delete VPD for FRU : " + i_dbusObjPath +
1799 " error: " + std::string(l_ex.what());
1800
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001801 if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001802 "postFailAction", "deletion",
1803 l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001804 {
1805 if (!jsonUtility::executePostFailAction(m_parsedJson, l_fruPath,
Rekha Aparnaff7d7992025-09-01 11:08:53 -05001806 "deletion", l_errCode))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001807 {
Rekha Aparnaff7d7992025-09-01 11:08:53 -05001808 l_errMsg += ". Post fail action also failed, error : " +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301809 commonUtility::getErrCodeMsg(l_errCode);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001810 }
1811 }
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001812 else if (l_errCode)
1813 {
1814 l_errMsg +=
1815 ". Failed to check if post fail action required, error : " +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301816 commonUtility::getErrCodeMsg(l_errCode);
Rekha Aparnab50bf0e2025-09-02 21:13:26 -05001817 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001818
Rekha Aparnaff7d7992025-09-01 11:08:53 -05001819 logging::logMessage(l_errMsg);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001820 }
1821}
Sunny Srivastavad159bb42025-01-09 11:13:50 +05301822
1823void Worker::setPresentProperty(const std::string& i_vpdPath,
1824 const bool& i_value)
1825{
1826 try
1827 {
1828 if (i_vpdPath.empty())
1829 {
1830 throw std::runtime_error(
1831 "Path is empty. Can't set present property");
1832 }
1833
1834 types::ObjectMap l_objectInterfaceMap;
1835
1836 // If the given path is EEPROM path.
1837 if (m_parsedJson["frus"].contains(i_vpdPath))
1838 {
1839 for (const auto& l_Fru : m_parsedJson["frus"][i_vpdPath])
1840 {
1841 sdbusplus::message::object_path l_fruObjectPath(
1842 l_Fru["inventoryPath"]);
1843
1844 types::PropertyMap l_propertyValueMap;
1845 l_propertyValueMap.emplace("Present", i_value);
1846
Rekha Aparnad3662222025-10-14 10:33:17 -05001847 uint16_t l_errCode = 0;
Sunny Srivastavad159bb42025-01-09 11:13:50 +05301848 types::InterfaceMap l_interfaces;
Rekha Aparnad3662222025-10-14 10:33:17 -05001849 vpdSpecificUtility::insertOrMerge(
1850 l_interfaces, constants::inventoryItemInf,
1851 move(l_propertyValueMap), l_errCode);
1852
1853 if (l_errCode)
1854 {
1855 logging::logMessage(
1856 "Failed to insert value into map, error : " +
1857 commonUtility::getErrCodeMsg(l_errCode));
1858 }
Sunny Srivastavad159bb42025-01-09 11:13:50 +05301859
1860 l_objectInterfaceMap.emplace(std::move(l_fruObjectPath),
1861 std::move(l_interfaces));
1862 }
1863 }
1864 else
1865 {
1866 // consider it as an inventory path.
1867 if (i_vpdPath.find(constants::pimPath) != constants::VALUE_0)
1868 {
1869 throw std::runtime_error(
1870 "Invalid inventory path: " + i_vpdPath);
1871 }
1872
1873 types::PropertyMap l_propertyValueMap;
1874 l_propertyValueMap.emplace("Present", i_value);
1875
Rekha Aparnad3662222025-10-14 10:33:17 -05001876 uint16_t l_errCode = 0;
Sunny Srivastavad159bb42025-01-09 11:13:50 +05301877 types::InterfaceMap l_interfaces;
Rekha Aparnad3662222025-10-14 10:33:17 -05001878 vpdSpecificUtility::insertOrMerge(
1879 l_interfaces, constants::inventoryItemInf,
1880 move(l_propertyValueMap), l_errCode);
1881
1882 if (l_errCode)
1883 {
1884 logging::logMessage(
1885 "Failed to insert value into map, error : " +
1886 commonUtility::getErrCodeMsg(l_errCode));
1887 }
Sunny Srivastavad159bb42025-01-09 11:13:50 +05301888
1889 l_objectInterfaceMap.emplace(i_vpdPath, std::move(l_interfaces));
1890 }
1891
1892 // Notify PIM
1893 if (!dbusUtility::callPIM(move(l_objectInterfaceMap)))
1894 {
Sunny Srivastava4c509c22025-03-25 12:43:40 +05301895 throw DbusException(
1896 std::string(__FUNCTION__) +
Sunny Srivastavad159bb42025-01-09 11:13:50 +05301897 "Call to PIM failed while setting present property for path " +
1898 i_vpdPath);
1899 }
1900 }
1901 catch (const std::exception& l_ex)
1902 {
Sunny Srivastava4c509c22025-03-25 12:43:40 +05301903 EventLogger::createSyncPel(
1904 EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
1905 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
1906 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavad159bb42025-01-09 11:13:50 +05301907 }
1908}
1909
Sunny Srivastava380efbb2025-04-25 10:28:30 +05301910void Worker::performVpdRecollection()
1911{
1912 try
1913 {
1914 // Check if system config JSON is present
1915 if (m_parsedJson.empty())
1916 {
1917 throw std::runtime_error(
1918 "System config json object is empty, can't process recollection.");
1919 }
1920
Rekha Aparna88d53302025-09-01 18:16:55 -05001921 uint16_t l_errCode = 0;
Sunny Srivastava380efbb2025-04-25 10:28:30 +05301922 const auto& l_frusReplaceableAtStandby =
Rekha Aparna88d53302025-09-01 18:16:55 -05001923 jsonUtility::getListOfFrusReplaceableAtStandby(m_parsedJson,
1924 l_errCode);
1925
1926 if (l_errCode)
1927 {
1928 logging::logMessage(
1929 "Failed to get list of FRUs replaceable at runtime, error : " +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301930 commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna88d53302025-09-01 18:16:55 -05001931 return;
1932 }
Sunny Srivastava380efbb2025-04-25 10:28:30 +05301933
1934 for (const auto& l_fruInventoryPath : l_frusReplaceableAtStandby)
1935 {
1936 // ToDo: Add some logic/trace to know the flow to
1937 // collectSingleFruVpd has been directed via
1938 // performVpdRecollection.
1939 collectSingleFruVpd(l_fruInventoryPath);
1940 }
1941 return;
1942 }
1943
1944 catch (const std::exception& l_ex)
1945 {
1946 // TODO Log PEL
1947 logging::logMessage(
1948 "VPD recollection failed with error: " + std::string(l_ex.what()));
1949 }
1950}
1951
1952void Worker::collectSingleFruVpd(
1953 const sdbusplus::message::object_path& i_dbusObjPath)
1954{
Anupama B R48f297b2025-08-13 04:29:06 -05001955 std::string l_fruPath{};
Rekha Aparna0578dd22025-09-02 08:20:21 -05001956 uint16_t l_errCode = 0;
1957
Sunny Srivastava380efbb2025-04-25 10:28:30 +05301958 try
1959 {
1960 // Check if system config JSON is present
1961 if (m_parsedJson.empty())
1962 {
1963 logging::logMessage(
1964 "System config JSON object not present. Single FRU VPD collection is not performed for " +
1965 std::string(i_dbusObjPath));
1966 return;
1967 }
1968
1969 // Get FRU path for the given D-bus object path from JSON
Rekha Aparna0578dd22025-09-02 08:20:21 -05001970 l_fruPath = jsonUtility::getFruPathFromJson(m_parsedJson, i_dbusObjPath,
1971 l_errCode);
Sunny Srivastava380efbb2025-04-25 10:28:30 +05301972
1973 if (l_fruPath.empty())
1974 {
Rekha Aparna0578dd22025-09-02 08:20:21 -05001975 if (l_errCode)
1976 {
1977 logging::logMessage(
1978 "Failed to get FRU path for [" +
Rekha Aparnac6159a22025-10-09 12:20:20 +05301979 std::string(i_dbusObjPath) +
1980 "], error : " + commonUtility::getErrCodeMsg(l_errCode) +
Rekha Aparna0578dd22025-09-02 08:20:21 -05001981 " Aborting single FRU VPD collection.");
1982 return;
1983 }
1984
Sunny Srivastava380efbb2025-04-25 10:28:30 +05301985 logging::logMessage(
1986 "D-bus object path not present in JSON. Single FRU VPD collection is not performed for " +
1987 std::string(i_dbusObjPath));
1988 return;
1989 }
1990
1991 // Check if host is up and running
1992 if (dbusUtility::isHostRunning())
1993 {
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05001994 uint16_t l_errCode = 0;
1995 bool isFruReplaceableAtRuntime =
1996 jsonUtility::isFruReplaceableAtRuntime(m_parsedJson, l_fruPath,
1997 l_errCode);
1998
1999 if (l_errCode)
2000 {
2001 logging::logMessage(
2002 "Failed to check if FRU is replaceable at runtime for FRU : [" +
Rekha Aparnac6159a22025-10-09 12:20:20 +05302003 std::string(i_dbusObjPath) +
2004 "], error : " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05002005 return;
2006 }
2007
2008 if (!isFruReplaceableAtRuntime)
Sunny Srivastava380efbb2025-04-25 10:28:30 +05302009 {
2010 logging::logMessage(
2011 "Given FRU is not replaceable at host runtime. Single FRU VPD collection is not performed for " +
2012 std::string(i_dbusObjPath));
2013 return;
2014 }
2015 }
2016 else if (dbusUtility::isBMCReady())
2017 {
Rekha Aparna40845612025-09-01 19:58:56 -05002018 uint16_t l_errCode = 0;
2019 bool isFruReplaceableAtStandby =
2020 jsonUtility::isFruReplaceableAtStandby(m_parsedJson, l_fruPath,
2021 l_errCode);
2022
2023 if (l_errCode)
2024 {
2025 logging::logMessage(
2026 "Error while checking if FRU is replaceable at standby for FRU [" +
Rekha Aparnac6159a22025-10-09 12:20:20 +05302027 std::string(i_dbusObjPath) +
2028 "], error : " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna40845612025-09-01 19:58:56 -05002029 }
2030
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05002031 bool isFruReplaceableAtRuntime =
2032 jsonUtility::isFruReplaceableAtRuntime(m_parsedJson, l_fruPath,
2033 l_errCode);
2034
2035 if (l_errCode)
2036 {
2037 logging::logMessage(
2038 "Failed to check if FRU is replaceable at runtime for FRU : [" +
Rekha Aparnac6159a22025-10-09 12:20:20 +05302039 std::string(i_dbusObjPath) +
2040 "], error : " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparnaad0db9e2025-09-01 20:29:18 -05002041 return;
2042 }
2043
2044 if (!isFruReplaceableAtStandby && (!isFruReplaceableAtRuntime))
Sunny Srivastava380efbb2025-04-25 10:28:30 +05302045 {
2046 logging::logMessage(
2047 "Given FRU is neither replaceable at standby nor replaceable at runtime. Single FRU VPD collection is not performed for " +
2048 std::string(i_dbusObjPath));
2049 return;
2050 }
2051 }
2052
Anupama B R5cd1b2d2025-08-05 04:57:40 -05002053 // Set collection Status as InProgress. Since it's an intermediate state
Sunny Srivastava380efbb2025-04-25 10:28:30 +05302054 // D-bus set-property call is good enough to update the status.
Anupama B R5cd1b2d2025-08-05 04:57:40 -05002055 const std::string& l_collStatusProp = "Status";
Sunny Srivastava380efbb2025-04-25 10:28:30 +05302056
Anupama B R4c65fcd2025-09-01 08:09:00 -05002057 setCollectionStatusProperty(l_fruPath,
2058 constants::vpdCollectionInProgress);
Sunny Srivastava380efbb2025-04-25 10:28:30 +05302059
2060 // Parse VPD
2061 types::VPDMapVariant l_parsedVpd = parseVpdFile(l_fruPath);
2062
2063 // If l_parsedVpd is pointing to std::monostate
2064 if (l_parsedVpd.index() == 0)
2065 {
2066 throw std::runtime_error(
2067 "VPD parsing failed for " + std::string(i_dbusObjPath));
2068 }
2069
2070 // Get D-bus object map from worker class
2071 types::ObjectMap l_dbusObjectMap;
2072 populateDbus(l_parsedVpd, l_dbusObjectMap, l_fruPath);
2073
2074 if (l_dbusObjectMap.empty())
2075 {
2076 throw std::runtime_error(
2077 "Failed to create D-bus object map. Single FRU VPD collection failed for " +
2078 std::string(i_dbusObjPath));
2079 }
2080
2081 // Call PIM's Notify method
2082 if (!dbusUtility::callPIM(move(l_dbusObjectMap)))
2083 {
2084 throw std::runtime_error(
2085 "Notify PIM failed. Single FRU VPD collection failed for " +
2086 std::string(i_dbusObjPath));
2087 }
Anupama B R4c65fcd2025-09-01 08:09:00 -05002088 setCollectionStatusProperty(l_fruPath,
2089 constants::vpdCollectionCompleted);
Sunny Srivastava380efbb2025-04-25 10:28:30 +05302090 }
2091 catch (const std::exception& l_error)
2092 {
Anupama B R48f297b2025-08-13 04:29:06 -05002093 setCollectionStatusProperty(l_fruPath, constants::vpdCollectionFailed);
Sunny Srivastava380efbb2025-04-25 10:28:30 +05302094 // TODO: Log PEL
2095 logging::logMessage(std::string(l_error.what()));
2096 }
2097}
Anupama B R24691d22025-05-21 08:14:15 -05002098
2099void Worker::setCollectionStatusProperty(
2100 const std::string& i_vpdPath, const std::string& i_value) const noexcept
2101{
2102 try
2103 {
2104 if (i_vpdPath.empty())
2105 {
2106 throw std::runtime_error(
Anupama B R5cd1b2d2025-08-05 04:57:40 -05002107 "Given path is empty. Can't set collection Status property");
Anupama B R24691d22025-05-21 08:14:15 -05002108 }
2109
Anupama B R4c65fcd2025-09-01 08:09:00 -05002110 types::PropertyMap l_timeStampMap;
2111 if (i_value == constants::vpdCollectionCompleted ||
2112 i_value == constants::vpdCollectionFailed)
2113 {
2114 l_timeStampMap.emplace(
2115 "CompletedTime",
2116 types::DbusVariantType{
2117 commonUtility::getCurrentTimeSinceEpoch()});
2118 }
2119 else if (i_value == constants::vpdCollectionInProgress)
2120 {
2121 l_timeStampMap.emplace(
2122 "StartTime", types::DbusVariantType{
2123 commonUtility::getCurrentTimeSinceEpoch()});
2124 }
2125 else if (i_value == constants::vpdCollectionNotStarted)
2126 {
2127 l_timeStampMap.emplace("StartTime", 0);
2128 l_timeStampMap.emplace("CompletedTime", 0);
2129 }
2130
Anupama B R24691d22025-05-21 08:14:15 -05002131 types::ObjectMap l_objectInterfaceMap;
2132
2133 if (m_parsedJson["frus"].contains(i_vpdPath))
2134 {
2135 for (const auto& l_Fru : m_parsedJson["frus"][i_vpdPath])
2136 {
2137 sdbusplus::message::object_path l_fruObjectPath(
2138 l_Fru["inventoryPath"]);
2139
2140 types::PropertyMap l_propertyValueMap;
Anupama B R5cd1b2d2025-08-05 04:57:40 -05002141 l_propertyValueMap.emplace("Status", i_value);
Anupama B R4c65fcd2025-09-01 08:09:00 -05002142 l_propertyValueMap.insert(l_timeStampMap.begin(),
2143 l_timeStampMap.end());
Anupama B R24691d22025-05-21 08:14:15 -05002144
Rekha Aparnad3662222025-10-14 10:33:17 -05002145 uint16_t l_errCode = 0;
Anupama B R24691d22025-05-21 08:14:15 -05002146 types::InterfaceMap l_interfaces;
2147 vpdSpecificUtility::insertOrMerge(
2148 l_interfaces, constants::vpdCollectionInterface,
Rekha Aparnad3662222025-10-14 10:33:17 -05002149 move(l_propertyValueMap), l_errCode);
2150
2151 if (l_errCode)
2152 {
2153 logging::logMessage(
2154 "Failed to insert value into map, error : " +
2155 commonUtility::getErrCodeMsg(l_errCode));
2156 }
Anupama B R24691d22025-05-21 08:14:15 -05002157
2158 l_objectInterfaceMap.emplace(std::move(l_fruObjectPath),
2159 std::move(l_interfaces));
2160 }
2161 }
2162 else
2163 {
2164 // consider it as an inventory path.
2165 if (i_vpdPath.find(constants::pimPath) != constants::VALUE_0)
2166 {
2167 throw std::runtime_error(
2168 "Invalid inventory path: " + i_vpdPath +
Anupama B R5cd1b2d2025-08-05 04:57:40 -05002169 ". Can't set collection Status property");
Anupama B R24691d22025-05-21 08:14:15 -05002170 }
2171
2172 types::PropertyMap l_propertyValueMap;
Anupama B R5cd1b2d2025-08-05 04:57:40 -05002173 l_propertyValueMap.emplace("Status", i_value);
Anupama B R4c65fcd2025-09-01 08:09:00 -05002174 l_propertyValueMap.insert(l_timeStampMap.begin(),
2175 l_timeStampMap.end());
Anupama B R24691d22025-05-21 08:14:15 -05002176
Rekha Aparnad3662222025-10-14 10:33:17 -05002177 uint16_t l_errCode = 0;
Anupama B R24691d22025-05-21 08:14:15 -05002178 types::InterfaceMap l_interfaces;
Rekha Aparnad3662222025-10-14 10:33:17 -05002179 vpdSpecificUtility::insertOrMerge(
2180 l_interfaces, constants::vpdCollectionInterface,
2181 move(l_propertyValueMap), l_errCode);
2182
2183 if (l_errCode)
2184 {
2185 logging::logMessage(
2186 "Failed to insert value into map, error : " +
2187 commonUtility::getErrCodeMsg(l_errCode));
2188 }
Anupama B R24691d22025-05-21 08:14:15 -05002189
2190 l_objectInterfaceMap.emplace(i_vpdPath, std::move(l_interfaces));
2191 }
2192
2193 // Notify PIM
2194 if (!dbusUtility::callPIM(move(l_objectInterfaceMap)))
2195 {
2196 throw DbusException(
2197 std::string(__FUNCTION__) +
Anupama B R5cd1b2d2025-08-05 04:57:40 -05002198 "Call to PIM failed while setting collection Status property for path " +
Anupama B R24691d22025-05-21 08:14:15 -05002199 i_vpdPath);
2200 }
2201 }
2202 catch (const std::exception& l_ex)
2203 {
2204 EventLogger::createSyncPel(
2205 EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
2206 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
2207 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
2208 }
2209}
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05002210} // namespace vpd