xref: /openbmc/pldm/pldmtool/pldm_fru_cmd.cpp (revision 16c2a0a0)
1f7f5da97SDeepak Kodihalli #include "pldm_fru_cmd.hpp"
2f7f5da97SDeepak Kodihalli 
3f7f5da97SDeepak Kodihalli #include "pldm_cmd_helper.hpp"
4f7f5da97SDeepak Kodihalli 
5b8baffa3SSridevi Ramesh #ifdef OEM_IBM
621f128d8SAndrew Jeffery #include <libpldm/oem/ibm/fru.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;
38a7dbca53SPavithra Barithaya     GetFruRecordTableMetadata& operator=(GetFruRecordTableMetadata&&) = delete;
39f7f5da97SDeepak Kodihalli 
40f7f5da97SDeepak Kodihalli     using CommandInterface::CommandInterface;
41f7f5da97SDeepak Kodihalli 
createRequestMsg()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 
parseResponseMsg(pldm_msg * responsePtr,size_t payloadLength)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:
FRUTablePrint(const uint8_t * table,size_t table_size)885bdde3a4SJohn Wang     explicit FRUTablePrint(const uint8_t* table, size_t table_size) :
895bdde3a4SJohn Wang         table(table), table_size(table_size)
905bdde3a4SJohn Wang     {}
915bdde3a4SJohn Wang 
print()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);
103*16c2a0a0SPatrick Williams             output["FRU Record Type"] =
104*16c2a0a0SPatrick Williams                 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                     {
127*16c2a0a0SPatrick Williams                         fruFieldValue =
128*16c2a0a0SPatrick Williams                             fruFieldParserU32(tlv->value, tlv->length);
1295bdde3a4SJohn Wang                     }
130b8baffa3SSridevi Ramesh                     else if (tlv->type == PLDM_FRU_FIELD_TYPE_MANUFAC_DATE)
131b8baffa3SSridevi Ramesh                     {
132*16c2a0a0SPatrick Williams                         fruFieldValue =
133*16c2a0a0SPatrick Williams                             fruFieldParserTimestamp(tlv->value, tlv->length);
134b8baffa3SSridevi Ramesh                     }
13571689b8bSPotin Lai                     else
13671689b8bSPotin Lai                     {
137*16c2a0a0SPatrick Williams                         fruFieldValue =
138*16c2a0a0SPatrick Williams                             fruFieldValuestring(tlv->value, tlv->length);
13971689b8bSPotin Lai                     }
140c50c6cd7SSridevi Ramesh 
141*16c2a0a0SPatrick Williams                     frudata["FRU Field Type"] =
142*16c2a0a0SPatrick Williams                         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                     {
152*16c2a0a0SPatrick Williams                         auto oemIPZValue =
153*16c2a0a0SPatrick Williams                             fruFieldValuestring(tlv->value, tlv->length);
154b8baffa3SSridevi Ramesh 
15506f9b29eSSagar Srinivas                         if (populateMaps.contains(oemIPZValue))
156b8baffa3SSridevi Ramesh                         {
157b8baffa3SSridevi Ramesh                             const std::map<uint8_t, std::string> IPZTypes =
158b8baffa3SSridevi Ramesh                                 populateMaps.at(oemIPZValue);
159b8baffa3SSridevi Ramesh                             FruFieldTypeMap.insert(IPZTypes.begin(),
160b8baffa3SSridevi Ramesh                                                    IPZTypes.end());
161b8baffa3SSridevi Ramesh                         }
162b8baffa3SSridevi Ramesh                     }
163b8baffa3SSridevi Ramesh                     else
164b8baffa3SSridevi Ramesh                     {
165b8baffa3SSridevi Ramesh                         FruFieldTypeMap.insert(fruOemFieldTypes.begin(),
166b8baffa3SSridevi Ramesh                                                fruOemFieldTypes.end());
167b8baffa3SSridevi Ramesh                     }
168b8baffa3SSridevi Ramesh                     if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_IANA)
169b8baffa3SSridevi Ramesh                     {
170*16c2a0a0SPatrick Williams                         fruFieldValue =
171*16c2a0a0SPatrick Williams                             fruFieldParserU32(tlv->value, tlv->length);
172b8baffa3SSridevi Ramesh                     }
173c50c6cd7SSridevi Ramesh                     else if (tlv->type != 2)
174b8baffa3SSridevi Ramesh                     {
175*16c2a0a0SPatrick Williams                         fruFieldValue =
176*16c2a0a0SPatrick Williams                             fruFieldIPZParser(tlv->value, tlv->length);
177b8baffa3SSridevi Ramesh                     }
178b8baffa3SSridevi Ramesh                     else
179b8baffa3SSridevi Ramesh                     {
180*16c2a0a0SPatrick Williams                         fruFieldValue =
181*16c2a0a0SPatrick Williams                             fruFieldValuestring(tlv->value, tlv->length);
182b8baffa3SSridevi Ramesh                     }
183*16c2a0a0SPatrick Williams                     frudata["FRU Field Type"] =
184*16c2a0a0SPatrick Williams                         typeToString(FruFieldTypeMap, tlv->type);
185dd04990dSSridevi Ramesh                     frudata["FRU Field Length"] = (int)(tlv->length);
186dd04990dSSridevi Ramesh                     frudata["FRU Field Value"] = fruFieldValue;
187dd04990dSSridevi Ramesh                     frufielddata.emplace_back(frudata);
188c50c6cd7SSridevi Ramesh 
189c50c6cd7SSridevi Ramesh #endif
190c50c6cd7SSridevi Ramesh                 }
1915bdde3a4SJohn Wang                 p += sizeof(pldm_fru_record_tlv) - 1 + tlv->length;
1925bdde3a4SJohn Wang             }
193dd04990dSSridevi Ramesh             frutable.emplace_back(frufielddata);
1945bdde3a4SJohn Wang         }
195dd04990dSSridevi Ramesh         pldmtool::helper::DisplayInJson(frutable);
1965bdde3a4SJohn Wang     }
1975bdde3a4SJohn Wang 
1985bdde3a4SJohn Wang   private:
1995bdde3a4SJohn Wang     const uint8_t* table;
2005bdde3a4SJohn Wang     size_t table_size;
2015bdde3a4SJohn Wang 
isTableEnd(const uint8_t * p)2025bdde3a4SJohn Wang     bool isTableEnd(const uint8_t* p)
2035bdde3a4SJohn Wang     {
2045bdde3a4SJohn Wang         auto offset = p - table;
2055bdde3a4SJohn Wang         return (table_size - offset) <= 7;
2065bdde3a4SJohn Wang     }
2075bdde3a4SJohn Wang 
208b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruEncodingType{
2095bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UNSPECIFIED, "Unspecified"},
2105bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_ASCII, "ASCII"},
2115bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF8, "UTF8"},
2125bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF16, "UTF16"},
2135bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF16LE, "UTF16LE"},
2145bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF16BE, "UTF16BE"}};
2155bdde3a4SJohn Wang 
216b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruGeneralFieldTypes{
217b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_CHASSIS, "Chassis"},
218b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_MODEL, "Model"},
219b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_PN, "Part Number"},
220b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_SN, "Serial Number"},
221b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_MANUFAC, "Manufacturer"},
222b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_MANUFAC_DATE, "Manufacture Date"},
223b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_VENDOR, "Vendor"},
224b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_NAME, "Name"},
225b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_SKU, "SKU"},
226b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_VERSION, "Version"},
227b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_ASSET_TAG, "Asset Tag"},
228b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_DESC, "Description"},
229b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_EC_LVL, "Engineering Change Level"},
230b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_OTHER, "Other Information"},
231b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_IANA, "Vendor IANA"}};
232b8baffa3SSridevi Ramesh 
233b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruRecordTypes{
2345bdde3a4SJohn Wang         {PLDM_FRU_RECORD_TYPE_GENERAL, "General"},
2355bdde3a4SJohn Wang         {PLDM_FRU_RECORD_TYPE_OEM, "OEM"}};
2365bdde3a4SJohn Wang 
237b8baffa3SSridevi Ramesh #ifdef OEM_IBM
238b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruOemFieldTypes{
239b8baffa3SSridevi Ramesh         {PLDM_OEM_FRU_FIELD_TYPE_IANA, "Vendor IANA"},
240b8baffa3SSridevi Ramesh         {PLDM_OEM_FRU_FIELD_TYPE_RT, "RT"},
241b8baffa3SSridevi Ramesh         {PLDM_OEM_FRU_FIELD_TYPE_LOCATION_CODE, "Location Code"}};
242b8baffa3SSridevi Ramesh 
243b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VINIFieldTypes{
244b8baffa3SSridevi Ramesh         {2, "RT"},  {3, "B3"},  {4, "B4"},  {5, "B7"},  {6, "CC"},  {7, "CE"},
245b8baffa3SSridevi Ramesh         {8, "CT"},  {9, "DR"},  {10, "FG"}, {11, "FN"}, {12, "HE"}, {13, "HW"},
246b8baffa3SSridevi Ramesh         {14, "HX"}, {15, "PN"}, {16, "SN"}, {17, "TS"}, {18, "VZ"}};
247b8baffa3SSridevi Ramesh 
248b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VSYSFieldTypes{
249b8baffa3SSridevi Ramesh         {2, "RT"},  {3, "BR"},  {4, "DR"},  {5, "FV"},  {6, "ID"},
250b8baffa3SSridevi Ramesh         {7, "MN"},  {8, "NN"},  {9, "RB"},  {10, "RG"}, {11, "SE"},
251b8baffa3SSridevi Ramesh         {12, "SG"}, {13, "SU"}, {14, "TM"}, {15, "TN"}, {16, "WN"}};
252b8baffa3SSridevi Ramesh 
253b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> LXR0FieldTypes{
254b8baffa3SSridevi Ramesh         {2, "RT"}, {3, "LX"}, {4, "VZ"}};
255b8baffa3SSridevi Ramesh 
256b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VW10FieldTypes{
257b8baffa3SSridevi Ramesh         {2, "RT"}, {3, "DR"}, {4, "GD"}};
258b8baffa3SSridevi Ramesh 
259b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VR10FieldTypes{
260b8baffa3SSridevi Ramesh         {2, "RT"}, {3, "DC"}, {4, "DR"}, {5, "FL"}, {6, "WA"}};
261b8baffa3SSridevi Ramesh 
262b8baffa3SSridevi Ramesh     static inline const std::map<std::string,
263b8baffa3SSridevi Ramesh                                  const std::map<uint8_t, std::string>>
264b8baffa3SSridevi Ramesh         populateMaps{{"VINI", VINIFieldTypes},
265b8baffa3SSridevi Ramesh                      {"VSYS", VSYSFieldTypes},
266b8baffa3SSridevi Ramesh                      {"LXR0", LXR0FieldTypes},
267b8baffa3SSridevi Ramesh                      {"VWX10", VW10FieldTypes},
268b8baffa3SSridevi Ramesh                      {"VR10", VR10FieldTypes}};
269b8baffa3SSridevi Ramesh #endif
270b8baffa3SSridevi Ramesh 
typeToString(std::map<uint8_t,std::string> typeMap,uint8_t type)271b8baffa3SSridevi Ramesh     std::string typeToString(std::map<uint8_t, std::string> typeMap,
2725bdde3a4SJohn Wang                              uint8_t type)
2735bdde3a4SJohn Wang     {
2745bdde3a4SJohn Wang         auto typeString = std::to_string(type);
2755bdde3a4SJohn Wang         try
2765bdde3a4SJohn Wang         {
277b8baffa3SSridevi Ramesh             return std::string(typeMap.at(type)) + "(" + typeString + ")";
2785bdde3a4SJohn Wang         }
2795bdde3a4SJohn Wang         catch (const std::out_of_range& e)
2805bdde3a4SJohn Wang         {
2815bdde3a4SJohn Wang             return typeString;
2825bdde3a4SJohn Wang         }
2835bdde3a4SJohn Wang     }
2845bdde3a4SJohn Wang 
fruFieldValuestring(const uint8_t * value,uint8_t length)285b8baffa3SSridevi Ramesh     std::string fruFieldValuestring(const uint8_t* value, uint8_t length)
2865bdde3a4SJohn Wang     {
2875bdde3a4SJohn Wang         return std::string(reinterpret_cast<const char*>(value), length);
2885bdde3a4SJohn Wang     }
2895bdde3a4SJohn Wang 
fruFieldParserU32(const uint8_t * value,uint8_t length)2905bdde3a4SJohn Wang     static std::string fruFieldParserU32(const uint8_t* value, uint8_t length)
2915bdde3a4SJohn Wang     {
2925bdde3a4SJohn Wang         assert(length == 4);
2935bdde3a4SJohn Wang         uint32_t v;
2945bdde3a4SJohn Wang         std::memcpy(&v, value, length);
2955bdde3a4SJohn Wang         return std::to_string(le32toh(v));
2965bdde3a4SJohn Wang     }
2975bdde3a4SJohn Wang 
fruFieldParserTimestamp(const uint8_t *,uint8_t)298b8baffa3SSridevi Ramesh     static std::string fruFieldParserTimestamp(const uint8_t*, uint8_t)
2995bdde3a4SJohn Wang     {
300b8baffa3SSridevi Ramesh         return std::string("TODO");
301b8baffa3SSridevi Ramesh     }
3025bdde3a4SJohn Wang 
fruFieldIPZParser(const uint8_t * value,uint8_t length)303b8baffa3SSridevi Ramesh     static std::string fruFieldIPZParser(const uint8_t* value, uint8_t length)
304b8baffa3SSridevi Ramesh     {
305b8baffa3SSridevi Ramesh         std::ostringstream tempStream;
306b8baffa3SSridevi Ramesh         for (int i = 0; i < int(length); ++i)
307b8baffa3SSridevi Ramesh         {
308b8baffa3SSridevi Ramesh             tempStream << "0x" << std::setfill('0') << std::setw(2) << std::hex
309b8baffa3SSridevi Ramesh                        << (unsigned)value[i] << " ";
310b8baffa3SSridevi Ramesh         }
311b8baffa3SSridevi Ramesh         return tempStream.str();
3125bdde3a4SJohn Wang     }
3135bdde3a4SJohn Wang };
3145bdde3a4SJohn Wang 
3155bdde3a4SJohn Wang class GetFRURecordByOption : public CommandInterface
3165bdde3a4SJohn Wang {
3175bdde3a4SJohn Wang   public:
3185bdde3a4SJohn Wang     ~GetFRURecordByOption() = default;
3195bdde3a4SJohn Wang     GetFRURecordByOption() = delete;
3205bdde3a4SJohn Wang     GetFRURecordByOption(const GetFRURecordByOption&) = delete;
3215bdde3a4SJohn Wang     GetFRURecordByOption(GetFruRecordTableMetadata&&) = delete;
3225bdde3a4SJohn Wang     GetFRURecordByOption& operator=(const GetFRURecordByOption&) = delete;
3235bdde3a4SJohn Wang     GetFRURecordByOption& operator=(GetFRURecordByOption&&) = delete;
3245bdde3a4SJohn Wang 
GetFRURecordByOption(const char * type,const char * name,CLI::App * app)3255bdde3a4SJohn Wang     explicit GetFRURecordByOption(const char* type, const char* name,
3265bdde3a4SJohn Wang                                   CLI::App* app) :
3275bdde3a4SJohn Wang         CommandInterface(type, name, app)
3285bdde3a4SJohn Wang     {
3295bdde3a4SJohn Wang         app->add_option("-i, --identifier", recordSetIdentifier,
3305bdde3a4SJohn Wang                         "Record Set Identifier\n"
3315bdde3a4SJohn Wang                         "Possible values: {All record sets = 0, Specific "
3325bdde3a4SJohn Wang                         "record set = 1 – 65535}")
3335bdde3a4SJohn Wang             ->required();
3345bdde3a4SJohn Wang         app->add_option("-r, --record", recordType,
3355bdde3a4SJohn Wang                         "Record Type\n"
3365bdde3a4SJohn Wang                         "Possible values: {All record types = 0, Specific "
3375bdde3a4SJohn Wang                         "record types = 1 – 255}")
3385bdde3a4SJohn Wang             ->required();
3395bdde3a4SJohn Wang         app->add_option("-f, --field", fieldType,
3405bdde3a4SJohn Wang                         "Field Type\n"
3415bdde3a4SJohn Wang                         "Possible values: {All record field types = 0, "
3425bdde3a4SJohn Wang                         "Specific field types = 1 – 15}")
3435bdde3a4SJohn Wang             ->required();
3445bdde3a4SJohn Wang     }
3455bdde3a4SJohn Wang 
createRequestMsg()3465bdde3a4SJohn Wang     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
3475bdde3a4SJohn Wang     {
3485bdde3a4SJohn Wang         if (fieldType != 0 && recordType == 0)
3495bdde3a4SJohn Wang         {
3505bdde3a4SJohn Wang             throw std::invalid_argument("if field type is non-zero, the record "
3515bdde3a4SJohn Wang                                         "type shall also be non-zero");
3525bdde3a4SJohn Wang         }
353b8baffa3SSridevi Ramesh         if (recordType == 254 && (fieldType > 2 && fieldType < 254))
354b8baffa3SSridevi Ramesh         {
355b8baffa3SSridevi Ramesh             throw std::invalid_argument(
356b8baffa3SSridevi Ramesh                 "GetFRURecordByOption is not supported for recordType : 254 "
357b8baffa3SSridevi Ramesh                 "and fieldType > 2");
358b8baffa3SSridevi Ramesh         }
3595bdde3a4SJohn Wang 
3605bdde3a4SJohn Wang         auto payloadLength = sizeof(pldm_get_fru_record_by_option_req);
3615bdde3a4SJohn Wang 
3625bdde3a4SJohn Wang         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + payloadLength,
3635bdde3a4SJohn Wang                                         0);
3645bdde3a4SJohn Wang         auto reqMsg = reinterpret_cast<pldm_msg*>(requestMsg.data());
3655bdde3a4SJohn Wang 
3665bdde3a4SJohn Wang         auto rc = encode_get_fru_record_by_option_req(
3675bdde3a4SJohn Wang             instanceId, 0 /* DataTransferHandle */, 0 /* FRUTableHandle */,
3685bdde3a4SJohn Wang             recordSetIdentifier, recordType, fieldType, PLDM_GET_FIRSTPART,
3695bdde3a4SJohn Wang             reqMsg, payloadLength);
3705bdde3a4SJohn Wang 
3715bdde3a4SJohn Wang         return {rc, requestMsg};
3725bdde3a4SJohn Wang     }
3735bdde3a4SJohn Wang 
parseResponseMsg(pldm_msg * responsePtr,size_t payloadLength)3745bdde3a4SJohn Wang     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
3755bdde3a4SJohn Wang     {
3765bdde3a4SJohn Wang         uint8_t cc;
3775bdde3a4SJohn Wang         uint32_t dataTransferHandle;
3785bdde3a4SJohn Wang         uint8_t transferFlag;
3795bdde3a4SJohn Wang         variable_field fruData;
3805bdde3a4SJohn Wang 
3815bdde3a4SJohn Wang         auto rc = decode_get_fru_record_by_option_resp(
3825bdde3a4SJohn Wang             responsePtr, payloadLength, &cc, &dataTransferHandle, &transferFlag,
3835bdde3a4SJohn Wang             &fruData);
3845bdde3a4SJohn Wang 
3855bdde3a4SJohn Wang         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
3865bdde3a4SJohn Wang         {
3875bdde3a4SJohn Wang             std::cerr << "Response Message Error: "
3885bdde3a4SJohn Wang                       << "rc=" << rc << ",cc=" << (int)cc << std::endl;
3895bdde3a4SJohn Wang             return;
3905bdde3a4SJohn Wang         }
3915bdde3a4SJohn Wang 
3925bdde3a4SJohn Wang         FRUTablePrint tablePrint(fruData.ptr, fruData.length);
3935bdde3a4SJohn Wang         tablePrint.print();
3945bdde3a4SJohn Wang     }
3955bdde3a4SJohn Wang 
3965bdde3a4SJohn Wang   private:
3975bdde3a4SJohn Wang     uint16_t recordSetIdentifier;
3985bdde3a4SJohn Wang     uint8_t recordType;
3995bdde3a4SJohn Wang     uint8_t fieldType;
4005bdde3a4SJohn Wang };
4015bdde3a4SJohn Wang 
402bd9440bdSSridevi Ramesh class GetFruRecordTable : public CommandInterface
403bd9440bdSSridevi Ramesh {
404bd9440bdSSridevi Ramesh   public:
405bd9440bdSSridevi Ramesh     ~GetFruRecordTable() = default;
406bd9440bdSSridevi Ramesh     GetFruRecordTable() = delete;
407bd9440bdSSridevi Ramesh     GetFruRecordTable(const GetFruRecordTable&) = delete;
408bd9440bdSSridevi Ramesh     GetFruRecordTable(GetFruRecordTable&&) = default;
409bd9440bdSSridevi Ramesh     GetFruRecordTable& operator=(const GetFruRecordTable&) = delete;
410a7dbca53SPavithra Barithaya     GetFruRecordTable& operator=(GetFruRecordTable&&) = delete;
411bd9440bdSSridevi Ramesh 
412bd9440bdSSridevi Ramesh     using CommandInterface::CommandInterface;
createRequestMsg()413bd9440bdSSridevi Ramesh     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
414bd9440bdSSridevi Ramesh     {
415*16c2a0a0SPatrick Williams         std::vector<uint8_t> requestMsg(
416*16c2a0a0SPatrick Williams             sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES);
417bd9440bdSSridevi Ramesh         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
418bd9440bdSSridevi Ramesh 
419bd9440bdSSridevi Ramesh         auto rc = encode_get_fru_record_table_req(
42071689b8bSPotin Lai             instanceId, 0, PLDM_GET_FIRSTPART, request,
421bd9440bdSSridevi Ramesh             requestMsg.size() - sizeof(pldm_msg_hdr));
422bd9440bdSSridevi Ramesh         return {rc, requestMsg};
423bd9440bdSSridevi Ramesh     }
parseResponseMsg(pldm_msg * responsePtr,size_t payloadLength)424bd9440bdSSridevi Ramesh     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
425bd9440bdSSridevi Ramesh     {
426bd9440bdSSridevi Ramesh         uint8_t cc = 0;
427bd9440bdSSridevi Ramesh         uint32_t next_data_transfer_handle = 0;
428bd9440bdSSridevi Ramesh         uint8_t transfer_flag = 0;
429bd9440bdSSridevi Ramesh         size_t fru_record_table_length = 0;
430bd9440bdSSridevi Ramesh         std::vector<uint8_t> fru_record_table_data(payloadLength);
431bd9440bdSSridevi Ramesh 
432bd9440bdSSridevi Ramesh         auto rc = decode_get_fru_record_table_resp(
433bd9440bdSSridevi Ramesh             responsePtr, payloadLength, &cc, &next_data_transfer_handle,
434bd9440bdSSridevi Ramesh             &transfer_flag, fru_record_table_data.data(),
435bd9440bdSSridevi Ramesh             &fru_record_table_length);
436bd9440bdSSridevi Ramesh 
437bd9440bdSSridevi Ramesh         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
438bd9440bdSSridevi Ramesh         {
439bd9440bdSSridevi Ramesh             std::cerr << "Response Message Error: "
440bd9440bdSSridevi Ramesh                       << "rc=" << rc << ",cc=" << (int)cc << std::endl;
441bd9440bdSSridevi Ramesh             return;
442bd9440bdSSridevi Ramesh         }
443bd9440bdSSridevi Ramesh 
444bd9440bdSSridevi Ramesh         FRUTablePrint tablePrint(fru_record_table_data.data(),
445bd9440bdSSridevi Ramesh                                  fru_record_table_length);
446bd9440bdSSridevi Ramesh         tablePrint.print();
447bd9440bdSSridevi Ramesh     }
448bd9440bdSSridevi Ramesh };
449bd9440bdSSridevi Ramesh 
registerCommand(CLI::App & app)450f7f5da97SDeepak Kodihalli void registerCommand(CLI::App& app)
451f7f5da97SDeepak Kodihalli {
452f7f5da97SDeepak Kodihalli     auto fru = app.add_subcommand("fru", "FRU type command");
453f7f5da97SDeepak Kodihalli     fru->require_subcommand(1);
454f7f5da97SDeepak Kodihalli     auto getFruRecordTableMetadata = fru->add_subcommand(
455f7f5da97SDeepak Kodihalli         "GetFruRecordTableMetadata", "get FRU record table metadata");
456f7f5da97SDeepak Kodihalli     commands.push_back(std::make_unique<GetFruRecordTableMetadata>(
457f7f5da97SDeepak Kodihalli         "fru", "GetFruRecordTableMetadata", getFruRecordTableMetadata));
4585bdde3a4SJohn Wang 
459*16c2a0a0SPatrick Williams     auto getFRURecordByOption =
460*16c2a0a0SPatrick Williams         fru->add_subcommand("GetFRURecordByOption", "get FRU Record By Option");
4615bdde3a4SJohn Wang     commands.push_back(std::make_unique<GetFRURecordByOption>(
4625bdde3a4SJohn Wang         "fru", "GetFRURecordByOption", getFRURecordByOption));
463bd9440bdSSridevi Ramesh 
464*16c2a0a0SPatrick Williams     auto getFruRecordTable =
465*16c2a0a0SPatrick Williams         fru->add_subcommand("GetFruRecordTable", "get FRU Record Table");
466bd9440bdSSridevi Ramesh     commands.push_back(std::make_unique<GetFruRecordTable>(
467bd9440bdSSridevi Ramesh         "fru", "GetFruRecordTable", getFruRecordTable));
468f7f5da97SDeepak Kodihalli }
469f7f5da97SDeepak Kodihalli 
470f7f5da97SDeepak Kodihalli } // namespace fru
471f7f5da97SDeepak Kodihalli 
472f7f5da97SDeepak Kodihalli } // namespace pldmtool
473