1 #include "pldm_bios_cmd.hpp" 2 3 #include "libpldm/bios_table.h" 4 #include "libpldm/utils.h" 5 6 #include "common/bios_utils.hpp" 7 #include "common/utils.hpp" 8 #include "pldm_cmd_helper.hpp" 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&&) = default; 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 = 64 decode_get_date_time_resp(responsePtr, payloadLength, &cc, &seconds, 65 &minutes, &hours, &day, &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&&) = default; 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 197 std::optional<Table> getBIOSTable(pldm_bios_table_types tableType) 198 { 199 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 200 PLDM_GET_BIOS_TABLE_REQ_BYTES); 201 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 202 203 auto rc = encode_get_bios_table_req(instanceId, 0, PLDM_GET_FIRSTPART, 204 tableType, request); 205 if (rc != PLDM_SUCCESS) 206 { 207 std::cerr << "Encode GetBIOSTable Error, tableType=," << tableType 208 << " ,rc=" << rc << std::endl; 209 return std::nullopt; 210 } 211 std::vector<uint8_t> responseMsg; 212 rc = pldmSendRecv(requestMsg, responseMsg); 213 if (rc != PLDM_SUCCESS) 214 { 215 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl; 216 return std::nullopt; 217 } 218 219 uint8_t cc = 0, transferFlag = 0; 220 uint32_t nextTransferHandle = 0; 221 size_t bios_table_offset; 222 auto responsePtr = 223 reinterpret_cast<struct pldm_msg*>(responseMsg.data()); 224 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr); 225 226 rc = decode_get_bios_table_resp(responsePtr, payloadLength, &cc, 227 &nextTransferHandle, &transferFlag, 228 &bios_table_offset); 229 230 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 231 { 232 std::cerr << "GetBIOSTable Response Error: tableType=" << tableType 233 << ", rc=" << rc << ", cc=" << (int)cc << std::endl; 234 return std::nullopt; 235 } 236 auto tableData = 237 reinterpret_cast<char*>((responsePtr->payload) + bios_table_offset); 238 auto tableSize = payloadLength - sizeof(nextTransferHandle) - 239 sizeof(transferFlag) - sizeof(cc); 240 return std::make_optional<Table>(tableData, tableData + tableSize); 241 } 242 243 const pldm_bios_attr_table_entry* 244 findAttrEntryByName(const std::string& name, const Table& attrTable, 245 const Table& stringTable) 246 { 247 auto stringEntry = pldm_bios_table_string_find_by_string( 248 stringTable.data(), stringTable.size(), name.c_str()); 249 if (stringEntry == nullptr) 250 { 251 return nullptr; 252 } 253 254 auto nameHandle = 255 pldm_bios_table_string_entry_decode_handle(stringEntry); 256 257 for (auto attr : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable.data(), 258 attrTable.size())) 259 { 260 auto attrNameHandle = 261 pldm_bios_table_attr_entry_decode_string_handle(attr); 262 if (attrNameHandle == nameHandle) 263 { 264 return attr; 265 } 266 } 267 return nullptr; 268 } 269 270 std::optional<uint16_t> findAttrHandleByName(const std::string& name, 271 const Table& attrTable, 272 const Table& stringTable) 273 { 274 auto attribute = findAttrEntryByName(name, attrTable, stringTable); 275 if (attribute == nullptr) 276 { 277 return std::nullopt; 278 } 279 280 return pldm_bios_table_attr_entry_decode_attribute_handle(attribute); 281 } 282 283 std::string decodeStringFromStringEntry( 284 const pldm_bios_string_table_entry* stringEntry) 285 { 286 auto strLength = 287 pldm_bios_table_string_entry_decode_string_length(stringEntry); 288 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */); 289 pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(), 290 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 auto pvNum = pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry); 337 std::vector<uint16_t> pvHandls(pvNum); 338 pldm_bios_table_attr_entry_enum_decode_pv_hdls( 339 attrEntry, pvHandls.data(), pvHandls.size()); 340 return displayStringHandle(pvHandls[index], stringTable, false); 341 } 342 343 void displayAttributeValueEntry( 344 const pldm_bios_attr_val_table_entry* tableEntry, 345 const std::optional<Table>& attrTable, 346 const std::optional<Table>& stringTable, bool verbose, 347 ordered_json& output) 348 { 349 auto attrHandle = 350 pldm_bios_table_attr_value_entry_decode_attribute_handle( 351 tableEntry); 352 auto attrType = static_cast<pldm_bios_attribute_type>( 353 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry)); 354 355 if (verbose) 356 { 357 output["AttributeHandle"] = attrHandle; 358 if (attrTypeMap.contains(attrType)) 359 { 360 output["AttributeType"] = attrTypeMap.at(attrType); 361 } 362 else 363 { 364 std::cout << "Get AttributeType failed.\n"; 365 } 366 } 367 switch (attrType) 368 { 369 case PLDM_BIOS_ENUMERATION: 370 case PLDM_BIOS_ENUMERATION_READ_ONLY: 371 { 372 auto count = 373 pldm_bios_table_attr_value_entry_enum_decode_number( 374 tableEntry); 375 std::vector<uint8_t> handles(count); 376 pldm_bios_table_attr_value_entry_enum_decode_handles( 377 tableEntry, handles.data(), handles.size()); 378 if (verbose) 379 { 380 output["NumberOfCurrentValues"] = (int)count; 381 } 382 for (size_t i = 0; i < handles.size(); i++) 383 { 384 if (verbose) 385 { 386 output["CurrentValueStringHandleIndex[" + 387 std::to_string(i) + "]"] = 388 displayEnumValueByIndex(attrHandle, handles[i], 389 attrTable, stringTable); 390 } 391 else 392 { 393 output["CurrentValue"] = displayEnumValueByIndex( 394 attrHandle, handles[i], attrTable, stringTable); 395 } 396 } 397 break; 398 } 399 case PLDM_BIOS_INTEGER: 400 case PLDM_BIOS_INTEGER_READ_ONLY: 401 { 402 auto cv = pldm_bios_table_attr_value_entry_integer_decode_cv( 403 tableEntry); 404 if (verbose) 405 { 406 output["CurrentValue"] = cv; 407 } 408 else 409 { 410 output["CurrentValue"] = cv; 411 } 412 break; 413 } 414 case PLDM_BIOS_STRING: 415 case PLDM_BIOS_STRING_READ_ONLY: 416 { 417 variable_field currentString; 418 pldm_bios_table_attr_value_entry_string_decode_string( 419 tableEntry, ¤tString); 420 if (verbose) 421 { 422 output["CurrentStringLength"] = currentString.length; 423 output["CurrentString"] = std::string( 424 reinterpret_cast<const char*>(currentString.ptr), 425 currentString.length); 426 } 427 else 428 { 429 output["CurrentValue"] = std::string( 430 reinterpret_cast<const char*>(currentString.ptr), 431 currentString.length); 432 } 433 434 break; 435 } 436 case PLDM_BIOS_PASSWORD: 437 case PLDM_BIOS_PASSWORD_READ_ONLY: 438 { 439 std::cout << "Password attribute: Not Supported" << std::endl; 440 break; 441 } 442 } 443 } 444 }; 445 446 class GetBIOSTable : public GetBIOSTableHandler 447 { 448 public: 449 ~GetBIOSTable() = default; 450 GetBIOSTable() = delete; 451 GetBIOSTable(const GetBIOSTable&) = delete; 452 GetBIOSTable(GetBIOSTable&&) = default; 453 GetBIOSTable& operator=(const GetBIOSTable&) = delete; 454 GetBIOSTable& operator=(GetBIOSTable&&) = default; 455 456 using Table = std::vector<uint8_t>; 457 458 explicit GetBIOSTable(const char* type, const char* name, CLI::App* app) : 459 GetBIOSTableHandler(type, name, app) 460 { 461 app->add_option("-t,--type", pldmBIOSTableType, "pldm bios table type") 462 ->required() 463 ->transform( 464 CLI::CheckedTransformer(pldmBIOSTableTypes, CLI::ignore_case)); 465 } 466 467 void exec() override 468 { 469 switch (pldmBIOSTableType) 470 { 471 case PLDM_BIOS_STRING_TABLE: 472 { 473 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 474 decodeStringTable(stringTable); 475 break; 476 } 477 case PLDM_BIOS_ATTR_TABLE: 478 { 479 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 480 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 481 482 decodeAttributeTable(attrTable, stringTable); 483 break; 484 } 485 case PLDM_BIOS_ATTR_VAL_TABLE: 486 { 487 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 488 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 489 auto attrValTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 490 491 decodeAttributeValueTable(attrValTable, attrTable, stringTable); 492 break; 493 } 494 } 495 } 496 497 private: 498 pldm_bios_table_types pldmBIOSTableType; 499 500 void decodeStringTable(const std::optional<Table>& stringTable) 501 { 502 if (!stringTable) 503 { 504 std::cerr << "GetBIOSStringTable Error" << std::endl; 505 return; 506 } 507 ordered_json stringdata; 508 509 for (auto tableEntry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>( 510 stringTable->data(), stringTable->size())) 511 { 512 auto strHandle = 513 pldm_bios_table_string_entry_decode_handle(tableEntry); 514 auto strTableData = decodeStringFromStringEntry(tableEntry); 515 stringdata[std::to_string(strHandle)] = strTableData; 516 } 517 pldmtool::helper::DisplayInJson(stringdata); 518 } 519 void decodeAttributeTable(const std::optional<Table>& attrTable, 520 const std::optional<Table>& stringTable) 521 { 522 if (!stringTable) 523 { 524 std::cerr << "GetBIOSAttributeTable Error" << std::endl; 525 return; 526 } 527 ordered_json output; 528 529 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>( 530 attrTable->data(), attrTable->size())) 531 { 532 ordered_json attrdata; 533 534 auto attrHandle = 535 pldm_bios_table_attr_entry_decode_attribute_handle(entry); 536 auto attrNameHandle = 537 pldm_bios_table_attr_entry_decode_string_handle(entry); 538 auto attrType = static_cast<pldm_bios_attribute_type>( 539 pldm_bios_table_attr_entry_decode_attribute_type(entry)); 540 541 attrdata["AttributeHandle"] = attrHandle; 542 attrdata["AttributeNameHandle"] = 543 displayStringHandle(attrNameHandle, stringTable); 544 if (attrTypeMap.contains(attrType)) 545 { 546 attrdata["AttributeType"] = attrTypeMap.at(attrType); 547 } 548 else 549 { 550 std::cout << "Get AttributeType failed.\n"; 551 } 552 553 switch (attrType) 554 { 555 case PLDM_BIOS_ENUMERATION: 556 case PLDM_BIOS_ENUMERATION_READ_ONLY: 557 { 558 auto pvNum = 559 pldm_bios_table_attr_entry_enum_decode_pv_num(entry); 560 std::vector<uint16_t> pvHandls(pvNum); 561 pldm_bios_table_attr_entry_enum_decode_pv_hdls( 562 entry, pvHandls.data(), pvHandls.size()); 563 auto defNum = 564 pldm_bios_table_attr_entry_enum_decode_def_num(entry); 565 std::vector<uint8_t> defIndices(defNum); 566 pldm_bios_table_attr_entry_enum_decode_def_indices( 567 entry, defIndices.data(), defIndices.size()); 568 569 attrdata["NumberOfPossibleValues"] = (int)pvNum; 570 571 for (size_t i = 0; i < pvHandls.size(); i++) 572 { 573 attrdata["PossibleValueStringHandle[" + 574 std::to_string(i) + "]"] = 575 displayStringHandle(pvHandls[i], stringTable); 576 } 577 attrdata["NumberOfDefaultValues"] = (int)defNum; 578 for (size_t i = 0; i < defIndices.size(); i++) 579 { 580 attrdata["DefaultValueStringHandleIndex[" + 581 std::to_string(i) + "]"] = (int)defIndices[i]; 582 attrdata["DefaultValueStringHandle"] = 583 displayStringHandle(pvHandls[defIndices[i]], 584 stringTable); 585 } 586 break; 587 } 588 case PLDM_BIOS_INTEGER: 589 case PLDM_BIOS_INTEGER_READ_ONLY: 590 { 591 uint64_t lower, upper, def; 592 uint32_t scalar; 593 pldm_bios_table_attr_entry_integer_decode( 594 entry, &lower, &upper, &scalar, &def); 595 attrdata["LowerBound"] = lower; 596 attrdata["UpperBound"] = upper; 597 attrdata["ScalarIncrement"] = scalar; 598 attrdata["DefaultValue"] = def; 599 break; 600 } 601 case PLDM_BIOS_STRING: 602 case PLDM_BIOS_STRING_READ_ONLY: 603 { 604 auto strType = 605 pldm_bios_table_attr_entry_string_decode_string_type( 606 entry); 607 auto min = 608 pldm_bios_table_attr_entry_string_decode_min_length( 609 entry); 610 auto max = 611 pldm_bios_table_attr_entry_string_decode_max_length( 612 entry); 613 auto def = 614 pldm_bios_table_attr_entry_string_decode_def_string_length( 615 entry); 616 std::vector<char> defString(def + 1); 617 pldm_bios_table_attr_entry_string_decode_def_string( 618 entry, defString.data(), defString.size()); 619 620 std::stringstream stringtype; 621 stringtype << "0x" << std::hex << std::setw(2) 622 << std::setfill('0') << (int)strType << std::dec 623 << std::setw(0); 624 attrdata["StringType"] = stringtype.str(); 625 attrdata["MinimumStringLength"] = (int)min; 626 attrdata["MaximumStringLength"] = (int)max; 627 attrdata["DefaultStringLength"] = (int)def; 628 attrdata["DefaultString"] = defString.data(); 629 break; 630 } 631 case PLDM_BIOS_PASSWORD: 632 case PLDM_BIOS_PASSWORD_READ_ONLY: 633 std::cout << "Password attribute: Not Supported" 634 << std::endl; 635 } 636 output.emplace_back(std::move(attrdata)); 637 } 638 pldmtool::helper::DisplayInJson(output); 639 } 640 void decodeAttributeValueTable(const std::optional<Table>& attrValTable, 641 const std::optional<Table>& attrTable, 642 const std::optional<Table>& stringTable) 643 { 644 if (!attrValTable) 645 { 646 std::cerr << "GetBIOSAttributeValueTable Error" << std::endl; 647 return; 648 } 649 ordered_json output; 650 for (auto tableEntry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>( 651 attrValTable->data(), attrValTable->size())) 652 { 653 ordered_json attrValueData; 654 displayAttributeValueEntry(tableEntry, attrTable, stringTable, true, 655 attrValueData); 656 output.emplace_back(attrValueData); 657 } 658 pldmtool::helper::DisplayInJson(output); 659 } 660 }; 661 662 class GetBIOSAttributeCurrentValueByHandle : public GetBIOSTableHandler 663 { 664 public: 665 ~GetBIOSAttributeCurrentValueByHandle() = default; 666 GetBIOSAttributeCurrentValueByHandle( 667 const GetBIOSAttributeCurrentValueByHandle&) = delete; 668 GetBIOSAttributeCurrentValueByHandle( 669 GetBIOSAttributeCurrentValueByHandle&&) = delete; 670 GetBIOSAttributeCurrentValueByHandle& 671 operator=(const GetBIOSAttributeCurrentValueByHandle&) = delete; 672 GetBIOSAttributeCurrentValueByHandle& 673 operator=(GetBIOSAttributeCurrentValueByHandle&&) = delete; 674 675 explicit GetBIOSAttributeCurrentValueByHandle(const char* type, 676 const char* name, 677 CLI::App* app) : 678 GetBIOSTableHandler(type, name, app) 679 { 680 app->add_option("-a, --attribute", attrName, "pldm BIOS attribute name") 681 ->required(); 682 } 683 684 void exec() 685 { 686 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 687 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 688 689 if (!stringTable || !attrTable) 690 { 691 std::cout << "StringTable/AttrTable Unavaliable" << std::endl; 692 return; 693 } 694 695 auto handle = findAttrHandleByName(attrName, *attrTable, *stringTable); 696 if (!handle) 697 { 698 699 std::cerr << "Can not find the attribute " << attrName << std::endl; 700 return; 701 } 702 703 std::vector<uint8_t> requestMsg( 704 sizeof(pldm_msg_hdr) + 705 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_REQ_BYTES); 706 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 707 708 auto rc = encode_get_bios_attribute_current_value_by_handle_req( 709 instanceId, 0, PLDM_GET_FIRSTPART, *handle, request); 710 if (rc != PLDM_SUCCESS) 711 { 712 std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl; 713 return; 714 } 715 716 std::vector<uint8_t> responseMsg; 717 rc = pldmSendRecv(requestMsg, responseMsg); 718 if (rc != PLDM_SUCCESS) 719 { 720 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl; 721 return; 722 } 723 724 uint8_t cc = 0, transferFlag = 0; 725 uint32_t nextTransferHandle = 0; 726 struct variable_field attributeData; 727 auto responsePtr = 728 reinterpret_cast<struct pldm_msg*>(responseMsg.data()); 729 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr); 730 731 rc = decode_get_bios_attribute_current_value_by_handle_resp( 732 responsePtr, payloadLength, &cc, &nextTransferHandle, &transferFlag, 733 &attributeData); 734 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 735 { 736 std::cerr << "Response Message Error: " 737 << "rc=" << rc << ",cc=" << (int)cc << std::endl; 738 return; 739 } 740 741 auto tableEntry = 742 reinterpret_cast<const struct pldm_bios_attr_val_table_entry*>( 743 attributeData.ptr); 744 745 ordered_json avdata; 746 displayAttributeValueEntry(tableEntry, attrTable, stringTable, false, 747 avdata); 748 pldmtool::helper::DisplayInJson(avdata); 749 } 750 751 private: 752 std::string attrName; 753 }; 754 755 class SetBIOSAttributeCurrentValue : public GetBIOSTableHandler 756 { 757 public: 758 ~SetBIOSAttributeCurrentValue() = default; 759 SetBIOSAttributeCurrentValue() = delete; 760 SetBIOSAttributeCurrentValue(const SetBIOSAttributeCurrentValue&) = delete; 761 SetBIOSAttributeCurrentValue(SetBIOSAttributeCurrentValue&&) = default; 762 SetBIOSAttributeCurrentValue& 763 operator=(const SetBIOSAttributeCurrentValue&) = delete; 764 SetBIOSAttributeCurrentValue& 765 operator=(SetBIOSAttributeCurrentValue&&) = default; 766 767 explicit SetBIOSAttributeCurrentValue(const char* type, const char* name, 768 CLI::App* app) : 769 GetBIOSTableHandler(type, name, app) 770 { 771 app->add_option("-a, --attribute", attrName, "pldm attribute name") 772 ->required(); 773 app->add_option("-d, --data", attrValue, "pldm attribute value") 774 ->required(); 775 // -v is conflict with --verbose in class CommandInterface, so used -d 776 } 777 778 void exec() 779 { 780 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 781 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 782 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 783 784 if (!stringTable || !attrTable) 785 { 786 std::cout << "StringTable/AttrTable Unavaliable" << std::endl; 787 return; 788 } 789 790 auto attrEntry = 791 findAttrEntryByName(attrName, *attrTable, *stringTable); 792 if (attrEntry == nullptr) 793 { 794 std::cout << "Could not find attribute :" << attrName << std::endl; 795 return; 796 } 797 798 std::vector<uint8_t> requestMsg; 799 800 int rc = 0; 801 auto attrType = attrEntry->attr_type; 802 size_t entryLength = 1; 803 std::vector<uint8_t> attrValueEntry(entryLength, 0); 804 805 switch (attrType) 806 { 807 case PLDM_BIOS_ENUMERATION: 808 case PLDM_BIOS_ENUMERATION_READ_ONLY: 809 { 810 entryLength = 811 pldm_bios_table_attr_value_entry_encode_enum_length(1); 812 auto pvNum = 813 pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry); 814 std::vector<uint16_t> pvHdls(pvNum, 0); 815 pldm_bios_table_attr_entry_enum_decode_pv_hdls( 816 attrEntry, pvHdls.data(), pvNum); 817 auto stringEntry = pldm_bios_table_string_find_by_string( 818 stringTable->data(), stringTable->size(), 819 attrValue.c_str()); 820 if (stringEntry == nullptr) 821 { 822 std::cout 823 << "Set Attribute Error: It's not a possible value" 824 << std::endl; 825 return; 826 } 827 auto valueHandle = 828 pldm_bios_table_string_entry_decode_handle(stringEntry); 829 830 uint8_t i; 831 for (i = 0; i < pvNum; i++) 832 { 833 if (valueHandle == pvHdls[i]) 834 break; 835 } 836 if (i == pvNum) 837 { 838 std::cout 839 << "Set Attribute Error: It's not a possible value" 840 << std::endl; 841 return; 842 } 843 844 attrValueEntry.resize(entryLength); 845 std::vector<uint8_t> handles = {i}; 846 pldm_bios_table_attr_value_entry_encode_enum( 847 attrValueEntry.data(), attrValueEntry.size(), 848 attrEntry->attr_handle, attrType, 1, handles.data()); 849 break; 850 } 851 case PLDM_BIOS_STRING: 852 case PLDM_BIOS_STRING_READ_ONLY: 853 { 854 entryLength = 855 pldm_bios_table_attr_value_entry_encode_string_length( 856 attrValue.size()); 857 858 attrValueEntry.resize(entryLength); 859 860 pldm_bios_table_attr_value_entry_encode_string( 861 attrValueEntry.data(), entryLength, attrEntry->attr_handle, 862 attrType, attrValue.size(), attrValue.c_str()); 863 break; 864 } 865 case PLDM_BIOS_INTEGER: 866 case PLDM_BIOS_INTEGER_READ_ONLY: 867 { 868 uint64_t value = std::stoll(attrValue); 869 entryLength = 870 pldm_bios_table_attr_value_entry_encode_integer_length(); 871 attrValueEntry.resize(entryLength); 872 pldm_bios_table_attr_value_entry_encode_integer( 873 attrValueEntry.data(), entryLength, attrEntry->attr_handle, 874 attrType, value); 875 break; 876 } 877 } 878 879 requestMsg.resize(entryLength + sizeof(pldm_msg_hdr) + 880 PLDM_SET_BIOS_ATTR_CURR_VAL_MIN_REQ_BYTES); 881 882 rc = encode_set_bios_attribute_current_value_req( 883 instanceId, 0, PLDM_START_AND_END, attrValueEntry.data(), 884 attrValueEntry.size(), 885 reinterpret_cast<pldm_msg*>(requestMsg.data()), 886 requestMsg.size() - sizeof(pldm_msg_hdr)); 887 888 if (rc != PLDM_SUCCESS) 889 { 890 std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl; 891 return; 892 } 893 std::vector<uint8_t> responseMsg; 894 rc = pldmSendRecv(requestMsg, responseMsg); 895 if (rc != PLDM_SUCCESS) 896 { 897 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl; 898 return; 899 } 900 uint8_t cc = 0; 901 uint32_t nextTransferHandle = 0; 902 auto responsePtr = 903 reinterpret_cast<struct pldm_msg*>(responseMsg.data()); 904 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr); 905 906 rc = decode_set_bios_attribute_current_value_resp( 907 responsePtr, payloadLength, &cc, &nextTransferHandle); 908 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 909 { 910 std::cerr << "Response Message Error: " 911 << "rc=" << rc << ",cc=" << (int)cc << std::endl; 912 return; 913 } 914 915 ordered_json data; 916 data["Response"] = "SUCCESS"; 917 pldmtool::helper::DisplayInJson(data); 918 } 919 920 private: 921 std::string attrName; 922 std::string attrValue; 923 }; 924 925 void registerCommand(CLI::App& app) 926 { 927 auto bios = app.add_subcommand("bios", "bios type command"); 928 bios->require_subcommand(1); 929 auto getDateTime = bios->add_subcommand("GetDateTime", "get date time"); 930 commands.push_back( 931 std::make_unique<GetDateTime>("bios", "GetDateTime", getDateTime)); 932 933 auto setDateTime = 934 bios->add_subcommand("SetDateTime", "set host date time"); 935 commands.push_back( 936 std::make_unique<SetDateTime>("bios", "setDateTime", setDateTime)); 937 938 auto getBIOSTable = bios->add_subcommand("GetBIOSTable", "get bios table"); 939 commands.push_back( 940 std::make_unique<GetBIOSTable>("bios", "GetBIOSTable", getBIOSTable)); 941 942 auto getBIOSAttributeCurrentValueByHandle = 943 bios->add_subcommand("GetBIOSAttributeCurrentValueByHandle", 944 "get bios attribute current value by handle"); 945 commands.push_back(std::make_unique<GetBIOSAttributeCurrentValueByHandle>( 946 "bios", "GetBIOSAttributeCurrentValueByHandle", 947 getBIOSAttributeCurrentValueByHandle)); 948 949 auto setBIOSAttributeCurrentValue = bios->add_subcommand( 950 "SetBIOSAttributeCurrentValue", "set bios attribute current value"); 951 commands.push_back(std::make_unique<SetBIOSAttributeCurrentValue>( 952 "bios", "SetBIOSAttributeCurrentValue", setBIOSAttributeCurrentValue)); 953 } 954 955 } // namespace bios 956 957 } // namespace pldmtool 958