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