| Sridevi Ramesh | d448975 | 2019-12-08 09:03:29 -0600 | [diff] [blame] | 1 | #include "pldm_fru_cmd.hpp" | 
 | 2 |  | 
 | 3 | #include "pldm_cmd_helper.hpp" | 
 | 4 |  | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 5 | #ifdef OEM_IBM | 
 | 6 | #include "oem/ibm/libpldm/fru.h" | 
 | 7 | #endif | 
 | 8 |  | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 9 | #include <endian.h> | 
 | 10 |  | 
 | 11 | #include <functional> | 
 | 12 | #include <tuple> | 
 | 13 |  | 
| Sridevi Ramesh | d448975 | 2019-12-08 09:03:29 -0600 | [diff] [blame] | 14 | namespace pldmtool | 
 | 15 | { | 
 | 16 |  | 
 | 17 | namespace fru | 
 | 18 | { | 
 | 19 |  | 
 | 20 | namespace | 
 | 21 | { | 
 | 22 |  | 
 | 23 | using namespace pldmtool::helper; | 
 | 24 |  | 
 | 25 | std::vector<std::unique_ptr<CommandInterface>> commands; | 
 | 26 |  | 
 | 27 | } // namespace | 
 | 28 |  | 
 | 29 | class GetFruRecordTableMetadata : public CommandInterface | 
 | 30 | { | 
 | 31 |   public: | 
 | 32 |     ~GetFruRecordTableMetadata() = default; | 
 | 33 |     GetFruRecordTableMetadata() = delete; | 
 | 34 |     GetFruRecordTableMetadata(const GetFruRecordTableMetadata&) = delete; | 
 | 35 |     GetFruRecordTableMetadata(GetFruRecordTableMetadata&&) = default; | 
 | 36 |     GetFruRecordTableMetadata& | 
 | 37 |         operator=(const GetFruRecordTableMetadata&) = delete; | 
 | 38 |     GetFruRecordTableMetadata& operator=(GetFruRecordTableMetadata&&) = default; | 
 | 39 |  | 
 | 40 |     using CommandInterface::CommandInterface; | 
 | 41 |  | 
 | 42 |     std::pair<int, std::vector<uint8_t>> createRequestMsg() override | 
 | 43 |     { | 
 | 44 |         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr)); | 
 | 45 |         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); | 
 | 46 |  | 
| Christian Geddes | 3bdb3c2 | 2020-05-01 14:55:39 -0500 | [diff] [blame] | 47 |         auto rc = encode_get_fru_record_table_metadata_req( | 
 | 48 |             instanceId, request, PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES); | 
| Sridevi Ramesh | d448975 | 2019-12-08 09:03:29 -0600 | [diff] [blame] | 49 |         return {rc, requestMsg}; | 
 | 50 |     } | 
 | 51 |  | 
 | 52 |     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override | 
 | 53 |     { | 
 | 54 |         uint8_t cc = 0; | 
 | 55 |         uint8_t fru_data_major_version, fru_data_minor_version; | 
 | 56 |         uint32_t fru_table_maximum_size, fru_table_length; | 
 | 57 |         uint16_t total_record_set_identifiers, total_table_records; | 
 | 58 |         uint32_t checksum; | 
 | 59 |  | 
 | 60 |         auto rc = decode_get_fru_record_table_metadata_resp( | 
 | 61 |             responsePtr, payloadLength, &cc, &fru_data_major_version, | 
 | 62 |             &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length, | 
 | 63 |             &total_record_set_identifiers, &total_table_records, &checksum); | 
 | 64 |         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) | 
 | 65 |         { | 
 | 66 |             std::cerr << "Response Message Error: " | 
 | 67 |                       << "rc=" << rc << ",cc=" << (int)cc << std::endl; | 
 | 68 |             return; | 
 | 69 |         } | 
