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