xref: /openbmc/pldm/pldmtool/pldm_fru_cmd.cpp (revision b8baffa32c65ba43dc0c2724f2642d3d668c4c5f)
1f7f5da97SDeepak Kodihalli #include "pldm_fru_cmd.hpp"
2f7f5da97SDeepak Kodihalli 
3f7f5da97SDeepak Kodihalli #include "pldm_cmd_helper.hpp"
4f7f5da97SDeepak Kodihalli 
5*b8baffa3SSridevi Ramesh #ifdef OEM_IBM
6*b8baffa3SSridevi Ramesh #include "oem/ibm/libpldm/fru.h"
7*b8baffa3SSridevi Ramesh #endif
8*b8baffa3SSridevi 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         }
70f7f5da97SDeepak Kodihalli         std::cout << "FRUDATAMajorVersion : "
71f7f5da97SDeepak Kodihalli                   << static_cast<uint32_t>(fru_data_major_version) << std::endl;
72f7f5da97SDeepak Kodihalli         std::cout << "FRUDATAMinorVersion : "
73f7f5da97SDeepak Kodihalli                   << static_cast<uint32_t>(fru_data_minor_version) << std::endl;
74f7f5da97SDeepak Kodihalli         std::cout << "FRUTableMaximumSize : " << fru_table_maximum_size
75f7f5da97SDeepak Kodihalli                   << std::endl;
76f7f5da97SDeepak Kodihalli         std::cout << "FRUTableLength : " << fru_table_length << std::endl;
77f7f5da97SDeepak Kodihalli         std::cout << "Total number of Record Set Identifiers in table : "
78f7f5da97SDeepak Kodihalli                   << total_record_set_identifiers << std::endl;
79f7f5da97SDeepak Kodihalli         std::cout << "Total number of records in table :  "
80f7f5da97SDeepak Kodihalli                   << total_table_records << std::endl;
81f7f5da97SDeepak Kodihalli         std::cout << "FRU DATAStructureTableIntegrityChecksum :  " << checksum
82f7f5da97SDeepak Kodihalli                   << std::endl;
83f7f5da97SDeepak Kodihalli     }
84f7f5da97SDeepak Kodihalli };
85f7f5da97SDeepak Kodihalli 
865bdde3a4SJohn Wang class FRUTablePrint
875bdde3a4SJohn Wang {
885bdde3a4SJohn Wang   public:
895bdde3a4SJohn Wang     explicit FRUTablePrint(const uint8_t* table, size_t table_size) :
905bdde3a4SJohn Wang         table(table), table_size(table_size)
915bdde3a4SJohn Wang     {}
925bdde3a4SJohn Wang 
935bdde3a4SJohn Wang     void print()
945bdde3a4SJohn Wang     {
955bdde3a4SJohn Wang         auto p = table;
965bdde3a4SJohn Wang         while (!isTableEnd(p))
975bdde3a4SJohn Wang         {
985bdde3a4SJohn Wang             auto record =
995bdde3a4SJohn Wang                 reinterpret_cast<const pldm_fru_record_data_format*>(p);
1005bdde3a4SJohn Wang             std::cout << "FRU Record Set Identifier: "
1015bdde3a4SJohn Wang                       << (int)le16toh(record->record_set_id) << std::endl;
1025bdde3a4SJohn Wang             std::cout << "FRU Record Type: "
1035bdde3a4SJohn Wang                       << typeToString(fruRecordTypes, record->record_type)
1045bdde3a4SJohn Wang                       << std::endl;
1055bdde3a4SJohn Wang             std::cout << "Number of FRU fields: " << (int)record->num_fru_fields
1065bdde3a4SJohn Wang                       << std::endl;
1075bdde3a4SJohn Wang             std::cout << "Encoding Type for FRU fields: "
1085bdde3a4SJohn Wang                       << typeToString(fruEncodingType, record->encoding_type)
1095bdde3a4SJohn Wang                       << std::endl;
1105bdde3a4SJohn Wang 
1115bdde3a4SJohn Wang             p += sizeof(pldm_fru_record_data_format) -
1125bdde3a4SJohn Wang                  sizeof(pldm_fru_record_tlv);
113*b8baffa3SSridevi Ramesh 
114*b8baffa3SSridevi Ramesh             auto isIPZ = false;
115*b8baffa3SSridevi Ramesh             std::map<uint8_t, std::string> FruFieldTypeMap;
116*b8baffa3SSridevi Ramesh             std::string fruFieldValue;
117*b8baffa3SSridevi Ramesh 
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);
121*b8baffa3SSridevi Ramesh                 if (record->record_type == PLDM_FRU_RECORD_TYPE_GENERAL)
1225bdde3a4SJohn Wang                 {
123*b8baffa3SSridevi Ramesh                     FruFieldTypeMap.insert(fruGeneralFieldTypes.begin(),
124*b8baffa3SSridevi Ramesh                                            fruGeneralFieldTypes.end());
125*b8baffa3SSridevi Ramesh                     if (tlv->type == PLDM_FRU_FIELD_TYPE_IANA)
126*b8baffa3SSridevi Ramesh                     {
127*b8baffa3SSridevi Ramesh                         fruFieldValue =
128*b8baffa3SSridevi Ramesh                             fruFieldParserU32(tlv->value, tlv->length);
1295bdde3a4SJohn Wang                     }
130*b8baffa3SSridevi Ramesh                     else if (tlv->type == PLDM_FRU_FIELD_TYPE_MANUFAC_DATE)
131*b8baffa3SSridevi Ramesh                     {
132*b8baffa3SSridevi Ramesh                         fruFieldValue =
133*b8baffa3SSridevi Ramesh                             fruFieldParserTimestamp(tlv->value, tlv->length);
134*b8baffa3SSridevi Ramesh                     }
135*b8baffa3SSridevi Ramesh                 }
136*b8baffa3SSridevi Ramesh                 else
137*b8baffa3SSridevi Ramesh                 {
138*b8baffa3SSridevi Ramesh #ifdef OEM_IBM
139*b8baffa3SSridevi Ramesh                     if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_RT)
140*b8baffa3SSridevi Ramesh                     {
141*b8baffa3SSridevi Ramesh                         auto oemIPZValue =
142*b8baffa3SSridevi Ramesh                             fruFieldValuestring(tlv->value, tlv->length);
143*b8baffa3SSridevi Ramesh 
144*b8baffa3SSridevi Ramesh                         if (populateMaps.find(oemIPZValue) !=
145*b8baffa3SSridevi Ramesh                             populateMaps.end())
146*b8baffa3SSridevi Ramesh                         {
147*b8baffa3SSridevi Ramesh                             isIPZ = true;
148*b8baffa3SSridevi Ramesh                             const std::map<uint8_t, std::string> IPZTypes =
149*b8baffa3SSridevi Ramesh                                 populateMaps.at(oemIPZValue);
150*b8baffa3SSridevi Ramesh                             FruFieldTypeMap.insert(IPZTypes.begin(),
151*b8baffa3SSridevi Ramesh                                                    IPZTypes.end());
152*b8baffa3SSridevi Ramesh                         }
153*b8baffa3SSridevi Ramesh                     }
154*b8baffa3SSridevi Ramesh                     else
155*b8baffa3SSridevi Ramesh                     {
156*b8baffa3SSridevi Ramesh                         FruFieldTypeMap.insert(fruOemFieldTypes.begin(),
157*b8baffa3SSridevi Ramesh                                                fruOemFieldTypes.end());
158*b8baffa3SSridevi Ramesh                     }
159*b8baffa3SSridevi Ramesh                     if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_IANA)
160*b8baffa3SSridevi Ramesh                     {
161*b8baffa3SSridevi Ramesh                         fruFieldValue =
162*b8baffa3SSridevi Ramesh                             fruFieldParserU32(tlv->value, tlv->length);
163*b8baffa3SSridevi Ramesh                     }
164*b8baffa3SSridevi Ramesh #endif
165*b8baffa3SSridevi Ramesh                 }
166*b8baffa3SSridevi Ramesh 
167*b8baffa3SSridevi Ramesh                 if (isIPZ && (tlv->type != 2))
168*b8baffa3SSridevi Ramesh                 {
169*b8baffa3SSridevi Ramesh                     fruFieldValue = fruFieldIPZParser(tlv->value, tlv->length);
170*b8baffa3SSridevi Ramesh                 }
171*b8baffa3SSridevi Ramesh                 else
172*b8baffa3SSridevi Ramesh                 {
173*b8baffa3SSridevi Ramesh                     fruFieldValue =
174*b8baffa3SSridevi Ramesh                         fruFieldValuestring(tlv->value, tlv->length);
175*b8baffa3SSridevi Ramesh                 }
176*b8baffa3SSridevi Ramesh 
177*b8baffa3SSridevi Ramesh                 std::cout << "\tFRU Field Type: "
178*b8baffa3SSridevi Ramesh                           << typeToString(FruFieldTypeMap, tlv->type)
179*b8baffa3SSridevi Ramesh                           << std::endl;
180*b8baffa3SSridevi Ramesh                 std::cout << "\tFRU Field Length: " << (int)(tlv->length)
181*b8baffa3SSridevi Ramesh                           << std::endl;
182*b8baffa3SSridevi Ramesh                 std::cout << "\tFRU Field Value: " << fruFieldValue
183*b8baffa3SSridevi Ramesh                           << std::endl;
184*b8baffa3SSridevi Ramesh 
1855bdde3a4SJohn Wang                 p += sizeof(pldm_fru_record_tlv) - 1 + tlv->length;
1865bdde3a4SJohn Wang             }
1875bdde3a4SJohn Wang         }
1885bdde3a4SJohn Wang     }
1895bdde3a4SJohn Wang 
1905bdde3a4SJohn Wang   private:
1915bdde3a4SJohn Wang     const uint8_t* table;
1925bdde3a4SJohn Wang     size_t table_size;
1935bdde3a4SJohn Wang 
1945bdde3a4SJohn Wang     bool isTableEnd(const uint8_t* p)
1955bdde3a4SJohn Wang     {
1965bdde3a4SJohn Wang         auto offset = p - table;
1975bdde3a4SJohn Wang         return (table_size - offset) <= 7;
1985bdde3a4SJohn Wang     }
1995bdde3a4SJohn Wang 
200*b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruEncodingType{
2015bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UNSPECIFIED, "Unspecified"},
2025bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_ASCII, "ASCII"},
2035bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF8, "UTF8"},
2045bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF16, "UTF16"},
2055bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF16LE, "UTF16LE"},
2065bdde3a4SJohn Wang         {PLDM_FRU_ENCODING_UTF16BE, "UTF16BE"}};
2075bdde3a4SJohn Wang 
208*b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruGeneralFieldTypes{
209*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_CHASSIS, "Chassis"},
210*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_MODEL, "Model"},
211*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_PN, "Part Number"},
212*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_SN, "Serial Number"},
213*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_MANUFAC, "Manufacturer"},
214*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_MANUFAC_DATE, "Manufacture Date"},
215*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_VENDOR, "Vendor"},
216*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_NAME, "Name"},
217*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_SKU, "SKU"},
218*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_VERSION, "Version"},
219*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_ASSET_TAG, "Asset Tag"},
220*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_DESC, "Description"},
221*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_EC_LVL, "Engineering Change Level"},
222*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_OTHER, "Other Information"},
223*b8baffa3SSridevi Ramesh         {PLDM_FRU_FIELD_TYPE_IANA, "Vendor IANA"}};
224*b8baffa3SSridevi Ramesh 
225*b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruRecordTypes{
2265bdde3a4SJohn Wang         {PLDM_FRU_RECORD_TYPE_GENERAL, "General"},
2275bdde3a4SJohn Wang         {PLDM_FRU_RECORD_TYPE_OEM, "OEM"}};
2285bdde3a4SJohn Wang 
229*b8baffa3SSridevi Ramesh #ifdef OEM_IBM
230*b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> fruOemFieldTypes{
231*b8baffa3SSridevi Ramesh         {PLDM_OEM_FRU_FIELD_TYPE_IANA, "Vendor IANA"},
232*b8baffa3SSridevi Ramesh         {PLDM_OEM_FRU_FIELD_TYPE_RT, "RT"},
233*b8baffa3SSridevi Ramesh         {PLDM_OEM_FRU_FIELD_TYPE_LOCATION_CODE, "Location Code"}};
234*b8baffa3SSridevi Ramesh 
235*b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VINIFieldTypes{
236*b8baffa3SSridevi Ramesh         {2, "RT"},  {3, "B3"},  {4, "B4"},  {5, "B7"},  {6, "CC"},  {7, "CE"},
237*b8baffa3SSridevi Ramesh         {8, "CT"},  {9, "DR"},  {10, "FG"}, {11, "FN"}, {12, "HE"}, {13, "HW"},
238*b8baffa3SSridevi Ramesh         {14, "HX"}, {15, "PN"}, {16, "SN"}, {17, "TS"}, {18, "VZ"}};
239*b8baffa3SSridevi Ramesh 
240*b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VSYSFieldTypes{
241*b8baffa3SSridevi Ramesh         {2, "RT"},  {3, "BR"},  {4, "DR"},  {5, "FV"},  {6, "ID"},
242*b8baffa3SSridevi Ramesh         {7, "MN"},  {8, "NN"},  {9, "RB"},  {10, "RG"}, {11, "SE"},
243*b8baffa3SSridevi Ramesh         {12, "SG"}, {13, "SU"}, {14, "TM"}, {15, "TN"}, {16, "WN"}};
244*b8baffa3SSridevi Ramesh 
245*b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> LXR0FieldTypes{
246*b8baffa3SSridevi Ramesh         {2, "RT"}, {3, "LX"}, {4, "VZ"}};
247*b8baffa3SSridevi Ramesh 
248*b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VW10FieldTypes{
249*b8baffa3SSridevi Ramesh         {2, "RT"}, {3, "DR"}, {4, "GD"}};
250*b8baffa3SSridevi Ramesh 
251*b8baffa3SSridevi Ramesh     static inline const std::map<uint8_t, std::string> VR10FieldTypes{
252*b8baffa3SSridevi Ramesh         {2, "RT"}, {3, "DC"}, {4, "DR"}, {5, "FL"}, {6, "WA"}};
253*b8baffa3SSridevi Ramesh 
254*b8baffa3SSridevi Ramesh     static inline const std::map<std::string,
255*b8baffa3SSridevi Ramesh                                  const std::map<uint8_t, std::string>>
256*b8baffa3SSridevi Ramesh         populateMaps{{"VINI", VINIFieldTypes},
257*b8baffa3SSridevi Ramesh                      {"VSYS", VSYSFieldTypes},
258*b8baffa3SSridevi Ramesh                      {"LXR0", LXR0FieldTypes},
259*b8baffa3SSridevi Ramesh                      {"VWX10", VW10FieldTypes},
260*b8baffa3SSridevi Ramesh                      {"VR10", VR10FieldTypes}};
261*b8baffa3SSridevi Ramesh #endif
262*b8baffa3SSridevi Ramesh 
263*b8baffa3SSridevi Ramesh     std::string typeToString(std::map<uint8_t, std::string> typeMap,
2645bdde3a4SJohn Wang                              uint8_t type)
2655bdde3a4SJohn Wang     {
2665bdde3a4SJohn Wang         auto typeString = std::to_string(type);
2675bdde3a4SJohn Wang         try
2685bdde3a4SJohn Wang         {
269*b8baffa3SSridevi Ramesh             return std::string(typeMap.at(type)) + "(" + typeString + ")";
2705bdde3a4SJohn Wang         }
2715bdde3a4SJohn Wang         catch (const std::out_of_range& e)
2725bdde3a4SJohn Wang         {
2735bdde3a4SJohn Wang             return typeString;
2745bdde3a4SJohn Wang         }
2755bdde3a4SJohn Wang     }
2765bdde3a4SJohn Wang 
277*b8baffa3SSridevi Ramesh     std::string fruFieldValuestring(const uint8_t* value, uint8_t length)
2785bdde3a4SJohn Wang     {
2795bdde3a4SJohn Wang         return std::string(reinterpret_cast<const char*>(value), length);
2805bdde3a4SJohn Wang     }
2815bdde3a4SJohn Wang 
2825bdde3a4SJohn Wang     static std::string fruFieldParserU32(const uint8_t* value, uint8_t length)
2835bdde3a4SJohn Wang     {
2845bdde3a4SJohn Wang         assert(length == 4);
2855bdde3a4SJohn Wang         uint32_t v;
2865bdde3a4SJohn Wang         std::memcpy(&v, value, length);
2875bdde3a4SJohn Wang         return std::to_string(le32toh(v));
2885bdde3a4SJohn Wang     }
2895bdde3a4SJohn Wang 
290*b8baffa3SSridevi Ramesh     static std::string fruFieldParserTimestamp(const uint8_t*, uint8_t)
2915bdde3a4SJohn Wang     {
292*b8baffa3SSridevi Ramesh         return std::string("TODO");
293*b8baffa3SSridevi Ramesh     }
2945bdde3a4SJohn Wang 
295*b8baffa3SSridevi Ramesh     static std::string fruFieldIPZParser(const uint8_t* value, uint8_t length)
296*b8baffa3SSridevi Ramesh     {
297*b8baffa3SSridevi Ramesh         std::ostringstream tempStream;
298*b8baffa3SSridevi Ramesh         for (int i = 0; i < int(length); ++i)
299*b8baffa3SSridevi Ramesh         {
300*b8baffa3SSridevi Ramesh             tempStream << "0x" << std::setfill('0') << std::setw(2) << std::hex
301*b8baffa3SSridevi Ramesh                        << (unsigned)value[i] << " ";
302*b8baffa3SSridevi Ramesh         }
303*b8baffa3SSridevi Ramesh         return tempStream.str();
3045bdde3a4SJohn Wang     }
3055bdde3a4SJohn Wang };
3065bdde3a4SJohn Wang 
3075bdde3a4SJohn Wang class GetFRURecordByOption : public CommandInterface
3085bdde3a4SJohn Wang {
3095bdde3a4SJohn Wang   public:
3105bdde3a4SJohn Wang     ~GetFRURecordByOption() = default;
3115bdde3a4SJohn Wang     GetFRURecordByOption() = delete;
3125bdde3a4SJohn Wang     GetFRURecordByOption(const GetFRURecordByOption&) = delete;
3135bdde3a4SJohn Wang     GetFRURecordByOption(GetFruRecordTableMetadata&&) = delete;
3145bdde3a4SJohn Wang     GetFRURecordByOption& operator=(const GetFRURecordByOption&) = delete;
3155bdde3a4SJohn Wang     GetFRURecordByOption& operator=(GetFRURecordByOption&&) = delete;
3165bdde3a4SJohn Wang 
3175bdde3a4SJohn Wang     explicit GetFRURecordByOption(const char* type, const char* name,
3185bdde3a4SJohn Wang                                   CLI::App* app) :
3195bdde3a4SJohn Wang         CommandInterface(type, name, app)
3205bdde3a4SJohn Wang     {
3215bdde3a4SJohn Wang         app->add_option("-i, --identifier", recordSetIdentifier,
3225bdde3a4SJohn Wang                         "Record Set Identifier\n"
3235bdde3a4SJohn Wang                         "Possible values: {All record sets = 0, Specific "
3245bdde3a4SJohn Wang                         "record set = 1 – 65535}")
3255bdde3a4SJohn Wang             ->required();
3265bdde3a4SJohn Wang         app->add_option("-r, --record", recordType,
3275bdde3a4SJohn Wang                         "Record Type\n"
3285bdde3a4SJohn Wang                         "Possible values: {All record types = 0, Specific "
3295bdde3a4SJohn Wang                         "record types = 1 – 255}")
3305bdde3a4SJohn Wang             ->required();
3315bdde3a4SJohn Wang         app->add_option("-f, --field", fieldType,
3325bdde3a4SJohn Wang                         "Field Type\n"
3335bdde3a4SJohn Wang                         "Possible values: {All record field types = 0, "
3345bdde3a4SJohn Wang                         "Specific field types = 1 – 15}")
3355bdde3a4SJohn Wang             ->required();
3365bdde3a4SJohn Wang     }
3375bdde3a4SJohn Wang 
3385bdde3a4SJohn Wang     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
3395bdde3a4SJohn Wang     {
3405bdde3a4SJohn Wang         if (fieldType != 0 && recordType == 0)
3415bdde3a4SJohn Wang         {
3425bdde3a4SJohn Wang             throw std::invalid_argument("if field type is non-zero, the record "
3435bdde3a4SJohn Wang                                         "type shall also be non-zero");
3445bdde3a4SJohn Wang         }
345*b8baffa3SSridevi Ramesh         if (recordType == 254 && (fieldType > 2 && fieldType < 254))
346*b8baffa3SSridevi Ramesh         {
347*b8baffa3SSridevi Ramesh             throw std::invalid_argument(
348*b8baffa3SSridevi Ramesh                 "GetFRURecordByOption is not supported for recordType : 254 "
349*b8baffa3SSridevi Ramesh                 "and fieldType > 2");
350*b8baffa3SSridevi Ramesh         }
3515bdde3a4SJohn Wang 
3525bdde3a4SJohn Wang         auto payloadLength = sizeof(pldm_get_fru_record_by_option_req);
3535bdde3a4SJohn Wang 
3545bdde3a4SJohn Wang         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + payloadLength,
3555bdde3a4SJohn Wang                                         0);
3565bdde3a4SJohn Wang         auto reqMsg = reinterpret_cast<pldm_msg*>(requestMsg.data());
3575bdde3a4SJohn Wang 
3585bdde3a4SJohn Wang         auto rc = encode_get_fru_record_by_option_req(
3595bdde3a4SJohn Wang             instanceId, 0 /* DataTransferHandle */, 0 /* FRUTableHandle */,
3605bdde3a4SJohn Wang             recordSetIdentifier, recordType, fieldType, PLDM_GET_FIRSTPART,
3615bdde3a4SJohn Wang             reqMsg, payloadLength);
3625bdde3a4SJohn Wang 
3635bdde3a4SJohn Wang         return {rc, requestMsg};
3645bdde3a4SJohn Wang     }
3655bdde3a4SJohn Wang 
3665bdde3a4SJohn Wang     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
3675bdde3a4SJohn Wang     {
3685bdde3a4SJohn Wang         uint8_t cc;
3695bdde3a4SJohn Wang         uint32_t dataTransferHandle;
3705bdde3a4SJohn Wang         uint8_t transferFlag;
3715bdde3a4SJohn Wang         variable_field fruData;
3725bdde3a4SJohn Wang 
3735bdde3a4SJohn Wang         auto rc = decode_get_fru_record_by_option_resp(
3745bdde3a4SJohn Wang             responsePtr, payloadLength, &cc, &dataTransferHandle, &transferFlag,
3755bdde3a4SJohn Wang             &fruData);
3765bdde3a4SJohn Wang 
3775bdde3a4SJohn Wang         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
3785bdde3a4SJohn Wang         {
3795bdde3a4SJohn Wang             std::cerr << "Response Message Error: "
3805bdde3a4SJohn Wang                       << "rc=" << rc << ",cc=" << (int)cc << std::endl;
3815bdde3a4SJohn Wang             return;
3825bdde3a4SJohn Wang         }
3835bdde3a4SJohn Wang 
3845bdde3a4SJohn Wang         FRUTablePrint tablePrint(fruData.ptr, fruData.length);
3855bdde3a4SJohn Wang         tablePrint.print();
3865bdde3a4SJohn Wang     }
3875bdde3a4SJohn Wang 
3885bdde3a4SJohn Wang   private:
3895bdde3a4SJohn Wang     uint16_t recordSetIdentifier;
3905bdde3a4SJohn Wang     uint8_t recordType;
3915bdde3a4SJohn Wang     uint8_t fieldType;
3925bdde3a4SJohn Wang };
3935bdde3a4SJohn Wang 
394bd9440bdSSridevi Ramesh class GetFruRecordTable : public CommandInterface
395bd9440bdSSridevi Ramesh {
396bd9440bdSSridevi Ramesh   public:
397bd9440bdSSridevi Ramesh     ~GetFruRecordTable() = default;
398bd9440bdSSridevi Ramesh     GetFruRecordTable() = delete;
399bd9440bdSSridevi Ramesh     GetFruRecordTable(const GetFruRecordTable&) = delete;
400bd9440bdSSridevi Ramesh     GetFruRecordTable(GetFruRecordTable&&) = default;
401bd9440bdSSridevi Ramesh     GetFruRecordTable& operator=(const GetFruRecordTable&) = delete;
402bd9440bdSSridevi Ramesh     GetFruRecordTable& operator=(GetFruRecordTable&&) = default;
403bd9440bdSSridevi Ramesh 
404bd9440bdSSridevi Ramesh     using CommandInterface::CommandInterface;
405bd9440bdSSridevi Ramesh     std::pair<int, std::vector<uint8_t>> createRequestMsg() override
406bd9440bdSSridevi Ramesh     {
407bd9440bdSSridevi Ramesh         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
408bd9440bdSSridevi Ramesh                                         PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES);
409bd9440bdSSridevi Ramesh         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
410bd9440bdSSridevi Ramesh 
411bd9440bdSSridevi Ramesh         auto rc = encode_get_fru_record_table_req(
412bd9440bdSSridevi Ramesh             instanceId, 0, PLDM_START_AND_END, request,
413bd9440bdSSridevi Ramesh             requestMsg.size() - sizeof(pldm_msg_hdr));
414bd9440bdSSridevi Ramesh         return {rc, requestMsg};
415bd9440bdSSridevi Ramesh     }
416bd9440bdSSridevi Ramesh     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
417bd9440bdSSridevi Ramesh     {
418bd9440bdSSridevi Ramesh         uint8_t cc = 0;
419bd9440bdSSridevi Ramesh         uint32_t next_data_transfer_handle = 0;
420bd9440bdSSridevi Ramesh         uint8_t transfer_flag = 0;
421bd9440bdSSridevi Ramesh         size_t fru_record_table_length = 0;
422bd9440bdSSridevi Ramesh         std::vector<uint8_t> fru_record_table_data(payloadLength);
423bd9440bdSSridevi Ramesh 
424bd9440bdSSridevi Ramesh         auto rc = decode_get_fru_record_table_resp(
425bd9440bdSSridevi Ramesh             responsePtr, payloadLength, &cc, &next_data_transfer_handle,
426bd9440bdSSridevi Ramesh             &transfer_flag, fru_record_table_data.data(),
427bd9440bdSSridevi Ramesh             &fru_record_table_length);
428bd9440bdSSridevi Ramesh 
429bd9440bdSSridevi Ramesh         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS)
430bd9440bdSSridevi Ramesh         {
431bd9440bdSSridevi Ramesh             std::cerr << "Response Message Error: "
432bd9440bdSSridevi Ramesh                       << "rc=" << rc << ",cc=" << (int)cc << std::endl;
433bd9440bdSSridevi Ramesh             return;
434bd9440bdSSridevi Ramesh         }
435bd9440bdSSridevi Ramesh 
436bd9440bdSSridevi Ramesh         FRUTablePrint tablePrint(fru_record_table_data.data(),
437bd9440bdSSridevi Ramesh                                  fru_record_table_length);
438bd9440bdSSridevi Ramesh         tablePrint.print();
439bd9440bdSSridevi Ramesh     }
440bd9440bdSSridevi Ramesh };
441bd9440bdSSridevi Ramesh 
442f7f5da97SDeepak Kodihalli void registerCommand(CLI::App& app)
443f7f5da97SDeepak Kodihalli {
444f7f5da97SDeepak Kodihalli     auto fru = app.add_subcommand("fru", "FRU type command");
445f7f5da97SDeepak Kodihalli     fru->require_subcommand(1);
446f7f5da97SDeepak Kodihalli     auto getFruRecordTableMetadata = fru->add_subcommand(
447f7f5da97SDeepak Kodihalli         "GetFruRecordTableMetadata", "get FRU record table metadata");
448f7f5da97SDeepak Kodihalli     commands.push_back(std::make_unique<GetFruRecordTableMetadata>(
449f7f5da97SDeepak Kodihalli         "fru", "GetFruRecordTableMetadata", getFruRecordTableMetadata));
4505bdde3a4SJohn Wang 
4515bdde3a4SJohn Wang     auto getFRURecordByOption =
4525bdde3a4SJohn Wang         fru->add_subcommand("GetFRURecordByOption", "get FRU Record By Option");
4535bdde3a4SJohn Wang     commands.push_back(std::make_unique<GetFRURecordByOption>(
4545bdde3a4SJohn Wang         "fru", "GetFRURecordByOption", getFRURecordByOption));
455bd9440bdSSridevi Ramesh 
456bd9440bdSSridevi Ramesh     auto getFruRecordTable =
457bd9440bdSSridevi Ramesh         fru->add_subcommand("GetFruRecordTable", "get FRU Record Table");
458bd9440bdSSridevi Ramesh     commands.push_back(std::make_unique<GetFruRecordTable>(
459bd9440bdSSridevi Ramesh         "fru", "GetFruRecordTable", getFruRecordTable));
460f7f5da97SDeepak Kodihalli }
461f7f5da97SDeepak Kodihalli 
462f7f5da97SDeepak Kodihalli } // namespace fru
463f7f5da97SDeepak Kodihalli 
464f7f5da97SDeepak Kodihalli } // namespace pldmtool
465