1 #include "pldm_base_cmd.hpp" 2 3 #include "pldm_cmd_helper.hpp" 4 5 #include <libpldm/utils.h> 6 7 #ifdef OEM_IBM 8 #include <libpldm/file_io.h> 9 #include <libpldm/host.h> 10 #endif 11 12 #include <string> 13 14 namespace pldmtool 15 { 16 17 namespace base 18 { 19 20 namespace 21 { 22 23 using namespace pldmtool::helper; 24 25 std::vector<std::unique_ptr<CommandInterface>> commands; 26 const std::map<const char*, pldm_supported_types> pldmTypes{ 27 {"base", PLDM_BASE}, {"platform", PLDM_PLATFORM}, 28 {"bios", PLDM_BIOS}, {"fru", PLDM_FRU}, 29 #ifdef OEM_IBM 30 {"oem-ibm", PLDM_OEM}, 31 #endif 32 }; 33 34 const std::map<const char*, pldm_supported_commands> pldmBaseCmds{ 35 {"GetTID", PLDM_GET_TID}, 36 {"GetPLDMVersion", PLDM_GET_PLDM_VERSION}, 37 {"GetPLDMTypes", PLDM_GET_PLDM_TYPES}, 38 {"GetPLDMCommands", PLDM_GET_PLDM_COMMANDS}}; 39 40 const std::map<const char*, pldm_bios_commands> pldmBiosCmds{ 41 {"GetBIOSTable", PLDM_GET_BIOS_TABLE}, 42 {"SetBIOSTable", PLDM_SET_BIOS_TABLE}, 43 {"SetBIOSAttributeCurrentValue", PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE}, 44 {"GetBIOSAttributeCurrentValueByHandle", 45 PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE}, 46 {"GetDateTime", PLDM_GET_DATE_TIME}, 47 {"SetDateTime", PLDM_SET_DATE_TIME}}; 48 49 const std::map<const char*, pldm_platform_commands> pldmPlatformCmds{ 50 {"SetNumericEffecterValue", PLDM_SET_NUMERIC_EFFECTER_VALUE}, 51 {"SetStateEffecterStates", PLDM_SET_STATE_EFFECTER_STATES}, 52 {"GetPDR", PLDM_GET_PDR}, 53 {"GetNumericEffecterValue", PLDM_GET_NUMERIC_EFFECTER_VALUE}, 54 {"SetEventReceiver", PLDM_SET_EVENT_RECEIVER}, 55 {"GetSensorReading", PLDM_GET_SENSOR_READING}, 56 {"GetStateSensorReadings", PLDM_GET_STATE_SENSOR_READINGS}, 57 {"PlatformEventMessage", PLDM_PLATFORM_EVENT_MESSAGE}}; 58 59 const std::map<const char*, pldm_fru_commands> pldmFruCmds{ 60 {"GetFRURecordTableMetadata", PLDM_GET_FRU_RECORD_TABLE_METADATA}, 61 {"GetFRURecordTable", PLDM_GET_FRU_RECORD_TABLE}, 62 {"GetFRURecordByOption", PLDM_GET_FRU_RECORD_BY_OPTION}}; 63 64 #ifdef OEM_IBM 65 const std::map<const char*, pldm_host_commands> pldmIBMHostCmds{ 66 {"GetAlertStatus", PLDM_HOST_GET_ALERT_STATUS}}; 67 68 const std::map<const char*, pldm_fileio_commands> pldmIBMFileIOCmds{ 69 {"GetFileTable", PLDM_GET_FILE_TABLE}, 70 {"ReadFile", PLDM_READ_FILE}, 71 {"WriteFile", PLDM_WRITE_FILE}, 72 {"ReadFileInToMemory", PLDM_READ_FILE_INTO_MEMORY}, 73 {"WriteFileFromMemory", PLDM_WRITE_FILE_FROM_MEMORY}, 74 {"ReadFileByTypeIntoMemory", PLDM_READ_FILE_BY_TYPE_INTO_MEMORY}, 75 {"WriteFileByTypeFromMemory", PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY}, 76 {"NewFileAvailable", PLDM_NEW_FILE_AVAILABLE}, 77 {"ReadFileByType", PLDM_READ_FILE_BY_TYPE}, 78 {"WriteFileByType", PLDM_WRITE_FILE_BY_TYPE}, 79 {"FileAck", PLDM_FILE_ACK}}; 80 #endif 81 82 } // namespace 83 84 class GetPLDMTypes : public CommandInterface 85 { 86 public: 87 ~GetPLDMTypes() = default; 88 GetPLDMTypes() = delete; 89 GetPLDMTypes(const GetPLDMTypes&) = delete; 90 GetPLDMTypes(GetPLDMTypes&&) = default; 91 GetPLDMTypes& operator=(const GetPLDMTypes&) = delete; 92 GetPLDMTypes& operator=(GetPLDMTypes&&) = delete; 93 94 using CommandInterface::CommandInterface; 95 96 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 97 { 98 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr)); 99 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 100 auto rc = encode_get_types_req(instanceId, request); 101 return {rc, requestMsg}; 102 } 103 104 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 105 { 106 uint8_t cc = 0; 107 std::vector<bitfield8_t> types(8); 108 auto rc = decode_get_types_resp(responsePtr, payloadLength, &cc, 109 types.data()); 110 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 111 { 112 std::cerr << "Response Message Error: " 113 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 114 return; 115 } 116 117 printPldmTypes(types); 118 } 119 120 private: 121 void printPldmTypes(std::vector<bitfield8_t>& types) 122 { 123 ordered_json data; 124 ordered_json jarray; 125 for (int i = 0; i < PLDM_MAX_TYPES; i++) 126 { 127 bitfield8_t b = types[i / 8]; 128 if (b.byte & (1 << i % 8)) 129 { 130 auto it = std::find_if(pldmTypes.begin(), pldmTypes.end(), 131 [i](const auto& typePair) { 132 return typePair.second == i; 133 }); 134 if (it != pldmTypes.end()) 135 { 136 jarray["PLDM Type"] = it->first; 137 jarray["PLDM Type Code"] = i; 138 data.emplace_back(jarray); 139 } 140 } 141 } 142 pldmtool::helper::DisplayInJson(data); 143 } 144 }; 145 146 class GetPLDMVersion : public CommandInterface 147 { 148 public: 149 ~GetPLDMVersion() = default; 150 GetPLDMVersion() = delete; 151 GetPLDMVersion(const GetPLDMVersion&) = delete; 152 GetPLDMVersion(GetPLDMVersion&&) = default; 153 GetPLDMVersion& operator=(const GetPLDMVersion&) = delete; 154 GetPLDMVersion& operator=(GetPLDMVersion&&) = delete; 155 156 explicit GetPLDMVersion(const char* type, const char* name, CLI::App* app) : 157 CommandInterface(type, name, app) 158 { 159 app->add_option("-t,--type", pldmType, "pldm supported type") 160 ->required() 161 ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case)); 162 } 163 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 164 { 165 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 166 PLDM_GET_VERSION_REQ_BYTES); 167 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 168 169 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART, 170 pldmType, request); 171 return {rc, requestMsg}; 172 } 173 174 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 175 { 176 uint8_t cc = 0, transferFlag = 0; 177 uint32_t transferHandle = 0; 178 ver32_t version; 179 auto rc = decode_get_version_resp(responsePtr, payloadLength, &cc, 180 &transferHandle, &transferFlag, 181 &version); 182 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 183 { 184 std::cerr << "Response Message Error: " 185 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 186 return; 187 } 188 char buffer[16] = {0}; 189 ver2str(&version, buffer, sizeof(buffer)); 190 ordered_json data; 191 auto it = std::find_if(pldmTypes.begin(), pldmTypes.end(), 192 [&](const auto& typePair) { 193 return typePair.second == pldmType; 194 }); 195 196 if (it != pldmTypes.end()) 197 { 198 data["Response"] = buffer; 199 } 200 pldmtool::helper::DisplayInJson(data); 201 } 202 203 private: 204 pldm_supported_types pldmType; 205 }; 206 207 class GetTID : public CommandInterface 208 { 209 public: 210 ~GetTID() = default; 211 GetTID() = delete; 212 GetTID(const GetTID&) = delete; 213 GetTID(GetTID&&) = default; 214 GetTID& operator=(const GetTID&) = delete; 215 GetTID& operator=(GetTID&&) = delete; 216 217 using CommandInterface::CommandInterface; 218 219 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 220 { 221 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr)); 222 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 223 auto rc = encode_get_tid_req(instanceId, request); 224 return {rc, requestMsg}; 225 } 226 227 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 228 { 229 uint8_t cc = 0; 230 uint8_t tid = 0; 231 std::vector<bitfield8_t> types(8); 232 auto rc = decode_get_tid_resp(responsePtr, payloadLength, &cc, &tid); 233 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 234 { 235 std::cerr << "Response Message Error: " 236 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 237 return; 238 } 239 ordered_json data; 240 data["Response"] = static_cast<uint32_t>(tid); 241 pldmtool::helper::DisplayInJson(data); 242 } 243 }; 244 245 class GetPLDMCommands : public CommandInterface 246 { 247 public: 248 ~GetPLDMCommands() = default; 249 GetPLDMCommands() = delete; 250 GetPLDMCommands(const GetPLDMCommands&) = delete; 251 GetPLDMCommands(GetPLDMCommands&&) = default; 252 GetPLDMCommands& operator=(const GetPLDMCommands&) = delete; 253 GetPLDMCommands& operator=(GetPLDMCommands&&) = delete; 254 255 explicit GetPLDMCommands(const char* type, const char* name, 256 CLI::App* app) : 257 CommandInterface(type, name, app) 258 { 259 app->add_option("-t,--type", pldmType, "pldm supported type") 260 ->required() 261 ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case)); 262 } 263 264 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 265 { 266 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 267 PLDM_GET_COMMANDS_REQ_BYTES); 268 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 269 ver32_t version{0xFF, 0xFF, 0xFF, 0xFF}; 270 auto rc = encode_get_commands_req(instanceId, pldmType, version, 271 request); 272 return {rc, requestMsg}; 273 } 274 275 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 276 { 277 uint8_t cc = 0; 278 std::vector<bitfield8_t> cmdTypes(32); 279 auto rc = decode_get_commands_resp(responsePtr, payloadLength, &cc, 280 cmdTypes.data()); 281 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 282 { 283 std::cerr << "Response Message Error: " 284 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 285 return; 286 } 287 printPldmCommands(cmdTypes, pldmType); 288 } 289 290 private: 291 pldm_supported_types pldmType; 292 293 template <typename CommandMap> 294 void printCommand(CommandMap& commandMap, int i, ordered_json& jarray) 295 { 296 auto it = std::find_if(commandMap.begin(), commandMap.end(), 297 [i](const auto& typePair) { 298 return typePair.second == i; 299 }); 300 if (it != commandMap.end()) 301 { 302 jarray["PLDM Command Code"] = i; 303 jarray["PLDM Command"] = it->first; 304 } 305 } 306 307 void printPldmCommands(std::vector<bitfield8_t>& cmdTypes, 308 pldm_supported_types pldmType) 309 { 310 ordered_json output; 311 for (int i = 0; i < PLDM_MAX_CMDS_PER_TYPE; i++) 312 { 313 ordered_json cmdinfo; 314 bitfield8_t b = cmdTypes[i / 8]; 315 if (b.byte & (1 << i % 8)) 316 { 317 switch (pldmType) 318 { 319 case PLDM_BASE: 320 printCommand(pldmBaseCmds, i, cmdinfo); 321 break; 322 case PLDM_PLATFORM: 323 printCommand(pldmPlatformCmds, i, cmdinfo); 324 break; 325 case PLDM_BIOS: 326 printCommand(pldmBiosCmds, i, cmdinfo); 327 break; 328 case PLDM_FRU: 329 printCommand(pldmFruCmds, i, cmdinfo); 330 break; 331 case PLDM_OEM: 332 #ifdef OEM_IBM 333 printCommand(pldmIBMHostCmds, i, cmdinfo); 334 printCommand(pldmIBMFileIOCmds, i, cmdinfo); 335 #endif 336 break; 337 default: 338 break; 339 } 340 output.emplace_back(cmdinfo); 341 } 342 } 343 pldmtool::helper::DisplayInJson(output); 344 } 345 }; 346 347 void registerCommand(CLI::App& app) 348 { 349 auto base = app.add_subcommand("base", "base type command"); 350 base->require_subcommand(1); 351 352 auto getPLDMTypes = base->add_subcommand("GetPLDMTypes", 353 "get pldm supported types"); 354 commands.push_back( 355 std::make_unique<GetPLDMTypes>("base", "GetPLDMTypes", getPLDMTypes)); 356 357 auto getPLDMVersion = base->add_subcommand("GetPLDMVersion", 358 "get version of a certain type"); 359 commands.push_back(std::make_unique<GetPLDMVersion>( 360 "base", "GetPLDMVersion", getPLDMVersion)); 361 362 auto getPLDMTID = base->add_subcommand("GetTID", "get Terminus ID (TID)"); 363 commands.push_back(std::make_unique<GetTID>("base", "GetTID", getPLDMTID)); 364 365 auto getPLDMCommands = base->add_subcommand( 366 "GetPLDMCommands", "get supported commands of pldm type"); 367 commands.push_back(std::make_unique<GetPLDMCommands>( 368 "base", "GetPLDMCommands", getPLDMCommands)); 369 } 370 371 } // namespace base 372 } // namespace pldmtool 373