| #pragma once |
| |
| #include "message_handler.hpp" |
| |
| #include <ipmid/api.h> |
| |
| #include <cstddef> |
| #include <functional> |
| #include <map> |
| |
| namespace command |
| { |
| |
| struct CommandID |
| { |
| static constexpr size_t lunBits = 2; |
| CommandID(uint32_t command) : command(command) |
| { |
| } |
| |
| uint8_t netFnLun() const |
| { |
| return static_cast<uint8_t>(command >> CHAR_BIT); |
| } |
| uint8_t netFn() const |
| { |
| return netFnLun() >> lunBits; |
| } |
| uint8_t lun() const |
| { |
| return netFnLun() & ((1 << (lunBits + 1)) - 1); |
| } |
| uint8_t cmd() const |
| { |
| return static_cast<uint8_t>(command); |
| } |
| uint32_t command; |
| }; |
| |
| /** |
| * CommandFunctor is the functor register for commands defined in |
| * phosphor-net-ipmid. This would take the request part of the command as a |
| * vector and a reference to the message handler. The response part of the |
| * command is returned as a vector. |
| */ |
| using CommandFunctor = std::function<std::vector<uint8_t>( |
| const std::vector<uint8_t>&, std::shared_ptr<message::Handler>&)>; |
| |
| /** |
| * @struct CmdDetails |
| * |
| * Command details is used to register commands supported in phosphor-net-ipmid. |
| */ |
| struct CmdDetails |
| { |
| CommandID command; |
| CommandFunctor functor; |
| session::Privilege privilege; |
| bool sessionless; |
| }; |
| |
| /** |
| * @enum NetFns |
| * |
| * A field that identifies the functional class of the message. The Network |
| * Function clusters IPMI commands into different sets. |
| */ |
| enum class NetFns |
| { |
| CHASSIS = (0x00 << 10), |
| CHASSIS_RESP = (0x01 << 10), |
| |
| BRIDGE = (0x02 << 10), |
| BRIDGE_RESP = (0x03 << 10), |
| |
| SENSOR = (0x04 << 10), |
| SENSOR_RESP = (0x05 << 10), |
| EVENT = (0x04 << 10), |
| EVENT_RESP = (0x05 << 10), |
| |
| APP = (0x06 << 10), |
| APP_RESP = (0x07 << 10), |
| |
| FIRMWARE = (0x08 << 10), |
| FIRMWARE_RESP = (0x09 << 10), |
| |
| STORAGE = (0x0A << 10), |
| STORAGE_RESP = (0x0B << 10), |
| |
| TRANSPORT = (0x0C << 10), |
| TRANSPORT_RESP = (0x0D << 10), |
| |
| //>> |
| RESERVED_START = (0x0E << 10), |
| RESERVED_END = (0x2B << 10), |
| //<< |
| |
| GROUP_EXTN = (0x2C << 10), |
| GROUP_EXTN_RESP = (0x2D << 10), |
| |
| OEM = (0x2E << 10), |
| OEM_RESP = (0x2F << 10), |
| }; |
| |
| /** |
| * @class Entry |
| * |
| * This is the base class for registering IPMI commands. There are two ways of |
| * registering commands to phosphor-net-ipmid, the session related commands and |
| * provider commands |
| * |
| * Every commands has a privilege level which mentions the minimum session |
| * privilege level needed to execute the command |
| */ |
| |
| class Entry |
| { |
| |
| public: |
| Entry(CommandID command, session::Privilege privilege) : |
| command(command), privilege(privilege) |
| { |
| } |
| |
| /** |
| * @brief Execute the command |
| * |
| * Execute the command |
| * |
| * @param[in] commandData - Request Data for the command |
| * @param[in] handler - Reference to the Message Handler |
| * |
| * @return Response data for the command |
| */ |
| virtual std::vector<uint8_t> |
| executeCommand(std::vector<uint8_t>& commandData, |
| std::shared_ptr<message::Handler> handler) = 0; |
| |
| auto getCommand() const |
| { |
| return command; |
| } |
| |
| auto getPrivilege() const |
| { |
| return privilege; |
| } |
| |
| virtual ~Entry() = default; |
| Entry(const Entry&) = default; |
| Entry& operator=(const Entry&) = default; |
| Entry(Entry&&) = default; |
| Entry& operator=(Entry&&) = default; |
| |
| protected: |
| CommandID command; |
| |
| // Specifies the minimum privilege level required to execute this command |
| session::Privilege privilege; |
| }; |
| |
| /** |
| * @class NetIpmidEntry |
| * |
| * NetIpmidEntry is used to register commands that are consumed only in |
| * phosphor-net-ipmid. The RAKP commands, session commands and user management |
| * commands are examples of this. |
| * |
| * There are certain IPMI commands that can be executed before session can be |
| * established like Get System GUID, Get Channel Authentication Capabilities |
| * and RAKP commands. |
| */ |
| class NetIpmidEntry final : public Entry |
| { |
| |
| public: |
| NetIpmidEntry(CommandID command, CommandFunctor functor, |
| session::Privilege privilege, bool sessionless) : |
| Entry(command, privilege), |
| functor(functor), sessionless(sessionless) |
| { |
| } |
| |
| /** |
| * @brief Execute the command |
| * |
| * Execute the command |
| * |
| * @param[in] commandData - Request Data for the command |
| * @param[in] handler - Reference to the Message Handler |
| * |
| * @return Response data for the command |
| */ |
| std::vector<uint8_t> |
| executeCommand(std::vector<uint8_t>& commandData, |
| std::shared_ptr<message::Handler> handler) override; |
| |
| virtual ~NetIpmidEntry() = default; |
| NetIpmidEntry(const NetIpmidEntry&) = default; |
| NetIpmidEntry& operator=(const NetIpmidEntry&) = default; |
| NetIpmidEntry(NetIpmidEntry&&) = default; |
| NetIpmidEntry& operator=(NetIpmidEntry&&) = default; |
| |
| private: |
| CommandFunctor functor; |
| |
| bool sessionless; |
| }; |
| |
| /** |
| * @class Table |
| * |
| * Table keeps the IPMI command entries as a sorted associative container with |
| * Command ID as the unique key. It has interfaces for registering commands |
| * and executing a command. |
| */ |
| class Table |
| { |
| private: |
| struct Private |
| { |
| }; |
| |
| public: |
| explicit Table(const Private&) |
| { |
| } |
| Table() = delete; |
| ~Table() = default; |
| // Command Table is a singleton so copy, copy-assignment, move and |
| // move assignment is deleted |
| Table(const Table&) = delete; |
| Table& operator=(const Table&) = delete; |
| Table(Table&&) = default; |
| Table& operator=(Table&&) = default; |
| |
| /** |
| * @brief Get a reference to the singleton Table |
| * |
| * @return Table reference |
| */ |
| static Table& get() |
| { |
| static std::shared_ptr<Table> ptr = nullptr; |
| if (!ptr) |
| { |
| ptr = std::make_shared<Table>(Private()); |
| } |
| return *ptr; |
| } |
| |
| using CommandTable = std::map<uint32_t, std::unique_ptr<Entry>>; |
| |
| /** |
| * @brief Register a command |
| * |
| * Register a command with the command table |
| * |
| * @param[in] inCommand - Command ID |
| * @param[in] entry - Command Entry |
| * |
| * @return: None |
| * |
| * @note: Duplicate registrations will be rejected. |
| * |
| */ |
| void registerCommand(CommandID inCommand, std::unique_ptr<Entry>&& entry); |
| |
| /** |
| * @brief Execute the command |
| * |
| * Execute the command for the corresponding CommandID |
| * |
| * @param[in] inCommand - Command ID to execute. |
| * @param[in] commandData - Request Data for the command |
| * @param[in] handler - Reference to the Message Handler |
| * |
| */ |
| void executeCommand(uint32_t inCommand, std::vector<uint8_t>& commandData, |
| std::shared_ptr<message::Handler> handler); |
| |
| private: |
| CommandTable commandTable; |
| }; |
| |
| } // namespace command |