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 72 std::stringstream dt; 73 ordered_json data; 74 dt << bcd2dec16(year) << "-" << setWidth(month) << "-" << setWidth(day) 75 << " " << setWidth(hours) << ":" << setWidth(minutes) << ":" 76 << setWidth(seconds); 77 data["Response"] = dt.str(); 78 pldmtool::helper::DisplayInJson(data); 79 } 80 81 private: 82 static std::string setWidth(uint8_t data) 83 { 84 std::stringstream s; 85 s << std::setfill('0') << std::setw(2) 86 << static_cast<uint32_t>(bcd2dec8(data)); 87 return s.str(); 88 } 89 }; 90 91 class SetDateTime : public CommandInterface 92 { 93 public: 94 ~SetDateTime() = default; 95 SetDateTime() = delete; 96 SetDateTime(const SetDateTime&) = delete; 97 SetDateTime(SetDateTime&&) = default; 98 SetDateTime& operator=(const SetDateTime&) = delete; 99 SetDateTime& operator=(SetDateTime&&) = default; 100 101 explicit SetDateTime(const char* type, const char* name, CLI::App* app) : 102 CommandInterface(type, name, app) 103 { 104 app->add_option("-d,--data", tmData, 105 "set date time data\n" 106 "eg: YYYYMMDDHHMMSS") 107 ->required(); 108 } 109 110 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 111 { 112 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 113 sizeof(struct pldm_set_date_time_req)); 114 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 115 uint16_t year = 0; 116 uint8_t month = 0; 117 uint8_t day = 0; 118 uint8_t hours = 0; 119 uint8_t minutes = 0; 120 uint8_t seconds = 0; 121 122 if (!uintToDate(tmData, &year, &month, &day, &hours, &minutes, 123 &seconds)) 124 { 125 std::cerr << "decode date Error: " 126 << "tmData=" << tmData << std::endl; 127 128 return {PLDM_ERROR_INVALID_DATA, requestMsg}; 129 } 130 131 auto rc = encode_set_date_time_req( 132 instanceId, seconds, minutes, hours, day, month, year, request, 133 sizeof(struct pldm_set_date_time_req)); 134 135 return {rc, requestMsg}; 136 } 137 138 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 139 { 140 uint8_t completionCode = 0; 141 auto rc = decode_set_date_time_resp(responsePtr, payloadLength, 142 &completionCode); 143 144 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 145 { 146 std::cerr << "Response Message Error: " 147 << "rc=" << rc << ",cc=" << (int)completionCode 148 << std::endl; 149 return; 150 } 151 152 ordered_json data; 153 data["Response"] = "SUCCESS"; 154 pldmtool::helper::DisplayInJson(data); 155 } 156 157 private: 158 uint64_t tmData; 159 }; 160 161 class GetBIOSTableHandler : public CommandInterface 162 { 163 public: 164 ~GetBIOSTableHandler() = default; 165 GetBIOSTableHandler() = delete; 166 GetBIOSTableHandler(const GetBIOSTableHandler&) = delete; 167 GetBIOSTableHandler(GetBIOSTableHandler&&) = delete; 168 GetBIOSTableHandler& operator=(const GetBIOSTableHandler&) = delete; 169 GetBIOSTableHandler& operator=(GetBIOSTableHandler&&) = delete; 170 171 using Table = std::vector<uint8_t>; 172 173 using CommandInterface::CommandInterface; 174 175 static inline const std::map<pldm_bios_attribute_type, const char*> 176 attrTypeMap = { 177 {PLDM_BIOS_ENUMERATION, "BIOSEnumeration"}, 178 {PLDM_BIOS_ENUMERATION_READ_ONLY, "BIOSEnumerationReadOnly"}, 179 {PLDM_BIOS_STRING, "BIOSString"}, 180 {PLDM_BIOS_STRING_READ_ONLY, "BIOSStringReadOnly"}, 181 {PLDM_BIOS_PASSWORD, "BIOSPassword"}, 182 {PLDM_BIOS_PASSWORD_READ_ONLY, "BIOSPasswordReadOnly"}, 183 {PLDM_BIOS_INTEGER, "BIOSInteger"}, 184 {PLDM_BIOS_INTEGER_READ_ONLY, "BIOSIntegerReadOnly"}, 185 186 }; 187 188 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 189 { 190 return {PLDM_ERROR, {}}; 191 } 192 193 void parseResponseMsg(pldm_msg*, size_t) override 194 {} 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 output["AttributeType"] = attrTypeMap.at(attrType); 358 } 359 switch (attrType) 360 { 361 case PLDM_BIOS_ENUMERATION: 362 case PLDM_BIOS_ENUMERATION_READ_ONLY: 363 { 364 auto count = 365 pldm_bios_table_attr_value_entry_enum_decode_number( 366 tableEntry); 367 std::vector<uint8_t> handles(count); 368 pldm_bios_table_attr_value_entry_enum_decode_handles( 369 tableEntry, handles.data(), handles.size()); 370 if (verbose) 371 { 372 output["NumberOfCurrentValues"] = (int)count; 373 } 374 for (size_t i = 0; i < handles.size(); i++) 375 { 376 if (verbose) 377 { 378 output["CurrentValueStringHandleIndex[" + 379 std::to_string(i) + "]"] = 380 displayEnumValueByIndex(attrHandle, handles[i], 381 attrTable, stringTable); 382 } 383 else 384 { 385 output["CurrentValue"] = displayEnumValueByIndex( 386 attrHandle, handles[i], attrTable, stringTable); 387 } 388 } 389 break; 390 } 391 case PLDM_BIOS_INTEGER: 392 case PLDM_BIOS_INTEGER_READ_ONLY: 393 { 394 auto cv = pldm_bios_table_attr_value_entry_integer_decode_cv( 395 tableEntry); 396 if (verbose) 397 { 398 output["CurrentValue"] = cv; 399 } 400 else 401 { 402 output["CurrentValue"] = cv; 403 } 404 break; 405 } 406 case PLDM_BIOS_STRING: 407 case PLDM_BIOS_STRING_READ_ONLY: 408 { 409 variable_field currentString; 410 pldm_bios_table_attr_value_entry_string_decode_string( 411 tableEntry, ¤tString); 412 if (verbose) 413 { 414 output["CurrentStringLength"] = currentString.length; 415 output["CurrentString"] = std::string( 416 reinterpret_cast<const char*>(currentString.ptr), 417 currentString.length); 418 } 419 else 420 { 421 output["CurrentValue"] = std::string( 422 reinterpret_cast<const char*>(currentString.ptr), 423 currentString.length); 424 } 425 426 break; 427 } 428 case PLDM_BIOS_PASSWORD: 429 case PLDM_BIOS_PASSWORD_READ_ONLY: 430 { 431 std::cout << "Password attribute: Not Supported" << std::endl; 432 break; 433 } 434 } 435 } 436 }; 437 438 class GetBIOSTable : public GetBIOSTableHandler 439 { 440 public: 441 ~GetBIOSTable() = default; 442 GetBIOSTable() = delete; 443 GetBIOSTable(const GetBIOSTable&) = delete; 444 GetBIOSTable(GetBIOSTable&&) = default; 445 GetBIOSTable& operator=(const GetBIOSTable&) = delete; 446 GetBIOSTable& operator=(GetBIOSTable&&) = default; 447 448 using Table = std::vector<uint8_t>; 449 450 explicit GetBIOSTable(const char* type, const char* name, CLI::App* app) : 451 GetBIOSTableHandler(type, name, app) 452 { 453 app->add_option("-t,--type", pldmBIOSTableType, "pldm bios table type") 454 ->required() 455 ->transform( 456 CLI::CheckedTransformer(pldmBIOSTableTypes, CLI::ignore_case)); 457 } 458 459 void exec() override 460 { 461 switch (pldmBIOSTableType) 462 { 463 case PLDM_BIOS_STRING_TABLE: 464 { 465 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 466 decodeStringTable(stringTable); 467 break; 468 } 469 case PLDM_BIOS_ATTR_TABLE: 470 { 471 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 472 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 473 474 decodeAttributeTable(attrTable, stringTable); 475 break; 476 } 477 case PLDM_BIOS_ATTR_VAL_TABLE: 478 { 479 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 480 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 481 auto attrValTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 482 483 decodeAttributeValueTable(attrValTable, attrTable, stringTable); 484 break; 485 } 486 } 487 } 488 489 private: 490 pldm_bios_table_types pldmBIOSTableType; 491 492 void decodeStringTable(const std::optional<Table>& stringTable) 493 { 494 if (!stringTable) 495 { 496 std::cerr << "GetBIOSStringTable Error" << std::endl; 497 return; 498 } 499 ordered_json stringdata; 500 501 for (auto tableEntry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>( 502 stringTable->data(), stringTable->size())) 503 { 504 auto strHandle = 505 pldm_bios_table_string_entry_decode_handle(tableEntry); 506 auto strTableData = decodeStringFromStringEntry(tableEntry); 507 stringdata[std::to_string(strHandle)] = strTableData; 508 } 509 pldmtool::helper::DisplayInJson(stringdata); 510 } 511 void decodeAttributeTable(const std::optional<Table>& attrTable, 512 const std::optional<Table>& stringTable) 513 { 514 if (!stringTable) 515 { 516 std::cerr << "GetBIOSAttributeTable Error" << std::endl; 517 return; 518 } 519 ordered_json output; 520 521 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>( 522 attrTable->data(), attrTable->size())) 523 { 524 ordered_json attrdata; 525 526 auto attrHandle = 527 pldm_bios_table_attr_entry_decode_attribute_handle(entry); 528 auto attrNameHandle = 529 pldm_bios_table_attr_entry_decode_string_handle(entry); 530 auto attrType = static_cast<pldm_bios_attribute_type>( 531 pldm_bios_table_attr_entry_decode_attribute_type(entry)); 532 533 attrdata["AttributeHandle"] = attrHandle; 534 attrdata["AttributeNameHandle"] = 535 displayStringHandle(attrNameHandle, stringTable); 536 attrdata["AttributeType"] = attrTypeMap.at(attrType); 537 538 switch (attrType) 539 { 540 case PLDM_BIOS_ENUMERATION: 541 case PLDM_BIOS_ENUMERATION_READ_ONLY: 542 { 543 auto pvNum = 544 pldm_bios_table_attr_entry_enum_decode_pv_num(entry); 545 std::vector<uint16_t> pvHandls(pvNum); 546 pldm_bios_table_attr_entry_enum_decode_pv_hdls( 547 entry, pvHandls.data(), pvHandls.size()); 548 auto defNum = 549 pldm_bios_table_attr_entry_enum_decode_def_num(entry); 550 std::vector<uint8_t> defIndices(defNum); 551 pldm_bios_table_attr_entry_enum_decode_def_indices( 552 entry, defIndices.data(), defIndices.size()); 553 554 attrdata["NumberOfPossibleValues"] = (int)pvNum; 555 556 for (size_t i = 0; i < pvHandls.size(); i++) 557 { 558 attrdata["PossibleValueStringHandle[" + 559 std::to_string(i) + "]"] = 560 displayStringHandle(pvHandls[i], stringTable); 561 } 562 attrdata["NumberOfDefaultValues"] = (int)defNum; 563 for (size_t i = 0; i < defIndices.size(); i++) 564 { 565 attrdata["DefaultValueStringHandleIndex[" + 566 std::to_string(i) + "]"] = (int)defIndices[i]; 567 attrdata["DefaultValueStringHandle"] = 568 displayStringHandle(pvHandls[defIndices[i]], 569 stringTable); 570 } 571 break; 572 } 573 case PLDM_BIOS_INTEGER: 574 case PLDM_BIOS_INTEGER_READ_ONLY: 575 { 576 uint64_t lower, upper, def; 577 uint32_t scalar; 578 pldm_bios_table_attr_entry_integer_decode( 579 entry, &lower, &upper, &scalar, &def); 580 attrdata["LowerBound"] = lower; 581 attrdata["UpperBound"] = upper; 582 attrdata["ScalarIncrement"] = scalar; 583 attrdata["DefaultValue"] = def; 584 break; 585 } 586 case PLDM_BIOS_STRING: 587 case PLDM_BIOS_STRING_READ_ONLY: 588 { 589 auto strType = 590 pldm_bios_table_attr_entry_string_decode_string_type( 591 entry); 592 auto min = 593 pldm_bios_table_attr_entry_string_decode_min_length( 594 entry); 595 auto max = 596 pldm_bios_table_attr_entry_string_decode_max_length( 597 entry); 598 auto def = 599 pldm_bios_table_attr_entry_string_decode_def_string_length( 600 entry); 601 std::vector<char> defString(def + 1); 602 pldm_bios_table_attr_entry_string_decode_def_string( 603 entry, defString.data(), defString.size()); 604 605 std::stringstream stringtype; 606 stringtype << "0x" << std::hex << std::setw(2) 607 << std::setfill('0') << (int)strType << std::dec 608 << std::setw(0); 609 attrdata["StringType"] = stringtype.str(); 610 attrdata["MinimumStringLength"] = (int)min; 611 attrdata["MaximumStringLength"] = (int)max; 612 attrdata["DefaultStringLength"] = (int)def; 613 attrdata["DefaultString"] = defString.data(); 614 break; 615 } 616 case PLDM_BIOS_PASSWORD: 617 case PLDM_BIOS_PASSWORD_READ_ONLY: 618 std::cout << "Password attribute: Not Supported" 619 << std::endl; 620 } 621 output.emplace_back(std::move(attrdata)); 622 } 623 pldmtool::helper::DisplayInJson(output); 624 } 625 void decodeAttributeValueTable(const std::optional<Table>& attrValTable, 626 const std::optional<Table>& attrTable, 627 const std::optional<Table>& stringTable) 628 { 629 if (!attrValTable) 630 { 631 std::cerr << "GetBIOSAttributeValueTable Error" << std::endl; 632 return; 633 } 634 ordered_json output; 635 for (auto tableEntry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>( 636 attrValTable->data(), attrValTable->size())) 637 { 638 ordered_json attrValueData; 639 displayAttributeValueEntry(tableEntry, attrTable, stringTable, true, 640 attrValueData); 641 output.emplace_back(attrValueData); 642 } 643 pldmtool::helper::DisplayInJson(output); 644 } 645 }; 646 647 class GetBIOSAttributeCurrentValueByHandle : public GetBIOSTableHandler 648 { 649 public: 650 ~GetBIOSAttributeCurrentValueByHandle() = default; 651 GetBIOSAttributeCurrentValueByHandle( 652 const GetBIOSAttributeCurrentValueByHandle&) = delete; 653 GetBIOSAttributeCurrentValueByHandle( 654 GetBIOSAttributeCurrentValueByHandle&&) = delete; 655 GetBIOSAttributeCurrentValueByHandle& 656 operator=(const GetBIOSAttributeCurrentValueByHandle&) = delete; 657 GetBIOSAttributeCurrentValueByHandle& 658 operator=(GetBIOSAttributeCurrentValueByHandle&&) = delete; 659 660 explicit GetBIOSAttributeCurrentValueByHandle(const char* type, 661 const char* name, 662 CLI::App* app) : 663 GetBIOSTableHandler(type, name, app) 664 { 665 app->add_option("-a, --attribute", attrName, "pldm BIOS attribute name") 666 ->required(); 667 } 668 669 void exec() 670 { 671 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 672 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 673 674 if (!stringTable || !attrTable) 675 { 676 std::cout << "StringTable/AttrTable Unavaliable" << std::endl; 677 return; 678 } 679 680 auto handle = findAttrHandleByName(attrName, *attrTable, *stringTable); 681 if (!handle) 682 { 683 684 std::cerr << "Can not find the attribute " << attrName << std::endl; 685 return; 686 } 687 688 std::vector<uint8_t> requestMsg( 689 sizeof(pldm_msg_hdr) + 690 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_REQ_BYTES); 691 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 692 693 auto rc = encode_get_bios_attribute_current_value_by_handle_req( 694 instanceId, 0, PLDM_GET_FIRSTPART, *handle, request); 695 if (rc != PLDM_SUCCESS) 696 { 697 std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl; 698 return; 699 } 700 701 std::vector<uint8_t> responseMsg; 702 rc = pldmSendRecv(requestMsg, responseMsg); 703 if (rc != PLDM_SUCCESS) 704 { 705 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl; 706 return; 707 } 708 709 uint8_t cc = 0, transferFlag = 0; 710 uint32_t nextTransferHandle = 0; 711 struct variable_field attributeData; 712 auto responsePtr = 713 reinterpret_cast<struct pldm_msg*>(responseMsg.data()); 714 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr); 715 716 rc = decode_get_bios_attribute_current_value_by_handle_resp( 717 responsePtr, payloadLength, &cc, &nextTransferHandle, &transferFlag, 718 &attributeData); 719 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 720 { 721 std::cerr << "Response Message Error: " 722 << "rc=" << rc << ",cc=" << (int)cc << std::endl; 723 return; 724 } 725 726 auto tableEntry = 727 reinterpret_cast<const struct pldm_bios_attr_val_table_entry*>( 728 attributeData.ptr); 729 730 ordered_json avdata; 731 displayAttributeValueEntry(tableEntry, attrTable, stringTable, false, 732 avdata); 733 pldmtool::helper::DisplayInJson(avdata); 734 } 735 736 private: 737 std::string attrName; 738 }; 739 740 class SetBIOSAttributeCurrentValue : public GetBIOSTableHandler 741 { 742 public: 743 ~SetBIOSAttributeCurrentValue() = default; 744 SetBIOSAttributeCurrentValue() = delete; 745 SetBIOSAttributeCurrentValue(const SetBIOSAttributeCurrentValue&) = delete; 746 SetBIOSAttributeCurrentValue(SetBIOSAttributeCurrentValue&&) = default; 747 SetBIOSAttributeCurrentValue& 748 operator=(const SetBIOSAttributeCurrentValue&) = delete; 749 SetBIOSAttributeCurrentValue& 750 operator=(SetBIOSAttributeCurrentValue&&) = default; 751 752 explicit SetBIOSAttributeCurrentValue(const char* type, const char* name, 753 CLI::App* app) : 754 GetBIOSTableHandler(type, name, app) 755 { 756 app->add_option("-a, --attribute", attrName, "pldm attribute name") 757 ->required(); 758 app->add_option("-d, --data", attrValue, "pldm attribute value") 759 ->required(); 760 // -v is conflict with --verbose in class CommandInterface, so used -d 761 } 762 763 void exec() 764 { 765 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 766 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 767 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 768 769 if (!stringTable || !attrTable) 770 { 771 std::cout << "StringTable/AttrTable Unavaliable" << std::endl; 772 return; 773 } 774 775 auto attrEntry = 776 findAttrEntryByName(attrName, *attrTable, *stringTable); 777 if (attrEntry == nullptr) 778 { 779 std::cout << "Could not find attribute :" << attrName << std::endl; 780 return; 781 } 782 783 std::vector<uint8_t> requestMsg; 784 785 int rc = 0; 786 auto attrType = attrEntry->attr_type; 787 size_t entryLength = 1; 788 std::vector<uint8_t> attrValueEntry(entryLength, 0); 789 790 switch (attrType) 791 { 792 case PLDM_BIOS_ENUMERATION_READ_ONLY: 793 case PLDM_BIOS_STRING_READ_ONLY: 794 case PLDM_BIOS_INTEGER_READ_ONLY: 795 { 796 std::cerr << "Set attribute error: " << attrName 797 << "is read only." << std::endl; 798 return; 799 } 800 case PLDM_BIOS_ENUMERATION: 801 { 802 entryLength = 803 pldm_bios_table_attr_value_entry_encode_enum_length(1); 804 auto pvNum = 805 pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry); 806 std::vector<uint16_t> pvHdls(pvNum, 0); 807 pldm_bios_table_attr_entry_enum_decode_pv_hdls( 808 attrEntry, pvHdls.data(), pvNum); 809 auto stringEntry = pldm_bios_table_string_find_by_string( 810 stringTable->data(), stringTable->size(), 811 attrValue.c_str()); 812 if (stringEntry == nullptr) 813 { 814 std::cout 815 << "Set Attribute Error: It's not a possible value" 816 << std::endl; 817 return; 818 } 819 auto valueHandle = 820 pldm_bios_table_string_entry_decode_handle(stringEntry); 821 822 uint8_t i; 823 for (i = 0; i < pvNum; i++) 824 { 825 if (valueHandle == pvHdls[i]) 826 break; 827 } 828 if (i == pvNum) 829 { 830 std::cout 831 << "Set Attribute Error: It's not a possible value" 832 << std::endl; 833 return; 834 } 835 836 attrValueEntry.resize(entryLength); 837 std::vector<uint8_t> handles = {i}; 838 pldm_bios_table_attr_value_entry_encode_enum( 839 attrValueEntry.data(), attrValueEntry.size(), 840 attrEntry->attr_handle, attrType, 1, handles.data()); 841 break; 842 } 843 case PLDM_BIOS_STRING: 844 { 845 entryLength = 846 pldm_bios_table_attr_value_entry_encode_string_length( 847 attrValue.size()); 848 849 attrValueEntry.resize(entryLength); 850 851 pldm_bios_table_attr_value_entry_encode_string( 852 attrValueEntry.data(), entryLength, attrEntry->attr_handle, 853 attrType, attrValue.size(), attrValue.c_str()); 854 break; 855 } 856 case PLDM_BIOS_INTEGER: 857 { 858 uint64_t value = std::stoll(attrValue); 859 entryLength = 860 pldm_bios_table_attr_value_entry_encode_integer_length(); 861 attrValueEntry.resize(entryLength); 862 pldm_bios_table_attr_value_entry_encode_integer( 863 attrValueEntry.data(), entryLength, attrEntry->attr_handle, 864 attrType, value); 865 break; 866 } 867 } 868 869 requestMsg.resize(entryLength + sizeof(pldm_msg_hdr) + 870 PLDM_SET_BIOS_ATTR_CURR_VAL_MIN_REQ_BYTES); 871 872 rc = encode_set_bios_attribute_current_value_req( 873 instanceId, 0, PLDM_START_AND_END, attrValueEntry.data(), 874 attrValueEntry.size(), 875 reinterpret_cast<pldm_msg*>(requestMsg.data()), 876 requestMsg.size() - sizeof(pldm_msg_hdr)); 877 878 if (rc != PLDM_SUCCESS) 879 { 880 std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl; 881 return; 882 } 883 std::vector<uint8_t> responseMsg; 884 rc = pldmSendRecv(requestMsg, responseMsg); 885 if (rc != PLDM_SUCCESS) 886 { 887 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl; 888 return; 889 } 890 uint8_t cc = 0; 891 uint32_t nextTransferHandle = 0; 892 auto responsePtr = 893 reinterpret_cast<struct pldm_msg*>(responseMsg.data()); 894 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr); 895 896 rc = decode_set_bios_attribute_current_value_resp( 897 responsePtr, payloadLength, &cc, &nextTransferHandle); 898 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 899 { 900 std::cerr << "Response Message Error: " 901 << "rc=" << rc << ",cc=" << (int)cc << std::endl; 902 return; 903 } 904 905 ordered_json data; 906 data["Response"] = "SUCCESS"; 907 pldmtool::helper::DisplayInJson(data); 908 } 909 910 private: 911 std::string attrName; 912 std::string attrValue; 913 }; 914 915 void registerCommand(CLI::App& app) 916 { 917 auto bios = app.add_subcommand("bios", "bios type command"); 918 bios->require_subcommand(1); 919 auto getDateTime = bios->add_subcommand("GetDateTime", "get date time"); 920 commands.push_back( 921 std::make_unique<GetDateTime>("bios", "GetDateTime", getDateTime)); 922 923 auto setDateTime = 924 bios->add_subcommand("SetDateTime", "set host date time"); 925 commands.push_back( 926 std::make_unique<SetDateTime>("bios", "setDateTime", setDateTime)); 927 928 auto getBIOSTable = bios->add_subcommand("GetBIOSTable", "get bios table"); 929 commands.push_back( 930 std::make_unique<GetBIOSTable>("bios", "GetBIOSTable", getBIOSTable)); 931 932 auto getBIOSAttributeCurrentValueByHandle = 933 bios->add_subcommand("GetBIOSAttributeCurrentValueByHandle", 934 "get bios attribute current value by handle"); 935 commands.push_back(std::make_unique<GetBIOSAttributeCurrentValueByHandle>( 936 "bios", "GetBIOSAttributeCurrentValueByHandle", 937 getBIOSAttributeCurrentValueByHandle)); 938 939 auto setBIOSAttributeCurrentValue = bios->add_subcommand( 940 "SetBIOSAttributeCurrentValue", "set bios attribute current value"); 941 commands.push_back(std::make_unique<SetBIOSAttributeCurrentValue>( 942 "bios", "SetBIOSAttributeCurrentValue", setBIOSAttributeCurrentValue)); 943 } 944 945 } // namespace bios 946 947 } // namespace pldmtool 948