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(request->hdr.instance_id, PLDM_SUCCESS, types.data(), 57 responsePtr); 58 59 return response; 60 } 61 62 Response getPLDMCommands(const pldm_msg* request, size_t payloadLength) 63 { 64 ver32_t version{}; 65 Type type; 66 67 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_RESP_BYTES, 0); 68 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 69 70 auto rc = decode_get_commands_req(request->payload, payloadLength, &type, 71 &version); 72 73 if (rc != PLDM_SUCCESS) 74 { 75 encode_get_commands_resp(request->hdr.instance_id, rc, nullptr, 76 responsePtr); 77 return response; 78 } 79 80 // DSP0240 has this as a bitfield8[N], where N = 0 to 31 81 std::array<bitfield8_t, 32> cmds{}; 82 if (capabilities.find(type) == capabilities.end()) 83 { 84 encode_get_commands_resp(request->hdr.instance_id, 85 PLDM_ERROR_INVALID_PLDM_TYPE, nullptr, 86 responsePtr); 87 return response; 88 } 89 90 for (const auto& cmd : capabilities.at(type)) 91 { 92 auto index = cmd / 8; 93 // <Type Number> = <Array Index> * 8 + <bit position> 94 auto bit = cmd - (index * 8); 95 cmds[index].byte |= 1 << bit; 96 } 97 98 encode_get_commands_resp(request->hdr.instance_id, PLDM_SUCCESS, 99 cmds.data(), responsePtr); 100 101 return response; 102 } 103 104 Response getPLDMVersion(const pldm_msg* request, size_t payloadLength) 105 { 106 uint32_t transferHandle; 107 Type type; 108 uint8_t transferFlag; 109 110 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_RESP_BYTES, 0); 111 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 112 113 uint8_t rc = decode_get_version_req(request->payload, payloadLength, 114 &transferHandle, &transferFlag, &type); 115 116 if (rc != PLDM_SUCCESS) 117 { 118 encode_get_version_resp(request->hdr.instance_id, rc, 0, 0, nullptr, 4, 119 responsePtr); 120 return response; 121 } 122 123 ver32_t version{}; 124 auto search = versions.find(type); 125 126 if (search == versions.end()) 127 { 128 encode_get_version_resp(request->hdr.instance_id, 129 PLDM_ERROR_INVALID_PLDM_TYPE, 0, 0, nullptr, 4, 130 responsePtr); 131 return response; 132 } 133 134 memcpy(&version, &(search->second), sizeof(version)); 135 encode_get_version_resp(request->hdr.instance_id, PLDM_SUCCESS, 0, 136 PLDM_START_AND_END, &version, sizeof(pldm_version), 137 responsePtr); 138 139 return response; 140 } 141 142 } // namespace responder 143 } // namespace pldm 144