blob: 7a6ee8168b88ea92e3c8015ef526b8193e0e6eb6 [file] [log] [blame]
Tom Joseph07181f52016-08-08 08:17:08 -05001#pragma once
2
3#include <functional>
4#include <map>
5
Tom606e8cb2016-12-02 13:36:14 +05306#include <host-ipmid/ipmid-api.h>
Tom Joseph07181f52016-08-08 08:17:08 -05007#include "message_handler.hpp"
8
9namespace command
10{
11
12union CommandID
13{
14 uint32_t command;
15
16 uint8_t reserved;
17 message::PayloadType payloadType;
18
19 union
20 {
21 uint8_t netFn: 6;
22 uint8_t lun: 2;
23
24 uint8_t netFnLun;
25 } NetFnLun;
26
27 uint8_t cmd;
28} __attribute__((packed));
29
30/*
31 * CommandFunctor is the functor register for commands defined in
32 * phosphor-net-ipmid. This would take the request part of the command as a
33 * vector and a reference to the message handler. The response part of the
34 * command is returned as a vector.
35 */
36using CommandFunctor = std::function<std::vector<uint8_t>(
37 std::vector<uint8_t>&, const message::Handler&)>;
38
39/*
40 * @struct CmdDetails
41 *
42 * Command details is used to register commands supported in phosphor-net-ipmid.
43 */
44struct CmdDetails
45{
46 CommandID command;
47 CommandFunctor functor;
48 session::Privilege privilege;
49 bool sessionless;
50};
51
52/*
53 * @enum NetFns
54 *
55 * A field that identifies the functional class of the message. The Network
56 * Function clusters IPMI commands into different sets.
57 */
58enum class NetFns
59{
60 CHASSIS = (0x00 << 10),
61 CHASSIS_RESP = (0x01 << 10),
62
63 BRIDGE = (0x02 << 10),
64 BRIDGE_RESP = (0x03 << 10),
65
66 SENSOR = (0x04 << 10),
67 SENSOR_RESP = (0x05 << 10),
68 EVENT = (0x04 << 10),
69 EVENT_RESP = (0x05 << 10),
70
71 APP = (0x06 << 10),
72 APP_RESP = (0x07 << 10),
73
74 FIRMWARE = (0x08 << 10),
75 FIRMWARE_RESP = (0x09 << 10),
76
77 STORAGE = (0x0A << 10),
78 STORAGE_RESP = (0x0B << 10),
79
80 TRANSPORT = (0x0C << 10),
81 TRANSPORT_RESP = (0x0D << 10),
82
83 //>>
84 RESERVED_START = (0x0E << 10),
85 RESERVED_END = (0x2B << 10),
86 //<<
87
88 GROUP_EXTN = (0x2C << 10),
89 GROUP_EXTN_RESP = (0x2D << 10),
90
91 OEM = (0x2E << 10),
92 OEM_RESP = (0x2F << 10),
93};
94
95/*
96 * @class Entry
97 *
98 * This is the base class for registering IPMI commands. There are two ways of
99 * registering commands to phosphor-net-ipmid, the session related commands and
100 * provider commands
101 *
102 * Every commands has a privilege level which mentions the minimum session
103 * privilege level needed to execute the command
104 */
105
106class Entry
107{
108
109 public:
110 Entry(CommandID command, session::Privilege privilege):
111 command(command),
112 privilege(privilege) {}
113
114 /**
115 * @brief Execute the command
116 *
117 * Execute the command
118 *
119 * @param[in] commandData - Request Data for the command
120 * @param[in] handler - Reference to the Message Handler
121 *
122 * @return Response data for the command
123 */
124 virtual std::vector<uint8_t> executeCommand(
125 std::vector<uint8_t>& commandData,
126 const message::Handler& handler) = 0;
127
128 auto getCommand() const
129 {
130 return command;
131 }
132
133 auto getPrivilege() const
134 {
135 return privilege;
136 }
137
138 virtual ~Entry() = default;
139 Entry(const Entry&) = default;
140 Entry& operator=(const Entry&) = default;
141 Entry(Entry&&) = default;
142 Entry& operator=(Entry&&) = default;
143
144 protected:
145 CommandID command;
146
147 //Specifies the minimum privilege level required to execute this command
148 session::Privilege privilege;
149};
150
151/*
152 * @class NetIpmidEntry
153 *
154 * NetIpmidEntry is used to register commands that are consumed only in
155 * phosphor-net-ipmid. The RAKP commands, session commands and user management
156 * commands are examples of this.
157 *
158 * There are certain IPMI commands that can be executed before session can be
159 * established like Get System GUID, Get Channel Authentication Capabilities
160 * and RAKP commands.
161 */
162class NetIpmidEntry final: public Entry
163{
164
165 public:
166 NetIpmidEntry(CommandID command,
167 CommandFunctor functor,
168 session::Privilege privilege,
169 bool sessionless):
170 Entry(command, privilege),
171 functor(functor),
172 sessionless(sessionless) {}
173
174 /**
175 * @brief Execute the command
176 *
177 * Execute the command
178 *
179 * @param[in] commandData - Request Data for the command
180 * @param[in] handler - Reference to the Message Handler
181 *
182 * @return Response data for the command
183 */
184 std::vector<uint8_t> executeCommand(std::vector<uint8_t>& commandData,
185 const message::Handler& handler)
186 override;
187
188 virtual ~NetIpmidEntry() = default;
189 NetIpmidEntry(const NetIpmidEntry&) = default;
190 NetIpmidEntry& operator=(const NetIpmidEntry&) = default;
191 NetIpmidEntry(NetIpmidEntry&&) = default;
192 NetIpmidEntry& operator=(NetIpmidEntry&&) = default;
193
194 private:
195 CommandFunctor functor;
196
197 bool sessionless;
198};
199
200/*
Tom606e8cb2016-12-02 13:36:14 +0530201 * @class ProviderIpmidEntry
202 *
203 * ProviderIpmidEntry is used to register commands to the Command Table, that
204 * are registered by IPMI provider libraries.
205 *
206 */
207class ProviderIpmidEntry final: public Entry
208{
209 public:
210 ProviderIpmidEntry(CommandID command,
211 ipmid_callback_t functor,
212 session::Privilege privilege):
213 Entry(command, privilege),
214 functor(functor) {}
215
216 /**
217 * @brief Execute the command
218 *
219 * Execute the callback handler
220 *
221 * @param[in] commandData - Request Data for the command
222 * @param[in] handler - Reference to the Message Handler
223 *
224 * @return Response data for the command
225 */
226 std::vector<uint8_t> executeCommand(std::vector<uint8_t>& commandData,
227 const message::Handler& handler)
228 override;
229
230 virtual ~ProviderIpmidEntry() = default;
231 ProviderIpmidEntry(const ProviderIpmidEntry&) = default;
232 ProviderIpmidEntry& operator=(const ProviderIpmidEntry&) = default;
233 ProviderIpmidEntry(ProviderIpmidEntry&&) = default;
234 ProviderIpmidEntry& operator=(ProviderIpmidEntry&&) = default;
235
236 private:
237 ipmid_callback_t functor;
238};
239
240/*
Tom Joseph07181f52016-08-08 08:17:08 -0500241 * @class Table
242 *
243 * Table keeps the IPMI command entries as a sorted associative container with
244 * Command ID as the unique key. It has interfaces for registering commands
245 * and executing a command.
246 */
247class Table
248{
249 public:
250
251 Table() = default;
252 ~Table() = default;
253 // Command Table is a singleton so copy, copy-assignment, move and
254 // move assignment is deleted
255 Table(const Table&) = delete;
256 Table& operator=(const Table&) = delete;
257 Table(Table&&) = default;
258 Table& operator=(Table&&) = default;
259
260 using CommandTable = std::map<uint32_t, std::unique_ptr<Entry>>;
261
262 /**
263 * @brief Register a command
264 *
265 * Register a command with the command table
266 *
267 * @param[in] inCommand - Command ID
268 * @param[in] entry - Command Entry
269 *
270 * @return: None
271 *
272 * @note Registering an already registered command will overwrite the
273 * existing entry with the new one.
274 */
275 void registerCommand(CommandID inCommand,
276 std::unique_ptr<Entry>&& entry);
277
278 /**
279 * @brief Execute the command
280 *
281 * Execute the command for the corresponding CommandID
282 *
283 * @param[in] inCommand - Command ID to execute.
284 * @param[in] commandData - Request Data for the command
285 * @param[in] handler - Reference to the Message Handler
286 *
287 * @return Response data for the command
288 */
289 std::vector<uint8_t> executeCommand(uint32_t inCommand,
290 std::vector<uint8_t>& commandData,
291 const message::Handler& handler);
292 private:
293 CommandTable commandTable;
294};
295
296}// namespace command