| Sridevi Ramesh | dd04990 | 2020-08-12 01:43:51 -0500 | [diff] [blame] | 70 |         ordered_json output; | 
 | 71 |         output["FRUDATAMajorVersion"] = | 
 | 72 |             static_cast<uint32_t>(fru_data_major_version); | 
 | 73 |         output["FRUDATAMinorVersion"] = | 
 | 74 |             static_cast<uint32_t>(fru_data_minor_version); | 
 | 75 |         output["FRUTableMaximumSize"] = fru_table_maximum_size; | 
 | 76 |         output["FRUTableLength"] = fru_table_length; | 
 | 77 |         output["Total number of Record Set Identifiers in table"] = | 
 | 78 |             total_record_set_identifiers; | 
 | 79 |         output["Total number of records in table"] = total_table_records; | 
 | 80 |         output["FRU DATAStructureTableIntegrityChecksum"] = checksum; | 
 | 81 |         pldmtool::helper::DisplayInJson(output); | 
| Sridevi Ramesh | d448975 | 2019-12-08 09:03:29 -0600 | [diff] [blame] | 82 |     } | 
 | 83 | }; | 
 | 84 |  | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 85 | class FRUTablePrint | 
 | 86 | { | 
 | 87 |   public: | 
 | 88 |     explicit FRUTablePrint(const uint8_t* table, size_t table_size) : | 
 | 89 |         table(table), table_size(table_size) | 
 | 90 |     {} | 
 | 91 |  | 
 | 92 |     void print() | 
 | 93 |     { | 
 | 94 |         auto p = table; | 
| Sridevi Ramesh | dd04990 | 2020-08-12 01:43:51 -0500 | [diff] [blame] | 95 |         ordered_json frutable; | 
 | 96 |         ordered_json output; | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 97 |         while (!isTableEnd(p)) | 
 | 98 |         { | 
 | 99 |             auto record = | 
 | 100 |                 reinterpret_cast<const pldm_fru_record_data_format*>(p); | 
| Sridevi Ramesh | dd04990 | 2020-08-12 01:43:51 -0500 | [diff] [blame] | 101 |             output["FRU Record Set Identifier"] = | 
 | 102 |                 (int)le16toh(record->record_set_id); | 
 | 103 |             output["FRU Record Type"] = | 
 | 104 |                 typeToString(fruRecordTypes, record->record_type); | 
 | 105 |             output["Number of FRU fields"] = (int)record->num_fru_fields; | 
 | 106 |             output["Encoding Type for FRU fields"] = | 
 | 107 |                 typeToString(fruEncodingType, record->encoding_type); | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 108 |  | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 109 |             p += sizeof(pldm_fru_record_data_format) - | 
 | 110 |                  sizeof(pldm_fru_record_tlv); | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 111 |  | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 112 |             std::map<uint8_t, std::string> FruFieldTypeMap; | 
 | 113 |             std::string fruFieldValue; | 
 | 114 |  | 
| Sridevi Ramesh | dd04990 | 2020-08-12 01:43:51 -0500 | [diff] [blame] | 115 |             ordered_json frudata; | 
 | 116 |             ordered_json frufielddata; | 
 | 117 |             frufielddata.emplace_back(output); | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 118 |             for (int i = 0; i < record->num_fru_fields; i++) | 
 | 119 |             { | 
 | 120 |                 auto tlv = reinterpret_cast<const pldm_fru_record_tlv*>(p); | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 121 |                 if (record->record_type == PLDM_FRU_RECORD_TYPE_GENERAL) | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 122 |                 { | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 123 |                     FruFieldTypeMap.insert(fruGeneralFieldTypes.begin(), | 
 | 124 |                                            fruGeneralFieldTypes.end()); | 
 | 125 |                     if (tlv->type == PLDM_FRU_FIELD_TYPE_IANA) | 
 | 126 |                     { | 
 | 127 |                         fruFieldValue = | 
 | 128 |                             fruFieldParserU32(tlv->value, tlv->length); | 
 | 129 |                     } | 
 | 130 |                     else if (tlv->type == PLDM_FRU_FIELD_TYPE_MANUFAC_DATE) | 
 | 131 |                     { | 
 | 132 |                         fruFieldValue = | 
 | 133 |                             fruFieldParserTimestamp(tlv->value, tlv->length); | 
 | 134 |                     } | 
| Sridevi Ramesh | c50c6cd | 2021-06-08 07:14:17 -0500 | [diff] [blame] | 135 |  | 
 | 136 |                     frudata["FRU Field Type"] = | 
 | 137 |                         typeToString(FruFieldTypeMap, tlv->type); | 
 | 138 |                     frudata["FRU Field Length"] = (int)(tlv->length); | 
 | 139 |                     fruFieldValue = | 
 | 140 |                         fruFieldValuestring(tlv->value, tlv->length); | 
 | 141 |                     frudata["FRU Field Value"] = fruFieldValue; | 
 | 142 |                     frufielddata.emplace_back(frudata); | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 143 |                 } | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 144 |                 else | 
 | 145 |                 { | 
 | 146 | #ifdef OEM_IBM | 
 | 147 |                     if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_RT) | 
 | 148 |                     { | 
 | 149 |                         auto oemIPZValue = | 
 | 150 |                             fruFieldValuestring(tlv->value, tlv->length); | 
 | 151 |  | 
 | 152 |                         if (populateMaps.find(oemIPZValue) != | 
 | 153 |                             populateMaps.end()) | 
 | 154 |                         { | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 155 |                             const std::map<uint8_t, std::string> IPZTypes = | 
 | 156 |                                 populateMaps.at(oemIPZValue); | 
 | 157 |                             FruFieldTypeMap.insert(IPZTypes.begin(), | 
 | 158 |                                                    IPZTypes.end()); | 
 | 159 |                         } | 
 | 160 |                     } | 
 | 161 |                     else | 
 | 162 |                     { | 
 | 163 |                         FruFieldTypeMap.insert(fruOemFieldTypes.begin(), | 
 | 164 |                                                fruOemFieldTypes.end()); | 
 | 165 |                     } | 
 | 166 |                     if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_IANA) | 
 | 167 |                     { | 
 | 168 |                         fruFieldValue = | 
 | 169 |                             fruFieldParserU32(tlv->value, tlv->length); | 
 | 170 |                     } | 
| Sridevi Ramesh | c50c6cd | 2021-06-08 07:14:17 -0500 | [diff] [blame] | 171 |                     else if (tlv->type != 2) | 
 | 172 |                     { | 
 | 173 |                         fruFieldValue = | 
 | 174 |                             fruFieldIPZParser(tlv->value, tlv->length); | 
 | 175 |                     } | 
 | 176 |                     else | 
 | 177 |                     { | 
 | 178 |                         fruFieldValue = | 
 | 179 |                             fruFieldValuestring(tlv->value, tlv->length); | 
 | 180 |                     } | 
 | 181 |                     frudata["FRU Field Type"] = | 
 | 182 |                         typeToString(FruFieldTypeMap, tlv->type); | 
 | 183 |                     frudata["FRU Field Length"] = (int)(tlv->length); | 
 | 184 |                     frudata["FRU Field Value"] = fruFieldValue; | 
 | 185 |                     frufielddata.emplace_back(frudata); | 
 | 186 |  | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 187 | #endif | 
 | 188 |                 } | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 189 |                 p += sizeof(pldm_fru_record_tlv) - 1 + tlv->length; | 
 | 190 |             } | 
| Sridevi Ramesh | dd04990 | 2020-08-12 01:43:51 -0500 | [diff] [blame] | 191 |             frutable.emplace_back(frufielddata); | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 192 |         } | 
| Sridevi Ramesh | dd04990 | 2020-08-12 01:43:51 -0500 | [diff] [blame] | 193 |         pldmtool::helper::DisplayInJson(frutable); | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 194 |     } | 
 | 195 |  | 
 | 196 |   private: | 
 | 197 |     const uint8_t* table; | 
 | 198 |     size_t table_size; | 
 | 199 |  | 
 | 200 |     bool isTableEnd(const uint8_t* p) | 
 | 201 |     { | 
 | 202 |         auto offset = p - table; | 
 | 203 |         return (table_size - offset) <= 7; | 
 | 204 |     } | 
 | 205 |  | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 206 |     static inline const std::map<uint8_t, std::string> fruEncodingType{ | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 207 |         {PLDM_FRU_ENCODING_UNSPECIFIED, "Unspecified"}, | 
 | 208 |         {PLDM_FRU_ENCODING_ASCII, "ASCII"}, | 
 | 209 |         {PLDM_FRU_ENCODING_UTF8, "UTF8"}, | 
 | 210 |         {PLDM_FRU_ENCODING_UTF16, "UTF16"}, | 
 | 211 |         {PLDM_FRU_ENCODING_UTF16LE, "UTF16LE"}, | 
 | 212 |         {PLDM_FRU_ENCODING_UTF16BE, "UTF16BE"}}; | 
 | 213 |  | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 214 |     static inline const std::map<uint8_t, std::string> fruGeneralFieldTypes{ | 
 | 215 |         {PLDM_FRU_FIELD_TYPE_CHASSIS, "Chassis"}, | 
 | 216 |         {PLDM_FRU_FIELD_TYPE_MODEL, "Model"}, | 
 | 217 |         {PLDM_FRU_FIELD_TYPE_PN, "Part Number"}, | 
 | 218 |         {PLDM_FRU_FIELD_TYPE_SN, "Serial Number"}, | 
 | 219 |         {PLDM_FRU_FIELD_TYPE_MANUFAC, "Manufacturer"}, | 
 | 220 |         {PLDM_FRU_FIELD_TYPE_MANUFAC_DATE, "Manufacture Date"}, | 
 | 221 |         {PLDM_FRU_FIELD_TYPE_VENDOR, "Vendor"}, | 
 | 222 |         {PLDM_FRU_FIELD_TYPE_NAME, "Name"}, | 
 | 223 |         {PLDM_FRU_FIELD_TYPE_SKU, "SKU"}, | 
 | 224 |         {PLDM_FRU_FIELD_TYPE_VERSION, "Version"}, | 
 | 225 |         {PLDM_FRU_FIELD_TYPE_ASSET_TAG, "Asset Tag"}, | 
 | 226 |         {PLDM_FRU_FIELD_TYPE_DESC, "Description"}, | 
 | 227 |         {PLDM_FRU_FIELD_TYPE_EC_LVL, "Engineering Change Level"}, | 
 | 228 |         {PLDM_FRU_FIELD_TYPE_OTHER, "Other Information"}, | 
 | 229 |         {PLDM_FRU_FIELD_TYPE_IANA, "Vendor IANA"}}; | 
 | 230 |  | 
 | 231 |     static inline const std::map<uint8_t, std::string> fruRecordTypes{ | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 232 |         {PLDM_FRU_RECORD_TYPE_GENERAL, "General"}, | 
 | 233 |         {PLDM_FRU_RECORD_TYPE_OEM, "OEM"}}; | 
 | 234 |  | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 235 | #ifdef OEM_IBM | 
 | 236 |     static inline const std::map<uint8_t, std::string> fruOemFieldTypes{ | 
 | 237 |         {PLDM_OEM_FRU_FIELD_TYPE_IANA, "Vendor IANA"}, | 
 | 238 |         {PLDM_OEM_FRU_FIELD_TYPE_RT, "RT"}, | 
 | 239 |         {PLDM_OEM_FRU_FIELD_TYPE_LOCATION_CODE, "Location Code"}}; | 
 | 240 |  | 
 | 241 |     static inline const std::map<uint8_t, std::string> VINIFieldTypes{ | 
 | 242 |         {2, "RT"},  {3, "B3"},  {4, "B4"},  {5, "B7"},  {6, "CC"},  {7, "CE"}, | 
 | 243 |         {8, "CT"},  {9, "DR"},  {10, "FG"}, {11, "FN"}, {12, "HE"}, {13, "HW"}, | 
 | 244 |         {14, "HX"}, {15, "PN"}, {16, "SN"}, {17, "TS"}, {18, "VZ"}}; | 
 | 245 |  | 
 | 246 |     static inline const std::map<uint8_t, std::string> VSYSFieldTypes{ | 
 | 247 |         {2, "RT"},  {3, "BR"},  {4, "DR"},  {5, "FV"},  {6, "ID"}, | 
 | 248 |         {7, "MN"},  {8, "NN"},  {9, "RB"},  {10, "RG"}, {11, "SE"}, | 
 | 249 |         {12, "SG"}, {13, "SU"}, {14, "TM"}, {15, "TN"}, {16, "WN"}}; | 
 | 250 |  | 
 | 251 |     static inline const std::map<uint8_t, std::string> LXR0FieldTypes{ | 
 | 252 |         {2, "RT"}, {3, "LX"}, {4, "VZ"}}; | 
 | 253 |  | 
 | 254 |     static inline const std::map<uint8_t, std::string> VW10FieldTypes{ | 
 | 255 |         {2, "RT"}, {3, "DR"}, {4, "GD"}}; | 
 | 256 |  | 
 | 257 |     static inline const std::map<uint8_t, std::string> VR10FieldTypes{ | 
 | 258 |         {2, "RT"}, {3, "DC"}, {4, "DR"}, {5, "FL"}, {6, "WA"}}; | 
 | 259 |  | 
 | 260 |     static inline const std::map<std::string, | 
 | 261 |                                  const std::map<uint8_t, std::string>> | 
 | 262 |         populateMaps{{"VINI", VINIFieldTypes}, | 
 | 263 |                      {"VSYS", VSYSFieldTypes}, | 
 | 264 |                      {"LXR0", LXR0FieldTypes}, | 
 | 265 |                      {"VWX10", VW10FieldTypes}, | 
 | 266 |                      {"VR10", VR10FieldTypes}}; | 
 | 267 | #endif | 
 | 268 |  | 
 | 269 |     std::string typeToString(std::map<uint8_t, std::string> typeMap, | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 270 |                              uint8_t type) | 
 | 271 |     { | 
 | 272 |         auto typeString = std::to_string(type); | 
 | 273 |         try | 
 | 274 |         { | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 275 |             return std::string(typeMap.at(type)) + "(" + typeString + ")"; | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 276 |         } | 
 | 277 |         catch (const std::out_of_range& e) | 
 | 278 |         { | 
 | 279 |             return typeString; | 
 | 280 |         } | 
 | 281 |     } | 
 | 282 |  | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 283 |     std::string fruFieldValuestring(const uint8_t* value, uint8_t length) | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 284 |     { | 
 | 285 |         return std::string(reinterpret_cast<const char*>(value), length); | 
 | 286 |     } | 
 | 287 |  | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 288 |     static std::string fruFieldParserU32(const uint8_t* value, uint8_t length) | 
 | 289 |     { | 
 | 290 |         assert(length == 4); | 
 | 291 |         uint32_t v; | 
 | 292 |         std::memcpy(&v, value, length); | 
 | 293 |         return std::to_string(le32toh(v)); | 
 | 294 |     } | 
 | 295 |  | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 296 |     static std::string fruFieldParserTimestamp(const uint8_t*, uint8_t) | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 297 |     { | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 298 |         return std::string("TODO"); | 
 | 299 |     } | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 300 |  | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 301 |     static std::string fruFieldIPZParser(const uint8_t* value, uint8_t length) | 
 | 302 |     { | 
 | 303 |         std::ostringstream tempStream; | 
 | 304 |         for (int i = 0; i < int(length); ++i) | 
 | 305 |         { | 
 | 306 |             tempStream << "0x" << std::setfill('0') << std::setw(2) << std::hex | 
 | 307 |                        << (unsigned)value[i] << " "; | 
 | 308 |         } | 
 | 309 |         return tempStream.str(); | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 310 |     } | 
 | 311 | }; | 
 | 312 |  | 
 | 313 | class GetFRURecordByOption : public CommandInterface | 
 | 314 | { | 
 | 315 |   public: | 
 | 316 |     ~GetFRURecordByOption() = default; | 
 | 317 |     GetFRURecordByOption() = delete; | 
 | 318 |     GetFRURecordByOption(const GetFRURecordByOption&) = delete; | 
 | 319 |     GetFRURecordByOption(GetFruRecordTableMetadata&&) = delete; | 
 | 320 |     GetFRURecordByOption& operator=(const GetFRURecordByOption&) = delete; | 
 | 321 |     GetFRURecordByOption& operator=(GetFRURecordByOption&&) = delete; | 
 | 322 |  | 
 | 323 |     explicit GetFRURecordByOption(const char* type, const char* name, | 
 | 324 |                                   CLI::App* app) : | 
 | 325 |         CommandInterface(type, name, app) | 
 | 326 |     { | 
 | 327 |         app->add_option("-i, --identifier", recordSetIdentifier, | 
 | 328 |                         "Record Set Identifier\n" | 
 | 329 |                         "Possible values: {All record sets = 0, Specific " | 
 | 330 |                         "record set = 1 – 65535}") | 
 | 331 |             ->required(); | 
 | 332 |         app->add_option("-r, --record", recordType, | 
 | 333 |                         "Record Type\n" | 
 | 334 |                         "Possible values: {All record types = 0, Specific " | 
 | 335 |                         "record types = 1 – 255}") | 
 | 336 |             ->required(); | 
 | 337 |         app->add_option("-f, --field", fieldType, | 
 | 338 |                         "Field Type\n" | 
 | 339 |                         "Possible values: {All record field types = 0, " | 
 | 340 |                         "Specific field types = 1 – 15}") | 
 | 341 |             ->required(); | 
 | 342 |     } | 
 | 343 |  | 
 | 344 |     std::pair<int, std::vector<uint8_t>> createRequestMsg() override | 
 | 345 |     { | 
 | 346 |         if (fieldType != 0 && recordType == 0) | 
 | 347 |         { | 
 | 348 |             throw std::invalid_argument("if field type is non-zero, the record " | 
 | 349 |                                         "type shall also be non-zero"); | 
 | 350 |         } | 
| Sridevi Ramesh | b8baffa | 2020-07-22 06:44:39 -0500 | [diff] [blame] | 351 |         if (recordType == 254 && (fieldType > 2 && fieldType < 254)) | 
 | 352 |         { | 
 | 353 |             throw std::invalid_argument( | 
 | 354 |                 "GetFRURecordByOption is not supported for recordType : 254 " | 
 | 355 |                 "and fieldType > 2"); | 
 | 356 |         } | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 357 |  | 
 | 358 |         auto payloadLength = sizeof(pldm_get_fru_record_by_option_req); | 
 | 359 |  | 
 | 360 |         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + payloadLength, | 
 | 361 |                                         0); | 
 | 362 |         auto reqMsg = reinterpret_cast<pldm_msg*>(requestMsg.data()); | 
 | 363 |  | 
 | 364 |         auto rc = encode_get_fru_record_by_option_req( | 
 | 365 |             instanceId, 0 /* DataTransferHandle */, 0 /* FRUTableHandle */, | 
 | 366 |             recordSetIdentifier, recordType, fieldType, PLDM_GET_FIRSTPART, | 
 | 367 |             reqMsg, payloadLength); | 
 | 368 |  | 
 | 369 |         return {rc, requestMsg}; | 
 | 370 |     } | 
 | 371 |  | 
 | 372 |     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override | 
 | 373 |     { | 
 | 374 |         uint8_t cc; | 
 | 375 |         uint32_t dataTransferHandle; | 
 | 376 |         uint8_t transferFlag; | 
 | 377 |         variable_field fruData; | 
 | 378 |  | 
 | 379 |         auto rc = decode_get_fru_record_by_option_resp( | 
 | 380 |             responsePtr, payloadLength, &cc, &dataTransferHandle, &transferFlag, | 
 | 381 |             &fruData); | 
 | 382 |  | 
 | 383 |         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) | 
 | 384 |         { | 
 | 385 |             std::cerr << "Response Message Error: " | 
 | 386 |                       << "rc=" << rc << ",cc=" << (int)cc << std::endl; | 
 | 387 |             return; | 
 | 388 |         } | 
 | 389 |  | 
 | 390 |         FRUTablePrint tablePrint(fruData.ptr, fruData.length); | 
 | 391 |         tablePrint.print(); | 
 | 392 |     } | 
 | 393 |  | 
 | 394 |   private: | 
 | 395 |     uint16_t recordSetIdentifier; | 
 | 396 |     uint8_t recordType; | 
 | 397 |     uint8_t fieldType; | 
 | 398 | }; | 
 | 399 |  | 
