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