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/oem/ibm/file_io.h> 9 #include <libpldm/oem/ibm/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 {"GetStateEffecterStates", PLDM_GET_STATE_EFFECTER_STATES}, 53 {"GetPDR", PLDM_GET_PDR}, 54 {"GetNumericEffecterValue", PLDM_GET_NUMERIC_EFFECTER_VALUE}, 55 {"SetEventReceiver", PLDM_SET_EVENT_RECEIVER}, 56 {"GetSensorReading", PLDM_GET_SENSOR_READING}, 57 {"GetStateSensorReadings", PLDM_GET_STATE_SENSOR_READINGS}, 58 {"PlatformEventMessage", PLDM_PLATFORM_EVENT_MESSAGE}}; 59 60 const std::map<const char*, pldm_fru_commands> pldmFruCmds{ 61 {"GetFRURecordTableMetadata", PLDM_GET_FRU_RECORD_TABLE_METADATA}, 62 {"GetFRURecordTable", PLDM_GET_FRU_RECORD_TABLE}, 63 {"GetFRURecordByOption", PLDM_GET_FRU_RECORD_BY_OPTION}}; 64 65 #ifdef OEM_IBM 66 const std::map<const char*, pldm_host_commands> pldmIBMHostCmds{ 67 {"GetAlertStatus", PLDM_HOST_GET_ALERT_STATUS}}; 68 69 const std::map<const char*, pldm_fileio_commands> pldmIBMFileIOCmds{ 70 {"GetFileTable", PLDM_GET_FILE_TABLE}, 71 {"ReadFile", PLDM_READ_FILE}, 72 {"WriteFile", PLDM_WRITE_FILE}, 73 {"ReadFileInToMemory", PLDM_READ_FILE_INTO_MEMORY}, 74 {"WriteFileFromMemory", PLDM_WRITE_FILE_FROM_MEMORY}, 75 {"ReadFileByTypeIntoMemory", PLDM_READ_FILE_BY_TYPE_INTO_MEMORY}, 76 {"WriteFileByTypeFromMemory", PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY}, 77 {"NewFileAvailable", PLDM_NEW_FILE_AVAILABLE}, 78 {"ReadFileByType", PLDM_READ_FILE_BY_TYPE}, 79 {"WriteFileByType", PLDM_WRITE_FILE_BY_TYPE}, 80 {"FileAck", PLDM_FILE_ACK}}; 81 #endif 82 83 } // namespace 84 85 class GetPLDMTypes : public CommandInterface 86 { 87 public: 88 ~GetPLDMTypes() = default; 89 GetPLDMTypes() = delete; 90 GetPLDMTypes(const GetPLDMTypes&) = delete; 91 GetPLDMTypes(GetPLDMTypes&&) = default; 92 GetPLDMTypes& operator=(const GetPLDMTypes&) = delete; 93 GetPLDMTypes& operator=(GetPLDMTypes&&) = delete; 94 95 using CommandInterface::CommandInterface; 96 97 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 98 { 99 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr)); 100 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 101 auto rc = encode_get_types_req(instanceId, request); 102 return {rc, requestMsg}; 103 } 104 105 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 106 { 107 uint8_t cc = 0; 108 std::vector<bitfield8_t> types(8); 109 auto rc = decode_get_types_resp(responsePtr, payloadLength, &cc, 110 types.data()); 111 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 112 { 113 std::cerr << "Response Message Error: " 114 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 115 return; 116 } 117 118 printPldmTypes(types); 119 } 120 121 private: 122 void printPldmTypes(std::vector<bitfield8_t>& types) 123 { 124 ordered_json data; 125 ordered_json jarray; 126 for (int i = 0; i < PLDM_MAX_TYPES; i++) 127 { 128 bitfield8_t b = types[i / 8]; 129 if (b.byte & (1 << i % 8)) 130 { 131 auto it = std::find_if( 132 pldmTypes.begin(), pldmTypes.end(), 133 [i](const auto& typePair) { return typePair.second == i; }); 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( 192 pldmTypes.begin(), pldmTypes.end(), 193 [&](const auto& typePair) { return typePair.second == pldmType; }); 194 195 if (it != pldmTypes.end()) 196 { 197 data["Response"] = buffer; 198 } 199 pldmtool::helper::DisplayInJson(data); 200 } 201 202 private: 203 pldm_supported_types pldmType; 204 }; 205 206 class GetTID : public CommandInterface 207 { 208 public: 209 ~GetTID() = default; 210 GetTID() = delete; 211 GetTID(const GetTID&) = delete; 212 GetTID(GetTID&&) = default; 213 GetTID& operator=(const GetTID&) = delete; 214 GetTID& operator=(GetTID&&) = delete; 215 216 using CommandInterface::CommandInterface; 217 218 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 219 { 220 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr)); 221 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 222 auto rc = encode_get_tid_req(instanceId, request); 223 return {rc, requestMsg}; 224 } 225 226 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 227 { 228 uint8_t cc = 0; 229 uint8_t tid = 0; 230 std::vector<bitfield8_t> types(8); 231 auto rc = decode_get_tid_resp(responsePtr, payloadLength, &cc, &tid); 232 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 233 { 234 std::cerr << "Response Message Error: " 235 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 236 return; 237 } 238 ordered_json data; 239 data["Response"] = static_cast<uint32_t>(tid); 240 pldmtool::helper::DisplayInJson(data); 241 } 242 }; 243 244 class GetPLDMCommands : public CommandInterface 245 { 246 public: 247 ~GetPLDMCommands() = default; 248 GetPLDMCommands() = delete; 249 GetPLDMCommands(const GetPLDMCommands&) = delete; 250 GetPLDMCommands(GetPLDMCommands&&) = default; 251 GetPLDMCommands& operator=(const GetPLDMCommands&) = delete; 252 GetPLDMCommands& operator=(GetPLDMCommands&&) = delete; 253 254 explicit GetPLDMCommands(const char* type, const char* name, 255 CLI::App* app) : 256 CommandInterface(type, name, app) 257 { 258 app->add_option("-t,--type", pldmType, "pldm supported type") 259 ->required() 260 ->transform(CLI::CheckedTransformer(pldmTypes, CLI::ignore_case)); 261 } 262 263 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 264 { 265 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 266 PLDM_GET_COMMANDS_REQ_BYTES); 267 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 268 ver32_t version{0xFF, 0xFF, 0xFF, 0xFF}; 269 auto rc = encode_get_commands_req(instanceId, pldmType, version, 270 request); 271 return {rc, requestMsg}; 272 } 273 274 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 275 { 276 uint8_t cc = 0; 277 std::vector<bitfield8_t> cmdTypes(32); 278 auto rc = decode_get_commands_resp(responsePtr, payloadLength, &cc, 279 cmdTypes.data()); 280 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 281 { 282 std::cerr << "Response Message Error: " 283 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 284 return; 285 } 286 printPldmCommands(cmdTypes, pldmType); 287 } 288 289 private: 290 pldm_supported_types pldmType; 291 292 template <typename CommandMap> 293 void printCommand(CommandMap& commandMap, int i, ordered_json& jarray) 294 { 295 auto it = std::find_if( 296 commandMap.begin(), commandMap.end(), 297 [i](const auto& typePair) { return typePair.second == i; }); 298 if (it != commandMap.end()) 299 { 300 jarray["PLDM Command Code"] = i; 301 jarray["PLDM Command"] = it->first; 302 } 303 } 304 305 void printPldmCommands(std::vector<bitfield8_t>& cmdTypes, 306 pldm_supported_types pldmType) 307 { 308 ordered_json output; 309 for (int i = 0; i < PLDM_MAX_CMDS_PER_TYPE; i++) 310 { 311 ordered_json cmdinfo; 312 bitfield8_t b = cmdTypes[i / 8]; 313 if (b.byte & (1 << i % 8)) 314 { 315 switch (pldmType) 316 { 317 case PLDM_BASE: 318 printCommand(pldmBaseCmds, i, cmdinfo); 319 break; 320 case PLDM_PLATFORM: 321 printCommand(pldmPlatformCmds, i, cmdinfo); 322 break; 323 case PLDM_BIOS: 324 printCommand(pldmBiosCmds, i, cmdinfo); 325 break; 326 case PLDM_FRU: 327 printCommand(pldmFruCmds, i, cmdinfo); 328 break; 329 case PLDM_OEM: 330 #ifdef OEM_IBM 331 printCommand(pldmIBMHostCmds, i, cmdinfo); 332 printCommand(pldmIBMFileIOCmds, i, cmdinfo); 333 #endif 334 break; 335 default: 336 break; 337 } 338 output.emplace_back(cmdinfo); 339 } 340 } 341 pldmtool::helper::DisplayInJson(output); 342 } 343 }; 344 345 void registerCommand(CLI::App& app) 346 { 347 auto base = app.add_subcommand("base", "base type command"); 348 base->require_subcommand(1); 349 350 auto getPLDMTypes = base->add_subcommand("GetPLDMTypes", 351 "get pldm supported types"); 352 commands.push_back( 353 std::make_unique<GetPLDMTypes>("base", "GetPLDMTypes", getPLDMTypes)); 354 355 auto getPLDMVersion = base->add_subcommand("GetPLDMVersion", 356 "get version of a certain type"); 357 commands.push_back(std::make_unique<GetPLDMVersion>( 358 "base", "GetPLDMVersion", getPLDMVersion)); 359 360 auto getPLDMTID = base->add_subcommand("GetTID", "get Terminus ID (TID)"); 361 commands.push_back(std::make_unique<GetTID>("base", "GetTID", getPLDMTID)); 362 363 auto getPLDMCommands = base->add_subcommand( 364 "GetPLDMCommands", "get supported commands of pldm type"); 365 commands.push_back(std::make_unique<GetPLDMCommands>( 366 "base", "GetPLDMCommands", getPLDMCommands)); 367 } 368 369 } // namespace base 370 } // namespace pldmtool 371