| Sridevi Ramesh | bd9440b | 2020-03-24 02:14:36 -0500 | [diff] [blame] | 400 | class GetFruRecordTable : public CommandInterface | 
 | 401 | { | 
 | 402 |   public: | 
 | 403 |     ~GetFruRecordTable() = default; | 
 | 404 |     GetFruRecordTable() = delete; | 
 | 405 |     GetFruRecordTable(const GetFruRecordTable&) = delete; | 
 | 406 |     GetFruRecordTable(GetFruRecordTable&&) = default; | 
 | 407 |     GetFruRecordTable& operator=(const GetFruRecordTable&) = delete; | 
 | 408 |     GetFruRecordTable& operator=(GetFruRecordTable&&) = default; | 
 | 409 |  | 
 | 410 |     using CommandInterface::CommandInterface; | 
 | 411 |     std::pair<int, std::vector<uint8_t>> createRequestMsg() override | 
 | 412 |     { | 
 | 413 |         std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + | 
 | 414 |                                         PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES); | 
 | 415 |         auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); | 
 | 416 |  | 
 | 417 |         auto rc = encode_get_fru_record_table_req( | 
 | 418 |             instanceId, 0, PLDM_START_AND_END, request, | 
 | 419 |             requestMsg.size() - sizeof(pldm_msg_hdr)); | 
 | 420 |         return {rc, requestMsg}; | 
 | 421 |     } | 
 | 422 |     void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override | 
 | 423 |     { | 
 | 424 |         uint8_t cc = 0; | 
 | 425 |         uint32_t next_data_transfer_handle = 0; | 
 | 426 |         uint8_t transfer_flag = 0; | 
 | 427 |         size_t fru_record_table_length = 0; | 
 | 428 |         std::vector<uint8_t> fru_record_table_data(payloadLength); | 
 | 429 |  | 
 | 430 |         auto rc = decode_get_fru_record_table_resp( | 
 | 431 |             responsePtr, payloadLength, &cc, &next_data_transfer_handle, | 
 | 432 |             &transfer_flag, fru_record_table_data.data(), | 
 | 433 |             &fru_record_table_length); | 
 | 434 |  | 
 | 435 |         if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) | 
 | 436 |         { | 
 | 437 |             std::cerr << "Response Message Error: " | 
 | 438 |                       << "rc=" << rc << ",cc=" << (int)cc << std::endl; | 
 | 439 |             return; | 
 | 440 |         } | 
 | 441 |  | 
 | 442 |         FRUTablePrint tablePrint(fru_record_table_data.data(), | 
 | 443 |                                  fru_record_table_length); | 
 | 444 |         tablePrint.print(); | 
 | 445 |     } | 
 | 446 | }; | 
 | 447 |  | 
