1 #pragma once 2 3 #include <functional> 4 #include <map> 5 6 #include <host-ipmid/ipmid-api.h> 7 #include "message_handler.hpp" 8 9 namespace command 10 { 11 12 union 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 */ 36 using 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 */ 44 struct 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 */ 58 enum 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 106 class 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 */ 162 class 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 /* 201 * @class ProviderIpmidEntry 202 * 203 * ProviderIpmidEntry is used to register commands to the Command Table, that 204 * are registered by IPMI provider libraries. 205 * 206 */ 207 class 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 /* 241 * @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 */ 247 class 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 297