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