1 #include "libpldm/base.h" 2 3 #include "base.hpp" 4 #include "registration.hpp" 5 6 #include <array> 7 #include <cstring> 8 #include <map> 9 #include <stdexcept> 10 #include <vector> 11 12 namespace pldm 13 { 14 namespace responder 15 { 16 17 using Cmd = std::vector<uint8_t>; 18 19 static const std::map<Type, Cmd> capabilities{ 20 {PLDM_BASE, {PLDM_GET_PLDM_TYPES, PLDM_GET_PLDM_COMMANDS}}}; 21 22 static const std::map<Type, ver32_t> versions{ 23 {PLDM_BASE, {0xF1, 0xF0, 0xF0, 0x00}}, 24 {PLDM_PLATFORM, {0xF1, 0xF1, 0xF1, 0x00}}, 25 {PLDM_BIOS, {0xF1, 0xF0, 0xF0, 0x00}}, 26 }; 27 28 namespace base 29 { 30 31 void registerHandlers() 32 { 33 registerHandler(PLDM_BASE, PLDM_GET_PLDM_TYPES, std::move(getPLDMTypes)); 34 registerHandler(PLDM_BASE, PLDM_GET_PLDM_COMMANDS, 35 std::move(getPLDMCommands)); 36 registerHandler(PLDM_BASE, PLDM_GET_PLDM_VERSION, 37 std::move(getPLDMVersion)); 38 } 39 40 } // namespace base 41 42 Response getPLDMTypes(const pldm_msg* request, size_t payloadLength) 43 { 44 // DSP0240 has this as a bitfield8[N], where N = 0 to 7 45 std::array<bitfield8_t, 8> types{}; 46 for (const auto& type : capabilities) 47 { 48 auto index = type.first / 8; 49 // <Type Number> = <Array Index> * 8 + <bit position> 50 auto bit = type.first - (index * 8); 51 types[index].byte |= 1 << bit; 52 } 53 54 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_TYPES_RESP_BYTES, 0); 55 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 56 encode_get_types_resp(0, PLDM_SUCCESS, types.data(), responsePtr); 57 58 return response; 59 } 60 61 Response getPLDMCommands(const pldm_msg* request, size_t payloadLength) 62 { 63 ver32_t version{}; 64 Type type; 65 66 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_RESP_BYTES, 0); 67 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 68 69 auto rc = decode_get_commands_req(request->payload, payloadLength, &type, 70 &version); 71 72 if (rc != PLDM_SUCCESS) 73 { 74 encode_get_commands_resp(0, rc, nullptr, responsePtr); 75 return response; 76 } 77 78 // DSP0240 has this as a bitfield8[N], where N = 0 to 31 79 std::array<bitfield8_t, 32> cmds{}; 80 if (capabilities.find(type) == capabilities.end()) 81 { 82 encode_get_commands_resp(0, PLDM_ERROR_INVALID_PLDM_TYPE, nullptr, 83 responsePtr); 84 return response; 85 } 86 87 for (const auto& cmd : capabilities.at(type)) 88 { 89 auto index = cmd / 8; 90 // <Type Number> = <Array Index> * 8 + <bit position> 91 auto bit = cmd - (index * 8); 92 cmds[index].byte |= 1 << bit; 93 } 94 95 encode_get_commands_resp(0, PLDM_SUCCESS, cmds.data(), responsePtr); 96 97 return response; 98 } 99 100 Response getPLDMVersion(const pldm_msg* request, size_t payloadLength) 101 { 102 uint32_t transferHandle; 103 Type type; 104 uint8_t transferFlag; 105 106 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_RESP_BYTES, 0); 107 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 108 109 uint8_t rc = decode_get_version_req(request->payload, payloadLength, 110 &transferHandle, &transferFlag, &type); 111 112 if (rc != PLDM_SUCCESS) 113 { 114 encode_get_version_resp(0, rc, 0, 0, nullptr, 4, responsePtr); 115 return response; 116 } 117 118 ver32_t version{}; 119 auto search = versions.find(type); 120 121 if (search == versions.end()) 122 { 123 encode_get_version_resp(0, PLDM_ERROR_INVALID_PLDM_TYPE, 0, 0, nullptr, 124 4, responsePtr); 125 return response; 126 } 127 128 memcpy(&version, &(search->second), sizeof(version)); 129 encode_get_version_resp(0, PLDM_SUCCESS, 0, PLDM_START_AND_END, &version, 130 sizeof(pldm_version), responsePtr); 131 132 return response; 133 } 134 135 } // namespace responder 136 } // namespace pldm 137