107181f53STom Joseph #pragma once 207181f53STom Joseph 39e801a2bSVernon Mauery #include "message_handler.hpp" 407181f53STom Joseph 54f09eaeeSWilliam A. Kennington III #include <ipmid/api.h> 69e801a2bSVernon Mauery 79d9b7638SAndrew Geissler #include <cstddef> 89e801a2bSVernon Mauery #include <functional> 99e801a2bSVernon Mauery #include <map> 1007181f53STom Joseph 1107181f53STom Joseph namespace command 1207181f53STom Joseph { 1307181f53STom Joseph 1466501649SVernon Mauery struct CommandID 1507181f53STom Joseph { 1666501649SVernon Mauery static constexpr size_t lunBits = 2; CommandIDcommand::CommandID17099fb097SPatrick Williams CommandID(uint32_t command) : command(command) {} 1866501649SVernon Mauery netFnLuncommand::CommandID1966501649SVernon Mauery uint8_t netFnLun() const 2066501649SVernon Mauery { 2166501649SVernon Mauery return static_cast<uint8_t>(command >> CHAR_BIT); 2266501649SVernon Mauery } netFncommand::CommandID2366501649SVernon Mauery uint8_t netFn() const 2466501649SVernon Mauery { 2566501649SVernon Mauery return netFnLun() >> lunBits; 2666501649SVernon Mauery } luncommand::CommandID2766501649SVernon Mauery uint8_t lun() const 2866501649SVernon Mauery { 2966501649SVernon Mauery return netFnLun() & ((1 << (lunBits + 1)) - 1); 3066501649SVernon Mauery } cmdcommand::CommandID3166501649SVernon Mauery uint8_t cmd() const 3266501649SVernon Mauery { 3366501649SVernon Mauery return static_cast<uint8_t>(command); 3466501649SVernon Mauery } 3507181f53STom Joseph uint32_t command; 3666501649SVernon Mauery }; 3707181f53STom Joseph 383563f8feSTom Joseph /** 3907181f53STom Joseph * CommandFunctor is the functor register for commands defined in 4007181f53STom Joseph * phosphor-net-ipmid. This would take the request part of the command as a 4107181f53STom Joseph * vector and a reference to the message handler. The response part of the 4207181f53STom Joseph * command is returned as a vector. 4307181f53STom Joseph */ 4407181f53STom Joseph using CommandFunctor = std::function<std::vector<uint8_t>( 4541ff9b51SVernon Mauery const std::vector<uint8_t>&, std::shared_ptr<message::Handler>&)>; 4607181f53STom Joseph 473563f8feSTom Joseph /** 4807181f53STom Joseph * @struct CmdDetails 4907181f53STom Joseph * 5007181f53STom Joseph * Command details is used to register commands supported in phosphor-net-ipmid. 5107181f53STom Joseph */ 5207181f53STom Joseph struct CmdDetails 5307181f53STom Joseph { 5407181f53STom Joseph CommandID command; 5507181f53STom Joseph CommandFunctor functor; 5607181f53STom Joseph session::Privilege privilege; 5707181f53STom Joseph bool sessionless; 5807181f53STom Joseph }; 5907181f53STom Joseph 603563f8feSTom Joseph /** 6107181f53STom Joseph * @enum NetFns 6207181f53STom Joseph * 6307181f53STom Joseph * A field that identifies the functional class of the message. The Network 6407181f53STom Joseph * Function clusters IPMI commands into different sets. 6507181f53STom Joseph */ 6607181f53STom Joseph enum class NetFns 6707181f53STom Joseph { 6807181f53STom Joseph CHASSIS = (0x00 << 10), 6907181f53STom Joseph CHASSIS_RESP = (0x01 << 10), 7007181f53STom Joseph 7107181f53STom Joseph BRIDGE = (0x02 << 10), 7207181f53STom Joseph BRIDGE_RESP = (0x03 << 10), 7307181f53STom Joseph 7407181f53STom Joseph SENSOR = (0x04 << 10), 7507181f53STom Joseph SENSOR_RESP = (0x05 << 10), 7607181f53STom Joseph EVENT = (0x04 << 10), 7707181f53STom Joseph EVENT_RESP = (0x05 << 10), 7807181f53STom Joseph 7907181f53STom Joseph APP = (0x06 << 10), 8007181f53STom Joseph APP_RESP = (0x07 << 10), 8107181f53STom Joseph 8207181f53STom Joseph FIRMWARE = (0x08 << 10), 8307181f53STom Joseph FIRMWARE_RESP = (0x09 << 10), 8407181f53STom Joseph 8507181f53STom Joseph STORAGE = (0x0A << 10), 8607181f53STom Joseph STORAGE_RESP = (0x0B << 10), 8707181f53STom Joseph 8807181f53STom Joseph TRANSPORT = (0x0C << 10), 8907181f53STom Joseph TRANSPORT_RESP = (0x0D << 10), 9007181f53STom Joseph 9107181f53STom Joseph //>> 9207181f53STom Joseph RESERVED_START = (0x0E << 10), 9307181f53STom Joseph RESERVED_END = (0x2B << 10), 9407181f53STom Joseph //<< 9507181f53STom Joseph 9607181f53STom Joseph GROUP_EXTN = (0x2C << 10), 9707181f53STom Joseph GROUP_EXTN_RESP = (0x2D << 10), 9807181f53STom Joseph 9907181f53STom Joseph OEM = (0x2E << 10), 10007181f53STom Joseph OEM_RESP = (0x2F << 10), 10107181f53STom Joseph }; 10207181f53STom Joseph 1033563f8feSTom Joseph /** 10407181f53STom Joseph * @class Entry 10507181f53STom Joseph * 10607181f53STom Joseph * This is the base class for registering IPMI commands. There are two ways of 10707181f53STom Joseph * registering commands to phosphor-net-ipmid, the session related commands and 10807181f53STom Joseph * provider commands 10907181f53STom Joseph * 11007181f53STom Joseph * Every commands has a privilege level which mentions the minimum session 11107181f53STom Joseph * privilege level needed to execute the command 11207181f53STom Joseph */ 11307181f53STom Joseph 11407181f53STom Joseph class Entry 11507181f53STom Joseph { 11607181f53STom Joseph public: Entry(CommandID command,session::Privilege privilege)11707181f53STom Joseph Entry(CommandID command, session::Privilege privilege) : 1189e801a2bSVernon Mauery command(command), privilege(privilege) 119bc8958feSGeorge Liu {} 12007181f53STom Joseph 12107181f53STom Joseph /** 12207181f53STom Joseph * @brief Execute the command 12307181f53STom Joseph * 12407181f53STom Joseph * Execute the command 12507181f53STom Joseph * 12607181f53STom Joseph * @param[in] commandData - Request Data for the command 12707181f53STom Joseph * @param[in] handler - Reference to the Message Handler 12807181f53STom Joseph * 12907181f53STom Joseph * @return Response data for the command 13007181f53STom Joseph */ 131*33503e2aSPatrick Williams virtual std::vector<uint8_t> executeCommand( 132*33503e2aSPatrick Williams std::vector<uint8_t>& commandData, 1338d6f200cSVernon Mauery std::shared_ptr<message::Handler> handler) = 0; 13407181f53STom Joseph getCommand() const13507181f53STom Joseph auto getCommand() const 13607181f53STom Joseph { 13707181f53STom Joseph return command; 13807181f53STom Joseph } 13907181f53STom Joseph getPrivilege() const14007181f53STom Joseph auto getPrivilege() const 14107181f53STom Joseph { 14207181f53STom Joseph return privilege; 14307181f53STom Joseph } 14407181f53STom Joseph 14507181f53STom Joseph virtual ~Entry() = default; 14607181f53STom Joseph Entry(const Entry&) = default; 14707181f53STom Joseph Entry& operator=(const Entry&) = default; 14807181f53STom Joseph Entry(Entry&&) = default; 14907181f53STom Joseph Entry& operator=(Entry&&) = default; 15007181f53STom Joseph 15107181f53STom Joseph protected: 15207181f53STom Joseph CommandID command; 15307181f53STom Joseph 15407181f53STom Joseph // Specifies the minimum privilege level required to execute this command 15507181f53STom Joseph session::Privilege privilege; 15607181f53STom Joseph }; 15707181f53STom Joseph 1583563f8feSTom Joseph /** 15907181f53STom Joseph * @class NetIpmidEntry 16007181f53STom Joseph * 16107181f53STom Joseph * NetIpmidEntry is used to register commands that are consumed only in 16207181f53STom Joseph * phosphor-net-ipmid. The RAKP commands, session commands and user management 16307181f53STom Joseph * commands are examples of this. 16407181f53STom Joseph * 16507181f53STom Joseph * There are certain IPMI commands that can be executed before session can be 16607181f53STom Joseph * established like Get System GUID, Get Channel Authentication Capabilities 16707181f53STom Joseph * and RAKP commands. 16807181f53STom Joseph */ 16907181f53STom Joseph class NetIpmidEntry final : public Entry 17007181f53STom Joseph { 17107181f53STom Joseph public: NetIpmidEntry(CommandID command,CommandFunctor functor,session::Privilege privilege,bool sessionless)1729e801a2bSVernon Mauery NetIpmidEntry(CommandID command, CommandFunctor functor, 1739e801a2bSVernon Mauery session::Privilege privilege, bool sessionless) : 1748425624aSPatrick Williams Entry(command, privilege), functor(functor), sessionless(sessionless) 175bc8958feSGeorge Liu {} 17607181f53STom Joseph 17707181f53STom Joseph /** 17807181f53STom Joseph * @brief Execute the command 17907181f53STom Joseph * 18007181f53STom Joseph * Execute the command 18107181f53STom Joseph * 18207181f53STom Joseph * @param[in] commandData - Request Data for the command 18307181f53STom Joseph * @param[in] handler - Reference to the Message Handler 18407181f53STom Joseph * 18507181f53STom Joseph * @return Response data for the command 18607181f53STom Joseph */ 187*33503e2aSPatrick Williams std::vector<uint8_t> executeCommand( 188*33503e2aSPatrick Williams std::vector<uint8_t>& commandData, 1898d6f200cSVernon Mauery std::shared_ptr<message::Handler> handler) override; 19007181f53STom Joseph 19107181f53STom Joseph virtual ~NetIpmidEntry() = default; 19207181f53STom Joseph NetIpmidEntry(const NetIpmidEntry&) = default; 19307181f53STom Joseph NetIpmidEntry& operator=(const NetIpmidEntry&) = default; 19407181f53STom Joseph NetIpmidEntry(NetIpmidEntry&&) = default; 19507181f53STom Joseph NetIpmidEntry& operator=(NetIpmidEntry&&) = default; 19607181f53STom Joseph 19707181f53STom Joseph private: 19807181f53STom Joseph CommandFunctor functor; 19907181f53STom Joseph 20007181f53STom Joseph bool sessionless; 20107181f53STom Joseph }; 20207181f53STom Joseph 2033563f8feSTom Joseph /** 20407181f53STom Joseph * @class Table 20507181f53STom Joseph * 20607181f53STom Joseph * Table keeps the IPMI command entries as a sorted associative container with 20707181f53STom Joseph * Command ID as the unique key. It has interfaces for registering commands 20807181f53STom Joseph * and executing a command. 20907181f53STom Joseph */ 21007181f53STom Joseph class Table 21107181f53STom Joseph { 2122085ae07SVernon Mauery private: 2132085ae07SVernon Mauery struct Private 214bc8958feSGeorge Liu {}; 2152085ae07SVernon Mauery 21607181f53STom Joseph public: Table(const Private &)217099fb097SPatrick Williams explicit Table(const Private&) {} 2182085ae07SVernon Mauery Table() = delete; 21907181f53STom Joseph ~Table() = default; 22007181f53STom Joseph // Command Table is a singleton so copy, copy-assignment, move and 22107181f53STom Joseph // move assignment is deleted 22207181f53STom Joseph Table(const Table&) = delete; 22307181f53STom Joseph Table& operator=(const Table&) = delete; 22407181f53STom Joseph Table(Table&&) = default; 22507181f53STom Joseph Table& operator=(Table&&) = default; 22607181f53STom Joseph 2272085ae07SVernon Mauery /** 2282085ae07SVernon Mauery * @brief Get a reference to the singleton Table 2292085ae07SVernon Mauery * 2302085ae07SVernon Mauery * @return Table reference 2312085ae07SVernon Mauery */ get()2322085ae07SVernon Mauery static Table& get() 2332085ae07SVernon Mauery { 2342085ae07SVernon Mauery static std::shared_ptr<Table> ptr = nullptr; 2352085ae07SVernon Mauery if (!ptr) 2362085ae07SVernon Mauery { 2372085ae07SVernon Mauery ptr = std::make_shared<Table>(Private()); 2382085ae07SVernon Mauery } 2392085ae07SVernon Mauery return *ptr; 2402085ae07SVernon Mauery } 2412085ae07SVernon Mauery 24207181f53STom Joseph using CommandTable = std::map<uint32_t, std::unique_ptr<Entry>>; 24307181f53STom Joseph 24407181f53STom Joseph /** 24507181f53STom Joseph * @brief Register a command 24607181f53STom Joseph * 24707181f53STom Joseph * Register a command with the command table 24807181f53STom Joseph * 24907181f53STom Joseph * @param[in] inCommand - Command ID 25007181f53STom Joseph * @param[in] entry - Command Entry 25107181f53STom Joseph * 25207181f53STom Joseph * @return: None 25307181f53STom Joseph * 254bd45aae1SFeist, James * @note: Duplicate registrations will be rejected. 255bd45aae1SFeist, James * 25607181f53STom Joseph */ 2579e801a2bSVernon Mauery void registerCommand(CommandID inCommand, std::unique_ptr<Entry>&& entry); 25807181f53STom Joseph 25907181f53STom Joseph /** 26007181f53STom Joseph * @brief Execute the command 26107181f53STom Joseph * 26207181f53STom Joseph * Execute the command for the corresponding CommandID 26307181f53STom Joseph * 26407181f53STom Joseph * @param[in] inCommand - Command ID to execute. 26507181f53STom Joseph * @param[in] commandData - Request Data for the command 26607181f53STom Joseph * @param[in] handler - Reference to the Message Handler 26707181f53STom Joseph * 26807181f53STom Joseph */ 2698d6f200cSVernon Mauery void executeCommand(uint32_t inCommand, std::vector<uint8_t>& commandData, 2708d6f200cSVernon Mauery std::shared_ptr<message::Handler> handler); 2719e801a2bSVernon Mauery 27207181f53STom Joseph private: 27307181f53STom Joseph CommandTable commandTable; 27407181f53STom Joseph }; 27507181f53STom Joseph 27607181f53STom Joseph } // namespace command 277