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