xref: /openbmc/phosphor-net-ipmid/command_table.hpp (revision 33503e2a90d5615a11ec2d27961ffdefc3a5cd10)
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