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( 166 sizeof(pldm_msg_hdr) + 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 = 180 decode_get_version_resp(responsePtr, payloadLength, &cc, 181 &transferHandle, &transferFlag, &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) : 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 app->add_option( 261 "-d,--data", inputVersion, 262 "Set PLDM type version. Which is got from GetPLDMVersion\n" 263 "eg: version 1.1.0 then data will be `0xf1 0xf1 0xf0 0x00`"); 264 } 265 266 std::pair<int, std::vector<uint8_t>> createRequestMsg() override 267 { 268 std::vector<uint8_t> requestMsg( 269 sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES); 270 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 271 ver32_t version{0xFF, 0xFF, 0xFF, 0xFF}; 272 if (inputVersion.size() != 0) 273 { 274 if (inputVersion.size() != 4) 275 { 276 std::cerr << "Invalid version format. " 277 << "\n"; 278 } 279 else 280 { 281 version.major = inputVersion[3]; 282 version.minor = inputVersion[2]; 283 version.update = inputVersion[1]; 284 version.alpha = inputVersion[0]; 285 } 286 } 287 auto rc = 288 encode_get_commands_req(instanceId, pldmType, version, request); 289 return {rc, requestMsg}; 290 } 291 292 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override 293 { 294 uint8_t cc = 0; 295 std::vector<bitfield8_t> cmdTypes(32); 296 auto rc = decode_get_commands_resp(responsePtr, payloadLength, &cc, 297 cmdTypes.data()); 298 if (rc != PLDM_SUCCESS || cc != PLDM_SUCCESS) 299 { 300 std::cerr << "Response Message Error: " 301 << "rc=" << rc << ",cc=" << (int)cc << "\n"; 302 return; 303 } 304 printPldmCommands(cmdTypes, pldmType); 305 } 306 307 private: 308 pldm_supported_types pldmType; 309 std::vector<uint8_t> inputVersion; 310 311 template <typename CommandMap> 312 void printCommand(CommandMap& commandMap, int i, ordered_json& jarray) 313 { 314 auto it = std::find_if( 315 commandMap.begin(), commandMap.end(), 316 [i](const auto& typePair) { return typePair.second == i; }); 317 if (it != commandMap.end()) 318 { 319 jarray["PLDM Command Code"] = i; 320 jarray["PLDM Command"] = it->first; 321 } 322 } 323 324 void printPldmCommands(std::vector<bitfield8_t>& cmdTypes, 325 pldm_supported_types pldmType) 326 { 327 ordered_json output; 328 for (int i = 0; i < PLDM_MAX_CMDS_PER_TYPE; i++) 329 { 330 ordered_json cmdinfo; 331 bitfield8_t b = cmdTypes[i / 8]; 332 if (b.byte & (1 << i % 8)) 333 { 334 switch (pldmType) 335 { 336 case PLDM_BASE: 337 printCommand(pldmBaseCmds, i, cmdinfo); 338 break; 339 case PLDM_PLATFORM: 340 printCommand(pldmPlatformCmds, i, cmdinfo); 341 break; 342 case PLDM_BIOS: 343 printCommand(pldmBiosCmds, i, cmdinfo); 344 break; 345 case PLDM_FRU: 346 printCommand(pldmFruCmds, i, cmdinfo); 347 break; 348 case PLDM_OEM: 349 #ifdef OEM_IBM 350 printCommand(pldmIBMHostCmds, i, cmdinfo); 351 printCommand(pldmIBMFileIOCmds, i, cmdinfo); 352 #endif 353 break; 354 default: 355 break; 356 } 357 output.emplace_back(cmdinfo); 358 } 359 } 360 pldmtool::helper::DisplayInJson(output); 361 } 362 }; 363 364 void registerCommand(CLI::App& app) 365 { 366 auto base = app.add_subcommand("base", "base type command"); 367 base->require_subcommand(1); 368 369 auto getPLDMTypes = 370 base->add_subcommand("GetPLDMTypes", "get pldm supported types"); 371 commands.push_back( 372 std::make_unique<GetPLDMTypes>("base", "GetPLDMTypes", getPLDMTypes)); 373 374 auto getPLDMVersion = 375 base->add_subcommand("GetPLDMVersion", "get version of a certain type"); 376 commands.push_back(std::make_unique<GetPLDMVersion>( 377 "base", "GetPLDMVersion", getPLDMVersion)); 378 379 auto getPLDMTID = base->add_subcommand("GetTID", "get Terminus ID (TID)"); 380 commands.push_back(std::make_unique<GetTID>("base", "GetTID", getPLDMTID)); 381 382 auto getPLDMCommands = base->add_subcommand( 383 "GetPLDMCommands", "get supported commands of pldm type"); 384 commands.push_back(std::make_unique<GetPLDMCommands>( 385 "base", "GetPLDMCommands", getPLDMCommands)); 386 } 387 388 } // namespace base 389 } // namespace pldmtool 390