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