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