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