xref: /openbmc/pldm/pldmtool/pldm_fru_cmd.cpp (revision 71689b8ba313755077b102bb8d01ccb7ab0cbd48)
1f7f5da97SDeepak Kodihalli #include "pldm_fru_cmd.hpp"
2f7f5da97SDeepak Kodihalli 
3f7f5da97SDeepak Kodihalli #include "pldm_cmd_helper.hpp"
4f7f5da97SDeepak Kodihalli 
5b8baffa3SSridevi Ramesh #ifdef OEM_IBM
6c453e164SGeorge Liu #include <libpldm/fru_oem_ibm.h>
7b8baffa3SSridevi Ramesh #endif
8b8baffa3SSridevi Ramesh 
95bdde3a4SJohn Wang #include <endian.h>
105bdde3a4SJohn Wang 
115bdde3a4SJohn Wang #include <functional>
125bdde3a4SJohn Wang #include <tuple>
135bdde3a4SJohn Wang 
14f7f5da97SDeepak Kodihalli namespace pldmtool
15f7f5da97SDeepak Kodihalli {
16f7f5da97SDeepak Kodihalli 
17f7f5da97SDeepak Kodihalli namespace fru
18f7f5da97SDeepak Kodihalli {
19f7f5da97SDeepak Kodihalli 
20f7f5da97SDeepak Kodihalli namespace
21f7f5da97SDeepak Kodihalli {
22f7f5da97SDeepak Kodihalli 
23f7f5da97SDeepak Kodihalli using namespace pldmtool::helper;
24f7f5da97SDeepak Kodihalli 
25f7f5da97SDeepak Kodihalli std::vector<std::unique_ptr<CommandInterface>> commands;
26f7f5da97SDeepak Kodihalli 
27f7f5da97SDeepak Kodihalli } // namespace
28f7f5da97SDeepak Kodihalli 
29f7f5da97SDeepak Kodihalli class GetFruRecordTableMetadata : public CommandInterface
30f7f5da97SDeepak Kodihalli {
31f7f5da97SDeepak Kodihalli   public:
32f7f5da97SDeepak Kodihalli     ~GetFruRecordTableMetadata() = default;
33f7f5da97SDeepak Kodihalli     GetFruRecordTableMetadata() = delete;
34f7f5da97SDeepak Kodihalli     GetFruRecordTableMetadata(const GetFruRecordTableMetadata&) = delete;
35f7f5da97SDeepak Kodihalli     GetFruRecordTableMetadata(GetFruRecordTableMetadata&&) = default;
36f7f5da97SDeepak Kodihalli     GetFruRecordTableMetadata&
37f7f5da97SDeepak Kodihalli         operator=(const GetFruRecordTableMetadata&) = delete;
38f7f5da97SDeepak Kodihalli     GetFruRecordTableMetadata& operator=(GetFruRecordTableMetadata&&) = default;
39f7f5da97SDeepak Kodihalli 
40f7f5da97SDeepak Kodihalli     using CommandInterface::CommandInterface;
41f7f5da97SDeepak Kodihalli 
42f7f5da97SDeepak Kodihalli     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
43f7f5da97SDeepak Kodihalli     {
44f7f5da97SDeepak Kodihalli         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr));
45f7f5da97SDeepak Kodihalli         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
46f7f5da97SDeepak Kodihalli 
47f7f5da97SDeepak Kodihalli         auto rc = encode_get_fru_record_table_metadata_req(
48f7f5da97SDeepak Kodihalli             instanceId, request, PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES);
49f7f5da97SDeepak Kodihalli         return {rc, requestMsg};
50f7f5da97SDeepak Kodihalli     }
51f7f5da97SDeepak Kodihalli 
52f7f5da97SDeepak Kodihalli     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
53f7f5da97SDeepak Kodihalli     {
54f7f5da97SDeepak Kodihalli         uint8_t cc = 0;
55f7f5da97SDeepak Kodihalli         uint8_t fru_data_major_version, fru_data_minor_version;
56f7f5da97SDeepak Kodihalli         uint32_t fru_table_maximum_size, fru_table_length;
57f7f5da97SDeepak Kodihalli         uint16_t total_record_set_identifiers, total_table_records;
58f7f5da97SDeepak Kodihalli         uint32_t checksum;
59f7f5da97SDeepak Kodihalli 
60f7f5da97SDeepak Kodihalli         auto rc = decode_get_fru_record_table_metadata_resp(
61f7f5da97SDeepak Kodihalli             responsePtr, payloadLength, &cc, &fru_data_major_version,
62f7f5da97SDeepak Kodihalli             &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
63f7f5da97SDeepak Kodihalli             &total_record_set_identifiers, &total_table_records, &checksum);
64f7f5da97SDeepak Kodihalli         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
65f7f5da97SDeepak Kodihalli         {
66f7f5da97SDeepak Kodihalli             std::cerr << "Response Message Error: "
67f7f5da97SDeepak Kodihalli                       << "rc=" << rc << ",cc=" << (int)cc << std::endl;
68f7f5da97SDeepak Kodihalli             return;
69f7f5da97SDeepak Kodihalli         }
70dd04990dSSridevi Ramesh         ordered_json output;
71dd04990dSSridevi Ramesh         output["FRUDATAMajorVersion"] =
72dd04990dSSridevi Ramesh             static_cast<uint32_t>(fru_data_major_version);
73dd04990dSSridevi Ramesh         output["FRUDATAMinorVersion"] =
74dd04990dSSridevi Ramesh             static_cast<uint32_t>(fru_data_minor_version);
75dd04990dSSridevi Ramesh         output["FRUTableMaximumSize"] = fru_table_maximum_size;
76dd04990dSSridevi Ramesh         output["FRUTableLength"] = fru_table_length;
77dd04990dSSridevi Ramesh         output["Total number of Record Set Identifiers in table"] =
78dd04990dSSridevi Ramesh             total_record_set_identifiers;
79dd04990dSSridevi Ramesh         output["Total number of records in table"] = total_table_records;
80dd04990dSSridevi Ramesh         output["FRU DATAStructureTableIntegrityChecksum"] = checksum;
81dd04990dSSridevi Ramesh         pldmtool::helper::DisplayInJson(output);
82f7f5da97SDeepak Kodihalli     }
83f7f5da97SDeepak Kodihalli };
84f7f5da97SDeepak Kodihalli 
855bdde3a4SJohn Wang class FRUTablePrint
865bdde3a4SJohn Wang {
875bdde3a4SJohn Wang   public:
885bdde3a4SJohn Wang     explicit FRUTablePrint(const uint8_t* table, size_t table_size) :
895bdde3a4SJohn Wang         table(table), table_size(table_size)
905bdde3a4SJohn Wang     {}
915bdde3a4SJohn Wang 
925bdde3a4SJohn Wang     void print()
935bdde3a4SJohn Wang     {
945bdde3a4SJohn Wang         auto p = table;
95dd04990dSSridevi Ramesh         ordered_json frutable;
96dd04990dSSridevi Ramesh         ordered_json output;
975bdde3a4SJohn Wang         while (!isTableEnd(p))
985bdde3a4SJohn Wang         {
995bdde3a4SJohn Wang             auto record =
1005bdde3a4SJohn Wang                 reinterpret_cast<const pldm_fru_record_data_format*>(p);
101dd04990dSSridevi Ramesh             output["FRU Record Set Identifier"] =
102dd04990dSSridevi Ramesh                 (int)le16toh(record->record_set_id);
103dd04990dSSridevi Ramesh             output["FRU Record Type"] =
104dd04990dSSridevi Ramesh                 typeToString(fruRecordTypes, record->record_type);
105dd04990dSSridevi Ramesh             output["Number of FRU fields"] = (int)record->num_fru_fields;
106dd04990dSSridevi Ramesh             output["Encoding Type for FRU fields"] =
107dd04990dSSridevi Ramesh                 typeToString(fruEncodingType, record->encoding_type);
1085bdde3a4SJohn Wang 
1095bdde3a4SJohn Wang             p += sizeof(pldm_fru_record_data_format) -
1105bdde3a4SJohn Wang                  sizeof(pldm_fru_record_tlv);
111b8baffa3SSridevi Ramesh 
112b8baffa3SSridevi Ramesh             std::map<uint8_t, std::string> FruFieldTypeMap;
113b8baffa3SSridevi Ramesh             std::string fruFieldValue;
114b8baffa3SSridevi Ramesh 
115dd04990dSSridevi Ramesh             ordered_json frudata;
116dd04990dSSridevi Ramesh             ordered_json frufielddata;
117dd04990dSSridevi Ramesh             frufielddata.emplace_back(output);
1185bdde3a4SJohn Wang             for (int i = 0; i < record->num_fru_fields; i++)
1195bdde3a4SJohn Wang             {
1205bdde3a4SJohn Wang                 auto tlv = reinterpret_cast<const pldm_fru_record_tlv*>(p);
121b8baffa3SSridevi Ramesh                 if (record->record_type == PLDM_FRU_RECORD_TYPE_GENERAL)
1225bdde3a4SJohn Wang                 {
123b8baffa3SSridevi Ramesh                     FruFieldTypeMap.insert(fruGeneralFieldTypes.begin(),
124b8baffa3SSridevi Ramesh                                            fruGeneralFieldTypes.end());
125b8baffa3SSridevi Ramesh                     if (tlv->type == PLDM_FRU_FIELD_TYPE_IANA)
126b8baffa3SSridevi Ramesh                     {
127b8baffa3SSridevi Ramesh                         fruFieldValue =
128b8baffa3SSridevi Ramesh                             fruFieldParserU32(tlv->value, tlv->length);
1295bdde3a4SJohn Wang                     }
130b8baffa3SSridevi Ramesh                     else if (tlv->type == PLDM_FRU_FIELD_TYPE_MANUFAC_DATE)
131b8baffa3SSridevi Ramesh                     {
132b8baffa3SSridevi Ramesh                         fruFieldValue =
133b8baffa3SSridevi Ramesh                             fruFieldParserTimestamp(tlv->value, tlv->length);
134b8baffa3SSridevi Ramesh                     }
135*71689b8bSPotin Lai                     else
136*71689b8bSPotin Lai                     {
137*71689b8bSPotin Lai                         fruFieldValue =
138*71689b8bSPotin Lai                             fruFieldValuestring(tlv->value, tlv->length);
139*71689b8bSPotin Lai                     }
140c50c6cd7SSridevi Ramesh 
141c50c6cd7SSridevi Ramesh                     frudata["FRU Field Type"] =
142c50c6cd7SSridevi Ramesh                         typeToString(FruFieldTypeMap, tlv->type);
143c50c6cd7SSridevi Ramesh                     frudata["FRU Field Length"] = (int)(tlv->length);
144c50c6cd7SSridevi Ramesh                     frudata["FRU Field Value"] = fruFieldValue;
145c50c6cd7SSridevi Ramesh                     frufielddata.emplace_back(frudata);
146b8baffa3SSridevi Ramesh                 }
147b8baffa3SSridevi Ramesh                 else
148b8baffa3SSridevi Ramesh                 {
149b8baffa3SSridevi Ramesh #ifdef OEM_IBM
150b8baffa3SSridevi Ramesh                     if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_RT)
151b8baffa3SSridevi Ramesh                     {
152b8baffa3SSridevi Ramesh                         auto oemIPZValue =
153b8baffa3SSridevi Ramesh                             fruFieldValuestring(tlv->value, tlv->length);
154b8baffa3SSridevi Ramesh 
155b8baffa3SSridevi Ramesh                         if (populateMaps.find(oemIPZValue) !=
156b8baffa3SSridevi Ramesh                             populateMaps.end())
157b8baffa3SSridevi Ramesh                         {
158b8baffa3SSridevi Ramesh                             const std::map<uint8_t, std::string> IPZTypes =
159b8baffa3SSridevi Ramesh                                 populateMaps.at(oemIPZValue);
160b8baffa3SSridevi Ramesh                             FruFieldTypeMap.insert(IPZTypes.begin(),
161b8baffa3SSridevi Ramesh                                                    IPZTypes.end());
162b8baffa3SSridevi Ramesh                         }
163b8baffa3SSridevi Ramesh                     }
164b8baffa3SSridevi Ramesh                     else
165b8baffa3SSridevi Ramesh                     {
166b8baffa3SSridevi Ramesh                         FruFieldTypeMap.insert(fruOemFieldTypes.begin(),
167b8baffa3SSridevi Ramesh                                                fruOemFieldTypes.end());
168b8baffa3SSridevi Ramesh                     }
169b8baffa3SSridevi Ramesh                     if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_IANA)
170b8baffa3SSridevi Ramesh                     {
171b8baffa3SSridevi Ramesh                         fruFieldValue =
172b8baffa3SSridevi Ramesh                             fruFieldParserU32(tlv->value, tlv->length);
173b8baffa3SSridevi Ramesh                     }
174c50c6cd7SSridevi Ramesh                     else if (tlv->type != 2)
175b8baffa3SSridevi Ramesh                     {
176c50c6cd7SSridevi Ramesh                         fruFieldValue =
177c50c6cd7SSridevi Ramesh                             fruFieldIPZParser(tlv->value, tlv->length);
178b8baffa3SSridevi Ramesh                     }
179b8baffa3SSridevi Ramesh                     else
180b8baffa3SSridevi Ramesh                     {
181b8baffa3SSridevi Ramesh                         fruFieldValue =
182b8baffa3SSridevi Ramesh                             fruFieldValuestring(tlv->value, tlv->length);
183b8baffa3SSridevi Ramesh                     }
184dd04990dSSridevi Ramesh                     frudata["FRU Field Type"] =
185dd04990dSSridevi Ramesh                         typeToString(FruFieldTypeMap, tlv->type);
186dd04990dSSridevi Ramesh                     frudata["FRU Field Length"] = (int)(tlv->length);
187dd04990dSSridevi Ramesh                     frudata["FRU Field Value"] = fruFieldValue;
188dd04990dSSridevi Ramesh                     frufielddata.emplace_back(frudata);
189c50c6cd7SSridevi Ramesh 
190c50c6cd7SSridevi Ramesh #endif
191c50c6cd7SSridevi Ramesh                 }
1925bdde3a4SJohn Wang                 p += sizeof(pldm_fru_record_tlv) - 1 + tlv->length;
1935bdde3a4SJohn Wang             }
194dd04990dSSridevi Ramesh             frutable.emplace_back(frufielddata);
1955bdde3a4SJohn Wang         }
196dd04990dSSridevi Ramesh         pldmtool::helper::DisplayInJson(frutable);
1975bdde3a4SJohn Wang     }
1985bdde3a4SJohn Wang 
1995bdde3a4SJohn Wang   private:
2005bdde3a4SJohn Wang     const uint8_t* table;
2015bdde3a4SJohn Wang     size_t table_size;
2025bdde3a4SJohn Wang 
2035bdde3a4SJohn Wang     bool isTableEnd(const uint8_t* p)
2045bdde3a4SJohn Wang     {
2055bdde3a4SJohn Wang         auto offset = p - table;
2065bdde3a4SJohn Wang         return (table_size - offset) <= 7;
2075bdde3a4SJohn Wang     }
2085bdde3a4SJohn Wang 
209b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruEncodingType{
2105bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UNSPECIFIED, "Unspecified"},
2115bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_ASCII, "ASCII"},
2125bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF8, "UTF8"},
2135bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF16, "UTF16"},
2145bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF16LE, "UTF16LE"},
2155bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF16BE, "UTF16BE"}};
2165bdde3a4SJohn Wang 
217b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruGeneralFieldTypes{
218b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_CHASSIS, "Chassis"},
219b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_MODEL, "Model"},
220b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_PN, "Part Number"},
221b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_SN, "Serial Number"},
222b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_MANUFAC, "Manufacturer"},
223b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_MANUFAC_DATE, "Manufacture Date"},
224b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_VENDOR, "Vendor"},
225b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_NAME, "Name"},
226b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_SKU, "SKU"},
227b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_VERSION, "Version"},
228b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_ASSET_TAG, "Asset Tag"},
229b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_DESC, "Description"},
230b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_EC_LVL, "Engineering Change Level"},
231b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_OTHER, "Other Information"},
232b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_IANA, "Vendor IANA"}};
233b8baffa3SSridevi Ramesh 
234b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruRecordTypes{
2355bdde3a4SJohn Wang         {PLDM_FRU_RECORD_TYPE_GENERAL, "General"},
2365bdde3a4SJohn Wang         {PLDM_FRU_RECORD_TYPE_OEM, "OEM"}};
2375bdde3a4SJohn Wang 
238b8baffa3SSridevi Ramesh #ifdef OEM_IBM
239b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruOemFieldTypes{
240b8baffa3SSridevi Ramesh         {PLDM_OEM_FRU_FIELD_TYPE_IANA, "Vendor IANA"},
241b8baffa3SSridevi Ramesh         {PLDM_OEM_FRU_FIELD_TYPE_RT, "RT"},
242b8baffa3SSridevi Ramesh         {PLDM_OEM_FRU_FIELD_TYPE_LOCATION_CODE, "Location Code"}};
243b8baffa3SSridevi Ramesh 
244b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VINIFieldTypes{
245b8baffa3SSridevi Ramesh         {2, "RT"},  {3, "B3"},  {4, "B4"},  {5, "B7"},  {6, "CC"},  {7, "CE"},
246b8baffa3SSridevi Ramesh         {8, "CT"},  {9, "DR"},  {10, "FG"}, {11, "FN"}, {12, "HE"}, {13, "HW"},
247b8baffa3SSridevi Ramesh         {14, "HX"}, {15, "PN"}, {16, "SN"}, {17, "TS"}, {18, "VZ"}};
248b8baffa3SSridevi Ramesh 
249b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VSYSFieldTypes{
250b8baffa3SSridevi Ramesh         {2, "RT"},  {3, "BR"},  {4, "DR"},  {5, "FV"},  {6, "ID"},
251b8baffa3SSridevi Ramesh         {7, "MN"},  {8, "NN"},  {9, "RB"},  {10, "RG"}, {11, "SE"},
252b8baffa3SSridevi Ramesh         {12, "SG"}, {13, "SU"}, {14, "TM"}, {15, "TN"}, {16, "WN"}};
253b8baffa3SSridevi Ramesh 
254b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> LXR0FieldTypes{
255b8baffa3SSridevi Ramesh         {2, "RT"}, {3, "LX"}, {4, "VZ"}};
256b8baffa3SSridevi Ramesh 
257b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VW10FieldTypes{
258b8baffa3SSridevi Ramesh         {2, "RT"}, {3, "DR"}, {4, "GD"}};
259b8baffa3SSridevi Ramesh 
260b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VR10FieldTypes{
261b8baffa3SSridevi Ramesh         {2, "RT"}, {3, "DC"}, {4, "DR"}, {5, "FL"}, {6, "WA"}};
262b8baffa3SSridevi Ramesh 
263b8baffa3SSridevi Ramesh     static inline const std::map<std::string,
264b8baffa3SSridevi Ramesh                                  const std::map<uint8_t, std::string>>
265b8baffa3SSridevi Ramesh         populateMaps{{"VINI", VINIFieldTypes},
266b8baffa3SSridevi Ramesh                      {"VSYS", VSYSFieldTypes},
267b8baffa3SSridevi Ramesh                      {"LXR0", LXR0FieldTypes},
268b8baffa3SSridevi Ramesh                      {"VWX10", VW10FieldTypes},
269b8baffa3SSridevi Ramesh                      {"VR10", VR10FieldTypes}};
270b8baffa3SSridevi Ramesh #endif
271b8baffa3SSridevi Ramesh 
272b8baffa3SSridevi Ramesh     std::string typeToString(std::map<uint8_t, std::string> typeMap,
2735bdde3a4SJohn Wang                              uint8_t type)
2745bdde3a4SJohn Wang     {
2755bdde3a4SJohn Wang         auto typeString = std::to_string(type);
2765bdde3a4SJohn Wang         try
2775bdde3a4SJohn Wang         {
278b8baffa3SSridevi Ramesh             return std::string(typeMap.at(type)) + "(" + typeString + ")";
2795bdde3a4SJohn Wang         }
2805bdde3a4SJohn Wang         catch (const std::out_of_range& e)
2815bdde3a4SJohn Wang         {
2825bdde3a4SJohn Wang             return typeString;
2835bdde3a4SJohn Wang         }
2845bdde3a4SJohn Wang     }
2855bdde3a4SJohn Wang 
286b8baffa3SSridevi Ramesh     std::string fruFieldValuestring(const uint8_t* value, uint8_t length)
2875bdde3a4SJohn Wang     {
2885bdde3a4SJohn Wang         return std::string(reinterpret_cast<const char*>(value), length);
2895bdde3a4SJohn Wang     }
2905bdde3a4SJohn Wang 
2915bdde3a4SJohn Wang     static std::string fruFieldParserU32(const uint8_t* value, uint8_t length)
2925bdde3a4SJohn Wang     {
2935bdde3a4SJohn Wang         assert(length == 4);
2945bdde3a4SJohn Wang         uint32_t v;
2955bdde3a4SJohn Wang         std::memcpy(&v, value, length);
2965bdde3a4SJohn Wang         return std::to_string(le32toh(v));
2975bdde3a4SJohn Wang     }
2985bdde3a4SJohn Wang 
299b8baffa3SSridevi Ramesh     static std::string fruFieldParserTimestamp(const uint8_t*, uint8_t)
3005bdde3a4SJohn Wang     {
301b8baffa3SSridevi Ramesh         return std::string("TODO");
302b8baffa3SSridevi Ramesh     }
3035bdde3a4SJohn Wang 
304b8baffa3SSridevi Ramesh     static std::string fruFieldIPZParser(const uint8_t* value, uint8_t length)
305b8baffa3SSridevi Ramesh     {
306b8baffa3SSridevi Ramesh         std::ostringstream tempStream;
307b8baffa3SSridevi Ramesh         for (int i = 0; i < int(length); ++i)
308b8baffa3SSridevi Ramesh         {
309b8baffa3SSridevi Ramesh             tempStream << "0x" << std::setfill('0') << std::setw(2) << std::hex
310b8baffa3SSridevi Ramesh                        << (unsigned)value[i] << " ";
311b8baffa3SSridevi Ramesh         }
312b8baffa3SSridevi Ramesh         return tempStream.str();
3135bdde3a4SJohn Wang     }
3145bdde3a4SJohn Wang };
3155bdde3a4SJohn Wang 
3165bdde3a4SJohn Wang class GetFRURecordByOption : public CommandInterface
3175bdde3a4SJohn Wang {
3185bdde3a4SJohn Wang   public:
3195bdde3a4SJohn Wang     ~GetFRURecordByOption() = default;
3205bdde3a4SJohn Wang     GetFRURecordByOption() = delete;
3215bdde3a4SJohn Wang     GetFRURecordByOption(const GetFRURecordByOption&) = delete;
3225bdde3a4SJohn Wang     GetFRURecordByOption(GetFruRecordTableMetadata&&) = delete;
3235bdde3a4SJohn Wang     GetFRURecordByOption& operator=(const GetFRURecordByOption&) = delete;
3245bdde3a4SJohn Wang     GetFRURecordByOption& operator=(GetFRURecordByOption&&) = delete;
3255bdde3a4SJohn Wang 
3265bdde3a4SJohn Wang     explicit GetFRURecordByOption(const char* type, const char* name,
3275bdde3a4SJohn Wang                                   CLI::App* app) :
3285bdde3a4SJohn Wang         CommandInterface(type, name, app)
3295bdde3a4SJohn Wang     {
3305bdde3a4SJohn Wang         app->add_option("-i, --identifier", recordSetIdentifier,
3315bdde3a4SJohn Wang                         "Record Set Identifier\n"
3325bdde3a4SJohn Wang                         "Possible values: {All record sets = 0, Specific "
3335bdde3a4SJohn Wang                         "record set = 1 – 65535}")
3345bdde3a4SJohn Wang             ->required();
3355bdde3a4SJohn Wang         app->add_option("-r, --record", recordType,
3365bdde3a4SJohn Wang                         "Record Type\n"
3375bdde3a4SJohn Wang                         "Possible values: {All record types = 0, Specific "
3385bdde3a4SJohn Wang                         "record types = 1 – 255}")
3395bdde3a4SJohn Wang             ->required();
3405bdde3a4SJohn Wang         app->add_option("-f, --field", fieldType,
3415bdde3a4SJohn Wang                         "Field Type\n"
3425bdde3a4SJohn Wang                         "Possible values: {All record field types = 0, "
3435bdde3a4SJohn Wang                         "Specific field types = 1 – 15}")
3445bdde3a4SJohn Wang             ->required();
3455bdde3a4SJohn Wang     }
3465bdde3a4SJohn Wang 
3475bdde3a4SJohn Wang     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
3485bdde3a4SJohn Wang     {
3495bdde3a4SJohn Wang         if (fieldType != 0 && recordType == 0)
3505bdde3a4SJohn Wang         {
3515bdde3a4SJohn Wang             throw std::invalid_argument("if field type is non-zero, the record "
3525bdde3a4SJohn Wang                                         "type shall also be non-zero");
3535bdde3a4SJohn Wang         }
354b8baffa3SSridevi Ramesh         if (recordType == 254 && (fieldType > 2 && fieldType < 254))
355b8baffa3SSridevi Ramesh         {
356b8baffa3SSridevi Ramesh             throw std::invalid_argument(
357b8baffa3SSridevi Ramesh                 "GetFRURecordByOption is not supported for recordType : 254 "
358b8baffa3SSridevi Ramesh                 "and fieldType > 2");
359b8baffa3SSridevi Ramesh         }
3605bdde3a4SJohn Wang 
3615bdde3a4SJohn Wang         auto payloadLength = sizeof(pldm_get_fru_record_by_option_req);
3625bdde3a4SJohn Wang 
3635bdde3a4SJohn Wang         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + payloadLength,
3645bdde3a4SJohn Wang                                         0);
3655bdde3a4SJohn Wang         auto reqMsg = reinterpret_cast<pldm_msg*>(requestMsg.data());
3665bdde3a4SJohn Wang 
3675bdde3a4SJohn Wang         auto rc = encode_get_fru_record_by_option_req(
3685bdde3a4SJohn Wang             instanceId, 0 /* DataTransferHandle */, 0 /* FRUTableHandle */,
3695bdde3a4SJohn Wang             recordSetIdentifier, recordType, fieldType, PLDM_GET_FIRSTPART,
3705bdde3a4SJohn Wang             reqMsg, payloadLength);
3715bdde3a4SJohn Wang 
3725bdde3a4SJohn Wang         return {rc, requestMsg};
3735bdde3a4SJohn Wang     }
3745bdde3a4SJohn Wang 
3755bdde3a4SJohn Wang     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
3765bdde3a4SJohn Wang     {
3775bdde3a4SJohn Wang         uint8_t cc;
3785bdde3a4SJohn Wang         uint32_t dataTransferHandle;
3795bdde3a4SJohn Wang         uint8_t transferFlag;
3805bdde3a4SJohn Wang         variable_field fruData;
3815bdde3a4SJohn Wang 
3825bdde3a4SJohn Wang         auto rc = decode_get_fru_record_by_option_resp(
3835bdde3a4SJohn Wang             responsePtr, payloadLength, &cc, &dataTransferHandle, &transferFlag,
3845bdde3a4SJohn Wang             &fruData);
3855bdde3a4SJohn Wang 
3865bdde3a4SJohn Wang         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
3875bdde3a4SJohn Wang         {
3885bdde3a4SJohn Wang             std::cerr << "Response Message Error: "
3895bdde3a4SJohn Wang                       << "rc=" << rc << ",cc=" << (int)cc << std::endl;
3905bdde3a4SJohn Wang             return;
3915bdde3a4SJohn Wang         }
3925bdde3a4SJohn Wang 
3935bdde3a4SJohn Wang         FRUTablePrint tablePrint(fruData.ptr, fruData.length);
3945bdde3a4SJohn Wang         tablePrint.print();
3955bdde3a4SJohn Wang     }
3965bdde3a4SJohn Wang 
3975bdde3a4SJohn Wang   private:
3985bdde3a4SJohn Wang     uint16_t recordSetIdentifier;
3995bdde3a4SJohn Wang     uint8_t recordType;
4005bdde3a4SJohn Wang     uint8_t fieldType;
4015bdde3a4SJohn Wang };
4025bdde3a4SJohn Wang 
403bd9440bdSSridevi Ramesh class GetFruRecordTable : public CommandInterface
404bd9440bdSSridevi Ramesh {
405bd9440bdSSridevi Ramesh   public:
406bd9440bdSSridevi Ramesh     ~GetFruRecordTable() = default;
407bd9440bdSSridevi Ramesh     GetFruRecordTable() = delete;
408bd9440bdSSridevi Ramesh     GetFruRecordTable(const GetFruRecordTable&) = delete;
409bd9440bdSSridevi Ramesh     GetFruRecordTable(GetFruRecordTable&&) = default;
410bd9440bdSSridevi Ramesh     GetFruRecordTable& operator=(const GetFruRecordTable&) = delete;
411bd9440bdSSridevi Ramesh     GetFruRecordTable& operator=(GetFruRecordTable&&) = default;
412bd9440bdSSridevi Ramesh 
413bd9440bdSSridevi Ramesh     using CommandInterface::CommandInterface;
414bd9440bdSSridevi Ramesh     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
415bd9440bdSSridevi Ramesh     {
416bd9440bdSSridevi Ramesh         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
417bd9440bdSSridevi Ramesh                                         PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES);
418bd9440bdSSridevi Ramesh         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
419bd9440bdSSridevi Ramesh 
420bd9440bdSSridevi Ramesh         auto rc = encode_get_fru_record_table_req(
421*71689b8bSPotin Lai             instanceId, 0, PLDM_GET_FIRSTPART, request,
422bd9440bdSSridevi Ramesh             requestMsg.size() - sizeof(pldm_msg_hdr));
423bd9440bdSSridevi Ramesh         return {rc, requestMsg};
424bd9440bdSSridevi Ramesh     }
425bd9440bdSSridevi Ramesh     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
426bd9440bdSSridevi Ramesh     {
427bd9440bdSSridevi Ramesh         uint8_t cc = 0;
428bd9440bdSSridevi Ramesh         uint32_t next_data_transfer_handle = 0;
429bd9440bdSSridevi Ramesh         uint8_t transfer_flag = 0;
430bd9440bdSSridevi Ramesh         size_t fru_record_table_length = 0;
431bd9440bdSSridevi Ramesh         std::vector<uint8_t> fru_record_table_data(payloadLength);
432bd9440bdSSridevi Ramesh 
433bd9440bdSSridevi Ramesh         auto rc = decode_get_fru_record_table_resp(
434bd9440bdSSridevi Ramesh             responsePtr, payloadLength, &cc, &next_data_transfer_handle,
435bd9440bdSSridevi Ramesh             &transfer_flag, fru_record_table_data.data(),
436bd9440bdSSridevi Ramesh             &fru_record_table_length);
437bd9440bdSSridevi Ramesh 
438bd9440bdSSridevi Ramesh         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
439bd9440bdSSridevi Ramesh         {
440bd9440bdSSridevi Ramesh             std::cerr << "Response Message Error: "
441bd9440bdSSridevi Ramesh                       << "rc=" << rc << ",cc=" << (int)cc << std::endl;
442bd9440bdSSridevi Ramesh             return;
443bd9440bdSSridevi Ramesh         }
444bd9440bdSSridevi Ramesh 
445bd9440bdSSridevi Ramesh         FRUTablePrint tablePrint(fru_record_table_data.data(),
446bd9440bdSSridevi Ramesh                                  fru_record_table_length);
447bd9440bdSSridevi Ramesh         tablePrint.print();
448bd9440bdSSridevi Ramesh     }
449bd9440bdSSridevi Ramesh };
450bd9440bdSSridevi Ramesh 
451f7f5da97SDeepak Kodihalli void registerCommand(CLI::App& app)
452f7f5da97SDeepak Kodihalli {
453f7f5da97SDeepak Kodihalli     auto fru = app.add_subcommand("fru", "FRU type command");
454f7f5da97SDeepak Kodihalli     fru->require_subcommand(1);
455f7f5da97SDeepak Kodihalli     auto getFruRecordTableMetadata = fru->add_subcommand(
456f7f5da97SDeepak Kodihalli         "GetFruRecordTableMetadata", "get FRU record table metadata");
457f7f5da97SDeepak Kodihalli     commands.push_back(std::make_unique<GetFruRecordTableMetadata>(
458f7f5da97SDeepak Kodihalli         "fru", "GetFruRecordTableMetadata", getFruRecordTableMetadata));
4595bdde3a4SJohn Wang 
4605bdde3a4SJohn Wang     auto getFRURecordByOption =
4615bdde3a4SJohn Wang         fru->add_subcommand("GetFRURecordByOption", "get FRU Record By Option");
4625bdde3a4SJohn Wang     commands.push_back(std::make_unique<GetFRURecordByOption>(
4635bdde3a4SJohn Wang         "fru", "GetFRURecordByOption", getFRURecordByOption));
464bd9440bdSSridevi Ramesh 
465bd9440bdSSridevi Ramesh     auto getFruRecordTable =
466bd9440bdSSridevi Ramesh         fru->add_subcommand("GetFruRecordTable", "get FRU Record Table");
467bd9440bdSSridevi Ramesh     commands.push_back(std::make_unique<GetFruRecordTable>(
468bd9440bdSSridevi Ramesh         "fru", "GetFruRecordTable", getFruRecordTable));
469f7f5da97SDeepak Kodihalli }
470f7f5da97SDeepak Kodihalli 
471f7f5da97SDeepak Kodihalli } // namespace fru
472f7f5da97SDeepak Kodihalli 
473f7f5da97SDeepak Kodihalli } // namespace pldmtool
474