xref: /openbmc/pldm/libpldmresponder/base.cpp (revision a4a96162)
1 #include "libpldm/base.h"
2 
3 #include "libpldm/bios.h"
4 #include "libpldm/fru.h"
5 #include "libpldm/platform.h"
6 
7 #include "base.hpp"
8 
9 #include <array>
10 #include <cstring>
11 #include <map>
12 #include <stdexcept>
13 #include <vector>
14 
15 #ifdef OEM_IBM
16 #include "libpldm/file_io.h"
17 #include "libpldm/host.h"
18 #endif
19 
20 namespace pldm
21 {
22 
23 using Type = uint8_t;
24 
25 namespace responder
26 {
27 
28 using Cmd = std::vector<uint8_t>;
29 
30 static const std::map<Type, Cmd> capabilities{
31     {PLDM_BASE,
32      {PLDM_GET_TID, PLDM_GET_PLDM_VERSION, PLDM_GET_PLDM_TYPES,
33       PLDM_GET_PLDM_COMMANDS}},
34     {PLDM_PLATFORM, {PLDM_GET_PDR, PLDM_SET_STATE_EFFECTER_STATES}},
35     {PLDM_BIOS,
36      {PLDM_GET_DATE_TIME, PLDM_SET_DATE_TIME, PLDM_GET_BIOS_TABLE,
37       PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE,
38       PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE}},
39     {PLDM_FRU,
40      {PLDM_GET_FRU_RECORD_TABLE_METADATA, PLDM_GET_FRU_RECORD_TABLE,
41       PLDM_GET_FRU_RECORD_BY_OPTION}},
42 #ifdef OEM_IBM
43     {PLDM_OEM,
44      {PLDM_HOST_GET_ALERT_STATUS, PLDM_GET_FILE_TABLE, PLDM_READ_FILE,
45       PLDM_WRITE_FILE, PLDM_READ_FILE_INTO_MEMORY, PLDM_WRITE_FILE_FROM_MEMORY,
46       PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY,
47       PLDM_NEW_FILE_AVAILABLE, PLDM_READ_FILE_BY_TYPE, PLDM_WRITE_FILE_BY_TYPE,
48       PLDM_FILE_ACK}},
49 #endif
50 };
51 
52 static const std::map<Type, ver32_t> versions{
53     {PLDM_BASE, {0xF1, 0xF0, 0xF0, 0x00}},
54     {PLDM_PLATFORM, {0xF1, 0xF2, 0xF0, 0x00}},
55     {PLDM_BIOS, {0xF1, 0xF0, 0xF0, 0x00}},
56     {PLDM_FRU, {0xF1, 0xF0, 0xF0, 0x00}},
57 #ifdef OEM_IBM
58     {PLDM_OEM, {0xF1, 0xF0, 0xF0, 0x00}},
59 #endif
60 };
61 
62 namespace base
63 {
64 
65 Response Handler::getPLDMTypes(const pldm_msg* request,
66                                size_t /*payloadLength*/)
67 {
68     // DSP0240 has this as a bitfield8[N], where N = 0 to 7
69     std::array<bitfield8_t, 8> types{};
70     for (const auto& type : capabilities)
71     {
72         auto index = type.first / 8;
73         // <Type Number> = <Array Index> * 8 + <bit position>
74         auto bit = type.first - (index * 8);
75         types[index].byte |= 1 << bit;
76     }
77 
78     Response response(sizeof(pldm_msg_hdr) + PLDM_GET_TYPES_RESP_BYTES, 0);
79     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
80     auto rc = encode_get_types_resp(request->hdr.instance_id, PLDM_SUCCESS,
81                                     types.data(), responsePtr);
82     if (rc != PLDM_SUCCESS)
83     {
84         return CmdHandler::ccOnlyResponse(request, rc);
85     }
86 
87     return response;
88 }
89 
90 Response Handler::getPLDMCommands(const pldm_msg* request, size_t payloadLength)
91 {
92     ver32_t version{};
93     Type type;
94 
95     Response response(sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_RESP_BYTES, 0);
96     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
97 
98     auto rc = decode_get_commands_req(request, payloadLength, &type, &version);
99 
100     if (rc != PLDM_SUCCESS)
101     {
102         return CmdHandler::ccOnlyResponse(request, rc);
103     }
104 
105     // DSP0240 has this as a bitfield8[N], where N = 0 to 31
106     std::array<bitfield8_t, 32> cmds{};
107     if (capabilities.find(type) == capabilities.end())
108     {
109         return CmdHandler::ccOnlyResponse(request,
110                                           PLDM_ERROR_INVALID_PLDM_TYPE);
111     }
112 
113     for (const auto& cmd : capabilities.at(type))
114     {
115         auto index = cmd / 8;
116         // <Type Number> = <Array Index> * 8 + <bit position>
117         auto bit = cmd - (index * 8);
118         cmds[index].byte |= 1 << bit;
119     }
120 
121     rc = encode_get_commands_resp(request->hdr.instance_id, PLDM_SUCCESS,
122                                   cmds.data(), responsePtr);
123     if (rc != PLDM_SUCCESS)
124     {
125         return ccOnlyResponse(request, rc);
126     }
127 
128     return response;
129 }
130 
131 Response Handler::getPLDMVersion(const pldm_msg* request, size_t payloadLength)
132 {
133     uint32_t transferHandle;
134     Type type;
135     uint8_t transferFlag;
136 
137     Response response(sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_RESP_BYTES, 0);
138     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
139 
140     uint8_t rc = decode_get_version_req(request, payloadLength, &transferHandle,
141                                         &transferFlag, &type);
142 
143     if (rc != PLDM_SUCCESS)
144     {
145         return CmdHandler::ccOnlyResponse(request, rc);
146     }
147 
148     ver32_t version{};
149     auto search = versions.find(type);
150 
151     if (search == versions.end())
152     {
153         return CmdHandler::ccOnlyResponse(request,
154                                           PLDM_ERROR_INVALID_PLDM_TYPE);
155     }
156 
157     memcpy(&version, &(search->second), sizeof(version));
158     rc = encode_get_version_resp(request->hdr.instance_id, PLDM_SUCCESS, 0,
159                                  PLDM_START_AND_END, &version,
160                                  sizeof(pldm_version), responsePtr);
161     if (rc != PLDM_SUCCESS)
162     {
163         return ccOnlyResponse(request, rc);
164     }
165 
166     return response;
167 }
168 
169 Response Handler::getTID(const pldm_msg* request, size_t /*payloadLength*/)
170 {
171     // assigned 1 to the bmc as the PLDM terminus
172     uint8_t tid = 1;
173 
174     Response response(sizeof(pldm_msg_hdr) + PLDM_GET_TID_RESP_BYTES, 0);
175     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
176     auto rc = encode_get_tid_resp(request->hdr.instance_id, PLDM_SUCCESS, tid,
177                                   responsePtr);
178     if (rc != PLDM_SUCCESS)
179     {
180         return ccOnlyResponse(request, rc);
181     }
182 
183     return response;
184 }
185 
186 } // namespace base
187 } // namespace responder
188 } // namespace pldm
189