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