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