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