summaryrefslogtreecommitdiffstats
path: root/include/ipmid
diff options
context:
space:
mode:
Diffstat (limited to 'include/ipmid')
-rw-r--r--include/ipmid/handler.hpp106
-rw-r--r--include/ipmid/registration.hpp79
2 files changed, 185 insertions, 0 deletions
diff --git a/include/ipmid/handler.hpp b/include/ipmid/handler.hpp
index 203dcad..0c65436 100644
--- a/include/ipmid/handler.hpp
+++ b/include/ipmid/handler.hpp
@@ -354,6 +354,94 @@ class IpmiHandler<ipmid_callback_t> final : public HandlerBase
};
/**
+ * @brief Legacy IPMI OEM handler class
+ *
+ * Legacy IPMI OEM handlers will resolve into this class, which will behave the
+ * same way as the legacy IPMI queue, passing in a big buffer for the request
+ * and a big buffer for the response.
+ *
+ * As soon as all the handlers have been rewritten, this class will be marked as
+ * deprecated and eventually removed.
+ */
+template <>
+class IpmiHandler<oem::Handler> final : public HandlerBase
+{
+ public:
+ explicit IpmiHandler(const oem::Handler& handler) : handler_(handler)
+ {
+ }
+
+ private:
+ oem::Handler handler_;
+
+ /** @brief call the registered handler with the request
+ *
+ * This is called from the running queue context after it has already
+ * created a request object that contains all the information required to
+ * execute the ipmi command. This function will return the response object
+ * pointer that owns the response object that will ultimately get sent back
+ * to the requester.
+ *
+ * Because this is the legacy variety of IPMI handler, this function does
+ * not really have to do much other than pass the payload to the callback
+ * and return response to the caller.
+ *
+ * @param request a shared_ptr to a Request object
+ *
+ * @return a shared_ptr to a Response object
+ */
+ message::Response::ptr
+ executeCallback(message::Request::ptr request) override
+ {
+ message::Response::ptr response = request->makeResponse();
+ size_t len = request->payload.size();
+ // allocate a big response buffer here
+ response->payload.resize(
+ getChannelMaxTransferSize(request->ctx->channel));
+
+ Cc ccRet{ccSuccess};
+ try
+ {
+ ccRet = handler_(request->ctx->cmd, request->payload.data(),
+ response->payload.data(), &len);
+ }
+ catch (const std::exception& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Legacy OEM Handler failed to catch exception",
+ phosphor::logging::entry("EXCEPTION=%s", e.what()),
+ phosphor::logging::entry("NETFN=%x", request->ctx->netFn),
+ phosphor::logging::entry("CMD=%x", request->ctx->cmd));
+ return errorResponse(request, ccUnspecifiedError);
+ }
+ catch (...)
+ {
+ std::exception_ptr eptr;
+ try
+ {
+ eptr = std::current_exception();
+ if (eptr)
+ {
+ std::rethrow_exception(eptr);
+ }
+ }
+ catch (const std::exception& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Handler failed to catch exception",
+ phosphor::logging::entry("EXCEPTION=%s", e.what()),
+ phosphor::logging::entry("NETFN=%x", request->ctx->netFn),
+ phosphor::logging::entry("CMD=%x", request->ctx->cmd));
+ return errorResponse(request, ccUnspecifiedError);
+ }
+ }
+ response->cc = ccRet;
+ response->payload.resize(len);
+ return response;
+ }
+};
+
+/**
* @brief create a legacy IPMI handler class and return a shared_ptr
*
* The queue uses a map of pointers to do the lookup. This function returns the
@@ -371,6 +459,24 @@ inline auto makeLegacyHandler(const ipmid_callback_t& handler)
return ptr;
}
+/**
+ * @brief create a legacy IPMI OEM handler class and return a shared_ptr
+ *
+ * The queue uses a map of pointers to do the lookup. This function returns the
+ * shared_ptr that owns the Handler object.
+ *
+ * This is called internally via the Router::registerHandler method.
+ *
+ * @param handler the function pointer to the callback
+ *
+ * @return A shared_ptr to the created handler object
+ */
+inline auto makeLegacyHandler(oem::Handler&& handler)
+{
+ HandlerBase::ptr ptr(
+ new IpmiHandler<oem::Handler>(std::forward<oem::Handler>(handler)));
+ return ptr;
+}
#endif // ALLOW_DEPRECATED_API
/**
diff --git a/include/ipmid/registration.hpp b/include/ipmid/registration.hpp
index 151aca1..af89bc8 100644
--- a/include/ipmid/registration.hpp
+++ b/include/ipmid/registration.hpp
@@ -27,6 +27,11 @@ namespace impl
// IPMI command handler registration implementation
bool registerHandler(int prio, NetFn netFn, Cmd cmd, Privilege priv,
::ipmi::HandlerBase::ptr handler);
+bool registerGroupHandler(int prio, Group group, Cmd cmd, Privilege priv,
+ ::ipmi::HandlerBase::ptr handler);
+bool registerOemHandler(int prio, Iana iana, Cmd cmd, Privilege priv,
+ ::ipmi::HandlerBase::ptr handler);
+
} // namespace impl
/**
@@ -53,6 +58,80 @@ bool registerHandler(int prio, NetFn netFn, Cmd cmd, Privilege priv,
return impl::registerHandler(prio, netFn, cmd, priv, h);
}
+/**
+ * @brief register a IPMI OEM group handler
+ *
+ * From IPMI 2.0 spec Network Function Codes Table (Row 2Ch):
+ * The first data byte position in requests and responses under this network
+ * function identifies the defining body that specifies command functionality.
+ * Software assumes that the command and completion code field positions will
+ * hold command and completion code values.
+ *
+ * The following values are used to identify the defining body:
+ * 00h PICMG - PCI Industrial Computer Manufacturer’s Group. (www.picmg.com)
+ * 01h DMTF Pre-OS Working Group ASF Specification (www.dmtf.org)
+ * 02h Server System Infrastructure (SSI) Forum (www.ssiforum.org)
+ * 03h VITA Standards Organization (VSO) (www.vita.com)
+ * DCh DCMI Specifications (www.intel.com/go/dcmi)
+ * all other Reserved
+ *
+ * When this network function is used, the ID for the defining body occupies
+ * the first data byte in a request, and the second data byte (following the
+ * completion code) in a response.
+ *
+ * @tparam Handler - implicitly specified callback function type
+ * @param prio - priority at which to register; see api.hpp
+ * @param netFn - the IPMI net function number to register
+ * @param cmd - the IPMI command number to register
+ * @param priv - the IPMI user privilige required for this command
+ * @param handler - the callback function that will handle this request
+ *
+ * @return bool - success of registering the handler
+ *
+ */
+template <typename Handler>
+void registerGroupHandler(int prio, Group group, Cmd cmd, Privilege priv,
+ Handler&& handler)
+{
+ auto h = ipmi::makeHandler(handler);
+ impl::registerGroupHandler(prio, group, cmd, priv, h);
+}
+
+/**
+ * @brief register a IPMI OEM IANA handler
+ *
+ * From IPMI spec Network Function Codes Table (Row 2Eh):
+ * The first three data bytes of requests and responses under this network
+ * function explicitly identify the OEM or non-IPMI group that specifies the
+ * command functionality. While the OEM or non-IPMI group defines the
+ * functional semantics for the cmd and remaining data fields, the cmd field
+ * is required to hold the same value in requests and responses for a given
+ * operation in order to be supported under the IPMI message handling and
+ * transport mechanisms.
+ *
+ * When this network function is used, the IANA Enterprise Number for the
+ * defining body occupies the first three data bytes in a request, and the
+ * first three data bytes following the completion code position in a
+ * response.
+ *
+ * @tparam Handler - implicitly specified callback function type
+ * @param prio - priority at which to register; see api.hpp
+ * @param netFn - the IPMI net function number to register
+ * @param cmd - the IPMI command number to register
+ * @param priv - the IPMI user privilige required for this command
+ * @param handler - the callback function that will handle this request
+ *
+ * @return bool - success of registering the handler
+ *
+ */
+template <typename Handler>
+void registerOemHandler(int prio, Iana iana, Cmd cmd, Privilege priv,
+ Handler&& handler)
+{
+ auto h = ipmi::makeHandler(handler);
+ impl::registerOemHandler(prio, iana, cmd, priv, h);
+}
+
} // namespace ipmi
#ifdef ALLOW_DEPRECATED_API
OpenPOWER on IntegriCloud