1 #include "pldm_bios_cmd.hpp"
2
3 #include "common/bios_utils.hpp"
4 #include "common/utils.hpp"
5 #include "pldm_cmd_helper.hpp"
6
7 #include <libpldm/bios_table.h>
8 #include <libpldm/utils.h>
9
10 #include <map>
11 #include <optional>
12
13 namespace pldmtool
14 {
15
16 namespace bios
17 {
18
19 namespace
20 {
21
22 using namespace pldmtool::helper;
23 using namespace pldm::bios::utils;
24 using namespace pldm::utils;
25
26 std::vector<std::unique_ptr<CommandInterface>> commands;
27
28 const std::map<const char*, pldm_bios_table_types> pldmBIOSTableTypes{
29 {"StringTable", PLDM_BIOS_STRING_TABLE},
30 {"AttributeTable", PLDM_BIOS_ATTR_TABLE},
31 {"AttributeValueTable", PLDM_BIOS_ATTR_VAL_TABLE},
32 };
33
34 } // namespace
35
36 class GetDateTime : public CommandInterface
37 {
38 public:
39 ~GetDateTime() = default;
40 GetDateTime() = delete;
41 GetDateTime(const GetDateTime&) = delete;
42 GetDateTime(GetDateTime&&) = default;
43 GetDateTime& operator=(const GetDateTime&) = delete;
44 GetDateTime& operator=(GetDateTime&&) = delete;
45
46 using CommandInterface::CommandInterface;
47
createRequestMsg()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
parseResponseMsg(pldm_msg * responsePtr,size_t payloadLength)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:
setWidth(uint8_t data)83 static std::string setWidth(uint8_t data)
84 {
85 std::stringstream s;
86 s << std::setfill('0') << std::setw(2)
87 << static_cast<uint32_t>(bcd2dec8(data));
88 return s.str();
89 }
90 };
91
92 class SetDateTime : public CommandInterface
93 {
94 public:
95 ~SetDateTime() = default;
96 SetDateTime() = delete;
97 SetDateTime(const SetDateTime&) = delete;
98 SetDateTime(SetDateTime&&) = default;
99 SetDateTime& operator=(const SetDateTime&) = delete;
100 SetDateTime& operator=(SetDateTime&&) = delete;
101
SetDateTime(const char * type,const char * name,CLI::App * app)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
createRequestMsg()111 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
112 {
113 std::vector<uint8_t> requestMsg(
114 sizeof(pldm_msg_hdr) + 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
parseResponseMsg(pldm_msg * responsePtr,size_t payloadLength)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
createRequestMsg()189 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
190 {
191 return {PLDM_ERROR, {}};
192 }
193
parseResponseMsg(pldm_msg *,size_t)194 void parseResponseMsg(pldm_msg*, size_t) override {}
195
getBIOSTable(pldm_bios_table_types tableType)196 std::optional<Table> getBIOSTable(pldm_bios_table_types tableType)
197 {
198 std::vector<uint8_t> requestMsg(
199 sizeof(pldm_msg_hdr) + 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*
findAttrEntryByName(const std::string & name,const Table & attrTable,const Table & stringTable)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,const Table & attrTable,const Table & stringTable)270 findAttrHandleByName(const std::string& name, 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
decodeStringFromStringEntry(const pldm_bios_string_table_entry * stringEntry)282 std::string decodeStringFromStringEntry(
283 const pldm_bios_string_table_entry* stringEntry)
284 {
285 auto strLength =
286 pldm_bios_table_string_entry_decode_string_length(stringEntry);
287 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
288 // Preconditions are upheld therefore no error check necessary
289 pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(),
290 buffer.size());
291
292 return std::string(buffer.data(), buffer.data() + strLength);
293 }
294
displayStringHandle(uint16_t handle,const std::optional<Table> & stringTable,bool displayHandle=true)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
displayEnumValueByIndex(uint16_t attrHandle,uint8_t index,const std::optional<Table> & attrTable,const std::optional<Table> & stringTable)320 std::string displayEnumValueByIndex(uint16_t attrHandle, uint8_t index,
321 const std::optional<Table>& attrTable,
322 const std::optional<Table>& stringTable)
323 {
324 std::string displayString;
325 if (!attrTable)
326 {
327 return displayString;
328 }
329
330 auto attrEntry = pldm_bios_table_attr_find_by_handle(
331 attrTable->data(), attrTable->size(), attrHandle);
332 if (attrEntry == nullptr)
333 {
334 return displayString;
335 }
336 uint8_t pvNum;
337 int rc =
338 pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry, &pvNum);
339 if (rc != PLDM_SUCCESS)
340 {
341 return displayString;
342 }
343 std::vector<uint16_t> pvHandls(pvNum);
344 // Preconditions are upheld therefore no error check necessary
345 pldm_bios_table_attr_entry_enum_decode_pv_hdls(
346 attrEntry, pvHandls.data(), pvHandls.size());
347 return displayStringHandle(pvHandls[index], stringTable, false);
348 }
349
displayAttributeValueEntry(const pldm_bios_attr_val_table_entry * tableEntry,const std::optional<Table> & attrTable,const std::optional<Table> & stringTable,bool verbose,ordered_json & output)350 void displayAttributeValueEntry(
351 const pldm_bios_attr_val_table_entry* tableEntry,
352 const std::optional<Table>& attrTable,
353 const std::optional<Table>& stringTable, bool verbose,
354 ordered_json& output)
355 {
356 auto attrHandle =
357 pldm_bios_table_attr_value_entry_decode_attribute_handle(
358 tableEntry);
359 auto attrType = static_cast<pldm_bios_attribute_type>(
360 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
361
362 if (verbose)
363 {
364 output["AttributeHandle"] = attrHandle;
365 if (attrTypeMap.contains(attrType))
366 {
367 output["AttributeType"] = attrTypeMap.at(attrType);
368 }
369 else
370 {
371 std::cout << "Get AttributeType failed.\n";
372 }
373 }
374 switch (attrType)
375 {
376 case PLDM_BIOS_ENUMERATION:
377 case PLDM_BIOS_ENUMERATION_READ_ONLY:
378 {
379 auto count =
380 pldm_bios_table_attr_value_entry_enum_decode_number(
381 tableEntry);
382 std::vector<uint8_t> handles(count);
383 pldm_bios_table_attr_value_entry_enum_decode_handles(
384 tableEntry, handles.data(), handles.size());
385 if (verbose)
386 {
387 output["NumberOfCurrentValues"] = (int)count;
388 }
389 for (size_t i = 0; i < handles.size(); i++)
390 {
391 if (verbose)
392 {
393 output["CurrentValueStringHandleIndex[" +
394 std::to_string(i) + "]"] =
395 displayEnumValueByIndex(attrHandle, handles[i],
396 attrTable, stringTable);
397 }
398 else
399 {
400 output["CurrentValue"] = displayEnumValueByIndex(
401 attrHandle, handles[i], attrTable, stringTable);
402 }
403 }
404 break;
405 }
406 case PLDM_BIOS_INTEGER:
407 case PLDM_BIOS_INTEGER_READ_ONLY:
408 {
409 auto cv = pldm_bios_table_attr_value_entry_integer_decode_cv(
410 tableEntry);
411 output["CurrentValue"] = cv;
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&&) = delete;
453 GetBIOSTable& operator=(const GetBIOSTable&) = delete;
454 GetBIOSTable& operator=(GetBIOSTable&&) = delete;
455
456 using Table = std::vector<uint8_t>;
457
GetBIOSTable(const char * type,const char * name,CLI::App * app)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
exec()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
decodeStringTable(const std::optional<Table> & stringTable)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 }
decodeAttributeTable(const std::optional<Table> & attrTable,const std::optional<Table> & stringTable)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 uint8_t pvNum;
559 // Preconditions are upheld therefore no error check
560 // necessary
561 pldm_bios_table_attr_entry_enum_decode_pv_num(entry,
562 &pvNum);
563 std::vector<uint16_t> pvHandls(pvNum);
564 // Preconditions are upheld therefore no error check
565 // necessary
566 pldm_bios_table_attr_entry_enum_decode_pv_hdls(
567 entry, pvHandls.data(), pvHandls.size());
568 uint8_t defNum;
569 // Preconditions are upheld therefore no error check
570 // necessary
571 pldm_bios_table_attr_entry_enum_decode_def_num(entry,
572 &defNum);
573 std::vector<uint8_t> defIndices(defNum);
574 pldm_bios_table_attr_entry_enum_decode_def_indices(
575 entry, defIndices.data(), defIndices.size());
576
577 attrdata["NumberOfPossibleValues"] = (int)pvNum;
578
579 for (size_t i = 0; i < pvHandls.size(); i++)
580 {
581 attrdata["PossibleValueStringHandle[" +
582 std::to_string(i) + "]"] =
583 displayStringHandle(pvHandls[i], stringTable);
584 }
585 attrdata["NumberOfDefaultValues"] = (int)defNum;
586 for (size_t i = 0; i < defIndices.size(); i++)
587 {
588 attrdata["DefaultValueStringHandleIndex[" +
589 std::to_string(i) + "]"] = (int)defIndices[i];
590 attrdata["DefaultValueStringHandle"] =
591 displayStringHandle(pvHandls[defIndices[i]],
592 stringTable);
593 }
594 break;
595 }
596 case PLDM_BIOS_INTEGER:
597 case PLDM_BIOS_INTEGER_READ_ONLY:
598 {
599 uint64_t lower, upper, def;
600 uint32_t scalar;
601 pldm_bios_table_attr_entry_integer_decode(
602 entry, &lower, &upper, &scalar, &def);
603 attrdata["LowerBound"] = lower;
604 attrdata["UpperBound"] = upper;
605 attrdata["ScalarIncrement"] = scalar;
606 attrdata["DefaultValue"] = def;
607 break;
608 }
609 case PLDM_BIOS_STRING:
610 case PLDM_BIOS_STRING_READ_ONLY:
611 {
612 auto strType =
613 pldm_bios_table_attr_entry_string_decode_string_type(
614 entry);
615 auto min =
616 pldm_bios_table_attr_entry_string_decode_min_length(
617 entry);
618 auto max =
619 pldm_bios_table_attr_entry_string_decode_max_length(
620 entry);
621 uint16_t def;
622 // Preconditions are upheld therefore no error check
623 // necessary
624 pldm_bios_table_attr_entry_string_decode_def_string_length(
625 entry, &def);
626 std::vector<char> defString(def + 1);
627 pldm_bios_table_attr_entry_string_decode_def_string(
628 entry, defString.data(), defString.size());
629
630 std::stringstream stringtype;
631 stringtype
632 << "0x" << std::hex << std::setw(2) << std::setfill('0')
633 << (int)strType << std::dec << std::setw(0);
634 attrdata["StringType"] = stringtype.str();
635 attrdata["MinimumStringLength"] = (int)min;
636 attrdata["MaximumStringLength"] = (int)max;
637 attrdata["DefaultStringLength"] = (int)def;
638 attrdata["DefaultString"] = defString.data();
639 break;
640 }
641 case PLDM_BIOS_PASSWORD:
642 case PLDM_BIOS_PASSWORD_READ_ONLY:
643 std::cout
644 << "Password attribute: Not Supported" << std::endl;
645 }
646 output.emplace_back(std::move(attrdata));
647 }
648 pldmtool::helper::DisplayInJson(output);
649 }
decodeAttributeValueTable(const std::optional<Table> & attrValTable,const std::optional<Table> & attrTable,const std::optional<Table> & stringTable)650 void decodeAttributeValueTable(const std::optional<Table>& attrValTable,
651 const std::optional<Table>& attrTable,
652 const std::optional<Table>& stringTable)
653 {
654 if (!attrValTable)
655 {
656 std::cerr << "GetBIOSAttributeValueTable Error" << std::endl;
657 return;
658 }
659 ordered_json output;
660 for (auto tableEntry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
661 attrValTable->data(), attrValTable->size()))
662 {
663 ordered_json attrValueData;
664 displayAttributeValueEntry(tableEntry, attrTable, stringTable, true,
665 attrValueData);
666 output.emplace_back(attrValueData);
667 }
668 pldmtool::helper::DisplayInJson(output);
669 }
670 };
671
672 class GetBIOSAttributeCurrentValueByHandle : public GetBIOSTableHandler
673 {
674 public:
675 ~GetBIOSAttributeCurrentValueByHandle() = default;
676 GetBIOSAttributeCurrentValueByHandle(
677 const GetBIOSAttributeCurrentValueByHandle&) = delete;
678 GetBIOSAttributeCurrentValueByHandle(
679 GetBIOSAttributeCurrentValueByHandle&&) = delete;
680 GetBIOSAttributeCurrentValueByHandle&
681 operator=(const GetBIOSAttributeCurrentValueByHandle&) = delete;
682 GetBIOSAttributeCurrentValueByHandle&
683 operator=(GetBIOSAttributeCurrentValueByHandle&&) = delete;
684
GetBIOSAttributeCurrentValueByHandle(const char * type,const char * name,CLI::App * app)685 explicit GetBIOSAttributeCurrentValueByHandle(
686 const char* type, const char* name, CLI::App* app) :
687 GetBIOSTableHandler(type, name, app)
688 {
689 app->add_option("-a, --attribute", attrName, "pldm BIOS attribute name")
690 ->required();
691 }
692
exec()693 void exec()
694 {
695 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
696 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
697
698 if (!stringTable || !attrTable)
699 {
700 std::cout << "StringTable/AttrTable Unavailable" << std::endl;
701 return;
702 }
703
704 auto handle = findAttrHandleByName(attrName, *attrTable, *stringTable);
705 if (!handle)
706 {
707 std::cerr << "Can not find the attribute " << attrName << std::endl;
708 return;
709 }
710
711 std::vector<uint8_t> requestMsg(
712 sizeof(pldm_msg_hdr) +
713 PLDM_GET_BIOS_ATTR_CURR_VAL_BY_HANDLE_REQ_BYTES);
714 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
715
716 auto rc = encode_get_bios_attribute_current_value_by_handle_req(
717 instanceId, 0, PLDM_GET_FIRSTPART, *handle, request);
718 if (rc != PLDM_SUCCESS)
719 {
720 std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl;
721 return;
722 }
723
724 std::vector<uint8_t> responseMsg;
725 rc = pldmSendRecv(requestMsg, responseMsg);
726 if (rc != PLDM_SUCCESS)
727 {
728 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl;
729 return;
730 }
731
732 uint8_t cc = 0, transferFlag = 0;
733 uint32_t nextTransferHandle = 0;
734 struct variable_field attributeData;
735 auto responsePtr =
736 reinterpret_cast<struct pldm_msg*>(responseMsg.data());
737 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr);
738
739 rc = decode_get_bios_attribute_current_value_by_handle_resp(
740 responsePtr, payloadLength, &cc, &nextTransferHandle, &transferFlag,
741 &attributeData);
742 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
743 {
744 std::cerr << "Response Message Error: "
745 << "rc=" << rc << ",cc=" << (int)cc << std::endl;
746 return;
747 }
748
749 auto tableEntry =
750 reinterpret_cast<const struct pldm_bios_attr_val_table_entry*>(
751 attributeData.ptr);
752
753 ordered_json avdata;
754 displayAttributeValueEntry(tableEntry, attrTable, stringTable, false,
755 avdata);
756 pldmtool::helper::DisplayInJson(avdata);
757 }
758
759 private:
760 std::string attrName;
761 };
762
763 class SetBIOSAttributeCurrentValue : public GetBIOSTableHandler
764 {
765 public:
766 ~SetBIOSAttributeCurrentValue() = default;
767 SetBIOSAttributeCurrentValue() = delete;
768 SetBIOSAttributeCurrentValue(const SetBIOSAttributeCurrentValue&) = delete;
769 SetBIOSAttributeCurrentValue(SetBIOSAttributeCurrentValue&&) = delete;
770 SetBIOSAttributeCurrentValue&
771 operator=(const SetBIOSAttributeCurrentValue&) = delete;
772 SetBIOSAttributeCurrentValue&
773 operator=(SetBIOSAttributeCurrentValue&&) = delete;
774
SetBIOSAttributeCurrentValue(const char * type,const char * name,CLI::App * app)775 explicit SetBIOSAttributeCurrentValue(const char* type, const char* name,
776 CLI::App* app) :
777 GetBIOSTableHandler(type, name, app)
778 {
779 app->add_option("-a, --attribute", attrName, "pldm attribute name")
780 ->required();
781 app->add_option("-d, --data", attrValue, "pldm attribute value")
782 ->required();
783 // -v is conflict with --verbose in class CommandInterface, so used -d
784 }
785
exec()786 void exec()
787 {
788 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
789 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
790 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
791
792 if (!stringTable || !attrTable)
793 {
794 std::cout << "StringTable/AttrTable Unavailable" << std::endl;
795 return;
796 }
797
798 auto attrEntry =
799 findAttrEntryByName(attrName, *attrTable, *stringTable);
800 if (attrEntry == nullptr)
801 {
802 std::cout << "Could not find attribute :" << attrName << std::endl;
803 return;
804 }
805
806 std::vector<uint8_t> requestMsg;
807
808 int rc = 0;
809 auto attrType = attrEntry->attr_type;
810 size_t entryLength = 1;
811 std::vector<uint8_t> attrValueEntry(entryLength, 0);
812
813 switch (attrType)
814 {
815 case PLDM_BIOS_ENUMERATION:
816 case PLDM_BIOS_ENUMERATION_READ_ONLY:
817 {
818 entryLength =
819 pldm_bios_table_attr_value_entry_encode_enum_length(1);
820 uint8_t pvNum;
821 // Preconditions are upheld therefore no error check necessary
822 pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry,
823 &pvNum);
824 std::vector<uint16_t> pvHdls(pvNum, 0);
825 // Preconditions are upheld therefore no error check necessary
826 pldm_bios_table_attr_entry_enum_decode_pv_hdls(
827 attrEntry, pvHdls.data(), pvNum);
828 auto stringEntry = pldm_bios_table_string_find_by_string(
829 stringTable->data(), stringTable->size(),
830 attrValue.c_str());
831 if (stringEntry == nullptr)
832 {
833 std::cout
834 << "Set Attribute Error: It's not a possible value"
835 << std::endl;
836 return;
837 }
838 auto valueHandle =
839 pldm_bios_table_string_entry_decode_handle(stringEntry);
840
841 uint8_t i;
842 for (i = 0; i < pvNum; i++)
843 {
844 if (valueHandle == pvHdls[i])
845 break;
846 }
847 if (i == pvNum)
848 {
849 std::cout
850 << "Set Attribute Error: It's not a possible value"
851 << std::endl;
852 return;
853 }
854
855 attrValueEntry.resize(entryLength);
856 std::vector<uint8_t> handles = {i};
857 int rc = pldm_bios_table_attr_value_entry_encode_enum(
858 attrValueEntry.data(), attrValueEntry.size(),
859 attrEntry->attr_handle, attrType, 1, handles.data());
860 if (rc != PLDM_SUCCESS)
861 {
862 std::cout
863 << "Failed to encode BIOS table attribute enum: " << rc
864 << std::endl;
865 return;
866 }
867 break;
868 }
869 case PLDM_BIOS_STRING:
870 case PLDM_BIOS_STRING_READ_ONLY:
871 {
872 entryLength =
873 pldm_bios_table_attr_value_entry_encode_string_length(
874 attrValue.size());
875
876 attrValueEntry.resize(entryLength);
877
878 int rc = pldm_bios_table_attr_value_entry_encode_string(
879 attrValueEntry.data(), entryLength, attrEntry->attr_handle,
880 attrType, attrValue.size(), attrValue.c_str());
881 if (rc != PLDM_SUCCESS)
882 {
883 std::cout
884 << "Failed to encode BIOS table attribute string: "
885 << rc << std::endl;
886 return;
887 }
888 break;
889 }
890 case PLDM_BIOS_INTEGER:
891 case PLDM_BIOS_INTEGER_READ_ONLY:
892 {
893 uint64_t value = std::stoll(attrValue);
894 entryLength =
895 pldm_bios_table_attr_value_entry_encode_integer_length();
896 attrValueEntry.resize(entryLength);
897 int rc = pldm_bios_table_attr_value_entry_encode_integer(
898 attrValueEntry.data(), entryLength, attrEntry->attr_handle,
899 attrType, value);
900 if (rc != PLDM_SUCCESS)
901 {
902 std::cout
903 << "Failed to encode BIOS table attribute integer: "
904 << rc << std::endl;
905 return;
906 }
907 break;
908 }
909 }
910
911 requestMsg.resize(entryLength + sizeof(pldm_msg_hdr) +
912 PLDM_SET_BIOS_ATTR_CURR_VAL_MIN_REQ_BYTES);
913
914 rc = encode_set_bios_attribute_current_value_req(
915 instanceId, 0, PLDM_START_AND_END, attrValueEntry.data(),
916 attrValueEntry.size(),
917 reinterpret_cast<pldm_msg*>(requestMsg.data()),
918 requestMsg.size() - sizeof(pldm_msg_hdr));
919
920 if (rc != PLDM_SUCCESS)
921 {
922 std::cerr << "PLDM: Request Message Error, rc =" << rc << std::endl;
923 return;
924 }
925 std::vector<uint8_t> responseMsg;
926 rc = pldmSendRecv(requestMsg, responseMsg);
927 if (rc != PLDM_SUCCESS)
928 {
929 std::cerr << "PLDM: Communication Error, rc =" << rc << std::endl;
930 return;
931 }
932 uint8_t cc = 0;
933 uint32_t nextTransferHandle = 0;
934 auto responsePtr =
935 reinterpret_cast<struct pldm_msg*>(responseMsg.data());
936 auto payloadLength = responseMsg.size() - sizeof(pldm_msg_hdr);
937
938 rc = decode_set_bios_attribute_current_value_resp(
939 responsePtr, payloadLength, &cc, &nextTransferHandle);
940 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
941 {
942 std::cerr << "Response Message Error: "
943 << "rc=" << rc << ",cc=" << (int)cc << std::endl;
944 return;
945 }
946
947 ordered_json data;
948 data["Response"] = "SUCCESS";
949 pldmtool::helper::DisplayInJson(data);
950 }
951
952 private:
953 std::string attrName;
954 std::string attrValue;
955 };
956
registerCommand(CLI::App & app)957 void registerCommand(CLI::App& app)
958 {
959 auto bios = app.add_subcommand("bios", "bios type command");
960 bios->require_subcommand(1);
961 auto getDateTime = bios->add_subcommand("GetDateTime", "get date time");
962 commands.push_back(
963 std::make_unique<GetDateTime>("bios", "GetDateTime", getDateTime));
964
965 auto setDateTime =
966 bios->add_subcommand("SetDateTime", "set host date time");
967 commands.push_back(
968 std::make_unique<SetDateTime>("bios", "setDateTime", setDateTime));
969
970 auto getBIOSTable = bios->add_subcommand("GetBIOSTable", "get bios table");
971 commands.push_back(
972 std::make_unique<GetBIOSTable>("bios", "GetBIOSTable", getBIOSTable));
973
974 auto getBIOSAttributeCurrentValueByHandle =
975 bios->add_subcommand("GetBIOSAttributeCurrentValueByHandle",
976 "get bios attribute current value by handle");
977 commands.push_back(std::make_unique<GetBIOSAttributeCurrentValueByHandle>(
978 "bios", "GetBIOSAttributeCurrentValueByHandle",
979 getBIOSAttributeCurrentValueByHandle));
980
981 auto setBIOSAttributeCurrentValue = bios->add_subcommand(
982 "SetBIOSAttributeCurrentValue", "set bios attribute current value");
983 commands.push_back(std::make_unique<SetBIOSAttributeCurrentValue>(
984 "bios", "SetBIOSAttributeCurrentValue", setBIOSAttributeCurrentValue));
985 }
986
987 } // namespace bios
988
989 } // namespace pldmtool
990