xref: /openbmc/openpower-vpd-parser/vpd-manager/src/manager.cpp (revision e621c063f1f293f510d5e10ee63f33c1ea27d70e)
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     uint16_t l_errCode = 0;
176     types::Path l_fruPath;
177     nlohmann::json l_sysCfgJsonObj{};
178 
179     if (m_worker.get() != nullptr)
180     {
181         l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
182 
183         // Get the EEPROM path
184         if (!l_sysCfgJsonObj.empty())
185         {
186             l_fruPath = jsonUtility::getFruPathFromJson(l_sysCfgJsonObj,
187                                                         i_vpdPath, l_errCode);
188         }
189     }
190 
191     if (l_fruPath.empty())
192     {
193         if (l_errCode)
194         {
195             logging::logMessage(
196                 "Failed to get FRU path from JSON for [" + i_vpdPath +
197                 "], error : " + vpdSpecificUtility::getErrCodeMsg(l_errCode));
198         }
199 
200         l_fruPath = i_vpdPath;
201     }
202 
203     try
204     {
205         std::shared_ptr<Parser> l_parserObj =
206             std::make_shared<Parser>(l_fruPath, l_sysCfgJsonObj);
207 
208         types::DbusVariantType l_updatedValue;
209         auto l_rc =
210             l_parserObj->updateVpdKeyword(i_paramsToWriteData, l_updatedValue);
211 
212         if (l_rc != constants::FAILURE && m_backupAndRestoreObj)
213         {
214             if (m_backupAndRestoreObj->updateKeywordOnPrimaryOrBackupPath(
215                     l_fruPath, i_paramsToWriteData) < constants::VALUE_0)
216             {
217                 logging::logMessage(
218                     "Write success, but backup and restore failed for file[" +
219                     l_fruPath + "]");
220             }
221         }
222 
223         types::WriteVpdParams l_writeParams;
224         types::BinaryVector l_valueToUpdate;
225 
226         if (const types::IpzData* l_ipzData =
227                 std::get_if<types::IpzData>(&i_paramsToWriteData))
228         {
229             if (const types::BinaryVector* l_val =
230                     std::get_if<types::BinaryVector>(&l_updatedValue))
231             {
232                 l_valueToUpdate = *l_val;
233             }
234             else
235             {
236                 l_valueToUpdate = std::get<2>(*l_ipzData);
237             }
238             l_writeParams =
239                 std::make_tuple(std::get<0>(*l_ipzData),
240                                 std::get<1>(*l_ipzData), l_valueToUpdate);
241         }
242         else if (const types::KwData* l_kwData =
243                      std::get_if<types::KwData>(&i_paramsToWriteData))
244         {
245             if (const types::BinaryVector* l_val =
246                     std::get_if<types::BinaryVector>(&l_updatedValue))
247             {
248                 l_valueToUpdate = *l_val;
249             }
250             else
251             {
252                 l_valueToUpdate = std::get<1>(*l_kwData);
253             }
254 
255             l_writeParams =
256                 std::make_tuple(std::get<0>(*l_kwData), l_valueToUpdate);
257         }
258 
259         // update keyword in inherited FRUs
260         if (l_rc != constants::FAILURE)
261         {
262             vpdSpecificUtility::updateKwdOnInheritedFrus(
263                 l_fruPath, l_writeParams, l_sysCfgJsonObj);
264         }
265 
266         // update common interface(s) properties
267         if (l_rc != constants::FAILURE)
268         {
269             vpdSpecificUtility::updateCiPropertyOfInheritedFrus(
270                 l_fruPath, l_writeParams, l_sysCfgJsonObj);
271         }
272 
273         return l_rc;
274     }
275     catch (const std::exception& l_exception)
276     {
277         // TODO:: error log needed
278         logging::logMessage("Update keyword failed for file[" + i_vpdPath +
279                             "], reason: " + std::string(l_exception.what()));
280         return -1;
281     }
282 }
283 
284 int Manager::updateKeywordOnHardware(
285     const types::Path i_fruPath,
286     const types::WriteVpdParams i_paramsToWriteData) noexcept
287 {
288     try
289     {
290         if (i_fruPath.empty())
291         {
292             throw std::runtime_error("Given FRU path is empty");
293         }
294 
295         nlohmann::json l_sysCfgJsonObj{};
296 
297         if (m_worker.get() != nullptr)
298         {
299             l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
300         }
301 
302         std::shared_ptr<Parser> l_parserObj =
303             std::make_shared<Parser>(i_fruPath, l_sysCfgJsonObj);
304         return l_parserObj->updateVpdKeywordOnHardware(i_paramsToWriteData);
305     }
306     catch (const std::exception& l_exception)
307     {
308         EventLogger::createAsyncPel(
309             types::ErrorType::InvalidEeprom, types::SeverityType::Informational,
310             __FILE__, __FUNCTION__, 0,
311             "Update keyword on hardware failed for file[" + i_fruPath +
312                 "], reason: " + std::string(l_exception.what()),
313             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
314 
315         return constants::FAILURE;
316     }
317 }
318 
319 types::DbusVariantType Manager::readKeyword(
320     const types::Path i_fruPath, const types::ReadVpdParams i_paramsToReadData)
321 {
322     try
323     {
324         nlohmann::json l_jsonObj{};
325 
326         if (m_worker.get() != nullptr)
327         {
328             l_jsonObj = m_worker->getSysCfgJsonObj();
329         }
330 
331         std::error_code ec;
332 
333         // Check if given path is filesystem path
334         if (!std::filesystem::exists(i_fruPath, ec) && (ec))
335         {
336             throw std::runtime_error(
337                 "Given file path " + i_fruPath + " not found.");
338         }
339 
340         std::shared_ptr<vpd::Parser> l_parserObj =
341             std::make_shared<vpd::Parser>(i_fruPath, l_jsonObj);
342 
343         std::shared_ptr<vpd::ParserInterface> l_vpdParserInstance =
344             l_parserObj->getVpdParserInstance();
345 
346         return (
347             l_vpdParserInstance->readKeywordFromHardware(i_paramsToReadData));
348     }
349     catch (const std::exception& e)
350     {
351         logging::logMessage(
352             e.what() + std::string(". VPD manager read operation failed for ") +
353             i_fruPath);
354         throw types::DeviceError::ReadFailure();
355     }
356 }
357 
358 void Manager::collectSingleFruVpd(
359     const sdbusplus::message::object_path& i_dbusObjPath)
360 {
361     if (m_vpdCollectionStatus != constants::vpdCollectionCompleted)
362     {
363         logging::logMessage(
364             "Currently VPD CollectionStatus is not completed. Cannot perform single FRU VPD collection for " +
365             std::string(i_dbusObjPath));
366         return;
367     }
368 
369     if (m_worker.get() != nullptr)
370     {
371         m_worker->collectSingleFruVpd(i_dbusObjPath);
372     }
373 }
374 
375 void Manager::deleteSingleFruVpd(
376     const sdbusplus::message::object_path& i_dbusObjPath)
377 {
378     try
379     {
380         if (std::string(i_dbusObjPath).empty())
381         {
382             throw std::runtime_error(
383                 "Given DBus object path is empty. Aborting FRU VPD deletion.");
384         }
385 
386         if (m_worker.get() == nullptr)
387         {
388             throw std::runtime_error(
389                 "Worker object not found, can't perform FRU VPD deletion for: " +
390                 std::string(i_dbusObjPath));
391         }
392 
393         m_worker->deleteFruVpd(std::string(i_dbusObjPath));
394     }
395     catch (const std::exception& l_ex)
396     {
397         // TODO: Log PEL
398         logging::logMessage(l_ex.what());
399     }
400 }
401 
402 bool Manager::isValidUnexpandedLocationCode(
403     const std::string& i_unexpandedLocationCode)
404 {
405     if ((i_unexpandedLocationCode.length() <
406          constants::UNEXP_LOCATION_CODE_MIN_LENGTH) ||
407         ((i_unexpandedLocationCode.compare(0, 4, "Ufcs") !=
408           constants::STR_CMP_SUCCESS) &&
409          (i_unexpandedLocationCode.compare(0, 4, "Umts") !=
410           constants::STR_CMP_SUCCESS)) ||
411         ((i_unexpandedLocationCode.length() >
412           constants::UNEXP_LOCATION_CODE_MIN_LENGTH) &&
413          (i_unexpandedLocationCode.find("-") != 4)))
414     {
415         return false;
416     }
417 
418     return true;
419 }
420 
421 std::string Manager::getExpandedLocationCode(
422     const std::string& i_unexpandedLocationCode,
423     [[maybe_unused]] const uint16_t i_nodeNumber)
424 {
425     if (!isValidUnexpandedLocationCode(i_unexpandedLocationCode))
426     {
427         phosphor::logging::elog<types::DbusInvalidArgument>(
428             types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
429             types::InvalidArgument::ARGUMENT_VALUE(
430                 i_unexpandedLocationCode.c_str()));
431     }
432 
433     const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
434     if (!l_sysCfgJsonObj.contains("frus"))
435     {
436         logging::logMessage("Missing frus tag in system config JSON");
437     }
438 
439     const nlohmann::json& l_listOfFrus =
440         l_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
441 
442     for (const auto& l_frus : l_listOfFrus.items())
443     {
444         for (const auto& l_aFru : l_frus.value())
445         {
446             if (l_aFru["extraInterfaces"].contains(
447                     constants::locationCodeInf) &&
448                 l_aFru["extraInterfaces"][constants::locationCodeInf].value(
449                     "LocationCode", "") == i_unexpandedLocationCode)
450             {
451                 return std::get<std::string>(dbusUtility::readDbusProperty(
452                     l_aFru["serviceName"], l_aFru["inventoryPath"],
453                     constants::locationCodeInf, "LocationCode"));
454             }
455         }
456     }
457     phosphor::logging::elog<types::DbusInvalidArgument>(
458         types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
459         types::InvalidArgument::ARGUMENT_VALUE(
460             i_unexpandedLocationCode.c_str()));
461 }
462 
463 types::ListOfPaths Manager::getFrusByUnexpandedLocationCode(
464     const std::string& i_unexpandedLocationCode,
465     [[maybe_unused]] const uint16_t i_nodeNumber)
466 {
467     types::ListOfPaths l_inventoryPaths;
468 
469     if (!isValidUnexpandedLocationCode(i_unexpandedLocationCode))
470     {
471         phosphor::logging::elog<types::DbusInvalidArgument>(
472             types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
473             types::InvalidArgument::ARGUMENT_VALUE(
474                 i_unexpandedLocationCode.c_str()));
475     }
476 
477     const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
478     if (!l_sysCfgJsonObj.contains("frus"))
479     {
480         logging::logMessage("Missing frus tag in system config JSON");
481     }
482 
483     const nlohmann::json& l_listOfFrus =
484         l_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
485 
486     for (const auto& l_frus : l_listOfFrus.items())
487     {
488         for (const auto& l_aFru : l_frus.value())
489         {
490             if (l_aFru["extraInterfaces"].contains(
491                     constants::locationCodeInf) &&
492                 l_aFru["extraInterfaces"][constants::locationCodeInf].value(
493                     "LocationCode", "") == i_unexpandedLocationCode)
494             {
495                 l_inventoryPaths.push_back(
496                     l_aFru.at("inventoryPath")
497                         .get_ref<const nlohmann::json::string_t&>());
498             }
499         }
500     }
501 
502     if (l_inventoryPaths.empty())
503     {
504         phosphor::logging::elog<types::DbusInvalidArgument>(
505             types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
506             types::InvalidArgument::ARGUMENT_VALUE(
507                 i_unexpandedLocationCode.c_str()));
508     }
509 
510     return l_inventoryPaths;
511 }
512 
513 std::string Manager::getHwPath(
514     const sdbusplus::message::object_path& i_dbusObjPath)
515 {
516     // Dummy code to supress unused variable warning. To be removed.
517     logging::logMessage(std::string(i_dbusObjPath));
518 
519     return std::string{};
520 }
521 
522 std::tuple<std::string, uint16_t> Manager::getUnexpandedLocationCode(
523     const std::string& i_expandedLocationCode)
524 {
525     /**
526      * Location code should always start with U and fulfil minimum length
527      * criteria.
528      */
529     if (i_expandedLocationCode[0] != 'U' ||
530         i_expandedLocationCode.length() <
531             constants::EXP_LOCATION_CODE_MIN_LENGTH)
532     {
533         phosphor::logging::elog<types::DbusInvalidArgument>(
534             types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
535             types::InvalidArgument::ARGUMENT_VALUE(
536                 i_expandedLocationCode.c_str()));
537     }
538 
539     std::string l_fcKwd;
540 
541     auto l_fcKwdValue = dbusUtility::readDbusProperty(
542         "xyz.openbmc_project.Inventory.Manager",
543         "/xyz/openbmc_project/inventory/system/chassis/motherboard",
544         "com.ibm.ipzvpd.VCEN", "FC");
545 
546     if (auto l_kwdValue = std::get_if<types::BinaryVector>(&l_fcKwdValue))
547     {
548         l_fcKwd.assign(l_kwdValue->begin(), l_kwdValue->end());
549     }
550 
551     // Get the first part of expanded location code to check for FC or TM.
552     std::string l_firstKwd = i_expandedLocationCode.substr(1, 4);
553 
554     std::string l_unexpandedLocationCode{};
555     uint16_t l_nodeNummber = constants::INVALID_NODE_NUMBER;
556 
557     // Check if this value matches the value of FC keyword.
558     if (l_fcKwd.substr(0, 4) == l_firstKwd)
559     {
560         /**
561          * Period(.) should be there in expanded location code to seggregate
562          * FC, node number and SE values.
563          */
564         size_t l_nodeStartPos = i_expandedLocationCode.find('.');
565         if (l_nodeStartPos == std::string::npos)
566         {
567             phosphor::logging::elog<types::DbusInvalidArgument>(
568                 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
569                 types::InvalidArgument::ARGUMENT_VALUE(
570                     i_expandedLocationCode.c_str()));
571         }
572 
573         size_t l_nodeEndPos =
574             i_expandedLocationCode.find('.', l_nodeStartPos + 1);
575         if (l_nodeEndPos == std::string::npos)
576         {
577             phosphor::logging::elog<types::DbusInvalidArgument>(
578                 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
579                 types::InvalidArgument::ARGUMENT_VALUE(
580                     i_expandedLocationCode.c_str()));
581         }
582 
583         // Skip 3 bytes for '.ND'
584         l_nodeNummber = std::stoi(i_expandedLocationCode.substr(
585             l_nodeStartPos + 3, (l_nodeEndPos - l_nodeStartPos - 3)));
586 
587         /**
588          * Confirm if there are other details apart FC, node number and SE
589          * in location code
590          */
591         if (i_expandedLocationCode.length() >
592             constants::EXP_LOCATION_CODE_MIN_LENGTH)
593         {
594             l_unexpandedLocationCode =
595                 i_expandedLocationCode[0] + std::string("fcs") +
596                 i_expandedLocationCode.substr(
597                     l_nodeEndPos + 1 + constants::SE_KWD_LENGTH,
598                     std::string::npos);
599         }
600         else
601         {
602             l_unexpandedLocationCode = "Ufcs";
603         }
604     }
605     else
606     {
607         std::string l_tmKwd;
608         // Read TM keyword value.
609         auto l_tmKwdValue = dbusUtility::readDbusProperty(
610             "xyz.openbmc_project.Inventory.Manager",
611             "/xyz/openbmc_project/inventory/system/chassis/motherboard",
612             "com.ibm.ipzvpd.VSYS", "TM");
613 
614         if (auto l_kwdValue = std::get_if<types::BinaryVector>(&l_tmKwdValue))
615         {
616             l_tmKwd.assign(l_kwdValue->begin(), l_kwdValue->end());
617         }
618 
619         // Check if the substr matches to TM keyword value.
620         if (l_tmKwd.substr(0, 4) == l_firstKwd)
621         {
622             /**
623              * System location code will not have node number and any other
624              * details.
625              */
626             l_unexpandedLocationCode = "Umts";
627         }
628         // The given location code is neither "fcs" or "mts".
629         else
630         {
631             phosphor::logging::elog<types::DbusInvalidArgument>(
632                 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
633                 types::InvalidArgument::ARGUMENT_VALUE(
634                     i_expandedLocationCode.c_str()));
635         }
636     }
637 
638     return std::make_tuple(l_unexpandedLocationCode, l_nodeNummber);
639 }
640 
641 types::ListOfPaths Manager::getFrusByExpandedLocationCode(
642     const std::string& i_expandedLocationCode)
643 {
644     std::tuple<std::string, uint16_t> l_locationAndNodePair =
645         getUnexpandedLocationCode(i_expandedLocationCode);
646 
647     return getFrusByUnexpandedLocationCode(std::get<0>(l_locationAndNodePair),
648                                            std::get<1>(l_locationAndNodePair));
649 }
650 
651 void Manager::performVpdRecollection()
652 {
653     if (m_worker.get() != nullptr)
654     {
655         m_worker->performVpdRecollection();
656     }
657 }
658 
659 bool Manager::collectAllFruVpd() const noexcept
660 {
661     try
662     {
663         types::SeverityType l_severityType;
664         if (m_vpdCollectionStatus == constants::vpdCollectionNotStarted)
665         {
666             l_severityType = types::SeverityType::Informational;
667         }
668         else if (m_vpdCollectionStatus == constants::vpdCollectionCompleted ||
669                  m_vpdCollectionStatus == constants::vpdCollectionFailed)
670         {
671             l_severityType = types::SeverityType::Warning;
672         }
673         else
674         {
675             throw std::runtime_error(
676                 "Invalid collection status " + m_vpdCollectionStatus +
677                 ". Aborting all FRUs VPD collection.");
678         }
679 
680         EventLogger::createSyncPel(
681             types::ErrorType::FirmwareError, l_severityType, __FILE__,
682             __FUNCTION__, 0, "Collect all FRUs VPD is requested.", std::nullopt,
683             std::nullopt, std::nullopt, std::nullopt);
684 
685 // ToDo: Handle with OEM interface
686 #ifdef IBM_SYSTEM
687         if (m_ibmHandler.get() != nullptr)
688         {
689             m_ibmHandler->collectAllFruVpd();
690             return true;
691         }
692         else
693         {
694             throw std::runtime_error(
695                 "Not found any OEM handler to collect all FRUs VPD.");
696         }
697 #endif
698     }
699     catch (const std::exception& l_ex)
700     {
701         EventLogger::createSyncPel(
702             EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
703             __FILE__, __FUNCTION__, 0, std::string(l_ex.what()), std::nullopt,
704             std::nullopt, std::nullopt, std::nullopt);
705     }
706     return false;
707 }
708 } // namespace vpd
709