xref: /openbmc/openpower-vpd-parser/vpd-manager/src/manager.cpp (revision 7127ab4e64c12b02a014b8ac31bcaefb2f3e9cde)
1 #include "config.h"
2 
3 #include "manager.hpp"
4 
5 #include "constants.hpp"
6 #include "exceptions.hpp"
7 #include "logger.hpp"
8 #include "parser.hpp"
9 #include "parser_factory.hpp"
10 #include "parser_interface.hpp"
11 #include "single_fab.hpp"
12 #include "types.hpp"
13 #include "utility/dbus_utility.hpp"
14 #include "utility/json_utility.hpp"
15 #include "utility/vpd_specific_utility.hpp"
16 
17 #include <boost/asio/steady_timer.hpp>
18 #include <sdbusplus/bus/match.hpp>
19 #include <sdbusplus/message.hpp>
20 
21 namespace vpd
22 {
Manager(const std::shared_ptr<boost::asio::io_context> & ioCon,const std::shared_ptr<sdbusplus::asio::dbus_interface> & iFace,const std::shared_ptr<sdbusplus::asio::connection> & asioConnection)23 Manager::Manager(
24     const std::shared_ptr<boost::asio::io_context>& ioCon,
25     const std::shared_ptr<sdbusplus::asio::dbus_interface>& iFace,
26     const std::shared_ptr<sdbusplus::asio::connection>& asioConnection) :
27     m_ioContext(ioCon), m_interface(iFace), m_asioConnection(asioConnection)
28 {
29 #ifdef IBM_SYSTEM
30     if (!dbusUtility::isChassisPowerOn())
31     {
32         SingleFab l_singleFab;
33         const int& l_rc = l_singleFab.singleFabImOverride();
34 
35         if (l_rc == constants::FAILURE)
36         {
37             throw std::runtime_error(
38                 std::string(__FUNCTION__) +
39                 " : Found an invalid system configuration. Needs manual intervention. BMC is being quiesced.");
40         }
41     }
42 #endif
43 
44     try
45     {
46         // For backward compatibility. Should be depricated.
47         iFace->register_method(
48             "WriteKeyword",
49             [this](const sdbusplus::message::object_path i_path,
50                    const std::string i_recordName, const std::string i_keyword,
51                    const types::BinaryVector i_value) -> int {
52                 return this->updateKeyword(
53                     i_path, std::make_tuple(i_recordName, i_keyword, i_value));
54             });
55 
56         // Register methods under com.ibm.VPD.Manager interface
57         iFace->register_method(
58             "UpdateKeyword",
59             [this](const types::Path i_vpdPath,
60                    const types::WriteVpdParams i_paramsToWriteData) -> int {
61                 return this->updateKeyword(i_vpdPath, i_paramsToWriteData);
62             });
63 
64         iFace->register_method(
65             "WriteKeywordOnHardware",
66             [this](const types::Path i_fruPath,
67                    const types::WriteVpdParams i_paramsToWriteData) -> int {
68                 return this->updateKeywordOnHardware(i_fruPath,
69                                                      i_paramsToWriteData);
70             });
71 
72         iFace->register_method(
73             "ReadKeyword",
74             [this](const types::Path i_fruPath,
75                    const types::ReadVpdParams i_paramsToReadData)
76                 -> types::DbusVariantType {
77                 return this->readKeyword(i_fruPath, i_paramsToReadData);
78             });
79 
80         iFace->register_method(
81             "CollectFRUVPD",
82             [this](const sdbusplus::message::object_path& i_dbusObjPath) {
83                 this->collectSingleFruVpd(i_dbusObjPath);
84             });
85 
86         iFace->register_method(
87             "deleteFRUVPD",
88             [this](const sdbusplus::message::object_path& i_dbusObjPath) {
89                 this->deleteSingleFruVpd(i_dbusObjPath);
90             });
91 
92         iFace->register_method(
93             "GetExpandedLocationCode",
94             [this](const std::string& i_unexpandedLocationCode,
95                    uint16_t& i_nodeNumber) -> std::string {
96                 return this->getExpandedLocationCode(i_unexpandedLocationCode,
97                                                      i_nodeNumber);
98             });
99 
100         iFace->register_method("GetFRUsByExpandedLocationCode",
101                                [this](const std::string& i_expandedLocationCode)
102                                    -> types::ListOfPaths {
103                                    return this->getFrusByExpandedLocationCode(
104                                        i_expandedLocationCode);
105                                });
106 
107         iFace->register_method(
108             "GetFRUsByUnexpandedLocationCode",
109             [this](const std::string& i_unexpandedLocationCode,
110                    uint16_t& i_nodeNumber) -> types::ListOfPaths {
111                 return this->getFrusByUnexpandedLocationCode(
112                     i_unexpandedLocationCode, i_nodeNumber);
113             });
114 
115         iFace->register_method(
116             "GetHardwarePath",
117             [this](const sdbusplus::message::object_path& i_dbusObjPath)
118                 -> std::string { return this->getHwPath(i_dbusObjPath); });
119 
120         iFace->register_method("PerformVPDRecollection", [this]() {
121             this->performVpdRecollection();
122         });
123 
124         iFace->register_method("CollectAllFRUVPD", [this]() -> bool {
125             return this->collectAllFruVpd();
126         });
127 
128         // Indicates FRU VPD collection for the system has not started.
129         iFace->register_property_rw<std::string>(
130             "CollectionStatus", sdbusplus::vtable::property_::emits_change,
131             [this](const std::string& l_currStatus, const auto&) {
132                 if (m_vpdCollectionStatus != l_currStatus)
133                 {
134                     m_vpdCollectionStatus = l_currStatus;
135                     m_interface->signal_property("CollectionStatus");
136                 }
137                 return true;
138             },
139             [this](const auto&) { return m_vpdCollectionStatus; });
140 
141         // If required, instantiate OEM specific handler here.
142 #ifdef IBM_SYSTEM
143         m_ibmHandler = std::make_shared<IbmHandler>(
144             m_worker, m_backupAndRestoreObj, m_interface, m_ioContext,
145             m_asioConnection);
146 #else
147         m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT);
148         m_interface->set_property("CollectionStatus", std::string("Completed"));
149 #endif
150     }
151     catch (const std::exception& e)
152     {
153         logging::logMessage(
154             "Manager class instantiation failed. " + std::string(e.what()));
155 
156         vpd::EventLogger::createSyncPel(
157             vpd::EventLogger::getErrorType(e), vpd::types::SeverityType::Error,
158             __FILE__, __FUNCTION__, 0, vpd::EventLogger::getErrorMsg(e),
159             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
160     }
161 }
162 
updateKeyword(const types::Path i_vpdPath,const types::WriteVpdParams i_paramsToWriteData)163 int Manager::updateKeyword(const types::Path i_vpdPath,
164                            const types::WriteVpdParams i_paramsToWriteData)
165 {
166     if (i_vpdPath.empty())
167     {
168         logging::logMessage("Given VPD path is empty.");
169         return -1;
170     }
171 
172     types::Path l_fruPath;
173     nlohmann::json l_sysCfgJsonObj{};
174 
175     if (m_worker.get() != nullptr)
176     {
177         l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
178 
179         // Get the EEPROM path
180         if (!l_sysCfgJsonObj.empty())
181         {
182             l_fruPath =
183                 jsonUtility::getFruPathFromJson(l_sysCfgJsonObj, i_vpdPath);
184         }
185     }
186 
187     if (l_fruPath.empty())
188     {
189         l_fruPath = i_vpdPath;
190     }
191 
192     try
193     {
194         std::shared_ptr<Parser> l_parserObj =
195             std::make_shared<Parser>(l_fruPath, l_sysCfgJsonObj);
196         auto l_rc = l_parserObj->updateVpdKeyword(i_paramsToWriteData);
197 
198         if (l_rc != constants::FAILURE && m_backupAndRestoreObj)
199         {
200             if (m_backupAndRestoreObj->updateKeywordOnPrimaryOrBackupPath(
201                     l_fruPath, i_paramsToWriteData) < constants::VALUE_0)
202             {
203                 logging::logMessage(
204                     "Write success, but backup and restore failed for file[" +
205                     l_fruPath + "]");
206             }
207         }
208 
209         // update keyword in inherited FRUs
210         if (l_rc != constants::FAILURE)
211         {
212             vpdSpecificUtility::updateKwdOnInheritedFrus(
213                 l_fruPath, i_paramsToWriteData, l_sysCfgJsonObj);
214         }
215 
216         // update common interface(s) properties
217         if (l_rc != constants::FAILURE)
218         {
219             vpdSpecificUtility::updateCiPropertyOfInheritedFrus(
220                 l_fruPath, i_paramsToWriteData, l_sysCfgJsonObj);
221         }
222 
223         return l_rc;
224     }
225     catch (const std::exception& l_exception)
226     {
227         // TODO:: error log needed
228         logging::logMessage("Update keyword failed for file[" + i_vpdPath +
229                             "], reason: " + std::string(l_exception.what()));
230         return -1;
231     }
232 }
233 
updateKeywordOnHardware(const types::Path i_fruPath,const types::WriteVpdParams i_paramsToWriteData)234 int Manager::updateKeywordOnHardware(
235     const types::Path i_fruPath,
236     const types::WriteVpdParams i_paramsToWriteData) noexcept
237 {
238     try
239     {
240         if (i_fruPath.empty())
241         {
242             throw std::runtime_error("Given FRU path is empty");
243         }
244 
245         nlohmann::json l_sysCfgJsonObj{};
246 
247         if (m_worker.get() != nullptr)
248         {
249             l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
250         }
251 
252         std::shared_ptr<Parser> l_parserObj =
253             std::make_shared<Parser>(i_fruPath, l_sysCfgJsonObj);
254         return l_parserObj->updateVpdKeywordOnHardware(i_paramsToWriteData);
255     }
256     catch (const std::exception& l_exception)
257     {
258         EventLogger::createAsyncPel(
259             types::ErrorType::InvalidEeprom, types::SeverityType::Informational,
260             __FILE__, __FUNCTION__, 0,
261             "Update keyword on hardware failed for file[" + i_fruPath +
262                 "], reason: " + std::string(l_exception.what()),
263             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
264 
265         return constants::FAILURE;
266     }
267 }
268 
readKeyword(const types::Path i_fruPath,const types::ReadVpdParams i_paramsToReadData)269 types::DbusVariantType Manager::readKeyword(
270     const types::Path i_fruPath, const types::ReadVpdParams i_paramsToReadData)
271 {
272     try
273     {
274         nlohmann::json l_jsonObj{};
275 
276         if (m_worker.get() != nullptr)
277         {
278             l_jsonObj = m_worker->getSysCfgJsonObj();
279         }
280 
281         std::error_code ec;
282 
283         // Check if given path is filesystem path
284         if (!std::filesystem::exists(i_fruPath, ec) && (ec))
285         {
286             throw std::runtime_error(
287                 "Given file path " + i_fruPath + " not found.");
288         }
289 
290         logging::logMessage("Performing VPD read on " + i_fruPath);
291 
292         std::shared_ptr<vpd::Parser> l_parserObj =
293             std::make_shared<vpd::Parser>(i_fruPath, l_jsonObj);
294 
295         std::shared_ptr<vpd::ParserInterface> l_vpdParserInstance =
296             l_parserObj->getVpdParserInstance();
297 
298         return (
299             l_vpdParserInstance->readKeywordFromHardware(i_paramsToReadData));
300     }
301     catch (const std::exception& e)
302     {
303         logging::logMessage(
304             e.what() + std::string(". VPD manager read operation failed for ") +
305             i_fruPath);
306         throw types::DeviceError::ReadFailure();
307     }
308 }
309 
collectSingleFruVpd(const sdbusplus::message::object_path & i_dbusObjPath)310 void Manager::collectSingleFruVpd(
311     const sdbusplus::message::object_path& i_dbusObjPath)
312 {
313     if (m_vpdCollectionStatus != "Completed")
314     {
315         logging::logMessage(
316             "Currently VPD CollectionStatus is not completed. Cannot perform single FRU VPD collection for " +
317             std::string(i_dbusObjPath));
318         return;
319     }
320 
321     if (m_worker.get() != nullptr)
322     {
323         m_worker->collectSingleFruVpd(i_dbusObjPath);
324     }
325 }
326 
deleteSingleFruVpd(const sdbusplus::message::object_path & i_dbusObjPath)327 void Manager::deleteSingleFruVpd(
328     const sdbusplus::message::object_path& i_dbusObjPath)
329 {
330     try
331     {
332         if (std::string(i_dbusObjPath).empty())
333         {
334             throw std::runtime_error(
335                 "Given DBus object path is empty. Aborting FRU VPD deletion.");
336         }
337 
338         if (m_worker.get() == nullptr)
339         {
340             throw std::runtime_error(
341                 "Worker object not found, can't perform FRU VPD deletion for: " +
342                 std::string(i_dbusObjPath));
343         }
344 
345         m_worker->deleteFruVpd(std::string(i_dbusObjPath));
346     }
347     catch (const std::exception& l_ex)
348     {
349         // TODO: Log PEL
350         logging::logMessage(l_ex.what());
351     }
352 }
353 
isValidUnexpandedLocationCode(const std::string & i_unexpandedLocationCode)354 bool Manager::isValidUnexpandedLocationCode(
355     const std::string& i_unexpandedLocationCode)
356 {
357     if ((i_unexpandedLocationCode.length() <
358          constants::UNEXP_LOCATION_CODE_MIN_LENGTH) ||
359         ((i_unexpandedLocationCode.compare(0, 4, "Ufcs") !=
360           constants::STR_CMP_SUCCESS) &&
361          (i_unexpandedLocationCode.compare(0, 4, "Umts") !=
362           constants::STR_CMP_SUCCESS)) ||
363         ((i_unexpandedLocationCode.length() >
364           constants::UNEXP_LOCATION_CODE_MIN_LENGTH) &&
365          (i_unexpandedLocationCode.find("-") != 4)))
366     {
367         return false;
368     }
369 
370     return true;
371 }
372 
getExpandedLocationCode(const std::string & i_unexpandedLocationCode,const uint16_t i_nodeNumber)373 std::string Manager::getExpandedLocationCode(
374     const std::string& i_unexpandedLocationCode,
375     [[maybe_unused]] const uint16_t i_nodeNumber)
376 {
377     if (!isValidUnexpandedLocationCode(i_unexpandedLocationCode))
378     {
379         phosphor::logging::elog<types::DbusInvalidArgument>(
380             types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
381             types::InvalidArgument::ARGUMENT_VALUE(
382                 i_unexpandedLocationCode.c_str()));
383     }
384 
385     const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
386     if (!l_sysCfgJsonObj.contains("frus"))
387     {
388         logging::logMessage("Missing frus tag in system config JSON");
389     }
390 
391     const nlohmann::json& l_listOfFrus =
392         l_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
393 
394     for (const auto& l_frus : l_listOfFrus.items())
395     {
396         for (const auto& l_aFru : l_frus.value())
397         {
398             if (l_aFru["extraInterfaces"].contains(
399                     constants::locationCodeInf) &&
400                 l_aFru["extraInterfaces"][constants::locationCodeInf].value(
401                     "LocationCode", "") == i_unexpandedLocationCode)
402             {
403                 return std::get<std::string>(dbusUtility::readDbusProperty(
404                     l_aFru["serviceName"], l_aFru["inventoryPath"],
405                     constants::locationCodeInf, "LocationCode"));
406             }
407         }
408     }
409     phosphor::logging::elog<types::DbusInvalidArgument>(
410         types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
411         types::InvalidArgument::ARGUMENT_VALUE(
412             i_unexpandedLocationCode.c_str()));
413 }
414 
getFrusByUnexpandedLocationCode(const std::string & i_unexpandedLocationCode,const uint16_t i_nodeNumber)415 types::ListOfPaths Manager::getFrusByUnexpandedLocationCode(
416     const std::string& i_unexpandedLocationCode,
417     [[maybe_unused]] const uint16_t i_nodeNumber)
418 {
419     types::ListOfPaths l_inventoryPaths;
420 
421     if (!isValidUnexpandedLocationCode(i_unexpandedLocationCode))
422     {
423         phosphor::logging::elog<types::DbusInvalidArgument>(
424             types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
425             types::InvalidArgument::ARGUMENT_VALUE(
426                 i_unexpandedLocationCode.c_str()));
427     }
428 
429     const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
430     if (!l_sysCfgJsonObj.contains("frus"))
431     {
432         logging::logMessage("Missing frus tag in system config JSON");
433     }
434 
435     const nlohmann::json& l_listOfFrus =
436         l_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
437 
438     for (const auto& l_frus : l_listOfFrus.items())
439     {
440         for (const auto& l_aFru : l_frus.value())
441         {
442             if (l_aFru["extraInterfaces"].contains(
443                     constants::locationCodeInf) &&
444                 l_aFru["extraInterfaces"][constants::locationCodeInf].value(
445                     "LocationCode", "") == i_unexpandedLocationCode)
446             {
447                 l_inventoryPaths.push_back(
448                     l_aFru.at("inventoryPath")
449                         .get_ref<const nlohmann::json::string_t&>());
450             }
451         }
452     }
453 
454     if (l_inventoryPaths.empty())
455     {
456         phosphor::logging::elog<types::DbusInvalidArgument>(
457             types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
458             types::InvalidArgument::ARGUMENT_VALUE(
459                 i_unexpandedLocationCode.c_str()));
460     }
461 
462     return l_inventoryPaths;
463 }
464 
getHwPath(const sdbusplus::message::object_path & i_dbusObjPath)465 std::string Manager::getHwPath(
466     const sdbusplus::message::object_path& i_dbusObjPath)
467 {
468     // Dummy code to supress unused variable warning. To be removed.
469     logging::logMessage(std::string(i_dbusObjPath));
470 
471     return std::string{};
472 }
473 
getUnexpandedLocationCode(const std::string & i_expandedLocationCode)474 std::tuple<std::string, uint16_t> Manager::getUnexpandedLocationCode(
475     const std::string& i_expandedLocationCode)
476 {
477     /**
478      * Location code should always start with U and fulfil minimum length
479      * criteria.
480      */
481     if (i_expandedLocationCode[0] != 'U' ||
482         i_expandedLocationCode.length() <
483             constants::EXP_LOCATION_CODE_MIN_LENGTH)
484     {
485         phosphor::logging::elog<types::DbusInvalidArgument>(
486             types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
487             types::InvalidArgument::ARGUMENT_VALUE(
488                 i_expandedLocationCode.c_str()));
489     }
490 
491     std::string l_fcKwd;
492 
493     auto l_fcKwdValue = dbusUtility::readDbusProperty(
494         "xyz.openbmc_project.Inventory.Manager",
495         "/xyz/openbmc_project/inventory/system/chassis/motherboard",
496         "com.ibm.ipzvpd.VCEN", "FC");
497 
498     if (auto l_kwdValue = std::get_if<types::BinaryVector>(&l_fcKwdValue))
499     {
500         l_fcKwd.assign(l_kwdValue->begin(), l_kwdValue->end());
501     }
502 
503     // Get the first part of expanded location code to check for FC or TM.
504     std::string l_firstKwd = i_expandedLocationCode.substr(1, 4);
505 
506     std::string l_unexpandedLocationCode{};
507     uint16_t l_nodeNummber = constants::INVALID_NODE_NUMBER;
508 
509     // Check if this value matches the value of FC keyword.
510     if (l_fcKwd.substr(0, 4) == l_firstKwd)
511     {
512         /**
513          * Period(.) should be there in expanded location code to seggregate
514          * FC, node number and SE values.
515          */
516         size_t l_nodeStartPos = i_expandedLocationCode.find('.');
517         if (l_nodeStartPos == std::string::npos)
518         {
519             phosphor::logging::elog<types::DbusInvalidArgument>(
520                 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
521                 types::InvalidArgument::ARGUMENT_VALUE(
522                     i_expandedLocationCode.c_str()));
523         }
524 
525         size_t l_nodeEndPos =
526             i_expandedLocationCode.find('.', l_nodeStartPos + 1);
527         if (l_nodeEndPos == std::string::npos)
528         {
529             phosphor::logging::elog<types::DbusInvalidArgument>(
530                 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
531                 types::InvalidArgument::ARGUMENT_VALUE(
532                     i_expandedLocationCode.c_str()));
533         }
534 
535         // Skip 3 bytes for '.ND'
536         l_nodeNummber = std::stoi(i_expandedLocationCode.substr(
537             l_nodeStartPos + 3, (l_nodeEndPos - l_nodeStartPos - 3)));
538 
539         /**
540          * Confirm if there are other details apart FC, node number and SE
541          * in location code
542          */
543         if (i_expandedLocationCode.length() >
544             constants::EXP_LOCATION_CODE_MIN_LENGTH)
545         {
546             l_unexpandedLocationCode =
547                 i_expandedLocationCode[0] + std::string("fcs") +
548                 i_expandedLocationCode.substr(
549                     l_nodeEndPos + 1 + constants::SE_KWD_LENGTH,
550                     std::string::npos);
551         }
552         else
553         {
554             l_unexpandedLocationCode = "Ufcs";
555         }
556     }
557     else
558     {
559         std::string l_tmKwd;
560         // Read TM keyword value.
561         auto l_tmKwdValue = dbusUtility::readDbusProperty(
562             "xyz.openbmc_project.Inventory.Manager",
563             "/xyz/openbmc_project/inventory/system/chassis/motherboard",
564             "com.ibm.ipzvpd.VSYS", "TM");
565 
566         if (auto l_kwdValue = std::get_if<types::BinaryVector>(&l_tmKwdValue))
567         {
568             l_tmKwd.assign(l_kwdValue->begin(), l_kwdValue->end());
569         }
570 
571         // Check if the substr matches to TM keyword value.
572         if (l_tmKwd.substr(0, 4) == l_firstKwd)
573         {
574             /**
575              * System location code will not have node number and any other
576              * details.
577              */
578             l_unexpandedLocationCode = "Umts";
579         }
580         // The given location code is neither "fcs" or "mts".
581         else
582         {
583             phosphor::logging::elog<types::DbusInvalidArgument>(
584                 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
585                 types::InvalidArgument::ARGUMENT_VALUE(
586                     i_expandedLocationCode.c_str()));
587         }
588     }
589 
590     return std::make_tuple(l_unexpandedLocationCode, l_nodeNummber);
591 }
592 
getFrusByExpandedLocationCode(const std::string & i_expandedLocationCode)593 types::ListOfPaths Manager::getFrusByExpandedLocationCode(
594     const std::string& i_expandedLocationCode)
595 {
596     std::tuple<std::string, uint16_t> l_locationAndNodePair =
597         getUnexpandedLocationCode(i_expandedLocationCode);
598 
599     return getFrusByUnexpandedLocationCode(std::get<0>(l_locationAndNodePair),
600                                            std::get<1>(l_locationAndNodePair));
601 }
602 
performVpdRecollection()603 void Manager::performVpdRecollection()
604 {
605     if (m_worker.get() != nullptr)
606     {
607         m_worker->performVpdRecollection();
608     }
609 }
610 
collectAllFruVpd() const611 bool Manager::collectAllFruVpd() const noexcept
612 {
613     try
614     {
615         types::SeverityType l_severityType;
616         if (m_vpdCollectionStatus == "NotStarted")
617         {
618             l_severityType = types::SeverityType::Informational;
619         }
620         else if (m_vpdCollectionStatus == "Completed" ||
621                  m_vpdCollectionStatus == "Failure")
622         {
623             l_severityType = types::SeverityType::Warning;
624         }
625         else
626         {
627             throw std::runtime_error(
628                 "Invalid collection status " + m_vpdCollectionStatus +
629                 ". Aborting all FRUs VPD collection.");
630         }
631 
632         EventLogger::createSyncPel(
633             types::ErrorType::FirmwareError, l_severityType, __FILE__,
634             __FUNCTION__, 0, "Collect all FRUs VPD is requested.", std::nullopt,
635             std::nullopt, std::nullopt, std::nullopt);
636 
637         if (m_ibmHandler.get() != nullptr)
638         {
639             m_ibmHandler->collectAllFruVpd();
640             return true;
641         }
642         else
643         {
644             throw std::runtime_error(
645                 "Not found any OEM handler to collect all FRUs VPD.");
646         }
647     }
648     catch (const std::exception& l_ex)
649     {
650         EventLogger::createSyncPel(
651             EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
652             __FILE__, __FUNCTION__, 0, std::string(l_ex.what()), std::nullopt,
653             std::nullopt, std::nullopt, std::nullopt);
654     }
655     return false;
656 }
657 } // namespace vpd
658