blob: 03e1a48cf6137d3176c7d341d4c8722d38ea26b5 [file] [log] [blame]
Tom Joseph07181f52016-08-08 08:17:08 -05001#pragma once
2
Vernon Mauery9e801a22018-10-12 13:20:49 -07003#include "message_handler.hpp"
Tom Joseph07181f52016-08-08 08:17:08 -05004
William A. Kennington III4f09eae2019-02-12 17:10:35 -08005#include <ipmid/api.h>
Vernon Mauery9e801a22018-10-12 13:20:49 -07006
Andrew Geissler9d9b7632020-05-17 09:18:05 -05007#include <cstddef>
Vernon Mauery9e801a22018-10-12 13:20:49 -07008#include <functional>
9#include <map>
Tom Joseph07181f52016-08-08 08:17:08 -050010
11namespace command
12{
13
Vernon Mauery66501642018-07-30 09:07:10 -070014struct CommandID
Tom Joseph07181f52016-08-08 08:17:08 -050015{
Vernon Mauery66501642018-07-30 09:07:10 -070016 static constexpr size_t lunBits = 2;
Patrick Williams099fb092023-05-10 07:50:31 -050017 CommandID(uint32_t command) : command(command) {}
Tom Joseph07181f52016-08-08 08:17:08 -050018
Vernon Mauery66501642018-07-30 09:07:10 -070019 uint8_t netFnLun() const
20 {
21 return static_cast<uint8_t>(command >> CHAR_BIT);
22 }
23 uint8_t netFn() const
24 {
25 return netFnLun() >> lunBits;
26 }
27 uint8_t lun() const
28 {
29 return netFnLun() & ((1 << (lunBits + 1)) - 1);
30 }
31 uint8_t cmd() const
32 {
33 return static_cast<uint8_t>(command);
34 }
35 uint32_t command;
36};
Tom Joseph07181f52016-08-08 08:17:08 -050037
Tom Joseph3563f8f2017-05-08 15:42:54 +053038/**
Tom Joseph07181f52016-08-08 08:17:08 -050039 * CommandFunctor is the functor register for commands defined in
40 * phosphor-net-ipmid. This would take the request part of the command as a
41 * vector and a reference to the message handler. The response part of the
42 * command is returned as a vector.
43 */
44using CommandFunctor = std::function<std::vector<uint8_t>(
Vernon Mauery41ff9b52021-06-11 11:37:40 -070045 const std::vector<uint8_t>&, std::shared_ptr<message::Handler>&)>;
Tom Joseph07181f52016-08-08 08:17:08 -050046
Tom Joseph3563f8f2017-05-08 15:42:54 +053047/**
Tom Joseph07181f52016-08-08 08:17:08 -050048 * @struct CmdDetails
49 *
50 * Command details is used to register commands supported in phosphor-net-ipmid.
51 */
52struct CmdDetails
53{
54 CommandID command;
55 CommandFunctor functor;
56 session::Privilege privilege;
57 bool sessionless;
58};
59
Tom Joseph3563f8f2017-05-08 15:42:54 +053060/**
Tom Joseph07181f52016-08-08 08:17:08 -050061 * @enum NetFns
62 *
63 * A field that identifies the functional class of the message. The Network
64 * Function clusters IPMI commands into different sets.
65 */
66enum class NetFns
67{
Vernon Mauery9e801a22018-10-12 13:20:49 -070068 CHASSIS = (0x00 << 10),
69 CHASSIS_RESP = (0x01 << 10),
Tom Joseph07181f52016-08-08 08:17:08 -050070
Vernon Mauery9e801a22018-10-12 13:20:49 -070071 BRIDGE = (0x02 << 10),
72 BRIDGE_RESP = (0x03 << 10),
Tom Joseph07181f52016-08-08 08:17:08 -050073
Vernon Mauery9e801a22018-10-12 13:20:49 -070074 SENSOR = (0x04 << 10),
75 SENSOR_RESP = (0x05 << 10),
76 EVENT = (0x04 << 10),
77 EVENT_RESP = (0x05 << 10),
Tom Joseph07181f52016-08-08 08:17:08 -050078
Vernon Mauery9e801a22018-10-12 13:20:49 -070079 APP = (0x06 << 10),
80 APP_RESP = (0x07 << 10),
Tom Joseph07181f52016-08-08 08:17:08 -050081
Vernon Mauery9e801a22018-10-12 13:20:49 -070082 FIRMWARE = (0x08 << 10),
83 FIRMWARE_RESP = (0x09 << 10),
Tom Joseph07181f52016-08-08 08:17:08 -050084
Vernon Mauery9e801a22018-10-12 13:20:49 -070085 STORAGE = (0x0A << 10),
86 STORAGE_RESP = (0x0B << 10),
Tom Joseph07181f52016-08-08 08:17:08 -050087
Vernon Mauery9e801a22018-10-12 13:20:49 -070088 TRANSPORT = (0x0C << 10),
89 TRANSPORT_RESP = (0x0D << 10),
Tom Joseph07181f52016-08-08 08:17:08 -050090
91 //>>
Vernon Mauery9e801a22018-10-12 13:20:49 -070092 RESERVED_START = (0x0E << 10),
93 RESERVED_END = (0x2B << 10),
Tom Joseph07181f52016-08-08 08:17:08 -050094 //<<
95
Vernon Mauery9e801a22018-10-12 13:20:49 -070096 GROUP_EXTN = (0x2C << 10),
97 GROUP_EXTN_RESP = (0x2D << 10),
Tom Joseph07181f52016-08-08 08:17:08 -050098
Vernon Mauery9e801a22018-10-12 13:20:49 -070099 OEM = (0x2E << 10),
100 OEM_RESP = (0x2F << 10),
Tom Joseph07181f52016-08-08 08:17:08 -0500101};
102
Tom Joseph3563f8f2017-05-08 15:42:54 +0530103/**
Tom Joseph07181f52016-08-08 08:17:08 -0500104 * @class Entry
105 *
106 * This is the base class for registering IPMI commands. There are two ways of
107 * registering commands to phosphor-net-ipmid, the session related commands and
108 * provider commands
109 *
110 * Every commands has a privilege level which mentions the minimum session
111 * privilege level needed to execute the command
112 */
113
114class Entry
115{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700116 public:
117 Entry(CommandID command, session::Privilege privilege) :
118 command(command), privilege(privilege)
George Liubc8958f2022-07-04 09:29:49 +0800119 {}
Tom Joseph07181f52016-08-08 08:17:08 -0500120
Vernon Mauery9e801a22018-10-12 13:20:49 -0700121 /**
122 * @brief Execute the command
123 *
124 * Execute the command
125 *
126 * @param[in] commandData - Request Data for the command
127 * @param[in] handler - Reference to the Message Handler
128 *
129 * @return Response data for the command
130 */
131 virtual std::vector<uint8_t>
132 executeCommand(std::vector<uint8_t>& commandData,
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800133 std::shared_ptr<message::Handler> handler) = 0;
Tom Joseph07181f52016-08-08 08:17:08 -0500134
Vernon Mauery9e801a22018-10-12 13:20:49 -0700135 auto getCommand() const
136 {
137 return command;
138 }
Tom Joseph07181f52016-08-08 08:17:08 -0500139
Vernon Mauery9e801a22018-10-12 13:20:49 -0700140 auto getPrivilege() const
141 {
142 return privilege;
143 }
Tom Joseph07181f52016-08-08 08:17:08 -0500144
Vernon Mauery9e801a22018-10-12 13:20:49 -0700145 virtual ~Entry() = default;
146 Entry(const Entry&) = default;
147 Entry& operator=(const Entry&) = default;
148 Entry(Entry&&) = default;
149 Entry& operator=(Entry&&) = default;
Tom Joseph07181f52016-08-08 08:17:08 -0500150
Vernon Mauery9e801a22018-10-12 13:20:49 -0700151 protected:
152 CommandID command;
Tom Joseph07181f52016-08-08 08:17:08 -0500153
Vernon Mauery9e801a22018-10-12 13:20:49 -0700154 // Specifies the minimum privilege level required to execute this command
155 session::Privilege privilege;
Tom Joseph07181f52016-08-08 08:17:08 -0500156};
157
Tom Joseph3563f8f2017-05-08 15:42:54 +0530158/**
Tom Joseph07181f52016-08-08 08:17:08 -0500159 * @class NetIpmidEntry
160 *
161 * NetIpmidEntry is used to register commands that are consumed only in
162 * phosphor-net-ipmid. The RAKP commands, session commands and user management
163 * commands are examples of this.
164 *
165 * There are certain IPMI commands that can be executed before session can be
166 * established like Get System GUID, Get Channel Authentication Capabilities
167 * and RAKP commands.
168 */
Vernon Mauery9e801a22018-10-12 13:20:49 -0700169class NetIpmidEntry final : public Entry
Tom Joseph07181f52016-08-08 08:17:08 -0500170{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700171 public:
172 NetIpmidEntry(CommandID command, CommandFunctor functor,
173 session::Privilege privilege, bool sessionless) :
174 Entry(command, privilege),
175 functor(functor), sessionless(sessionless)
George Liubc8958f2022-07-04 09:29:49 +0800176 {}
Tom Joseph07181f52016-08-08 08:17:08 -0500177
Vernon Mauery9e801a22018-10-12 13:20:49 -0700178 /**
179 * @brief Execute the command
180 *
181 * Execute the command
182 *
183 * @param[in] commandData - Request Data for the command
184 * @param[in] handler - Reference to the Message Handler
185 *
186 * @return Response data for the command
187 */
188 std::vector<uint8_t>
189 executeCommand(std::vector<uint8_t>& commandData,
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800190 std::shared_ptr<message::Handler> handler) override;
Tom Joseph07181f52016-08-08 08:17:08 -0500191
Vernon Mauery9e801a22018-10-12 13:20:49 -0700192 virtual ~NetIpmidEntry() = default;
193 NetIpmidEntry(const NetIpmidEntry&) = default;
194 NetIpmidEntry& operator=(const NetIpmidEntry&) = default;
195 NetIpmidEntry(NetIpmidEntry&&) = default;
196 NetIpmidEntry& operator=(NetIpmidEntry&&) = default;
Tom Joseph07181f52016-08-08 08:17:08 -0500197
Vernon Mauery9e801a22018-10-12 13:20:49 -0700198 private:
199 CommandFunctor functor;
Tom Joseph07181f52016-08-08 08:17:08 -0500200
Vernon Mauery9e801a22018-10-12 13:20:49 -0700201 bool sessionless;
Tom Joseph07181f52016-08-08 08:17:08 -0500202};
203
Tom Joseph3563f8f2017-05-08 15:42:54 +0530204/**
Tom Joseph07181f52016-08-08 08:17:08 -0500205 * @class Table
206 *
207 * Table keeps the IPMI command entries as a sorted associative container with
208 * Command ID as the unique key. It has interfaces for registering commands
209 * and executing a command.
210 */
211class Table
212{
Vernon Mauery2085ae02021-06-10 11:51:00 -0700213 private:
214 struct Private
George Liubc8958f2022-07-04 09:29:49 +0800215 {};
Vernon Mauery2085ae02021-06-10 11:51:00 -0700216
Vernon Mauery9e801a22018-10-12 13:20:49 -0700217 public:
Patrick Williams099fb092023-05-10 07:50:31 -0500218 explicit Table(const Private&) {}
Vernon Mauery2085ae02021-06-10 11:51:00 -0700219 Table() = delete;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700220 ~Table() = default;
221 // Command Table is a singleton so copy, copy-assignment, move and
222 // move assignment is deleted
223 Table(const Table&) = delete;
224 Table& operator=(const Table&) = delete;
225 Table(Table&&) = default;
226 Table& operator=(Table&&) = default;
Tom Joseph07181f52016-08-08 08:17:08 -0500227
Vernon Mauery2085ae02021-06-10 11:51:00 -0700228 /**
229 * @brief Get a reference to the singleton Table
230 *
231 * @return Table reference
232 */
233 static Table& get()
234 {
235 static std::shared_ptr<Table> ptr = nullptr;
236 if (!ptr)
237 {
238 ptr = std::make_shared<Table>(Private());
239 }
240 return *ptr;
241 }
242
Vernon Mauery9e801a22018-10-12 13:20:49 -0700243 using CommandTable = std::map<uint32_t, std::unique_ptr<Entry>>;
Tom Joseph07181f52016-08-08 08:17:08 -0500244
Vernon Mauery9e801a22018-10-12 13:20:49 -0700245 /**
246 * @brief Register a command
247 *
248 * Register a command with the command table
249 *
250 * @param[in] inCommand - Command ID
251 * @param[in] entry - Command Entry
252 *
253 * @return: None
254 *
255 * @note: Duplicate registrations will be rejected.
256 *
257 */
258 void registerCommand(CommandID inCommand, std::unique_ptr<Entry>&& entry);
Tom Joseph07181f52016-08-08 08:17:08 -0500259
Vernon Mauery9e801a22018-10-12 13:20:49 -0700260 /**
261 * @brief Execute the command
262 *
263 * Execute the command for the corresponding CommandID
264 *
265 * @param[in] inCommand - Command ID to execute.
266 * @param[in] commandData - Request Data for the command
267 * @param[in] handler - Reference to the Message Handler
268 *
Vernon Mauery9e801a22018-10-12 13:20:49 -0700269 */
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800270 void executeCommand(uint32_t inCommand, std::vector<uint8_t>& commandData,
271 std::shared_ptr<message::Handler> handler);
Tom Joseph07181f52016-08-08 08:17:08 -0500272
Vernon Mauery9e801a22018-10-12 13:20:49 -0700273 private:
274 CommandTable commandTable;
Tom Joseph07181f52016-08-08 08:17:08 -0500275};
276
Vernon Mauery9e801a22018-10-12 13:20:49 -0700277} // namespace command