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&&) = 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 = 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&&) = 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 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 pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(), 289 buffer.size()); 290 291 return std::string(buffer.data(), buffer.data() + strLength); 292 } 293 294 std::string displayStringHandle(uint16_t handle, 295 const std::optional<Table>& stringTable, 296 bool displayHandle = true) 297 { 298 std::string displayString = std::to_string(handle); 299 if (!stringTable) 300 { 301 return displayString; 302 } 303 auto stringEntry = pldm_bios_table_string_find_by_handle( 304 stringTable->data(), stringTable->size(), handle); 305 if (stringEntry == nullptr) 306 { 307 return displayString; 308 } 309 310 auto decodedStr = decodeStringFromStringEntry(stringEntry); 311 if (!displayHandle) 312 { 313 return decodedStr; 314 } 315 316 return displayString + "(" + decodedStr + ")"; 317 } 318 319 std::string displayEnumValueByIndex(uint16_t attrHandle, uint8_t index, 320 const std::optional<Table>& attrTable, 321 const std::optional<Table>& stringTable) 322 { 323 std::string displayString; 324 if (!attrTable) 325 { 326 return displayString; 327 } 328 329 auto attrEntry = pldm_bios_table_attr_find_by_handle( 330 attrTable->data(), attrTable->size(), attrHandle); 331 if (attrEntry == nullptr) 332 { 333 return displayString; 334 } 335 auto pvNum = pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry); 336 std::vector<uint16_t> pvHandls(pvNum); 337 pldm_bios_table_attr_entry_enum_decode_pv_hdls( 338 attrEntry, pvHandls.data(), pvHandls.size()); 339 return displayStringHandle(pvHandls[index], stringTable, false); 340 } 341 342 void displayAttributeValueEntry( 343 const pldm_bios_attr_val_table_entry* tableEntry, 344 const std::optional<Table>& attrTable, 345 const std::optional<Table>& stringTable, bool verbose, 346 ordered_json& output) 347 { 348 auto attrHandle = 349 pldm_bios_table_attr_value_entry_decode_attribute_handle( 350 tableEntry); 351 auto attrType = static_cast<pldm_bios_attribute_type>( 352 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry)); 353 354 if (verbose) 355 { 356 output["AttributeHandle"] = attrHandle; 357 if (attrTypeMap.contains(attrType)) 358 { 359 output["AttributeType"] = attrTypeMap.at(attrType); 360 } 361 else 362 { 363 std::cout << "Get AttributeType failed.\n"; 364 } 365 } 366 switch (attrType) 367 { 368 case PLDM_BIOS_ENUMERATION: 369 case PLDM_BIOS_ENUMERATION_READ_ONLY: 370 { 371 auto count = 372 pldm_bios_table_attr_value_entry_enum_decode_number( 373 tableEntry); 374 std::vector<uint8_t> handles(count); 375 pldm_bios_table_attr_value_entry_enum_decode_handles( 376 tableEntry, handles.data(), handles.size()); 377 if (verbose) 378 { 379 output["NumberOfCurrentValues"] = (int)count; 380 } 381 for (size_t i = 0; i < handles.size(); i++) 382 { 383 if (verbose) 384 { 385 output["CurrentValueStringHandleIndex[" + 386 std::to_string(i) + "]"] = 387 displayEnumValueByIndex(attrHandle, handles[i], 388 attrTable, stringTable); 389 } 390 else 391 { 392 output["CurrentValue"] = displayEnumValueByIndex( 393 attrHandle, handles[i], attrTable, stringTable); 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 output["CurrentValue"] = cv; 406 } 407 else 408 { 409 output["CurrentValue"] = cv; 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 output["CurrentStringLength"] = currentString.length; 422 output["CurrentString"] = std::string( 423 reinterpret_cast<const char*>(currentString.ptr), 424 currentString.length); 425 } 426 else 427 { 428 output["CurrentValue"] = std::string( 429 reinterpret_cast<const char*>(currentString.ptr), 430 currentString.length); 431 } 432 433 break; 434 } 435 case PLDM_BIOS_PASSWORD: 436 case PLDM_BIOS_PASSWORD_READ_ONLY: 437 { 438 std::cout << "Password attribute: Not Supported" << std::endl; 439 break; 440 } 441 } 442 } 443 }; 444 445 class GetBIOSTable : public GetBIOSTableHandler 446 { 447 public: 448 ~GetBIOSTable() = default; 449 GetBIOSTable() = delete; 450 GetBIOSTable(const GetBIOSTable&) = delete; 451 GetBIOSTable(GetBIOSTable&&) = default; 452 GetBIOSTable& operator=(const GetBIOSTable&) = delete; 453 GetBIOSTable& operator=(GetBIOSTable&&) = default; 454 455 using Table = std::vector<uint8_t>; 456 457 explicit GetBIOSTable(const char* type, const char* name, CLI::App* app) : 458 GetBIOSTableHandler(type, name, app) 459 { 460 app->add_option("-t,--type", pldmBIOSTableType, "pldm bios table type") 461 ->required() 462 ->transform( 463 CLI::CheckedTransformer(pldmBIOSTableTypes, CLI::ignore_case)); 464 } 465 466 void exec() override 467 { 468 switch (pldmBIOSTableType) 469 { 470 case PLDM_BIOS_STRING_TABLE: 471 { 472 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 473 decodeStringTable(stringTable); 474 break; 475 } 476 case PLDM_BIOS_ATTR_TABLE: 477 { 478 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 479 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 480 481 decodeAttributeTable(attrTable, stringTable); 482 break; 483 } 484 case PLDM_BIOS_ATTR_VAL_TABLE: 485 { 486 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 487 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 488 auto attrValTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 489 490 decodeAttributeValueTable(attrValTable, attrTable, stringTable); 491 break; 492 } 493 } 494 } 495 496 private: 497 pldm_bios_table_types pldmBIOSTableType; 498 499 void decodeStringTable(const std::optional<Table>& stringTable) 500 { 501 if (!stringTable) 502 { 503 std::cerr << "GetBIOSStringTable Error" << std::endl; 504 return; 505 } 506 ordered_json stringdata; 507 508 for (auto tableEntry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>( 509 stringTable->data(), stringTable->size())) 510 { 511 auto strHandle = 512 pldm_bios_table_string_entry_decode_handle(tableEntry); 513 auto strTableData = decodeStringFromStringEntry(tableEntry); 514 stringdata[std::to_string(strHandle)] = strTableData; 515 } 516 pldmtool::helper::DisplayInJson(stringdata); 517 } 518 void decodeAttributeTable(const std::optional<Table>& attrTable, 519 const std::optional<Table>& stringTable) 520 { 521 if (!stringTable) 522 { 523 std::cerr << "GetBIOSAttributeTable Error" << std::endl; 524 return; 525 } 526 ordered_json output; 527 528 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>( 529 attrTable->data(), attrTable->size())) 530 { 531 ordered_json attrdata; 532 533 auto attrHandle = 534 pldm_bios_table_attr_entry_decode_attribute_handle(entry); 535 auto attrNameHandle = 536 pldm_bios_table_attr_entry_decode_string_handle(entry); 537 auto attrType = static_cast<pldm_bios_attribute_type>( 538 pldm_bios_table_attr_entry_decode_attribute_type(entry)); 539 540 attrdata["AttributeHandle"] = attrHandle; 541 attrdata["AttributeNameHandle"] = 542 displayStringHandle(attrNameHandle, stringTable); 543 if (attrTypeMap.contains(attrType)) 544 { 545 attrdata["AttributeType"] = attrTypeMap.at(attrType); 546 } 547 else 548 { 549 std::cout << "Get AttributeType failed.\n"; 550 } 551 552 switch (attrType) 553 { 554 case PLDM_BIOS_ENUMERATION: 555 case PLDM_BIOS_ENUMERATION_READ_ONLY: 556 { 557 auto pvNum = 558 pldm_bios_table_attr_entry_enum_decode_pv_num(entry); 559 std::vector<uint16_t> pvHandls(pvNum); 560 pldm_bios_table_attr_entry_enum_decode_pv_hdls( 561 entry, pvHandls.data(), pvHandls.size()); 562 auto defNum = 563 pldm_bios_table_attr_entry_enum_decode_def_num(entry); 564 std::vector<uint8_t> defIndices(defNum); 565 pldm_bios_table_attr_entry_enum_decode_def_indices( 566 entry, defIndices.data(), defIndices.size()); 567 568 attrdata["NumberOfPossibleValues"] = (int)pvNum; 569 570 for (size_t i = 0; i < pvHandls.size(); i++) 571 { 572 attrdata["PossibleValueStringHandle[" + 573 std::to_string(i) + "]"] = 574 displayStringHandle(pvHandls[i], stringTable); 575 } 576 attrdata["NumberOfDefaultValues"] = (int)defNum; 577 for (size_t i = 0; i < defIndices.size(); i++) 578 { 579 attrdata["DefaultValueStringHandleIndex[" + 580 std::to_string(i) + "]"] = (int)defIndices[i]; 581 attrdata["DefaultValueStringHandle"] = 582 displayStringHandle(pvHandls[defIndices[i]], 583 stringTable); 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 attrdata["LowerBound"] = lower; 595 attrdata["UpperBound"] = upper; 596 attrdata["ScalarIncrement"] = scalar; 597 attrdata["DefaultValue"] = def; 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 619 std::stringstream stringtype; 620 stringtype << "0x" << std::hex << std::setw(2) 621 << std::setfill('0') << (int)strType << std::dec 622 << std::setw(0); 623 attrdata["StringType"] = stringtype.str(); 624 attrdata["MinimumStringLength"] = (int)min; 625 attrdata["MaximumStringLength"] = (int)max; 626 attrdata["DefaultStringLength"] = (int)def; 627 attrdata["DefaultString"] = defString.data(); 628 break; 629 } 630 case PLDM_BIOS_PASSWORD: 631 case PLDM_BIOS_PASSWORD_READ_ONLY: 632 std::cout << "Password attribute: Not Supported" 633 << std::endl; 634 } 635 output.emplace_back(std::move(attrdata)); 636 } 637 pldmtool::helper::DisplayInJson(output); 638 } 639 void decodeAttributeValueTable(const std::optional<Table>& attrValTable, 640 const std::optional<Table>& attrTable, 641 const std::optional<Table>& stringTable) 642 { 643 if (!attrValTable) 644 { 645 std::cerr << "GetBIOSAttributeValueTable Error" << std::endl; 646 return; 647 } 648 ordered_json output; 649 for (auto tableEntry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>( 650 attrValTable->data(), attrValTable->size())) 651 { 652 ordered_json attrValueData; 653 displayAttributeValueEntry(tableEntry, attrTable, stringTable, true, 654 attrValueData); 655 output.emplace_back(attrValueData); 656 } 657 pldmtool::helper::DisplayInJson(output); 658 } 659 }; 660 661 class GetBIOSAttributeCurrentValueByHandle : public GetBIOSTableHandler 662 { 663 public: 664 ~GetBIOSAttributeCurrentValueByHandle() = default; 665 GetBIOSAttributeCurrentValueByHandle( 666 const GetBIOSAttributeCurrentValueByHandle&) = delete; 667 GetBIOSAttributeCurrentValueByHandle( 668 GetBIOSAttributeCurrentValueByHandle&&) = delete; 669 GetBIOSAttributeCurrentValueByHandle& 670 operator=(const GetBIOSAttributeCurrentValueByHandle&) = delete; 671 GetBIOSAttributeCurrentValueByHandle& 672 operator=(GetBIOSAttributeCurrentValueByHandle&&) = delete; 673 674 explicit GetBIOSAttributeCurrentValueByHandle(const char* type, 675 const char* name, 676 CLI::App* app) : 677 GetBIOSTableHandler(type, name, app) 678 { 679 app->add_option("-a, --attribute", attrName, "pldm BIOS attribute name") 680 ->required(); 681 } 682 683 void exec() 684 { 685 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 686 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 687 688 if (!stringTable || !attrTable) 689 { 690 std::cout << "StringTable/AttrTable Unavaliable" << std::endl; 691 return; 692 } 693 694 auto handle = findAttrHandleByName(attrName, *attrTable, *stringTable); 695 if (!handle) 696 { 697 std::cerr << "Can not find the attribute " << attrName << std::endl; 698 return; 699 } 700 701 std::vector<uint8_t> requestMsg( 702 sizeof(pldm_msg_hdr) + 703 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_REQ_BYTES); 704 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 705 706 auto rc = encode_get_bios_attribute_current_value_by_handle_req( 707 instanceId, 0, PLDM_GET_FIRSTPART, *handle, request); 708 if (rc != PLDM_SUCCESS) 709 { 710 std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl; 711 return; 712 } 713 714 std::vector<uint8_t> responseMsg; 715 rc = pldmSendRecv(requestMsg, responseMsg); 716 if (rc != PLDM_SUCCESS) 717 { 718 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl; 719 return; 720 } 721 722 uint8_t cc = 0, transferFlag = 0; 723 uint32_t nextTransferHandle = 0; 724 struct variable_field attributeData; 725 auto responsePtr = 726 reinterpret_cast<struct pldm_msg*>(responseMsg.data()); 727 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr); 728 729 rc = decode_get_bios_attribute_current_value_by_handle_resp( 730 responsePtr, payloadLength, &cc, &nextTransferHandle, &transferFlag, 731 &attributeData); 732 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 733 { 734 std::cerr << "Response Message Error: " 735 << "rc=" << rc << ",cc=" << (int)cc << std::endl; 736 return; 737 } 738 739 auto tableEntry = 740 reinterpret_cast<const struct pldm_bios_attr_val_table_entry*>( 741 attributeData.ptr); 742 743 ordered_json avdata; 744 displayAttributeValueEntry(tableEntry, attrTable, stringTable, false, 745 avdata); 746 pldmtool::helper::DisplayInJson(avdata); 747 } 748 749 private: 750 std::string attrName; 751 }; 752 753 class SetBIOSAttributeCurrentValue : public GetBIOSTableHandler 754 { 755 public: 756 ~SetBIOSAttributeCurrentValue() = default; 757 SetBIOSAttributeCurrentValue() = delete; 758 SetBIOSAttributeCurrentValue(const SetBIOSAttributeCurrentValue&) = delete; 759 SetBIOSAttributeCurrentValue(SetBIOSAttributeCurrentValue&&) = default; 760 SetBIOSAttributeCurrentValue& 761 operator=(const SetBIOSAttributeCurrentValue&) = delete; 762 SetBIOSAttributeCurrentValue& 763 operator=(SetBIOSAttributeCurrentValue&&) = default; 764 765 explicit SetBIOSAttributeCurrentValue(const char* type, const char* name, 766 CLI::App* app) : 767 GetBIOSTableHandler(type, name, app) 768 { 769 app->add_option("-a, --attribute", attrName, "pldm attribute name") 770 ->required(); 771 app->add_option("-d, --data", attrValue, "pldm attribute value") 772 ->required(); 773 // -v is conflict with --verbose in class CommandInterface, so used -d 774 } 775 776 void exec() 777 { 778 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 779 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 780 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 781 782 if (!stringTable || !attrTable) 783 { 784 std::cout << "StringTable/AttrTable Unavaliable" << std::endl; 785 return; 786 } 787 788 auto attrEntry = findAttrEntryByName(attrName, *attrTable, 789 *stringTable); 790 if (attrEntry == nullptr) 791 { 792 std::cout << "Could not find attribute :" << attrName << std::endl; 793 return; 794 } 795 796 std::vector<uint8_t> requestMsg; 797 798 int rc = 0; 799 auto attrType = attrEntry->attr_type; 800 size_t entryLength = 1; 801 std::vector<uint8_t> attrValueEntry(entryLength, 0); 802 803 switch (attrType) 804 { 805 case PLDM_BIOS_ENUMERATION: 806 case PLDM_BIOS_ENUMERATION_READ_ONLY: 807 { 808 entryLength = 809 pldm_bios_table_attr_value_entry_encode_enum_length(1); 810 auto pvNum = 811 pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry); 812 std::vector<uint16_t> pvHdls(pvNum, 0); 813 pldm_bios_table_attr_entry_enum_decode_pv_hdls( 814 attrEntry, pvHdls.data(), pvNum); 815 auto stringEntry = pldm_bios_table_string_find_by_string( 816 stringTable->data(), stringTable->size(), 817 attrValue.c_str()); 818 if (stringEntry == nullptr) 819 { 820 std::cout 821 << "Set Attribute Error: It's not a possible value" 822 << std::endl; 823 return; 824 } 825 auto valueHandle = 826 pldm_bios_table_string_entry_decode_handle(stringEntry); 827 828 uint8_t i; 829 for (i = 0; i < pvNum; i++) 830 { 831 if (valueHandle == pvHdls[i]) 832 break; 833 } 834 if (i == pvNum) 835 { 836 std::cout 837 << "Set Attribute Error: It's not a possible value" 838 << std::endl; 839 return; 840 } 841 842 attrValueEntry.resize(entryLength); 843 std::vector<uint8_t> handles = {i}; 844 pldm_bios_table_attr_value_entry_encode_enum( 845 attrValueEntry.data(), attrValueEntry.size(), 846 attrEntry->attr_handle, attrType, 1, handles.data()); 847 break; 848 } 849 case PLDM_BIOS_STRING: 850 case PLDM_BIOS_STRING_READ_ONLY: 851 { 852 entryLength = 853 pldm_bios_table_attr_value_entry_encode_string_length( 854 attrValue.size()); 855 856 attrValueEntry.resize(entryLength); 857 858 pldm_bios_table_attr_value_entry_encode_string( 859 attrValueEntry.data(), entryLength, attrEntry->attr_handle, 860 attrType, attrValue.size(), attrValue.c_str()); 861 break; 862 } 863 case PLDM_BIOS_INTEGER: 864 case PLDM_BIOS_INTEGER_READ_ONLY: 865 { 866 uint64_t value = std::stoll(attrValue); 867 entryLength = 868 pldm_bios_table_attr_value_entry_encode_integer_length(); 869 attrValueEntry.resize(entryLength); 870 pldm_bios_table_attr_value_entry_encode_integer( 871 attrValueEntry.data(), entryLength, attrEntry->attr_handle, 872 attrType, value); 873 break; 874 } 875 } 876 877 requestMsg.resize(entryLength + sizeof(pldm_msg_hdr) + 878 PLDM_SET_BIOS_ATTR_CURR_VAL_MIN_REQ_BYTES); 879 880 rc = encode_set_bios_attribute_current_value_req( 881 instanceId, 0, PLDM_START_AND_END, attrValueEntry.data(), 882 attrValueEntry.size(), 883 reinterpret_cast<pldm_msg*>(requestMsg.data()), 884 requestMsg.size() - sizeof(pldm_msg_hdr)); 885 886 if (rc != PLDM_SUCCESS) 887 { 888 std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl; 889 return; 890 } 891 std::vector<uint8_t> responseMsg; 892 rc = pldmSendRecv(requestMsg, responseMsg); 893 if (rc != PLDM_SUCCESS) 894 { 895 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl; 896 return; 897 } 898 uint8_t cc = 0; 899 uint32_t nextTransferHandle = 0; 900 auto responsePtr = 901 reinterpret_cast<struct pldm_msg*>(responseMsg.data()); 902 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr); 903 904 rc = decode_set_bios_attribute_current_value_resp( 905 responsePtr, payloadLength, &cc, &nextTransferHandle); 906 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 907 { 908 std::cerr << "Response Message Error: " 909 << "rc=" << rc << ",cc=" << (int)cc << std::endl; 910 return; 911 } 912 913 ordered_json data; 914 data["Response"] = "SUCCESS"; 915 pldmtool::helper::DisplayInJson(data); 916 } 917 918 private: 919 std::string attrName; 920 std::string attrValue; 921 }; 922 923 void registerCommand(CLI::App& app) 924 { 925 auto bios = app.add_subcommand("bios", "bios type command"); 926 bios->require_subcommand(1); 927 auto getDateTime = bios->add_subcommand("GetDateTime", "get date time"); 928 commands.push_back( 929 std::make_unique<GetDateTime>("bios", "GetDateTime", getDateTime)); 930 931 auto setDateTime = bios->add_subcommand("SetDateTime", 932 "set host date time"); 933 commands.push_back( 934 std::make_unique<SetDateTime>("bios", "setDateTime", setDateTime)); 935 936 auto getBIOSTable = bios->add_subcommand("GetBIOSTable", "get bios table"); 937 commands.push_back( 938 std::make_unique<GetBIOSTable>("bios", "GetBIOSTable", getBIOSTable)); 939 940 auto getBIOSAttributeCurrentValueByHandle = 941 bios->add_subcommand("GetBIOSAttributeCurrentValueByHandle", 942 "get bios attribute current value by handle"); 943 commands.push_back(std::make_unique<GetBIOSAttributeCurrentValueByHandle>( 944 "bios", "GetBIOSAttributeCurrentValueByHandle", 945 getBIOSAttributeCurrentValueByHandle)); 946 947 auto setBIOSAttributeCurrentValue = bios->add_subcommand( 948 "SetBIOSAttributeCurrentValue", "set bios attribute current value"); 949 commands.push_back(std::make_unique<SetBIOSAttributeCurrentValue>( 950 "bios", "SetBIOSAttributeCurrentValue", setBIOSAttributeCurrentValue)); 951 } 952 953 } // namespace bios 954 955 } // namespace pldmtool 956