blob: b825796a695b2197b95f705ad932cc052d900037 [file] [log] [blame]
Vernon Mauerye7329c72018-10-08 12:05:16 -07001/*
2 * Copyright © 2018 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17#pragma once
18
19#define ALLOW_DEPRECATED_API 1
20
21#include <ipmid/iana.hpp>
22#include <ipmid/message/types.hpp>
23#include <optional>
24#include <sdbusplus/asio/connection.hpp>
25#include <sdbusplus/asio/object_server.hpp>
26
27/* NOTE:
28 *
29 * This is intended for native C++ use. For the legacy C api, include
30 * ipmid-api.h for a reduced functionality. Note that the C api is now marked
31 * as deprecated and will be removed once all the internal users of it have
32 * been updated to use the new C++ api.
33 */
34
35namespace ipmi
36{
37
38using Iana = oem::Number;
39
40using Group = uint8_t;
41constexpr Group groupPICMG = 0x00;
42constexpr Group groupDMTG = 0x01;
43constexpr Group groupSSI = 0x02;
44constexpr Group groupVSO = 0x03;
45constexpr Group groupDCMI = 0xDC;
46
47/*
48 * Set the priority as the lowest number that is necessary so
49 * it is possible that others can override it if desired.
50 * This may be linked to what level of integration the handler
51 * is being created at.
52 */
53constexpr int prioOpenBmcBase = 10;
54constexpr int prioOemBase = 20;
55constexpr int prioOdmBase = 30;
56constexpr int prioCustomBase = 40;
57constexpr int prioMax = 50;
58
59/*
60 * Channel IDs pulled from the IPMI 2.0 specification
61 */
62constexpr int channelPrimaryIpmb = 0x00;
63// 0x01-0x0B Implementation specific
64// Implementation specific channel numbers are specified
65// by a configuration file external to ipmid
66// 0x0C-0x0D reserved
67constexpr int channelCurrentIface = 0x0E; // 'Present I/F'
68constexpr int channelSystemIface = 0x0F;
69
70/*
71 * Specifies the minimum privilege level required to execute the command
72 * This means the command can be executed at a given privilege level or higher
73 * privilege level. Those commands which can be executed via system interface
74 * only should use SYSTEM_INTERFACE
75 */
76enum class Privilege : uint8_t
77{
78 None = 0x00,
79 Callback,
80 User,
81 Operator,
82 Admin,
83 Oem,
84};
85
86// IPMI Net Function number as specified by IPMI V2.0 spec.
87using NetFn = uint8_t;
88
89// IPMI Command for a Net Function number as specified by IPMI V2.0 spec.
90using Cmd = uint8_t;
91
92// ipmi function return the status code
93using Cc = uint8_t;
94
95// These are the command network functions, the response
96// network functions are the function + 1. So to determine
97// the proper network function which issued the command
98// associated with a response, subtract 1.
99// Note: these will be left shifted when combined with the LUN
100constexpr NetFn netFnChassis = 0x00;
101constexpr NetFn netFnBridge = 0x02;
102constexpr NetFn netFnSensor = 0x04;
103constexpr NetFn netFnApp = 0x06;
104constexpr NetFn netFnFirmware = 0x08;
105constexpr NetFn netFnStorage = 0x0A;
106constexpr NetFn netFnTransport = 0x0C;
107// reserved 0Eh..28h
108constexpr NetFn netFnGroup = 0x2C;
109constexpr NetFn netFnOem = 0x2E;
110constexpr NetFn netFnOemOne = 0x30;
111constexpr NetFn netFnOemTwo = 0x32;
112constexpr NetFn netFnOemThree = 0x34;
113constexpr NetFn netFnOemFour = 0x36;
114constexpr NetFn netFnOemFive = 0x38;
115constexpr NetFn netFnOemSix = 0x3A;
116constexpr NetFn netFnOemSeven = 0x3C;
117constexpr NetFn netFnOemEight = 0x3E;
118
119// IPMI commands for net functions. Callbacks using this should be careful to
120// parse arguments to the sub-functions and can take advantage of the built-in
121// message handling mechanism to create custom routing
122constexpr Cmd cmdWildcard = 0xFF;
123
124// IPMI standard completion codes specified by the IPMI V2.0 spec.
125//
126// This might have been an enum class, but that would make it hard for
127// OEM- and command-specific completion codes to be added elsewhere.
128//
129// Custom completion codes can be defined in individual modules for
130// command specific errors in the 0x80-0xBE range
131//
132// Alternately, OEM completion codes are in the 0x01-0x7E range
133constexpr Cc ccSuccess = 0x00;
134constexpr Cc ccBusy = 0xC0;
135constexpr Cc ccInvalidCommand = 0xC1;
136constexpr Cc ccInvalidCommandOnLun = 0xC2;
137constexpr Cc ccTimeout = 0xC2;
138constexpr Cc ccOutOfSpace = 0xC2;
139constexpr Cc ccInvalidReservationId = 0xC5;
140constexpr Cc ccReqDataTruncated = 0xC6;
141constexpr Cc ccReqDataLenInvalid = 0xC7;
142constexpr Cc ccReqDataLenExceeded = 0xC8;
143constexpr Cc ccParmOutOfRange = 0xC9;
144constexpr Cc ccRetBytesUnavailable = 0xCA;
145constexpr Cc ccSensorInvalid = 0xCB;
146constexpr Cc ccInvalidFieldRequest = 0xCC;
147constexpr Cc ccIllegalCommand = 0xCD;
148constexpr Cc ccResponseError = 0xCE;
149constexpr Cc ccDuplicateRequest = 0xCF;
150constexpr Cc ccCmdFailSdrMode = 0xD0;
151constexpr Cc ccCmdFailFwUpdMode = 0xD1;
152constexpr Cc ccCmdFailInitAgent = 0xD2;
153constexpr Cc ccDestinationUnavailable = 0xD3;
154constexpr Cc ccInsufficientPrivilege = 0xD4;
155constexpr Cc ccCommandNotAvailable = 0xD5;
156constexpr Cc ccCommandDisabled = 0xD6;
157constexpr Cc ccUnspecifiedError = 0xFF;
158
159/* ipmi often has two return types:
160 * 1. Failure: CC is non-zero; no trailing data
161 * 2. Success: CC is zero; trailing data (usually a fixed type)
162 *
163 * using ipmi::response(cc, ...), it will automatically always pack
164 * the correct type for the response without having to explicitly type out all
165 * the parameters that the function would return.
166 *
167 * To enable this feature, you just define the ipmi function as returning an
168 * ipmi::RspType which has the optional trailing data built in, with your types
169 * defined as parameters.
170 */
171
172template <typename... RetTypes>
173using RspType = std::tuple<ipmi::Cc, std::optional<std::tuple<RetTypes...>>>;
174
175/**
176 * @brief helper function to create an IPMI response tuple
177 *
178 * IPMI handlers all return a tuple with two parts: a completion code and an
179 * optional tuple containing the rest of the data to return. This helper
180 * function makes it easier by constructing that out of an arbitrary number of
181 * arguments.
182 *
183 * @param cc - the completion code for the response
184 * @param args... - the optional list of values to return
185 *
186 * @return a standard IPMI return type (as described above)
187 */
188template <typename... Args>
189static inline auto response(ipmi::Cc cc, Args&&... args)
190{
191 return std::make_tuple(cc, std::make_optional(std::make_tuple(args...)));
192}
193static inline auto response(ipmi::Cc cc)
194{
195 return std::make_tuple(cc, std::nullopt);
196}
197
198/**
199 * @brief helper function to create an IPMI success response tuple
200 *
201 * IPMI handlers all return a tuple with two parts: a completion code and an
202 * optional tuple containing the rest of the data to return. This helper
203 * function makes it easier by constructing that out of an arbitrary number of
204 * arguments. Because it is a success response, this automatically packs
205 * the completion code, without needing to explicitly pass it in.
206 *
207 * @param args... - the optional list of values to return
208 *
209 * @return a standard IPMI return type (as described above)
210 */
211template <typename... Args>
212static inline auto responseSuccess(Args&&... args)
213{
214 return std::make_tuple(ipmi::ccSuccess,
215 std::make_optional(std::make_tuple(args...)));
216}
217static inline auto responseSuccess()
218{
219 return std::make_tuple(ipmi::ccSuccess, std::nullopt);
220}
221
222} // namespace ipmi
223
Vernon Mauery20ff3332019-03-01 16:52:25 -0800224// any client can interact with the main asio context
225std::shared_ptr<boost::asio::io_context> getIoContext();
Vernon Mauerye7329c72018-10-08 12:05:16 -0700226
227// any client can interact with the main sdbus
228std::shared_ptr<sdbusplus::asio::connection> getSdBus();
229
230/**
231 * @brief post some work to the async exection queue
232 *
233 * The IPMI daemon runs an async exection queue; this allows any function to
234 * pass in work to be executed in that context
235 *
236 * @tparam WorkFn - a function of type void(void)
237 * @param work - the callback function to be executed
238 */
239template <typename WorkFn>
240static inline void post_work(WorkFn work)
241{
Vernon Mauery20ff3332019-03-01 16:52:25 -0800242 getIoContext()->post(std::forward<WorkFn>(work));
Vernon Mauerye7329c72018-10-08 12:05:16 -0700243}
Vernon Mauery3719c2f2019-03-20 13:00:20 -0700244
245enum class SignalResponse : int
246{
247 breakExecution,
248 continueExecution,
249};
250
251/**
252 * @brief add a signal handler
253 *
254 * This registers a handler to be called asynchronously via the execution
255 * queue when the specified signal is received.
256 *
257 * Priority allows a signal handler to specify what order in the handler
258 * chain it gets called. Lower priority numbers will cause the handler to
259 * be executed later in the chain, while the highest priority numbers will cause
260 * the handler to be executed first.
261 *
262 * In order to facilitate a chain of handlers, each handler in the chain will be
263 * able to return breakExecution or continueExecution. Returning breakExecution
264 * will break the chain and no further handlers will execute for that signal.
265 * Returning continueExecution will allow lower-priority handlers to execute.
266 *
267 * By default, the main asio execution loop will register a low priority
268 * (prioOpenBmcBase) handler for SIGINT and SIGTERM to cause the process to stop
269 * on either of those signals. To prevent one of those signals from causing the
270 * process to stop, simply register a higher priority handler that returns
271 * breakExecution.
272 *
273 * @param int - priority of handler
274 * @param int - signal number to wait for
275 * @param handler - the callback function to be executed
276 */
277void registerSignalHandler(int priority, int signalNumber,
278 const std::function<SignalResponse(int)>& handler);