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