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