blob: b825796a695b2197b95f705ad932cc052d900037 [file] [log] [blame]
/*
* Copyright © 2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#pragma once
#define ALLOW_DEPRECATED_API 1
#include <ipmid/iana.hpp>
#include <ipmid/message/types.hpp>
#include <optional>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
/* NOTE:
*
* This is intended for native C++ use. For the legacy C api, include
* ipmid-api.h for a reduced functionality. Note that the C api is now marked
* as deprecated and will be removed once all the internal users of it have
* been updated to use the new C++ api.
*/
namespace ipmi
{
using Iana = oem::Number;
using Group = uint8_t;
constexpr Group groupPICMG = 0x00;
constexpr Group groupDMTG = 0x01;
constexpr Group groupSSI = 0x02;
constexpr Group groupVSO = 0x03;
constexpr Group groupDCMI = 0xDC;
/*
* Set the priority as the lowest number that is necessary so
* it is possible that others can override it if desired.
* This may be linked to what level of integration the handler
* is being created at.
*/
constexpr int prioOpenBmcBase = 10;
constexpr int prioOemBase = 20;
constexpr int prioOdmBase = 30;
constexpr int prioCustomBase = 40;
constexpr int prioMax = 50;
/*
* Channel IDs pulled from the IPMI 2.0 specification
*/
constexpr int channelPrimaryIpmb = 0x00;
// 0x01-0x0B Implementation specific
// Implementation specific channel numbers are specified
// by a configuration file external to ipmid
// 0x0C-0x0D reserved
constexpr int channelCurrentIface = 0x0E; // 'Present I/F'
constexpr int channelSystemIface = 0x0F;
/*
* Specifies the minimum privilege level required to execute the command
* This means the command can be executed at a given privilege level or higher
* privilege level. Those commands which can be executed via system interface
* only should use SYSTEM_INTERFACE
*/
enum class Privilege : uint8_t
{
None = 0x00,
Callback,
User,
Operator,
Admin,
Oem,
};
// IPMI Net Function number as specified by IPMI V2.0 spec.
using NetFn = uint8_t;
// IPMI Command for a Net Function number as specified by IPMI V2.0 spec.
using Cmd = uint8_t;
// ipmi function return the status code
using Cc = uint8_t;
// These are the command network functions, the response
// network functions are the function + 1. So to determine
// the proper network function which issued the command
// associated with a response, subtract 1.
// Note: these will be left shifted when combined with the LUN
constexpr NetFn netFnChassis = 0x00;
constexpr NetFn netFnBridge = 0x02;
constexpr NetFn netFnSensor = 0x04;
constexpr NetFn netFnApp = 0x06;
constexpr NetFn netFnFirmware = 0x08;
constexpr NetFn netFnStorage = 0x0A;
constexpr NetFn netFnTransport = 0x0C;
// reserved 0Eh..28h
constexpr NetFn netFnGroup = 0x2C;
constexpr NetFn netFnOem = 0x2E;
constexpr NetFn netFnOemOne = 0x30;
constexpr NetFn netFnOemTwo = 0x32;
constexpr NetFn netFnOemThree = 0x34;
constexpr NetFn netFnOemFour = 0x36;
constexpr NetFn netFnOemFive = 0x38;
constexpr NetFn netFnOemSix = 0x3A;
constexpr NetFn netFnOemSeven = 0x3C;
constexpr NetFn netFnOemEight = 0x3E;
// IPMI commands for net functions. Callbacks using this should be careful to
// parse arguments to the sub-functions and can take advantage of the built-in
// message handling mechanism to create custom routing
constexpr Cmd cmdWildcard = 0xFF;
// IPMI standard completion codes specified by the IPMI V2.0 spec.
//
// This might have been an enum class, but that would make it hard for
// OEM- and command-specific completion codes to be added elsewhere.
//
// Custom completion codes can be defined in individual modules for
// command specific errors in the 0x80-0xBE range
//
// Alternately, OEM completion codes are in the 0x01-0x7E range
constexpr Cc ccSuccess = 0x00;
constexpr Cc ccBusy = 0xC0;
constexpr Cc ccInvalidCommand = 0xC1;
constexpr Cc ccInvalidCommandOnLun = 0xC2;
constexpr Cc ccTimeout = 0xC2;
constexpr Cc ccOutOfSpace = 0xC2;
constexpr Cc ccInvalidReservationId = 0xC5;
constexpr Cc ccReqDataTruncated = 0xC6;
constexpr Cc ccReqDataLenInvalid = 0xC7;
constexpr Cc ccReqDataLenExceeded = 0xC8;
constexpr Cc ccParmOutOfRange = 0xC9;
constexpr Cc ccRetBytesUnavailable = 0xCA;
constexpr Cc ccSensorInvalid = 0xCB;
constexpr Cc ccInvalidFieldRequest = 0xCC;
constexpr Cc ccIllegalCommand = 0xCD;
constexpr Cc ccResponseError = 0xCE;
constexpr Cc ccDuplicateRequest = 0xCF;
constexpr Cc ccCmdFailSdrMode = 0xD0;
constexpr Cc ccCmdFailFwUpdMode = 0xD1;
constexpr Cc ccCmdFailInitAgent = 0xD2;
constexpr Cc ccDestinationUnavailable = 0xD3;
constexpr Cc ccInsufficientPrivilege = 0xD4;
constexpr Cc ccCommandNotAvailable = 0xD5;
constexpr Cc ccCommandDisabled = 0xD6;
constexpr Cc ccUnspecifiedError = 0xFF;
/* ipmi often has two return types:
* 1. Failure: CC is non-zero; no trailing data
* 2. Success: CC is zero; trailing data (usually a fixed type)
*
* using ipmi::response(cc, ...), it will automatically always pack
* the correct type for the response without having to explicitly type out all
* the parameters that the function would return.
*
* To enable this feature, you just define the ipmi function as returning an
* ipmi::RspType which has the optional trailing data built in, with your types
* defined as parameters.
*/
template <typename... RetTypes>
using RspType = std::tuple<ipmi::Cc, std::optional<std::tuple<RetTypes...>>>;
/**
* @brief helper function to create an IPMI response tuple
*
* IPMI handlers all return a tuple with two parts: a completion code and an
* optional tuple containing the rest of the data to return. This helper
* function makes it easier by constructing that out of an arbitrary number of
* arguments.
*
* @param cc - the completion code for the response
* @param args... - the optional list of values to return
*
* @return a standard IPMI return type (as described above)
*/
template <typename... Args>
static inline auto response(ipmi::Cc cc, Args&&... args)
{
return std::make_tuple(cc, std::make_optional(std::make_tuple(args...)));
}
static inline auto response(ipmi::Cc cc)
{
return std::make_tuple(cc, std::nullopt);
}
/**
* @brief helper function to create an IPMI success response tuple
*
* IPMI handlers all return a tuple with two parts: a completion code and an
* optional tuple containing the rest of the data to return. This helper
* function makes it easier by constructing that out of an arbitrary number of
* arguments. Because it is a success response, this automatically packs
* the completion code, without needing to explicitly pass it in.
*
* @param args... - the optional list of values to return
*
* @return a standard IPMI return type (as described above)
*/
template <typename... Args>
static inline auto responseSuccess(Args&&... args)
{
return std::make_tuple(ipmi::ccSuccess,
std::make_optional(std::make_tuple(args...)));
}
static inline auto responseSuccess()
{
return std::make_tuple(ipmi::ccSuccess, std::nullopt);
}
} // namespace ipmi
// any client can interact with the main asio context
std::shared_ptr<boost::asio::io_context> getIoContext();
// any client can interact with the main sdbus
std::shared_ptr<sdbusplus::asio::connection> getSdBus();
/**
* @brief post some work to the async exection queue
*
* The IPMI daemon runs an async exection queue; this allows any function to
* pass in work to be executed in that context
*
* @tparam WorkFn - a function of type void(void)
* @param work - the callback function to be executed
*/
template <typename WorkFn>
static inline void post_work(WorkFn work)
{
getIoContext()->post(std::forward<WorkFn>(work));
}
enum class SignalResponse : int
{
breakExecution,
continueExecution,
};
/**
* @brief add a signal handler
*
* This registers a handler to be called asynchronously via the execution
* queue when the specified signal is received.
*
* Priority allows a signal handler to specify what order in the handler
* chain it gets called. Lower priority numbers will cause the handler to
* be executed later in the chain, while the highest priority numbers will cause
* the handler to be executed first.
*
* In order to facilitate a chain of handlers, each handler in the chain will be
* able to return breakExecution or continueExecution. Returning breakExecution
* will break the chain and no further handlers will execute for that signal.
* Returning continueExecution will allow lower-priority handlers to execute.
*
* By default, the main asio execution loop will register a low priority
* (prioOpenBmcBase) handler for SIGINT and SIGTERM to cause the process to stop
* on either of those signals. To prevent one of those signals from causing the
* process to stop, simply register a higher priority handler that returns
* breakExecution.
*
* @param int - priority of handler
* @param int - signal number to wait for
* @param handler - the callback function to be executed
*/
void registerSignalHandler(int priority, int signalNumber,
const std::function<SignalResponse(int)>& handler);