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