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