| #pragma once |
| |
| #include "message_handler.hpp" |
| |
| #include <host-ipmid/ipmid-api.h> |
| |
| #include <functional> |
| #include <map> |
| |
| namespace command |
| { |
| |
| union CommandID |
| { |
| uint32_t command; |
| |
| uint8_t reserved; |
| message::PayloadType payloadType; |
| |
| union |
| { |
| uint8_t netFn : 6; |
| uint8_t lun : 2; |
| |
| uint8_t netFnLun; |
| } NetFnLun; |
| |
| uint8_t cmd; |
| } __attribute__((packed)); |
| |
| /** |
| * 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>&, const 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, |
| const 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, |
| const 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 ProviderIpmidEntry |
| * |
| * ProviderIpmidEntry is used to register commands to the Command Table, that |
| * are registered by IPMI provider libraries. |
| * |
| */ |
| class ProviderIpmidEntry final : public Entry |
| { |
| public: |
| ProviderIpmidEntry(CommandID command, ipmid_callback_t functor, |
| session::Privilege privilege) : |
| Entry(command, privilege), |
| functor(functor) |
| { |
| } |
| |
| /** |
| * @brief Execute the command |
| * |
| * Execute the callback handler |
| * |
| * @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, |
| const message::Handler& handler) override; |
| |
| virtual ~ProviderIpmidEntry() = default; |
| ProviderIpmidEntry(const ProviderIpmidEntry&) = default; |
| ProviderIpmidEntry& operator=(const ProviderIpmidEntry&) = default; |
| ProviderIpmidEntry(ProviderIpmidEntry&&) = default; |
| ProviderIpmidEntry& operator=(ProviderIpmidEntry&&) = default; |
| |
| private: |
| ipmid_callback_t functor; |
| }; |
| |
| /** |
| * @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 |
| { |
| public: |
| Table() = default; |
| ~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; |
| |
| 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 |
| * |
| * @return Response data for the command |
| */ |
| std::vector<uint8_t> executeCommand(uint32_t inCommand, |
| std::vector<uint8_t>& commandData, |
| const message::Handler& handler); |
| |
| private: |
| CommandTable commandTable; |
| }; |
| |
| } // namespace command |