1 #include "pldm_bios_cmd.hpp" 2 3 #include "common/bios_utils.hpp" 4 #include "common/utils.hpp" 5 #include "pldm_cmd_helper.hpp" 6 7 #include <libpldm/bios_table.h> 8 #include <libpldm/utils.h> 9 10 #include <map> 11 #include <optional> 12 13 namespace pldmtool 14 { 15 16 namespace bios 17 { 18 19 namespace 20 { 21 22 using namespace pldmtool::helper; 23 using namespace pldm::bios::utils; 24 using namespace pldm::utils; 25 26 std::vector<std::unique_ptr<CommandInterface>> commands; 27 28 const std::map<const char*, pldm_bios_table_types> pldmBIOSTableTypes{ 29 {"StringTable", PLDM_BIOS_STRING_TABLE}, 30 {"AttributeTable", PLDM_BIOS_ATTR_TABLE}, 31 {"AttributeValueTable", PLDM_BIOS_ATTR_VAL_TABLE}, 32 }; 33 34 } // namespace 35 36 class GetDateTime : public CommandInterface 37 { 38 public: 39 ~GetDateTime() = default; 40 GetDateTime() = delete; 41 GetDateTime(const GetDateTime&) = delete; 42 GetDateTime(GetDateTime&&) = default; 43 GetDateTime& operator=(const GetDateTime&) = delete; 44 GetDateTime& operator=(GetDateTime&&) = delete; 45 46 using CommandInterface::CommandInterface; 47 48 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 49 { 50 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr)); 51 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 52 53 auto rc = encode_get_date_time_req(instanceId, request); 54 return {rc, requestMsg}; 55 } 56 57 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 58 { 59 uint8_t cc = 0; 60 61 uint8_t seconds, minutes, hours, day, month; 62 uint16_t year; 63 auto rc = decode_get_date_time_resp(responsePtr, payloadLength, &cc, 64 &seconds, &minutes, &hours, &day, 65 &month, &year); 66 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 67 { 68 std::cerr << "Response Message Error: " 69 << "rc=" << rc << ",cc=" << (int)cc << std::endl; 70 return; 71 } 72 73 std::stringstream dt; 74 ordered_json data; 75 dt << bcd2dec16(year) << "-" << setWidth(month) << "-" << setWidth(day) 76 << " " << setWidth(hours) << ":" << setWidth(minutes) << ":" 77 << setWidth(seconds); 78 data["Response"] = dt.str(); 79 pldmtool::helper::DisplayInJson(data); 80 } 81 82 private: 83 static std::string setWidth(uint8_t data) 84 { 85 std::stringstream s; 86 s << std::setfill('0') << std::setw(2) 87 << static_cast<uint32_t>(bcd2dec8(data)); 88 return s.str(); 89 } 90 }; 91 92 class SetDateTime : public CommandInterface 93 { 94 public: 95 ~SetDateTime() = default; 96 SetDateTime() = delete; 97 SetDateTime(const SetDateTime&) = delete; 98 SetDateTime(SetDateTime&&) = default; 99 SetDateTime& operator=(const SetDateTime&) = delete; 100 SetDateTime& operator=(SetDateTime&&) = delete; 101 102 explicit SetDateTime(const char* type, const char* name, CLI::App* app) : 103 CommandInterface(type, name, app) 104 { 105 app->add_option("-d,--data", tmData, 106 "set date time data\n" 107 "eg: YYYYMMDDHHMMSS") 108 ->required(); 109 } 110 111 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 112 { 113 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 114 sizeof(struct pldm_set_date_time_req)); 115 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 116 uint16_t year = 0; 117 uint8_t month = 0; 118 uint8_t day = 0; 119 uint8_t hours = 0; 120 uint8_t minutes = 0; 121 uint8_t seconds = 0; 122 123 if (!uintToDate(tmData, &year, &month, &day, &hours, &minutes, 124 &seconds)) 125 { 126 std::cerr << "decode date Error: " 127 << "tmData=" << tmData << std::endl; 128 129 return {PLDM_ERROR_INVALID_DATA, requestMsg}; 130 } 131 132 auto rc = encode_set_date_time_req( 133 instanceId, seconds, minutes, hours, day, month, year, request, 134 sizeof(struct pldm_set_date_time_req)); 135 136 return {rc, requestMsg}; 137 } 138 139 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 140 { 141 uint8_t completionCode = 0; 142 auto rc = decode_set_date_time_resp(responsePtr, payloadLength, 143 &completionCode); 144 145 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 146 { 147 std::cerr << "Response Message Error: " 148 << "rc=" << rc << ",cc=" << (int)completionCode 149 << std::endl; 150 return; 151 } 152 153 ordered_json data; 154 data["Response"] = "SUCCESS"; 155 pldmtool::helper::DisplayInJson(data); 156 } 157 158 private: 159 uint64_t tmData; 160 }; 161 162 class GetBIOSTableHandler : public CommandInterface 163 { 164 public: 165 ~GetBIOSTableHandler() = default; 166 GetBIOSTableHandler() = delete; 167 GetBIOSTableHandler(const GetBIOSTableHandler&) = delete; 168 GetBIOSTableHandler(GetBIOSTableHandler&&) = delete; 169 GetBIOSTableHandler& operator=(const GetBIOSTableHandler&) = delete; 170 GetBIOSTableHandler& operator=(GetBIOSTableHandler&&) = delete; 171 172 using Table = std::vector<uint8_t>; 173 174 using CommandInterface::CommandInterface; 175 176 static inline const std::map<pldm_bios_attribute_type, const char*> 177 attrTypeMap = { 178 {PLDM_BIOS_ENUMERATION, "BIOSEnumeration"}, 179 {PLDM_BIOS_ENUMERATION_READ_ONLY, "BIOSEnumerationReadOnly"}, 180 {PLDM_BIOS_STRING, "BIOSString"}, 181 {PLDM_BIOS_STRING_READ_ONLY, "BIOSStringReadOnly"}, 182 {PLDM_BIOS_PASSWORD, "BIOSPassword"}, 183 {PLDM_BIOS_PASSWORD_READ_ONLY, "BIOSPasswordReadOnly"}, 184 {PLDM_BIOS_INTEGER, "BIOSInteger"}, 185 {PLDM_BIOS_INTEGER_READ_ONLY, "BIOSIntegerReadOnly"}, 186 187 }; 188 189 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 190 { 191 return {PLDM_ERROR, {}}; 192 } 193 194 void parseResponseMsg(pldm_msg*, size_t) override {} 195 196 std::optional<Table> getBIOSTable(pldm_bios_table_types tableType) 197 { 198 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 199 PLDM_GET_BIOS_TABLE_REQ_BYTES); 200 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 201 202 auto rc = encode_get_bios_table_req(instanceId, 0, PLDM_GET_FIRSTPART, 203 tableType, request); 204 if (rc != PLDM_SUCCESS) 205 { 206 std::cerr << "Encode GetBIOSTable Error, tableType=," << tableType 207 << " ,rc=" << rc << std::endl; 208 return std::nullopt; 209 } 210 std::vector<uint8_t> responseMsg; 211 rc = pldmSendRecv(requestMsg, responseMsg); 212 if (rc != PLDM_SUCCESS) 213 { 214 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl; 215 return std::nullopt; 216 } 217 218 uint8_t cc = 0, transferFlag = 0; 219 uint32_t nextTransferHandle = 0; 220 size_t bios_table_offset; 221 auto responsePtr = 222 reinterpret_cast<struct pldm_msg*>(responseMsg.data()); 223 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr); 224 225 rc = decode_get_bios_table_resp(responsePtr, payloadLength, &cc, 226 &nextTransferHandle, &transferFlag, 227 &bios_table_offset); 228 229 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 230 { 231 std::cerr << "GetBIOSTable Response Error: tableType=" << tableType 232 << ", rc=" << rc << ", cc=" << (int)cc << std::endl; 233 return std::nullopt; 234 } 235 auto tableData = 236 reinterpret_cast<char*>((responsePtr->payload) + bios_table_offset); 237 auto tableSize = payloadLength - sizeof(nextTransferHandle) - 238 sizeof(transferFlag) - sizeof(cc); 239 return std::make_optional<Table>(tableData, tableData + tableSize); 240 } 241 242 const pldm_bios_attr_table_entry* 243 findAttrEntryByName(const std::string& name, const Table& attrTable, 244 const Table& stringTable) 245 { 246 auto stringEntry = pldm_bios_table_string_find_by_string( 247 stringTable.data(), stringTable.size(), name.c_str()); 248 if (stringEntry == nullptr) 249 { 250 return nullptr; 251 } 252 253 auto nameHandle = 254 pldm_bios_table_string_entry_decode_handle(stringEntry); 255 256 for (auto attr : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable.data(), 257 attrTable.size())) 258 { 259 auto attrNameHandle = 260 pldm_bios_table_attr_entry_decode_string_handle(attr); 261 if (attrNameHandle == nameHandle) 262 { 263 return attr; 264 } 265 } 266 return nullptr; 267 } 268 269 std::optional<uint16_t> findAttrHandleByName(const std::string& name, 270 const Table& attrTable, 271 const Table& stringTable) 272 { 273 auto attribute = findAttrEntryByName(name, attrTable, stringTable); 274 if (attribute == nullptr) 275 { 276 return std::nullopt; 277 } 278 279 return pldm_bios_table_attr_entry_decode_attribute_handle(attribute); 280 } 281 282 std::string decodeStringFromStringEntry( 283 const pldm_bios_string_table_entry* stringEntry) 284 { 285 auto strLength = 286 pldm_bios_table_string_entry_decode_string_length(stringEntry); 287 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */); 288 // Preconditions are upheld therefore no error check necessary 289 pldm_bios_table_string_entry_decode_string_check( 290 stringEntry, buffer.data(), buffer.size()); 291 292 return std::string(buffer.data(), buffer.data() + strLength); 293 } 294 295 std::string displayStringHandle(uint16_t handle, 296 const std::optional<Table>& stringTable, 297 bool displayHandle = true) 298 { 299 std::string displayString = std::to_string(handle); 300 if (!stringTable) 301 { 302 return displayString; 303 } 304 auto stringEntry = pldm_bios_table_string_find_by_handle( 305 stringTable->data(), stringTable->size(), handle); 306 if (stringEntry == nullptr) 307 { 308 return displayString; 309 } 310 311 auto decodedStr = decodeStringFromStringEntry(stringEntry); 312 if (!displayHandle) 313 { 314 return decodedStr; 315 } 316 317 return displayString + "(" + decodedStr + ")"; 318 } 319 320 std::string displayEnumValueByIndex(uint16_t attrHandle, uint8_t index, 321 const std::optional<Table>& attrTable, 322 const std::optional<Table>& stringTable) 323 { 324 std::string displayString; 325 if (!attrTable) 326 { 327 return displayString; 328 } 329 330 auto attrEntry = pldm_bios_table_attr_find_by_handle( 331 attrTable->data(), attrTable->size(), attrHandle); 332 if (attrEntry == nullptr) 333 { 334 return displayString; 335 } 336 uint8_t pvNum; 337 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry, 338 &pvNum); 339 if (rc != PLDM_SUCCESS) 340 { 341 return displayString; 342 } 343 std::vector<uint16_t> pvHandls(pvNum); 344 // Preconditions are upheld therefore no error check necessary 345 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check( 346 attrEntry, pvHandls.data(), pvHandls.size()); 347 return displayStringHandle(pvHandls[index], stringTable, false); 348 } 349 350 void displayAttributeValueEntry( 351 const pldm_bios_attr_val_table_entry* tableEntry, 352 const std::optional<Table>& attrTable, 353 const std::optional<Table>& stringTable, bool verbose, 354 ordered_json& output) 355 { 356 auto attrHandle = 357 pldm_bios_table_attr_value_entry_decode_attribute_handle( 358 tableEntry); 359 auto attrType = static_cast<pldm_bios_attribute_type>( 360 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry)); 361 362 if (verbose) 363 { 364 output["AttributeHandle"] = attrHandle; 365 if (attrTypeMap.contains(attrType)) 366 { 367 output["AttributeType"] = attrTypeMap.at(attrType); 368 } 369 else 370 { 371 std::cout << "Get AttributeType failed.\n"; 372 } 373 } 374 switch (attrType) 375 { 376 case PLDM_BIOS_ENUMERATION: 377 case PLDM_BIOS_ENUMERATION_READ_ONLY: 378 { 379 auto count = 380 pldm_bios_table_attr_value_entry_enum_decode_number( 381 tableEntry); 382 std::vector<uint8_t> handles(count); 383 pldm_bios_table_attr_value_entry_enum_decode_handles( 384 tableEntry, handles.data(), handles.size()); 385 if (verbose) 386 { 387 output["NumberOfCurrentValues"] = (int)count; 388 } 389 for (size_t i = 0; i < handles.size(); i++) 390 { 391 if (verbose) 392 { 393 output["CurrentValueStringHandleIndex[" + 394 std::to_string(i) + "]"] = 395 displayEnumValueByIndex(attrHandle, handles[i], 396 attrTable, stringTable); 397 } 398 else 399 { 400 output["CurrentValue"] = displayEnumValueByIndex( 401 attrHandle, handles[i], attrTable, stringTable); 402 } 403 } 404 break; 405 } 406 case PLDM_BIOS_INTEGER: 407 case PLDM_BIOS_INTEGER_READ_ONLY: 408 { 409 auto cv = pldm_bios_table_attr_value_entry_integer_decode_cv( 410 tableEntry); 411 if (verbose) 412 { 413 output["CurrentValue"] = cv; 414 } 415 else 416 { 417 output["CurrentValue"] = cv; 418 } 419 break; 420 } 421 case PLDM_BIOS_STRING: 422 case PLDM_BIOS_STRING_READ_ONLY: 423 { 424 variable_field currentString; 425 pldm_bios_table_attr_value_entry_string_decode_string( 426 tableEntry, ¤tString); 427 if (verbose) 428 { 429 output["CurrentStringLength"] = currentString.length; 430 output["CurrentString"] = std::string( 431 reinterpret_cast<const char*>(currentString.ptr), 432 currentString.length); 433 } 434 else 435 { 436 output["CurrentValue"] = std::string( 437 reinterpret_cast<const char*>(currentString.ptr), 438 currentString.length); 439 } 440 441 break; 442 } 443 case PLDM_BIOS_PASSWORD: 444 case PLDM_BIOS_PASSWORD_READ_ONLY: 445 { 446 std::cout << "Password attribute: Not Supported" << std::endl; 447 break; 448 } 449 } 450 } 451 }; 452 453 class GetBIOSTable : public GetBIOSTableHandler 454 { 455 public: 456 ~GetBIOSTable() = default; 457 GetBIOSTable() = delete; 458 GetBIOSTable(const GetBIOSTable&) = delete; 459 GetBIOSTable(GetBIOSTable&&) = delete; 460 GetBIOSTable& operator=(const GetBIOSTable&) = delete; 461 GetBIOSTable& operator=(GetBIOSTable&&) = delete; 462 463 using Table = std::vector<uint8_t>; 464 465 explicit GetBIOSTable(const char* type, const char* name, CLI::App* app) : 466 GetBIOSTableHandler(type, name, app) 467 { 468 app->add_option("-t,--type", pldmBIOSTableType, "pldm bios table type") 469 ->required() 470 ->transform( 471 CLI::CheckedTransformer(pldmBIOSTableTypes, CLI::ignore_case)); 472 } 473 474 void exec() override 475 { 476 switch (pldmBIOSTableType) 477 { 478 case PLDM_BIOS_STRING_TABLE: 479 { 480 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 481 decodeStringTable(stringTable); 482 break; 483 } 484 case PLDM_BIOS_ATTR_TABLE: 485 { 486 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 487 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 488 489 decodeAttributeTable(attrTable, stringTable); 490 break; 491 } 492 case PLDM_BIOS_ATTR_VAL_TABLE: 493 { 494 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 495 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 496 auto attrValTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 497 498 decodeAttributeValueTable(attrValTable, attrTable, stringTable); 499 break; 500 } 501 } 502 } 503 504 private: 505 pldm_bios_table_types pldmBIOSTableType; 506 507 void decodeStringTable(const std::optional<Table>& stringTable) 508 { 509 if (!stringTable) 510 { 511 std::cerr << "GetBIOSStringTable Error" << std::endl; 512 return; 513 } 514 ordered_json stringdata; 515 516 for (auto tableEntry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>( 517 stringTable->data(), stringTable->size())) 518 { 519 auto strHandle = 520 pldm_bios_table_string_entry_decode_handle(tableEntry); 521 auto strTableData = decodeStringFromStringEntry(tableEntry); 522 stringdata[std::to_string(strHandle)] = strTableData; 523 } 524 pldmtool::helper::DisplayInJson(stringdata); 525 } 526 void decodeAttributeTable(const std::optional<Table>& attrTable, 527 const std::optional<Table>& stringTable) 528 { 529 if (!stringTable) 530 { 531 std::cerr << "GetBIOSAttributeTable Error" << std::endl; 532 return; 533 } 534 ordered_json output; 535 536 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>( 537 attrTable->data(), attrTable->size())) 538 { 539 ordered_json attrdata; 540 541 auto attrHandle = 542 pldm_bios_table_attr_entry_decode_attribute_handle(entry); 543 auto attrNameHandle = 544 pldm_bios_table_attr_entry_decode_string_handle(entry); 545 auto attrType = static_cast<pldm_bios_attribute_type>( 546 pldm_bios_table_attr_entry_decode_attribute_type(entry)); 547 548 attrdata["AttributeHandle"] = attrHandle; 549 attrdata["AttributeNameHandle"] = 550 displayStringHandle(attrNameHandle, stringTable); 551 if (attrTypeMap.contains(attrType)) 552 { 553 attrdata["AttributeType"] = attrTypeMap.at(attrType); 554 } 555 else 556 { 557 std::cout << "Get AttributeType failed.\n"; 558 } 559 560 switch (attrType) 561 { 562 case PLDM_BIOS_ENUMERATION: 563 case PLDM_BIOS_ENUMERATION_READ_ONLY: 564 { 565 uint8_t pvNum; 566 // Preconditions are upheld therefore no error check 567 // necessary 568 pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, 569 &pvNum); 570 std::vector<uint16_t> pvHandls(pvNum); 571 // Preconditions are upheld therefore no error check 572 // necessary 573 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check( 574 entry, pvHandls.data(), pvHandls.size()); 575 uint8_t defNum; 576 // Preconditions are upheld therefore no error check 577 // necessary 578 pldm_bios_table_attr_entry_enum_decode_def_num_check( 579 entry, &defNum); 580 std::vector<uint8_t> defIndices(defNum); 581 pldm_bios_table_attr_entry_enum_decode_def_indices( 582 entry, defIndices.data(), defIndices.size()); 583 584 attrdata["NumberOfPossibleValues"] = (int)pvNum; 585 586 for (size_t i = 0; i < pvHandls.size(); i++) 587 { 588 attrdata["PossibleValueStringHandle[" + 589 std::to_string(i) + "]"] = 590 displayStringHandle(pvHandls[i], stringTable); 591 } 592 attrdata["NumberOfDefaultValues"] = (int)defNum; 593 for (size_t i = 0; i < defIndices.size(); i++) 594 { 595 attrdata["DefaultValueStringHandleIndex[" + 596 std::to_string(i) + "]"] = (int)defIndices[i]; 597 attrdata["DefaultValueStringHandle"] = 598 displayStringHandle(pvHandls[defIndices[i]], 599 stringTable); 600 } 601 break; 602 } 603 case PLDM_BIOS_INTEGER: 604 case PLDM_BIOS_INTEGER_READ_ONLY: 605 { 606 uint64_t lower, upper, def; 607 uint32_t scalar; 608 pldm_bios_table_attr_entry_integer_decode( 609 entry, &lower, &upper, &scalar, &def); 610 attrdata["LowerBound"] = lower; 611 attrdata["UpperBound"] = upper; 612 attrdata["ScalarIncrement"] = scalar; 613 attrdata["DefaultValue"] = def; 614 break; 615 } 616 case PLDM_BIOS_STRING: 617 case PLDM_BIOS_STRING_READ_ONLY: 618 { 619 auto strType = 620 pldm_bios_table_attr_entry_string_decode_string_type( 621 entry); 622 auto min = 623 pldm_bios_table_attr_entry_string_decode_min_length( 624 entry); 625 auto max = 626 pldm_bios_table_attr_entry_string_decode_max_length( 627 entry); 628 uint16_t def; 629 // Preconditions are upheld therefore no error check 630 // necessary 631 pldm_bios_table_attr_entry_string_decode_def_string_length_check( 632 entry, &def); 633 std::vector<char> defString(def + 1); 634 pldm_bios_table_attr_entry_string_decode_def_string( 635 entry, defString.data(), defString.size()); 636 637 std::stringstream stringtype; 638 stringtype << "0x" << std::hex << std::setw(2) 639 << std::setfill('0') << (int)strType << std::dec 640 << std::setw(0); 641 attrdata["StringType"] = stringtype.str(); 642 attrdata["MinimumStringLength"] = (int)min; 643 attrdata["MaximumStringLength"] = (int)max; 644 attrdata["DefaultStringLength"] = (int)def; 645 attrdata["DefaultString"] = defString.data(); 646 break; 647 } 648 case PLDM_BIOS_PASSWORD: 649 case PLDM_BIOS_PASSWORD_READ_ONLY: 650 std::cout << "Password attribute: Not Supported" 651 << std::endl; 652 } 653 output.emplace_back(std::move(attrdata)); 654 } 655 pldmtool::helper::DisplayInJson(output); 656 } 657 void decodeAttributeValueTable(const std::optional<Table>& attrValTable, 658 const std::optional<Table>& attrTable, 659 const std::optional<Table>& stringTable) 660 { 661 if (!attrValTable) 662 { 663 std::cerr << "GetBIOSAttributeValueTable Error" << std::endl; 664 return; 665 } 666 ordered_json output; 667 for (auto tableEntry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>( 668 attrValTable->data(), attrValTable->size())) 669 { 670 ordered_json attrValueData; 671 displayAttributeValueEntry(tableEntry, attrTable, stringTable, true, 672 attrValueData); 673 output.emplace_back(attrValueData); 674 } 675 pldmtool::helper::DisplayInJson(output); 676 } 677 }; 678 679 class GetBIOSAttributeCurrentValueByHandle : public GetBIOSTableHandler 680 { 681 public: 682 ~GetBIOSAttributeCurrentValueByHandle() = default; 683 GetBIOSAttributeCurrentValueByHandle( 684 const GetBIOSAttributeCurrentValueByHandle&) = delete; 685 GetBIOSAttributeCurrentValueByHandle( 686 GetBIOSAttributeCurrentValueByHandle&&) = delete; 687 GetBIOSAttributeCurrentValueByHandle& 688 operator=(const GetBIOSAttributeCurrentValueByHandle&) = delete; 689 GetBIOSAttributeCurrentValueByHandle& 690 operator=(GetBIOSAttributeCurrentValueByHandle&&) = delete; 691 692 explicit GetBIOSAttributeCurrentValueByHandle(const char* type, 693 const char* name, 694 CLI::App* app) : 695 GetBIOSTableHandler(type, name, app) 696 { 697 app->add_option("-a, --attribute", attrName, "pldm BIOS attribute name") 698 ->required(); 699 } 700 701 void exec() 702 { 703 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 704 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 705 706 if (!stringTable || !attrTable) 707 { 708 std::cout << "StringTable/AttrTable Unavaliable" << std::endl; 709 return; 710 } 711 712 auto handle = findAttrHandleByName(attrName, *attrTable, *stringTable); 713 if (!handle) 714 { 715 std::cerr << "Can not find the attribute " << attrName << std::endl; 716 return; 717 } 718 719 std::vector<uint8_t> requestMsg( 720 sizeof(pldm_msg_hdr) + 721 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_REQ_BYTES); 722 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 723 724 auto rc = encode_get_bios_attribute_current_value_by_handle_req( 725 instanceId, 0, PLDM_GET_FIRSTPART, *handle, request); 726 if (rc != PLDM_SUCCESS) 727 { 728 std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl; 729 return; 730 } 731 732 std::vector<uint8_t> responseMsg; 733 rc = pldmSendRecv(requestMsg, responseMsg); 734 if (rc != PLDM_SUCCESS) 735 { 736 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl; 737 return; 738 } 739 740 uint8_t cc = 0, transferFlag = 0; 741 uint32_t nextTransferHandle = 0; 742 struct variable_field attributeData; 743 auto responsePtr = 744 reinterpret_cast<struct pldm_msg*>(responseMsg.data()); 745 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr); 746 747 rc = decode_get_bios_attribute_current_value_by_handle_resp( 748 responsePtr, payloadLength, &cc, &nextTransferHandle, &transferFlag, 749 &attributeData); 750 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 751 { 752 std::cerr << "Response Message Error: " 753 << "rc=" << rc << ",cc=" << (int)cc << std::endl; 754 return; 755 } 756 757 auto tableEntry = 758 reinterpret_cast<const struct pldm_bios_attr_val_table_entry*>( 759 attributeData.ptr); 760 761 ordered_json avdata; 762 displayAttributeValueEntry(tableEntry, attrTable, stringTable, false, 763 avdata); 764 pldmtool::helper::DisplayInJson(avdata); 765 } 766 767 private: 768 std::string attrName; 769 }; 770 771 class SetBIOSAttributeCurrentValue : public GetBIOSTableHandler 772 { 773 public: 774 ~SetBIOSAttributeCurrentValue() = default; 775 SetBIOSAttributeCurrentValue() = delete; 776 SetBIOSAttributeCurrentValue(const SetBIOSAttributeCurrentValue&) = delete; 777 SetBIOSAttributeCurrentValue(SetBIOSAttributeCurrentValue&&) = delete; 778 SetBIOSAttributeCurrentValue& 779 operator=(const SetBIOSAttributeCurrentValue&) = delete; 780 SetBIOSAttributeCurrentValue& 781 operator=(SetBIOSAttributeCurrentValue&&) = delete; 782 783 explicit SetBIOSAttributeCurrentValue(const char* type, const char* name, 784 CLI::App* app) : 785 GetBIOSTableHandler(type, name, app) 786 { 787 app->add_option("-a, --attribute", attrName, "pldm attribute name") 788 ->required(); 789 app->add_option("-d, --data", attrValue, "pldm attribute value") 790 ->required(); 791 // -v is conflict with --verbose in class CommandInterface, so used -d 792 } 793 794 void exec() 795 { 796 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 797 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 798 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 799 800 if (!stringTable || !attrTable) 801 { 802 std::cout << "StringTable/AttrTable Unavaliable" << std::endl; 803 return; 804 } 805 806 auto attrEntry = findAttrEntryByName(attrName, *attrTable, 807 *stringTable); 808 if (attrEntry == nullptr) 809 { 810 std::cout << "Could not find attribute :" << attrName << std::endl; 811 return; 812 } 813 814 std::vector<uint8_t> requestMsg; 815 816 int rc = 0; 817 auto attrType = attrEntry->attr_type; 818 size_t entryLength = 1; 819 std::vector<uint8_t> attrValueEntry(entryLength, 0); 820 821 switch (attrType) 822 { 823 case PLDM_BIOS_ENUMERATION: 824 case PLDM_BIOS_ENUMERATION_READ_ONLY: 825 { 826 entryLength = 827 pldm_bios_table_attr_value_entry_encode_enum_length(1); 828 uint8_t pvNum; 829 // Preconditions are upheld therefore no error check necessary 830 pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry, 831 &pvNum); 832 std::vector<uint16_t> pvHdls(pvNum, 0); 833 // Preconditions are upheld therefore no error check necessary 834 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check( 835 attrEntry, pvHdls.data(), pvNum); 836 auto stringEntry = pldm_bios_table_string_find_by_string( 837 stringTable->data(), stringTable->size(), 838 attrValue.c_str()); 839 if (stringEntry == nullptr) 840 { 841 std::cout 842 << "Set Attribute Error: It's not a possible value" 843 << std::endl; 844 return; 845 } 846 auto valueHandle = 847 pldm_bios_table_string_entry_decode_handle(stringEntry); 848 849 uint8_t i; 850 for (i = 0; i < pvNum; i++) 851 { 852 if (valueHandle == pvHdls[i]) 853 break; 854 } 855 if (i == pvNum) 856 { 857 std::cout 858 << "Set Attribute Error: It's not a possible value" 859 << std::endl; 860 return; 861 } 862 863 attrValueEntry.resize(entryLength); 864 std::vector<uint8_t> handles = {i}; 865 int rc = pldm_bios_table_attr_value_entry_encode_enum_check( 866 attrValueEntry.data(), attrValueEntry.size(), 867 attrEntry->attr_handle, attrType, 1, handles.data()); 868 if (rc != PLDM_SUCCESS) 869 { 870 std::cout 871 << "Failed to encode BIOS table attribute enum: " << rc 872 << std::endl; 873 return; 874 } 875 break; 876 } 877 case PLDM_BIOS_STRING: 878 case PLDM_BIOS_STRING_READ_ONLY: 879 { 880 entryLength = 881 pldm_bios_table_attr_value_entry_encode_string_length( 882 attrValue.size()); 883 884 attrValueEntry.resize(entryLength); 885 886 int rc = pldm_bios_table_attr_value_entry_encode_string_check( 887 attrValueEntry.data(), entryLength, attrEntry->attr_handle, 888 attrType, attrValue.size(), attrValue.c_str()); 889 if (rc != PLDM_SUCCESS) 890 { 891 std::cout 892 << "Failed to encode BIOS table attribute string: " 893 << rc << std::endl; 894 return; 895 } 896 break; 897 } 898 case PLDM_BIOS_INTEGER: 899 case PLDM_BIOS_INTEGER_READ_ONLY: 900 { 901 uint64_t value = std::stoll(attrValue); 902 entryLength = 903 pldm_bios_table_attr_value_entry_encode_integer_length(); 904 attrValueEntry.resize(entryLength); 905 int rc = pldm_bios_table_attr_value_entry_encode_integer_check( 906 attrValueEntry.data(), entryLength, attrEntry->attr_handle, 907 attrType, value); 908 if (rc != PLDM_SUCCESS) 909 { 910 std::cout 911 << "Failed to encode BIOS table attribute integer: " 912 << rc << std::endl; 913 return; 914 } 915 break; 916 } 917 } 918 919 requestMsg.resize(entryLength + sizeof(pldm_msg_hdr) + 920 PLDM_SET_BIOS_ATTR_CURR_VAL_MIN_REQ_BYTES); 921 922 rc = encode_set_bios_attribute_current_value_req( 923 instanceId, 0, PLDM_START_AND_END, attrValueEntry.data(), 924 attrValueEntry.size(), 925 reinterpret_cast<pldm_msg*>(requestMsg.data()), 926 requestMsg.size() - sizeof(pldm_msg_hdr)); 927 928 if (rc != PLDM_SUCCESS) 929 { 930 std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl; 931 return; 932 } 933 std::vector<uint8_t> responseMsg; 934 rc = pldmSendRecv(requestMsg, responseMsg); 935 if (rc != PLDM_SUCCESS) 936 { 937 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl; 938 return; 939 } 940 uint8_t cc = 0; 941 uint32_t nextTransferHandle = 0; 942 auto responsePtr = 943 reinterpret_cast<struct pldm_msg*>(responseMsg.data()); 944 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr); 945 946 rc = decode_set_bios_attribute_current_value_resp( 947 responsePtr, payloadLength, &cc, &nextTransferHandle); 948 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 949 { 950 std::cerr << "Response Message Error: " 951 << "rc=" << rc << ",cc=" << (int)cc << std::endl; 952 return; 953 } 954 955 ordered_json data; 956 data["Response"] = "SUCCESS"; 957 pldmtool::helper::DisplayInJson(data); 958 } 959 960 private: 961 std::string attrName; 962 std::string attrValue; 963 }; 964 965 void registerCommand(CLI::App& app) 966 { 967 auto bios = app.add_subcommand("bios", "bios type command"); 968 bios->require_subcommand(1); 969 auto getDateTime = bios->add_subcommand("GetDateTime", "get date time"); 970 commands.push_back( 971 std::make_unique<GetDateTime>("bios", "GetDateTime", getDateTime)); 972 973 auto setDateTime = bios->add_subcommand("SetDateTime", 974 "set host date time"); 975 commands.push_back( 976 std::make_unique<SetDateTime>("bios", "setDateTime", setDateTime)); 977 978 auto getBIOSTable = bios->add_subcommand("GetBIOSTable", "get bios table"); 979 commands.push_back( 980 std::make_unique<GetBIOSTable>("bios", "GetBIOSTable", getBIOSTable)); 981 982 auto getBIOSAttributeCurrentValueByHandle = 983 bios->add_subcommand("GetBIOSAttributeCurrentValueByHandle", 984 "get bios attribute current value by handle"); 985 commands.push_back(std::make_unique<GetBIOSAttributeCurrentValueByHandle>( 986 "bios", "GetBIOSAttributeCurrentValueByHandle", 987 getBIOSAttributeCurrentValueByHandle)); 988 989 auto setBIOSAttributeCurrentValue = bios->add_subcommand( 990 "SetBIOSAttributeCurrentValue", "set bios attribute current value"); 991 commands.push_back(std::make_unique<SetBIOSAttributeCurrentValue>( 992 "bios", "SetBIOSAttributeCurrentValue", setBIOSAttributeCurrentValue)); 993 } 994 995 } // namespace bios 996 997 } // namespace pldmtool 998