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&&) = default; 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( 131 pldmTypes.begin(), pldmTypes.end(), 132 [i](const auto& typePair) { return typePair.second == i; }); 133 if (it != pldmTypes.end()) 134 { 135 jarray["PLDM Type"] = it->first; 136 jarray["PLDM Type Code"] = i; 137 data.emplace_back(jarray); 138 } 139 } 140 } 141 pldmtool::helper::DisplayInJson(data); 142 } 143 }; 144 145 class GetPLDMVersion : public CommandInterface 146 { 147 public: 148 ~GetPLDMVersion() = default; 149 GetPLDMVersion() = delete; 150 GetPLDMVersion(const GetPLDMVersion&) = delete; 151 GetPLDMVersion(GetPLDMVersion&&) = default; 152 GetPLDMVersion& operator=(const GetPLDMVersion&) = delete; 153 GetPLDMVersion& operator=(GetPLDMVersion&&) = default; 154 155 explicit GetPLDMVersion(const char* type, const char* name, CLI::App* app) : 156 CommandInterface(type, name, app) 157 { 158 app->add_option("-t,--type", pldmType, "pldm supported type") 159 ->required() 160 ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case)); 161 } 162 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 163 { 164 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 165 PLDM_GET_VERSION_REQ_BYTES); 166 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 167 168 auto rc = encode_get_version_req(instanceId, 0, PLDM_GET_FIRSTPART, 169 pldmType, request); 170 return {rc, requestMsg}; 171 } 172 173 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 174 { 175 uint8_t cc = 0, transferFlag = 0; 176 uint32_t transferHandle = 0; 177 ver32_t version; 178 auto rc = 179 decode_get_version_resp(responsePtr, payloadLength, &cc, 180 &transferHandle, &transferFlag, &version); 181 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 182 { 183 std::cerr << "Response Message Error: " 184 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 185 return; 186 } 187 char buffer[16] = {0}; 188 ver2str(&version, buffer, sizeof(buffer)); 189 ordered_json data; 190 auto it = std::find_if( 191 pldmTypes.begin(), pldmTypes.end(), 192 [&](const auto& typePair) { return typePair.second == pldmType; }); 193 194 if (it != pldmTypes.end()) 195 { 196 data["Response"] = buffer; 197 } 198 pldmtool::helper::DisplayInJson(data); 199 } 200 201 private: 202 pldm_supported_types pldmType; 203 }; 204 205 class GetTID : public CommandInterface 206 { 207 public: 208 ~GetTID() = default; 209 GetTID() = delete; 210 GetTID(const GetTID&) = delete; 211 GetTID(GetTID&&) = default; 212 GetTID& operator=(const GetTID&) = delete; 213 GetTID& operator=(GetTID&&) = default; 214 215 using CommandInterface::CommandInterface; 216 217 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 218 { 219 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr)); 220 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 221 auto rc = encode_get_tid_req(instanceId, request); 222 return {rc, requestMsg}; 223 } 224 225 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 226 { 227 uint8_t cc = 0; 228 uint8_t tid = 0; 229 std::vector<bitfield8_t> types(8); 230 auto rc = decode_get_tid_resp(responsePtr, payloadLength, &cc, &tid); 231 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 232 { 233 std::cerr << "Response Message Error: " 234 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 235 return; 236 } 237 ordered_json data; 238 data["Response"] = static_cast<uint32_t>(tid); 239 pldmtool::helper::DisplayInJson(data); 240 } 241 }; 242 243 class GetPLDMCommands : public CommandInterface 244 { 245 public: 246 ~GetPLDMCommands() = default; 247 GetPLDMCommands() = delete; 248 GetPLDMCommands(const GetPLDMCommands&) = delete; 249 GetPLDMCommands(GetPLDMCommands&&) = default; 250 GetPLDMCommands& operator=(const GetPLDMCommands&) = delete; 251 GetPLDMCommands& operator=(GetPLDMCommands&&) = default; 252 253 explicit GetPLDMCommands(const char* type, const char* name, 254 CLI::App* app) : 255 CommandInterface(type, name, app) 256 { 257 app->add_option("-t,--type", pldmType, "pldm supported type") 258 ->required() 259 ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case)); 260 } 261 262 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 263 { 264 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 265 PLDM_GET_COMMANDS_REQ_BYTES); 266 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 267 ver32_t version{0xFF, 0xFF, 0xFF, 0xFF}; 268 auto rc = 269 encode_get_commands_req(instanceId, pldmType, version, request); 270 return {rc, requestMsg}; 271 } 272 273 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 274 { 275 uint8_t cc = 0; 276 std::vector<bitfield8_t> cmdTypes(32); 277 auto rc = decode_get_commands_resp(responsePtr, payloadLength, &cc, 278 cmdTypes.data()); 279 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 280 { 281 std::cerr << "Response Message Error: " 282 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 283 return; 284 } 285 printPldmCommands(cmdTypes, pldmType); 286 } 287 288 private: 289 pldm_supported_types pldmType; 290 291 template <typename CommandMap> 292 void printCommand(CommandMap& commandMap, int i, ordered_json& jarray) 293 { 294 auto it = std::find_if( 295 commandMap.begin(), commandMap.end(), 296 [i](const auto& typePair) { return typePair.second == i; }); 297 if (it != commandMap.end()) 298 { 299 jarray["PLDM Command Code"] = i; 300 jarray["PLDM Command"] = it->first; 301 } 302 } 303 304 void printPldmCommands(std::vector<bitfield8_t>& cmdTypes, 305 pldm_supported_types pldmType) 306 { 307 ordered_json output; 308 for (int i = 0; i < PLDM_MAX_CMDS_PER_TYPE; i++) 309 { 310 ordered_json cmdinfo; 311 bitfield8_t b = cmdTypes[i / 8]; 312 if (b.byte & (1 << i % 8)) 313 { 314 switch (pldmType) 315 { 316 case PLDM_BASE: 317 printCommand(pldmBaseCmds, i, cmdinfo); 318 break; 319 case PLDM_PLATFORM: 320 printCommand(pldmPlatformCmds, i, cmdinfo); 321 break; 322 case PLDM_BIOS: 323 printCommand(pldmBiosCmds, i, cmdinfo); 324 break; 325 case PLDM_FRU: 326 printCommand(pldmFruCmds, i, cmdinfo); 327 break; 328 case PLDM_OEM: 329 #ifdef OEM_IBM 330 printCommand(pldmIBMHostCmds, i, cmdinfo); 331 printCommand(pldmIBMFileIOCmds, i, cmdinfo); 332 #endif 333 break; 334 default: 335 break; 336 } 337 output.emplace_back(cmdinfo); 338 } 339 } 340 pldmtool::helper::DisplayInJson(output); 341 } 342 }; 343 344 void registerCommand(CLI::App& app) 345 { 346 auto base = app.add_subcommand("base", "base type command"); 347 base->require_subcommand(1); 348 349 auto getPLDMTypes = 350 base->add_subcommand("GetPLDMTypes", "get pldm supported types"); 351 commands.push_back( 352 std::make_unique<GetPLDMTypes>("base", "GetPLDMTypes", getPLDMTypes)); 353 354 auto getPLDMVersion = 355 base->add_subcommand("GetPLDMVersion", "get version of a certain type"); 356 commands.push_back(std::make_unique<GetPLDMVersion>( 357 "base", "GetPLDMVersion", getPLDMVersion)); 358 359 auto getPLDMTID = base->add_subcommand("GetTID", "get Terminus ID (TID)"); 360 commands.push_back(std::make_unique<GetTID>("base", "GetTID", getPLDMTID)); 361 362 auto getPLDMCommands = base->add_subcommand( 363 "GetPLDMCommands", "get supported commands of pldm type"); 364 commands.push_back(std::make_unique<GetPLDMCommands>( 365 "base", "GetPLDMCommands", getPLDMCommands)); 366 } 367 368 } // namespace base 369 } // namespace pldmtool 370