| Sridevi Ramesh | d448975 | 2019-12-08 09:03:29 -0600 | [diff] [blame] | 448 | void registerCommand(CLI::App& app) | 
 | 449 | { | 
 | 450 |     auto fru = app.add_subcommand("fru", "FRU type command"); | 
 | 451 |     fru->require_subcommand(1); | 
 | 452 |     auto getFruRecordTableMetadata = fru->add_subcommand( | 
 | 453 |         "GetFruRecordTableMetadata", "get FRU record table metadata"); | 
 | 454 |     commands.push_back(std::make_unique<GetFruRecordTableMetadata>( | 
 | 455 |         "fru", "GetFruRecordTableMetadata", getFruRecordTableMetadata)); | 
| John Wang | 5bdde3a | 2020-06-16 15:02:33 +0800 | [diff] [blame] | 456 |  | 
 | 457 |     auto getFRURecordByOption = | 
 | 458 |         fru->add_subcommand("GetFRURecordByOption", "get FRU Record By Option"); | 
 | 459 |     commands.push_back(std::make_unique<GetFRURecordByOption>( | 
 | 460 |         "fru", "GetFRURecordByOption", getFRURecordByOption)); | 
| Sridevi Ramesh | bd9440b | 2020-03-24 02:14:36 -0500 | [diff] [blame] | 461 |  | 
 | 462 |     auto getFruRecordTable = | 
 | 463 |         fru->add_subcommand("GetFruRecordTable", "get FRU Record Table"); | 
 | 464 |     commands.push_back(std::make_unique<GetFruRecordTable>( | 
 | 465 |         "fru", "GetFruRecordTable", getFruRecordTable)); | 
| Sridevi Ramesh | d448975 | 2019-12-08 09:03:29 -0600 | [diff] [blame] | 466 | } | 
 | 467 |  | 
 | 468 | } // namespace fru | 
 | 469 |  | 
 | 470 | } // namespace pldmtool |