1 /*
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 
35 namespace ipmi
36 {
37 
38 using Iana = oem::Number;
39 
40 using Group = uint8_t;
41 constexpr Group groupPICMG = 0x00;
42 constexpr Group groupDMTG = 0x01;
43 constexpr Group groupSSI = 0x02;
44 constexpr Group groupVSO = 0x03;
45 constexpr 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  */
53 constexpr int prioOpenBmcBase = 10;
54 constexpr int prioOemBase = 20;
55 constexpr int prioOdmBase = 30;
56 constexpr int prioCustomBase = 40;
57 constexpr int prioMax = 50;
58 
59 /*
60  * Channel IDs pulled from the IPMI 2.0 specification
61  */
62 constexpr 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
67 constexpr int channelCurrentIface = 0x0E; // 'Present I/F'
68 constexpr 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  */
76 enum 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.
87 using NetFn = uint8_t;
88 
89 // IPMI Command for a Net Function number as specified by IPMI V2.0 spec.
90 using Cmd = uint8_t;
91 
92 // ipmi function return the status code
93 using 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
100 constexpr NetFn netFnChassis = 0x00;
101 constexpr NetFn netFnBridge = 0x02;
102 constexpr NetFn netFnSensor = 0x04;
103 constexpr NetFn netFnApp = 0x06;
104 constexpr NetFn netFnFirmware = 0x08;
105 constexpr NetFn netFnStorage = 0x0A;
106 constexpr NetFn netFnTransport = 0x0C;
107 // reserved 0Eh..28h
108 constexpr NetFn netFnGroup = 0x2C;
109 constexpr NetFn netFnOem = 0x2E;
110 constexpr NetFn netFnOemOne = 0x30;
111 constexpr NetFn netFnOemTwo = 0x32;
112 constexpr NetFn netFnOemThree = 0x34;
113 constexpr NetFn netFnOemFour = 0x36;
114 constexpr NetFn netFnOemFive = 0x38;
115 constexpr NetFn netFnOemSix = 0x3A;
116 constexpr NetFn netFnOemSeven = 0x3C;
117 constexpr 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
122 constexpr 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
133 constexpr Cc ccSuccess = 0x00;
134 constexpr Cc ccBusy = 0xC0;
135 constexpr Cc ccInvalidCommand = 0xC1;
136 constexpr Cc ccInvalidCommandOnLun = 0xC2;
137 constexpr Cc ccTimeout = 0xC2;
138 constexpr Cc ccOutOfSpace = 0xC2;
139 constexpr Cc ccInvalidReservationId = 0xC5;
140 constexpr Cc ccReqDataTruncated = 0xC6;
141 constexpr Cc ccReqDataLenInvalid = 0xC7;
142 constexpr Cc ccReqDataLenExceeded = 0xC8;
143 constexpr Cc ccParmOutOfRange = 0xC9;
144 constexpr Cc ccRetBytesUnavailable = 0xCA;
145 constexpr Cc ccSensorInvalid = 0xCB;
146 constexpr Cc ccInvalidFieldRequest = 0xCC;
147 constexpr Cc ccIllegalCommand = 0xCD;
148 constexpr Cc ccResponseError = 0xCE;
149 constexpr Cc ccDuplicateRequest = 0xCF;
150 constexpr Cc ccCmdFailSdrMode = 0xD0;
151 constexpr Cc ccCmdFailFwUpdMode = 0xD1;
152 constexpr Cc ccCmdFailInitAgent = 0xD2;
153 constexpr Cc ccDestinationUnavailable = 0xD3;
154 constexpr Cc ccInsufficientPrivilege = 0xD4;
155 constexpr Cc ccCommandNotAvailable = 0xD5;
156 constexpr Cc ccCommandDisabled = 0xD6;
157 constexpr 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 
172 template <typename... RetTypes>
173 using 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  */
188 template <typename... Args>
189 static inline auto response(ipmi::Cc cc, Args&&... args)
190 {
191     return std::make_tuple(cc, std::make_optional(std::make_tuple(args...)));
192 }
193 static 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  */
211 template <typename... Args>
212 static inline auto responseSuccess(Args&&... args)
213 {
214     return std::make_tuple(ipmi::ccSuccess,
215                            std::make_optional(std::make_tuple(args...)));
216 }
217 static inline auto responseSuccess()
218 {
219     return std::make_tuple(ipmi::ccSuccess, std::nullopt);
220 }
221 
222 } // namespace ipmi
223 
224 // any client can interact with the main asio context
225 std::shared_ptr<boost::asio::io_context> getIoContext();
226 
227 // any client can interact with the main sdbus
228 std::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  */
239 template <typename WorkFn>
240 static inline void post_work(WorkFn work)
241 {
242     getIoContext()->post(std::forward<WorkFn>(work));
243 }
244