blob: e0bb322223892a761603b77af4a08a8f577fff1e [file] [log] [blame]
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +05301/*
2 * Copyright (c) 2018 Intel Corporation.
3 * Copyright (c) 2018-present Facebook.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <ipmid/api.hpp>
19#include <ipmid/api-types.hpp>
20
21#include <commandutils.hpp>
22#include <biccommands.hpp>
23#include <phosphor-logging/log.hpp>
24
25#include <vector>
Kumar Thangavelad049242020-08-31 22:27:33 +053026#include <variant>
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053027#include <iostream>
28
29namespace ipmi
30{
31
Kumar Thangavel05d0ce92022-11-17 17:53:57 +053032int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
33 std::vector<uint8_t>&);
34
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053035using namespace phosphor::logging;
36
Patrick Williams58c1ca22021-04-22 12:29:35 -050037#ifdef BIC_ENABLED
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053038static void registerBICFunctions() __attribute__((constructor));
Patrick Williams58c1ca22021-04-22 12:29:35 -050039#endif
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053040
41extern message::Response::ptr executeIpmiCommand(message::Request::ptr);
42
Bonnie Lo25b79bf2022-12-16 15:41:48 +080043int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
44 std::vector<uint8_t>&);
45
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053046//----------------------------------------------------------------------
47// ipmiOemBicHandler (IPMI/Section - ) (CMD_OEM_BIC_INFO)
48// This Function will handle BIC request for netfn=0x38 and cmd=1
49// send the response back to the sender.
50//----------------------------------------------------------------------
51
Bonnie Lo25b79bf2022-12-16 15:41:48 +080052ipmi::RspType<IanaType, uint8_t, uint2_t, uint6_t, uint8_t, uint8_t,
53 ipmi::message::Payload>
54 ipmiOemBicHandler(ipmi::Context::ptr ctx, IanaType reqIana,
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053055 uint8_t interface, uint2_t lun, uint6_t netFnReq,
Patrick Williams485f9b32021-09-03 16:14:47 -050056 uint8_t cmdReq, SecureBuffer data)
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053057{
58
59 ipmi::message::Response::ptr res;
60
61 // Updating the correct netfn and cmd in the ipmi Context
62 ctx->netFn = ((uint8_t)netFnReq);
63 ctx->cmd = cmdReq;
64
65 // creating ipmi message request for calling executeIpmiCommand function
Patrick Williams485f9b32021-09-03 16:14:47 -050066 auto req = std::make_shared<ipmi::message::Request>(ctx, std::move(data));
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053067
68 // Calling executeIpmiCommand request function
69 res = ipmi::executeIpmiCommand(req);
70
71 // sending the response with headers and payload
Bonnie Lo25b79bf2022-12-16 15:41:48 +080072 return ipmi::responseSuccess(reqIana, interface, lun, ++netFnReq, cmdReq,
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053073 res->cc, res->payload);
74}
75
Kumar Thangavelad049242020-08-31 22:27:33 +053076//----------------------------------------------------------------------
77// ipmiOemPostCodeHandler (CMD_OEM_BIC_POST_BUFFER_INFO)
78// This Function will handle BIC incomming postcode from multi-host for
79// netfn=0x38 and cmd=0x08 send the response back to the sender.
80//----------------------------------------------------------------------
81
Bonnie Lo25b79bf2022-12-16 15:41:48 +080082ipmi::RspType<IanaType> ipmiOemPostCodeHandler(ipmi::Context::ptr ctx,
83 IanaType reqIana,
84 uint8_t dataLen,
85 std::vector<uint8_t> data)
Kumar Thangavelad049242020-08-31 22:27:33 +053086{
87 // creating bus connection
88 auto conn = getSdBus();
89
Bonnie Lod8ef7b32022-10-24 16:42:42 +080090 using postcode_t = std::tuple<uint64_t, std::vector<uint8_t>>;
Manojkiran Edac723d6a2021-03-11 14:53:32 +053091
Bonnie Lod8ef7b32022-10-24 16:42:42 +080092 std::string dbusObjStr = dbusObj + std::to_string((ctx->hostIdx + 1));
93
94 for (unsigned int index = 0; index < dataLen; index++)
95 {
96 uint64_t primaryPostCode = static_cast<uint64_t>(data[index]);
Kumar Thangavel0fcfbee2021-04-16 12:38:20 +053097 auto postCode = postcode_t(primaryPostCode, {});
Kumar Thangavelad049242020-08-31 22:27:33 +053098
Bonnie Lod8ef7b32022-10-24 16:42:42 +080099 try
100 {
101 auto method = conn->new_method_call(
102 "xyz.openbmc_project.State.Boot.Raw", dbusObjStr.c_str(),
103 "org.freedesktop.DBus.Properties", "Set");
Kumar Thangavelad049242020-08-31 22:27:33 +0530104
Bonnie Lod8ef7b32022-10-24 16:42:42 +0800105 // Adding paramters to method call
106 method.append(dbusService, "Value",
107 std::variant<postcode_t>(postCode));
Kumar Thangavelad049242020-08-31 22:27:33 +0530108
Bonnie Lod8ef7b32022-10-24 16:42:42 +0800109 // Invoke method call function
110 auto reply = conn->call(method);
111 }
Kumar Thangavelad049242020-08-31 22:27:33 +0530112
Bonnie Lod8ef7b32022-10-24 16:42:42 +0800113 catch (std::exception& e)
114 {
115 phosphor::logging::log<phosphor::logging::level::ERR>(
116 "post code handler error\n");
Kumar Thangavelad049242020-08-31 22:27:33 +0530117
Bonnie Lod8ef7b32022-10-24 16:42:42 +0800118 // sending the Error response
119 return ipmi::responseResponseError();
120 }
Kumar Thangavelad049242020-08-31 22:27:33 +0530121 }
Kumar Thangavelad049242020-08-31 22:27:33 +0530122
Bonnie Lo25b79bf2022-12-16 15:41:48 +0800123 return ipmi::responseSuccess(reqIana);
124}
125
126//----------------------------------------------------------------------
127// ipmiOemGetBicGpioState (CMD_OEM_GET_BIC_GPIO_STATE)
128// This Function will handle BIC GPIO stats for
129// netfn=0x38 and cmd=0x03 send the response back to the sender.
130//----------------------------------------------------------------------
131
132ipmi::RspType<IanaType, std::vector<uint8_t>>
133 ipmiOemGetBicGpioState(ipmi::Context::ptr ctx, std::vector<uint8_t> reqIana)
134{
135 std::vector<uint8_t> respData;
136
137 if (std::equal(reqIana.begin(), reqIana.end(), iana.begin()) == false)
138 {
139 phosphor::logging::log<phosphor::logging::level::ERR>(
140 "Invalid IANA number");
141 return ipmi::responseInvalidFieldRequest();
142 }
143
144 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
145
146 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqIana, respData))
147 {
148 return ipmi::responseUnspecifiedError();
149 }
150
151 std::vector<uint8_t> gpioState;
152 IanaType respIana;
153
154 auto r =
155 std::ranges::copy_n(respData.begin(), iana.size(), respIana.begin()).in;
156 std::copy(r, respData.end(), std::back_inserter(gpioState));
157
158 return ipmi::responseSuccess(respIana, gpioState);
Kumar Thangavelad049242020-08-31 22:27:33 +0530159}
160
Bonnie Lo41027b92022-12-16 16:21:08 +0800161//----------------------------------------------------------------------
162// ipmiOemSetHostPowerState (CMD_OEM_SET_HOST_POWER_STATE)
163// This Function will handle BIC incomming IPMI request for
164// setting host current state for netfn=0x38 and cmd=0x0C
165// send the response back to the sender.
166//----------------------------------------------------------------------
167
168ipmi::RspType<IanaType> ipmiOemSetHostPowerState(ipmi::Context::ptr ctx,
169 IanaType reqIana,
170 uint8_t status)
171{
172 std::string targetUnit;
173
174 switch (static_cast<HostPowerState>(status))
175 {
176 case HostPowerState::HOST_POWER_ON:
177 targetUnit = "obmc-host-startmin@.target";
178 break;
179 case HostPowerState::HOST_POWER_OFF:
180 targetUnit = "obmc-host-stop@.target";
181 break;
182 default:
183 phosphor::logging::log<phosphor::logging::level::ERR>(
184 "IPMI ipmiOemHostPowerStatus power status error");
185 return ipmi::responseUnspecifiedError();
186 }
187
188 int mousePos = targetUnit.find('@');
189 targetUnit.insert(mousePos + 1, std::to_string(ctx->hostIdx + 1));
190
191 auto conn = getSdBus();
192 auto method = conn->new_method_call(systemdService, systemdObjPath,
193 systemdInterface, "StartUnit");
194 method.append(targetUnit);
195 method.append("replace");
196
197 try
198 {
199 conn->call_noreply(method);
200 }
201 catch (const sdbusplus::exception::SdBusError& e)
202 {
203 phosphor::logging::log<phosphor::logging::level::ERR>(
204 "IPMI ipmiOemHostPowerStatus Failed in call method",
205 phosphor::logging::entry("ERROR=%s", e.what()));
206 return ipmi::responseUnspecifiedError();
207 }
208
209 return ipmi::responseSuccess(reqIana);
210}
211
Kumar Thangavel05d0ce92022-11-17 17:53:57 +0530212//----------------------------------------------------------------------
213// ipmiOemGetBiosFlashSize (CMD_OEM_GET_FLASH_SIZE)
214// This Function will return the bios flash size
215// netfn=0x38 and cmd=0x19 send the response back to the sender.
216//----------------------------------------------------------------------
217
218ipmi::RspType<IanaType, flashSize>
219 ipmiOemGetBiosFlashSize(ipmi::Context::ptr ctx, IanaType ianaReq,
220 uint8_t target)
221{
222 if (iana != ianaReq)
223 {
224 phosphor::logging::log<phosphor::logging::level::ERR>(
225 "Invalid IANA ID length received");
226 return ipmi::responseReqDataLenInvalid();
227 }
228
229 std::vector<uint8_t> respData;
230 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
231 std::vector<uint8_t> reqData(ianaReq.begin(), ianaReq.end());
232 reqData.emplace_back(target);
233
234 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
235 {
236 return ipmi::responseUnspecifiedError();
237 }
238
239 if (respData.size() != flashSizeRespLen)
240 {
241 phosphor::logging::log<phosphor::logging::level::ERR>(
242 "Invalid Response Data length received");
243 return ipmi::responseReqDataLenInvalid();
244 }
245
246 IanaType ianaResp;
247 std::copy_n(respData.begin(), ianaResp.size(), ianaResp.begin());
248
249 if (iana != ianaResp)
250 {
251 phosphor::logging::log<phosphor::logging::level::ERR>(
252 "Invalid IANA ID received");
253 return ipmi::responseInvalidCommand();
254 }
255
256 flashSize flashResp;
257 std::vector<uint8_t>::iterator respDataIter = respData.begin();
258 std::advance(respDataIter, ianaResp.size());
259 std::copy_n(respDataIter, flashResp.size(), flashResp.begin());
260
261 // sending the success response.
262 return ipmi::responseSuccess(ianaResp, flashResp);
263}
264
Jayashree Dhanapal6c931e42022-12-05 13:09:24 +0530265//----------------------------------------------------------------------
266// ipmiOemClearCmos (CMD_OEM_CLEAR_CMOS)
267// This Function will clear the CMOS.
268// netfn=0x38 and cmd=0x25
269//----------------------------------------------------------------------
270ipmi::RspType<IanaType> ipmiOemClearCmos(ipmi::Context::ptr ctx,
271 IanaType ianaReq)
272{
273 if (iana != ianaReq)
274 {
275 phosphor::logging::log<phosphor::logging::level::ERR>(
276 "Invalid request of IANA ID length received");
277 return ipmi::responseReqDataLenInvalid();
278 }
279
280 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
281
282 std::vector<uint8_t> respData;
283 std::vector<uint8_t> reqData(ianaReq.begin(), ianaReq.end());
284
285 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
286 {
287 return ipmi::responseUnspecifiedError();
288 }
289
290 if (respData.size() != iana.size())
291 {
292 return ipmi::responseReqDataLenInvalid();
293 }
294
295 IanaType resp;
296 std::copy_n(respData.begin(), resp.size(), resp.begin());
297
298 if (iana != resp)
299 {
300 phosphor::logging::log<phosphor::logging::level::ERR>(
301 "Invalid response of IANA ID received");
302 return ipmi::responseUnspecifiedError();
303 }
304
305 // sending the success response.
306 return ipmi::responseSuccess(resp);
307}
308
Willy Tue39f9392022-06-15 13:24:20 -0700309[[maybe_unused]] static void registerBICFunctions(void)
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +0530310{
311
312 phosphor::logging::log<phosphor::logging::level::INFO>(
313 "Registering BIC commands");
314
315 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
Bonnie Lo25b79bf2022-12-16 15:41:48 +0800316 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_BIC_INFO),
317 ipmi::Privilege::User, ipmiOemBicHandler);
318 ipmi::registerHandler(
319 ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
320 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_SEND_POST_BUFFER_TO_BMC),
321 ipmi::Privilege::User, ipmiOemPostCodeHandler);
322 ipmi::registerHandler(
323 ipmi::prioOemBase, ipmi::netFnOemFive,
324 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_GET_BIC_GPIO_STATE),
325 ipmi::Privilege::User, ipmiOemGetBicGpioState);
Bonnie Lo41027b92022-12-16 16:21:08 +0800326 ipmi::registerHandler(
327 ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
328 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_SET_HOST_POWER_STATE),
329 ipmi::Privilege::User, ipmiOemSetHostPowerState);
Kumar Thangavel05d0ce92022-11-17 17:53:57 +0530330 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
331 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_GET_FLASH_SIZE),
332 ipmi::Privilege::User, ipmiOemGetBiosFlashSize);
Jayashree Dhanapal6c931e42022-12-05 13:09:24 +0530333 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
334 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_CLEAR_CMOS),
335 ipmi::Privilege::User, ipmiOemClearCmos);
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +0530336 return;
337}
338
339} // namespace ipmi