1 #include "vpd_tool_impl.hpp" 2 3 #include "impl.hpp" 4 #include "parser_factory.hpp" 5 #include "vpd_exceptions.hpp" 6 7 #include <cstdlib> 8 #include <filesystem> 9 #include <iostream> 10 #include <sdbusplus/bus.hpp> 11 #include <variant> 12 #include <vector> 13 14 using namespace std; 15 using namespace openpower::vpd; 16 using namespace inventory; 17 using namespace openpower::vpd::manager::editor; 18 namespace fs = std::filesystem; 19 using json = nlohmann::json; 20 using namespace openpower::vpd::exceptions; 21 using namespace openpower::vpd::parser; 22 using namespace openpower::vpd::parser::factory; 23 using namespace openpower::vpd::parser::interface; 24 25 Binary VpdTool::toBinary(const std::string& value) 26 { 27 Binary val{}; 28 if (value.find("0x") == string::npos) 29 { 30 val.assign(value.begin(), value.end()); 31 } 32 else if (value.find("0x") != string::npos) 33 { 34 stringstream ss; 35 ss.str(value.substr(2)); 36 string byteStr{}; 37 38 if (value.length() % 2 != 0) 39 { 40 throw runtime_error( 41 "VPD-TOOL write option accepts 2 digit hex numbers. (Eg. 0x1 " 42 "should be given as 0x01). Aborting the write operation."); 43 } 44 45 if (value.find_first_not_of("0123456789abcdefABCDEF", 2) != 46 std::string::npos) 47 { 48 throw runtime_error("Provide a valid hexadecimal input."); 49 } 50 51 while (ss >> setw(2) >> byteStr) 52 { 53 uint8_t byte = strtoul(byteStr.c_str(), nullptr, 16); 54 55 val.push_back(byte); 56 } 57 } 58 59 else 60 { 61 throw runtime_error("The value to be updated should be either in ascii " 62 "or in hex. Refer --help option"); 63 } 64 return val; 65 } 66 67 void VpdTool::printReturnCode(int returnCode) 68 { 69 if (returnCode) 70 { 71 cout << "\n Command failed with the return code " << returnCode 72 << ". Continuing the execution. " << endl; 73 } 74 } 75 76 void VpdTool::eraseInventoryPath(string& fru) 77 { 78 // Power supply frupath comes with INVENTORY_PATH appended in prefix. 79 // Stripping it off inorder to avoid INVENTORY_PATH duplication 80 // during getVINIProperties() execution. 81 fru.erase(0, sizeof(INVENTORY_PATH) - 1); 82 } 83 84 void VpdTool::debugger(json output) 85 { 86 cout << output.dump(4) << '\n'; 87 } 88 89 auto VpdTool::makeDBusCall(const string& objectName, const string& interface, 90 const string& kw) 91 { 92 auto bus = sdbusplus::bus::new_default(); 93 auto properties = 94 bus.new_method_call(INVENTORY_MANAGER_SERVICE, objectName.c_str(), 95 "org.freedesktop.DBus.Properties", "Get"); 96 properties.append(interface); 97 properties.append(kw); 98 auto result = bus.call(properties); 99 100 if (result.is_method_error()) 101 { 102 throw runtime_error("Get api failed"); 103 } 104 return result; 105 } 106 107 json VpdTool::getVINIProperties(string invPath) 108 { 109 variant<Binary> response; 110 json kwVal = json::object({}); 111 112 vector<string> keyword{"CC", "SN", "PN", "FN", "DR"}; 113 string interface = "com.ibm.ipzvpd.VINI"; 114 string objectName = {}; 115 116 if (invPath.find(INVENTORY_PATH) != string::npos) 117 { 118 objectName = invPath; 119 eraseInventoryPath(invPath); 120 } 121 else 122 { 123 objectName = INVENTORY_PATH + invPath; 124 } 125 for (string kw : keyword) 126 { 127 try 128 { 129 makeDBusCall(objectName, interface, kw).read(response); 130 131 if (auto vec = get_if<Binary>(&response)) 132 { 133 string printableVal = getPrintableValue(*vec); 134 kwVal.emplace(kw, printableVal); 135 } 136 } 137 catch (const sdbusplus::exception_t& e) 138 { 139 if (string(e.name()) == 140 string("org.freedesktop.DBus.Error.UnknownObject")) 141 { 142 kwVal.emplace(invPath, json::object({})); 143 objFound = false; 144 break; 145 } 146 } 147 } 148 149 return kwVal; 150 } 151 152 void VpdTool::getExtraInterfaceProperties(const string& invPath, 153 const string& extraInterface, 154 const json& prop, json& output) 155 { 156 variant<string> response; 157 158 string objectName = INVENTORY_PATH + invPath; 159 160 for (const auto& itProp : prop.items()) 161 { 162 string kw = itProp.key(); 163 try 164 { 165 makeDBusCall(objectName, extraInterface, kw).read(response); 166 167 if (auto str = get_if<string>(&response)) 168 { 169 output.emplace(kw, *str); 170 } 171 } 172 catch (const sdbusplus::exception_t& e) 173 { 174 if (std::string(e.name()) == 175 std::string("org.freedesktop.DBus.Error.UnknownObject")) 176 { 177 objFound = false; 178 break; 179 } 180 else if (std::string(e.name()) == 181 std::string("org.freedesktop.DBus.Error.UnknownProperty")) 182 { 183 output.emplace(kw, ""); 184 } 185 } 186 } 187 } 188 189 json VpdTool::interfaceDecider(json& itemEEPROM) 190 { 191 if (itemEEPROM.find("inventoryPath") == itemEEPROM.end()) 192 { 193 throw runtime_error("Inventory Path not found"); 194 } 195 196 if (itemEEPROM.find("extraInterfaces") == itemEEPROM.end()) 197 { 198 throw runtime_error("Extra Interfaces not found"); 199 } 200 201 json subOutput = json::object({}); 202 fruType = "FRU"; 203 204 json j; 205 objFound = true; 206 string invPath = itemEEPROM.at("inventoryPath"); 207 208 j = getVINIProperties(invPath); 209 210 if (objFound) 211 { 212 subOutput.insert(j.begin(), j.end()); 213 json js; 214 if (itemEEPROM.find("type") != itemEEPROM.end()) 215 { 216 fruType = itemEEPROM.at("type"); 217 } 218 js.emplace("TYPE", fruType); 219 220 if (invPath.find("powersupply") != string::npos) 221 { 222 js.emplace("type", POWER_SUPPLY_TYPE_INTERFACE); 223 } 224 else if (invPath.find("fan") != string::npos) 225 { 226 js.emplace("type", FAN_INTERFACE); 227 } 228 229 for (const auto& ex : itemEEPROM["extraInterfaces"].items()) 230 { 231 if (!(ex.value().is_null())) 232 { 233 // TODO: Remove this if condition check once inventory json is 234 // updated with xyz location code interface. 235 if (ex.key() == "com.ibm.ipzvpd.Location") 236 { 237 getExtraInterfaceProperties( 238 invPath, 239 "xyz.openbmc_project.Inventory.Decorator.LocationCode", 240 ex.value(), js); 241 } 242 else 243 { 244 getExtraInterfaceProperties(invPath, ex.key(), ex.value(), 245 js); 246 } 247 } 248 if ((ex.key().find("Item") != string::npos) && 249 (ex.value().is_null())) 250 { 251 js.emplace("type", ex.key()); 252 } 253 subOutput.insert(js.begin(), js.end()); 254 } 255 } 256 return subOutput; 257 } 258 259 json VpdTool::getPresentPropJson(const std::string& invPath, 260 std::string& parentPresence) 261 { 262 std::variant<bool> response; 263 makeDBusCall(invPath, "xyz.openbmc_project.Inventory.Item", "Present") 264 .read(response); 265 266 std::string presence{}; 267 268 if (auto pVal = get_if<bool>(&response)) 269 { 270 presence = *pVal ? "true" : "false"; 271 if (parentPresence.empty()) 272 { 273 parentPresence = presence; 274 } 275 } 276 else 277 { 278 presence = parentPresence; 279 } 280 281 json js; 282 js.emplace("Present", presence); 283 return js; 284 } 285 286 json VpdTool::parseInvJson(const json& jsObject, char flag, string fruPath) 287 { 288 json output = json::object({}); 289 bool validObject = false; 290 291 if (jsObject.find("frus") == jsObject.end()) 292 { 293 throw runtime_error("Frus missing in Inventory json"); 294 } 295 else 296 { 297 for (const auto& itemFRUS : jsObject["frus"].items()) 298 { 299 string parentPresence{}; 300 for (auto itemEEPROM : itemFRUS.value()) 301 { 302 json subOutput = json::object({}); 303 try 304 { 305 if (flag == 'O') 306 { 307 if (itemEEPROM.find("inventoryPath") == 308 itemEEPROM.end()) 309 { 310 throw runtime_error("Inventory Path not found"); 311 } 312 else if (itemEEPROM.at("inventoryPath") == fruPath) 313 { 314 validObject = true; 315 subOutput = interfaceDecider(itemEEPROM); 316 json presentJs = getPresentPropJson( 317 "/xyz/openbmc_project/inventory" + fruPath, 318 parentPresence); 319 subOutput.insert(presentJs.begin(), 320 presentJs.end()); 321 output.emplace(fruPath, subOutput); 322 return output; 323 } 324 else // this else is to keep track of parent present 325 // property. 326 { 327 json presentJs = getPresentPropJson( 328 "/xyz/openbmc_project/inventory" + 329 string(itemEEPROM.at("inventoryPath")), 330 parentPresence); 331 } 332 } 333 else 334 { 335 subOutput = interfaceDecider(itemEEPROM); 336 json presentJs = getPresentPropJson( 337 "/xyz/openbmc_project/inventory" + 338 string(itemEEPROM.at("inventoryPath")), 339 parentPresence); 340 subOutput.insert(presentJs.begin(), presentJs.end()); 341 output.emplace(string(itemEEPROM.at("inventoryPath")), 342 subOutput); 343 } 344 } 345 catch (const sdbusplus::exception::SdBusError& e) 346 { 347 // if any of frupath doesn't have Present property of its 348 // own, emplace its parent's present property value. 349 if (e.name() == std::string("org.freedesktop.DBus.Error." 350 "UnknownProperty") && 351 (((flag == 'O') && validObject) || flag == 'I')) 352 { 353 json presentJs; 354 presentJs.emplace("Present", parentPresence); 355 subOutput.insert(presentJs.begin(), presentJs.end()); 356 output.emplace(string(itemEEPROM.at("inventoryPath")), 357 subOutput); 358 } 359 360 // for the user given child frupath which doesn't have 361 // Present prop (vpd-tool -o). 362 if ((flag == 'O') && validObject) 363 { 364 return output; 365 } 366 } 367 catch (const exception& e) 368 { 369 cerr << e.what(); 370 } 371 } 372 } 373 if ((flag == 'O') && (!validObject)) 374 { 375 throw runtime_error( 376 "Invalid object path. Refer --dumpInventory/-i option."); 377 } 378 } 379 return output; 380 } 381 382 void VpdTool::dumpInventory(const nlohmann::basic_json<>& jsObject) 383 { 384 char flag = 'I'; 385 json output = json::array({}); 386 output.emplace_back(parseInvJson(jsObject, flag, "")); 387 debugger(output); 388 } 389 390 void VpdTool::dumpObject(const nlohmann::basic_json<>& jsObject) 391 { 392 char flag = 'O'; 393 json output = json::array({}); 394 output.emplace_back(parseInvJson(jsObject, flag, fruPath)); 395 debugger(output); 396 } 397 398 void VpdTool::readKeyword() 399 { 400 string interface = "com.ibm.ipzvpd."; 401 variant<Binary> response; 402 403 try 404 { 405 json output = json::object({}); 406 json kwVal = json::object({}); 407 makeDBusCall(INVENTORY_PATH + fruPath, interface + recordName, keyword) 408 .read(response); 409 410 string printableVal{}; 411 if (auto vec = get_if<Binary>(&response)) 412 { 413 printableVal = getPrintableValue(*vec); 414 } 415 kwVal.emplace(keyword, printableVal); 416 417 output.emplace(fruPath, kwVal); 418 419 debugger(output); 420 } 421 catch (const json::exception& e) 422 { 423 json output = json::object({}); 424 json kwVal = json::object({}); 425 } 426 } 427 428 int VpdTool::updateKeyword() 429 { 430 Binary val = toBinary(value); 431 auto bus = sdbusplus::bus::new_default(); 432 auto properties = 433 bus.new_method_call(BUSNAME, OBJPATH, IFACE, "WriteKeyword"); 434 properties.append(static_cast<sdbusplus::message::object_path>(fruPath)); 435 properties.append(recordName); 436 properties.append(keyword); 437 properties.append(val); 438 auto result = bus.call(properties); 439 440 if (result.is_method_error()) 441 { 442 throw runtime_error("Get api failed"); 443 } 444 return 0; 445 } 446 447 void VpdTool::forceReset(const nlohmann::basic_json<>& jsObject) 448 { 449 for (const auto& itemFRUS : jsObject["frus"].items()) 450 { 451 for (const auto& itemEEPROM : itemFRUS.value().items()) 452 { 453 string fru = itemEEPROM.value().at("inventoryPath"); 454 455 fs::path fruCachePath = INVENTORY_MANAGER_CACHE; 456 fruCachePath += INVENTORY_PATH; 457 fruCachePath += fru; 458 459 try 460 { 461 for (const auto& it : fs::directory_iterator(fruCachePath)) 462 { 463 if (fs::is_regular_file(it.status())) 464 { 465 fs::remove(it); 466 } 467 } 468 } 469 catch (const fs::filesystem_error& e) 470 { 471 } 472 } 473 } 474 475 cout.flush(); 476 string udevRemove = "udevadm trigger -c remove -s \"*nvmem*\" -v"; 477 int returnCode = system(udevRemove.c_str()); 478 printReturnCode(returnCode); 479 480 string invManagerRestart = 481 "systemctl restart xyz.openbmc_project.Inventory.Manager.service"; 482 returnCode = system(invManagerRestart.c_str()); 483 printReturnCode(returnCode); 484 485 string sysVpdRestart = "systemctl restart system-vpd.service"; 486 returnCode = system(sysVpdRestart.c_str()); 487 printReturnCode(returnCode); 488 489 string udevAdd = "udevadm trigger -c add -s \"*nvmem*\" -v"; 490 returnCode = system(udevAdd.c_str()); 491 printReturnCode(returnCode); 492 } 493 494 int VpdTool::updateHardware(const uint32_t offset) 495 { 496 int rc = 0; 497 const Binary& val = static_cast<const Binary&>(toBinary(value)); 498 ifstream inventoryJson(INVENTORY_JSON_SYM_LINK); 499 try 500 { 501 auto json = nlohmann::json::parse(inventoryJson); 502 EditorImpl edit(fruPath, json, recordName, keyword); 503 504 edit.updateKeyword(val, offset, false); 505 } 506 catch (const json::parse_error& ex) 507 { 508 throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK)); 509 } 510 return rc; 511 } 512 513 void VpdTool::readKwFromHw(const uint32_t& startOffset) 514 { 515 ifstream inventoryJson(INVENTORY_JSON_SYM_LINK); 516 auto jsonFile = nlohmann::json::parse(inventoryJson); 517 518 Binary completeVPDFile; 519 completeVPDFile.resize(65504); 520 fstream vpdFileStream; 521 vpdFileStream.open(fruPath, 522 std::ios::in | std::ios::out | std::ios::binary); 523 524 vpdFileStream.seekg(startOffset, ios_base::cur); 525 vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]), 65504); 526 completeVPDFile.resize(vpdFileStream.gcount()); 527 vpdFileStream.clear(std::ios_base::eofbit); 528 529 if (completeVPDFile.empty()) 530 { 531 throw std::runtime_error("Invalid File"); 532 } 533 534 const std::string& inventoryPath = 535 jsonFile["frus"][fruPath][0]["inventoryPath"]; 536 537 Impl obj(completeVPDFile, (constants::pimPath + inventoryPath)); 538 std::string keywordVal = obj.readKwFromHw(recordName, keyword); 539 540 if (!keywordVal.empty()) 541 { 542 json output = json::object({}); 543 json kwVal = json::object({}); 544 kwVal.emplace(keyword, keywordVal); 545 546 output.emplace(fruPath, kwVal); 547 548 debugger(output); 549 } 550 else 551 { 552 std::cerr << "The given keyword " << keyword << " or record " 553 << recordName 554 << " or both are not present in the given FRU path " 555 << fruPath << std::endl; 556 } 557 } 558 559 void VpdTool::printFixSystemVPDOption(UserOption option) 560 { 561 switch (option) 562 { 563 case VpdTool::EXIT: 564 cout << "\nEnter 0 => To exit successfully : "; 565 break; 566 case VpdTool::BMC_DATA_FOR_ALL: 567 cout << "\n\nEnter 1 => If you choose the data on BMC for all " 568 "mismatching record-keyword pairs"; 569 break; 570 case VpdTool::SYSTEM_BACKPLANE_DATA_FOR_ALL: 571 cout << "\nEnter 2 => If you choose the data on System " 572 "Backplane for all mismatching record-keyword pairs"; 573 break; 574 case VpdTool::MORE_OPTIONS: 575 cout << "\nEnter 3 => If you wish to explore more options"; 576 break; 577 case VpdTool::BMC_DATA_FOR_CURRENT: 578 cout << "\nEnter 4 => If you choose the data on BMC as the " 579 "right value"; 580 break; 581 case VpdTool::SYSTEM_BACKPLANE_DATA_FOR_CURRENT: 582 cout << "\nEnter 5 => If you choose the data on System " 583 "Backplane as the right value"; 584 break; 585 case VpdTool::NEW_VALUE_ON_BOTH: 586 cout << "\nEnter 6 => If you wish to enter a new value to " 587 "update both on BMC and System Backplane"; 588 break; 589 case VpdTool::SKIP_CURRENT: 590 cout << "\nEnter 7 => If you wish to skip the above " 591 "record-keyword pair"; 592 break; 593 } 594 } 595 596 int VpdTool::fixSystemVPD() 597 { 598 std::string outline(191, '='); 599 cout << "\nRestorable record-keyword pairs and their data on BMC & " 600 "System Backplane.\n\n" 601 << outline << std::endl; 602 603 cout << left << setw(6) << "S.No" << left << setw(8) << "Record" << left 604 << setw(9) << "Keyword" << left << setw(75) << "Data On BMC" << left 605 << setw(75) << "Data On System Backplane" << left << setw(14) 606 << "Data Mismatch\n" 607 << outline << std::endl; 608 609 int num = 0; 610 611 // Get system VPD data in map 612 Binary vpdVector{}; 613 json js{}; 614 615 auto jsonToParse = INVENTORY_JSON_DEFAULT; 616 if (fs::exists(INVENTORY_JSON_SYM_LINK)) 617 { 618 jsonToParse = INVENTORY_JSON_SYM_LINK; 619 } 620 621 ifstream inventoryJson(jsonToParse); 622 if (!inventoryJson) 623 { 624 throw runtime_error("VPD JSON file not found"); 625 } 626 js = json::parse(inventoryJson); 627 628 vpdVector = getVpdDataInVector(js, constants::systemVpdFilePath); 629 ParserInterface* parser = ParserFactory::getParser( 630 vpdVector, constants::pimPath + std::string(constants::SYSTEM_OBJECT)); 631 auto parseResult = parser->parse(); 632 ParserFactory::freeParser(parser); 633 634 unordered_map<string, DbusPropertyMap> vpdMap; 635 636 if (auto pVal = get_if<Store>(&parseResult)) 637 { 638 vpdMap = pVal->getVpdMap(); 639 } 640 else 641 { 642 std::cerr << "\n System backplane VPD is not of type IPZ. Unable to " 643 "parse the VPD " 644 << constants::systemVpdFilePath << " . Exit with error." 645 << std::endl; 646 exit(1); 647 } 648 649 // Get system VPD D-Bus Data and store it in a map 650 using GetAllResultType = 651 std::vector<std::pair<std::string, std::variant<Binary>>>; 652 using IntfPropMap = std::map<std::string, GetAllResultType>; 653 654 IntfPropMap svpdBusData; 655 656 const auto vsys = getAllDBusProperty<GetAllResultType>( 657 constants::pimIntf, 658 "/xyz/openbmc_project/inventory/system/chassis/motherboard", 659 "com.ibm.ipzvpd.VSYS"); 660 svpdBusData.emplace("VSYS", vsys); 661 662 const auto vcen = getAllDBusProperty<GetAllResultType>( 663 constants::pimIntf, 664 "/xyz/openbmc_project/inventory/system/chassis/motherboard", 665 "com.ibm.ipzvpd.VCEN"); 666 svpdBusData.emplace("VCEN", vcen); 667 668 const auto lxr0 = getAllDBusProperty<GetAllResultType>( 669 constants::pimIntf, 670 "/xyz/openbmc_project/inventory/system/chassis/motherboard", 671 "com.ibm.ipzvpd.LXR0"); 672 svpdBusData.emplace("LXR0", lxr0); 673 674 const auto util = getAllDBusProperty<GetAllResultType>( 675 constants::pimIntf, 676 "/xyz/openbmc_project/inventory/system/chassis/motherboard", 677 "com.ibm.ipzvpd.UTIL"); 678 svpdBusData.emplace("UTIL", util); 679 680 for (const auto& recordKw : svpdKwdMap) 681 { 682 string record = recordKw.first; 683 684 // Extract specific record data from the svpdBusData map. 685 const auto& rec = svpdBusData.find(record); 686 687 if (rec == svpdBusData.end()) 688 { 689 std::cerr << record << " not a part of critical system VPD records." 690 << std::endl; 691 continue; 692 } 693 694 const auto& recData = svpdBusData.find(record)->second; 695 696 string busStr{}, hwValStr{}; 697 string mismatch = "NO"; // no mismatch 698 699 for (const auto& keyword : recordKw.second) 700 { 701 string hardwareValue{}; 702 auto recItr = vpdMap.find(record); 703 704 if (recItr != vpdMap.end()) 705 { 706 DbusPropertyMap& kwValMap = recItr->second; 707 auto kwItr = kwValMap.find(keyword); 708 if (kwItr != kwValMap.end()) 709 { 710 hardwareValue = kwItr->second; 711 } 712 } 713 714 std::variant<Binary> kwValue; 715 for (auto& kwData : recData) 716 { 717 if (kwData.first == keyword) 718 { 719 kwValue = kwData.second; 720 break; 721 } 722 } 723 724 if (keyword != "SE") 725 { 726 ostringstream hwValStream; 727 hwValStream << "0x"; 728 hwValStr = hwValStream.str(); 729 730 for (uint16_t byte : hardwareValue) 731 { 732 hwValStream << setfill('0') << setw(2) << hex << byte; 733 hwValStr = hwValStream.str(); 734 } 735 736 if (const auto value = get_if<Binary>(&kwValue)) 737 { 738 busStr = byteArrayToHexString(*value); 739 } 740 if (busStr != hwValStr) 741 { 742 mismatch = "YES"; 743 } 744 } 745 else 746 { 747 if (const auto value = get_if<Binary>(&kwValue)) 748 { 749 busStr = getPrintableValue(*value); 750 } 751 if (busStr != hardwareValue) 752 { 753 mismatch = "YES"; 754 } 755 hwValStr = hardwareValue; 756 } 757 recKwData.push_back( 758 make_tuple(++num, record, keyword, busStr, hwValStr, mismatch)); 759 760 std::string splitLine(191, '-'); 761 cout << left << setw(6) << num << left << setw(8) << record << left 762 << setw(9) << keyword << left << setw(75) << setfill(' ') 763 << busStr << left << setw(75) << setfill(' ') << hwValStr 764 << left << setw(14) << mismatch << '\n' 765 << splitLine << endl; 766 } 767 } 768 parseSVPDOptions(js); 769 return 0; 770 } 771 772 void VpdTool::parseSVPDOptions(const nlohmann::json& json) 773 { 774 do 775 { 776 printFixSystemVPDOption(VpdTool::BMC_DATA_FOR_ALL); 777 printFixSystemVPDOption(VpdTool::SYSTEM_BACKPLANE_DATA_FOR_ALL); 778 printFixSystemVPDOption(VpdTool::MORE_OPTIONS); 779 printFixSystemVPDOption(VpdTool::EXIT); 780 781 int option = 0; 782 cin >> option; 783 784 std::string outline(191, '='); 785 cout << '\n' << outline << endl; 786 787 if (json.find("frus") == json.end()) 788 { 789 throw runtime_error("Frus not found in json"); 790 } 791 792 bool mismatchFound = false; 793 794 if (option == VpdTool::BMC_DATA_FOR_ALL) 795 { 796 for (const auto& data : recKwData) 797 { 798 if (get<5>(data) == "YES") 799 { 800 EditorImpl edit(constants::systemVpdFilePath, json, 801 get<1>(data), get<2>(data)); 802 edit.updateKeyword(toBinary(get<3>(data)), 0, true); 803 mismatchFound = true; 804 } 805 } 806 807 if (mismatchFound) 808 { 809 cout << "\nData updated successfully for all mismatching " 810 "record-keyword pairs by choosing their corresponding " 811 "data on BMC. Exit successfully.\n" 812 << endl; 813 } 814 else 815 { 816 cout << "\nNo mismatch found for any of the above mentioned " 817 "record-keyword pair. Exit successfully.\n"; 818 } 819 820 exit(0); 821 } 822 else if (option == VpdTool::SYSTEM_BACKPLANE_DATA_FOR_ALL) 823 { 824 for (const auto& data : recKwData) 825 { 826 if (get<5>(data) == "YES") 827 { 828 EditorImpl edit(constants::systemVpdFilePath, json, 829 get<1>(data), get<2>(data)); 830 edit.updateKeyword(toBinary(get<4>(data)), 0, true); 831 mismatchFound = true; 832 } 833 } 834 835 if (mismatchFound) 836 { 837 cout << "\nData updated successfully for all mismatching " 838 "record-keyword pairs by choosing their corresponding " 839 "data on System Backplane.\n" 840 << endl; 841 } 842 else 843 { 844 cout << "\nNo mismatch found for any of the above mentioned " 845 "record-keyword pair. Exit successfully.\n"; 846 } 847 848 exit(0); 849 } 850 else if (option == VpdTool::MORE_OPTIONS) 851 { 852 cout << "\nIterate through all restorable record-keyword pairs\n"; 853 854 for (const auto& data : recKwData) 855 { 856 do 857 { 858 cout << '\n' << outline << endl; 859 860 cout << left << setw(6) << "S.No" << left << setw(8) 861 << "Record" << left << setw(9) << "Keyword" << left 862 << setw(75) << setfill(' ') << "Data On BMC" << left 863 << setw(75) << setfill(' ') 864 << "Data On System Backplane" << left << setw(14) 865 << "Data Mismatch" << endl; 866 867 cout << left << setw(6) << get<0>(data) << left << setw(8) 868 << get<1>(data) << left << setw(9) << get<2>(data) 869 << left << setw(75) << setfill(' ') << get<3>(data) 870 << left << setw(75) << setfill(' ') << get<4>(data) 871 << left << setw(14) << get<5>(data); 872 873 cout << '\n' << outline << endl; 874 875 if (get<5>(data) == "NO") 876 { 877 cout << "\nNo mismatch found.\n"; 878 printFixSystemVPDOption(VpdTool::NEW_VALUE_ON_BOTH); 879 printFixSystemVPDOption(VpdTool::SKIP_CURRENT); 880 printFixSystemVPDOption(VpdTool::EXIT); 881 } 882 else 883 { 884 printFixSystemVPDOption(VpdTool::BMC_DATA_FOR_CURRENT); 885 printFixSystemVPDOption( 886 VpdTool::SYSTEM_BACKPLANE_DATA_FOR_CURRENT); 887 printFixSystemVPDOption(VpdTool::NEW_VALUE_ON_BOTH); 888 printFixSystemVPDOption(VpdTool::SKIP_CURRENT); 889 printFixSystemVPDOption(VpdTool::EXIT); 890 } 891 892 cin >> option; 893 cout << '\n' << outline << endl; 894 895 EditorImpl edit(constants::systemVpdFilePath, json, 896 get<1>(data), get<2>(data)); 897 898 if (option == VpdTool::BMC_DATA_FOR_CURRENT) 899 { 900 edit.updateKeyword(toBinary(get<3>(data)), 0, true); 901 cout << "\nData updated successfully.\n"; 902 break; 903 } 904 else if (option == 905 VpdTool::SYSTEM_BACKPLANE_DATA_FOR_CURRENT) 906 { 907 edit.updateKeyword(toBinary(get<4>(data)), 0, true); 908 cout << "\nData updated successfully.\n"; 909 break; 910 } 911 else if (option == VpdTool::NEW_VALUE_ON_BOTH) 912 { 913 string value; 914 cout << "\nEnter the new value to update both on BMC & " 915 "System Backplane (Value should be in ASCII or " 916 "in HEX(prefixed with 0x)) : "; 917 cin >> value; 918 cout << '\n' << outline << endl; 919 920 edit.updateKeyword(toBinary(value), 0, true); 921 cout << "\nData updated successfully.\n"; 922 break; 923 } 924 else if (option == VpdTool::SKIP_CURRENT) 925 { 926 cout << "\nSkipped the above record-keyword pair. " 927 "Continue to the next available pair.\n"; 928 break; 929 } 930 else if (option == VpdTool::EXIT) 931 { 932 cout << "\nExit successfully\n"; 933 exit(0); 934 } 935 else 936 { 937 cout << "\nProvide a valid option. Retrying for the " 938 "current record-keyword pair\n"; 939 } 940 } while (1); 941 } 942 exit(0); 943 } 944 else if (option == VpdTool::EXIT) 945 { 946 cout << "\nExit successfully"; 947 exit(0); 948 } 949 else 950 { 951 cout << "\nProvide a valid option. Retry."; 952 continue; 953 } 954 955 } while (true); 956 } 957