blob: 49ae97fb02aaefa06b757da9df55e5d0322d6791 [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
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053018#include <biccommands.hpp>
Patrick Williams2405ae92023-05-10 07:50:09 -050019#include <commandutils.hpp>
20#include <ipmid/api-types.hpp>
21#include <ipmid/api.hpp>
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053022#include <phosphor-logging/log.hpp>
23
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053024#include <iostream>
Patrick Williams2405ae92023-05-10 07:50:09 -050025#include <variant>
26#include <vector>
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053027
28namespace ipmi
29{
30
Kumar Thangavel05d0ce92022-11-17 17:53:57 +053031int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
32 std::vector<uint8_t>&);
33
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053034using namespace phosphor::logging;
35
Patrick Williams58c1ca22021-04-22 12:29:35 -050036#ifdef BIC_ENABLED
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053037static void registerBICFunctions() __attribute__((constructor));
Patrick Williams58c1ca22021-04-22 12:29:35 -050038#endif
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053039
40extern message::Response::ptr executeIpmiCommand(message::Request::ptr);
41
Bonnie Lo25b79bf2022-12-16 15:41:48 +080042int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
43 std::vector<uint8_t>&);
44
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053045//----------------------------------------------------------------------
46// ipmiOemBicHandler (IPMI/Section - ) (CMD_OEM_BIC_INFO)
47// This Function will handle BIC request for netfn=0x38 and cmd=1
48// send the response back to the sender.
49//----------------------------------------------------------------------
50
Bonnie Lo25b79bf2022-12-16 15:41:48 +080051ipmi::RspType<IanaType, uint8_t, uint2_t, uint6_t, uint8_t, uint8_t,
52 ipmi::message::Payload>
53 ipmiOemBicHandler(ipmi::Context::ptr ctx, IanaType reqIana,
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053054 uint8_t interface, uint2_t lun, uint6_t netFnReq,
Patrick Williams485f9b32021-09-03 16:14:47 -050055 uint8_t cmdReq, SecureBuffer data)
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053056{
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053057 ipmi::message::Response::ptr res;
58
59 // Updating the correct netfn and cmd in the ipmi Context
60 ctx->netFn = ((uint8_t)netFnReq);
61 ctx->cmd = cmdReq;
62
63 // creating ipmi message request for calling executeIpmiCommand function
Patrick Williams485f9b32021-09-03 16:14:47 -050064 auto req = std::make_shared<ipmi::message::Request>(ctx, std::move(data));
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053065
66 // Calling executeIpmiCommand request function
67 res = ipmi::executeIpmiCommand(req);
68
69 // sending the response with headers and payload
Bonnie Lo25b79bf2022-12-16 15:41:48 +080070 return ipmi::responseSuccess(reqIana, interface, lun, ++netFnReq, cmdReq,
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +053071 res->cc, res->payload);
72}
73
Kumar Thangavelad049242020-08-31 22:27:33 +053074//----------------------------------------------------------------------
75// ipmiOemPostCodeHandler (CMD_OEM_BIC_POST_BUFFER_INFO)
76// This Function will handle BIC incomming postcode from multi-host for
77// netfn=0x38 and cmd=0x08 send the response back to the sender.
78//----------------------------------------------------------------------
79
Bonnie Lo25b79bf2022-12-16 15:41:48 +080080ipmi::RspType<IanaType> ipmiOemPostCodeHandler(ipmi::Context::ptr ctx,
81 IanaType reqIana,
82 uint8_t dataLen,
83 std::vector<uint8_t> data)
Kumar Thangavelad049242020-08-31 22:27:33 +053084{
85 // creating bus connection
86 auto conn = getSdBus();
87
Bonnie Lod8ef7b32022-10-24 16:42:42 +080088 using postcode_t = std::tuple<uint64_t, std::vector<uint8_t>>;
Manojkiran Edac723d6a2021-03-11 14:53:32 +053089
Bonnie Lod8ef7b32022-10-24 16:42:42 +080090 std::string dbusObjStr = dbusObj + std::to_string((ctx->hostIdx + 1));
91
92 for (unsigned int index = 0; index < dataLen; index++)
93 {
94 uint64_t primaryPostCode = static_cast<uint64_t>(data[index]);
Kumar Thangavel0fcfbee2021-04-16 12:38:20 +053095 auto postCode = postcode_t(primaryPostCode, {});
Kumar Thangavelad049242020-08-31 22:27:33 +053096
Bonnie Lod8ef7b32022-10-24 16:42:42 +080097 try
98 {
99 auto method = conn->new_method_call(
100 "xyz.openbmc_project.State.Boot.Raw", dbusObjStr.c_str(),
101 "org.freedesktop.DBus.Properties", "Set");
Kumar Thangavelad049242020-08-31 22:27:33 +0530102
Bonnie Lod8ef7b32022-10-24 16:42:42 +0800103 // Adding paramters to method call
104 method.append(dbusService, "Value",
105 std::variant<postcode_t>(postCode));
Kumar Thangavelad049242020-08-31 22:27:33 +0530106
Bonnie Lod8ef7b32022-10-24 16:42:42 +0800107 // Invoke method call function
108 auto reply = conn->call(method);
109 }
Kumar Thangavelad049242020-08-31 22:27:33 +0530110
Bonnie Lod8ef7b32022-10-24 16:42:42 +0800111 catch (std::exception& e)
112 {
113 phosphor::logging::log<phosphor::logging::level::ERR>(
114 "post code handler error\n");
Kumar Thangavelad049242020-08-31 22:27:33 +0530115
Bonnie Lod8ef7b32022-10-24 16:42:42 +0800116 // sending the Error response
117 return ipmi::responseResponseError();
118 }
Kumar Thangavelad049242020-08-31 22:27:33 +0530119 }
Kumar Thangavelad049242020-08-31 22:27:33 +0530120
Bonnie Lo25b79bf2022-12-16 15:41:48 +0800121 return ipmi::responseSuccess(reqIana);
122}
123
124//----------------------------------------------------------------------
125// ipmiOemGetBicGpioState (CMD_OEM_GET_BIC_GPIO_STATE)
126// This Function will handle BIC GPIO stats for
127// netfn=0x38 and cmd=0x03 send the response back to the sender.
128//----------------------------------------------------------------------
129
130ipmi::RspType<IanaType, std::vector<uint8_t>>
131 ipmiOemGetBicGpioState(ipmi::Context::ptr ctx, std::vector<uint8_t> reqIana)
132{
133 std::vector<uint8_t> respData;
134
135 if (std::equal(reqIana.begin(), reqIana.end(), iana.begin()) == false)
136 {
137 phosphor::logging::log<phosphor::logging::level::ERR>(
138 "Invalid IANA number");
139 return ipmi::responseInvalidFieldRequest();
140 }
141
142 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
143
144 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqIana, respData))
145 {
146 return ipmi::responseUnspecifiedError();
147 }
148
149 std::vector<uint8_t> gpioState;
150 IanaType respIana;
151
152 auto r =
153 std::ranges::copy_n(respData.begin(), iana.size(), respIana.begin()).in;
154 std::copy(r, respData.end(), std::back_inserter(gpioState));
155
156 return ipmi::responseSuccess(respIana, gpioState);
Kumar Thangavelad049242020-08-31 22:27:33 +0530157}
158
Bonnie Lo41027b92022-12-16 16:21:08 +0800159//----------------------------------------------------------------------
160// ipmiOemSetHostPowerState (CMD_OEM_SET_HOST_POWER_STATE)
161// This Function will handle BIC incomming IPMI request for
162// setting host current state for netfn=0x38 and cmd=0x0C
163// send the response back to the sender.
164//----------------------------------------------------------------------
165
166ipmi::RspType<IanaType> ipmiOemSetHostPowerState(ipmi::Context::ptr ctx,
167 IanaType reqIana,
168 uint8_t status)
169{
170 std::string targetUnit;
171
172 switch (static_cast<HostPowerState>(status))
173 {
174 case HostPowerState::HOST_POWER_ON:
175 targetUnit = "obmc-host-startmin@.target";
176 break;
177 case HostPowerState::HOST_POWER_OFF:
178 targetUnit = "obmc-host-stop@.target";
179 break;
180 default:
181 phosphor::logging::log<phosphor::logging::level::ERR>(
182 "IPMI ipmiOemHostPowerStatus power status error");
183 return ipmi::responseUnspecifiedError();
184 }
185
186 int mousePos = targetUnit.find('@');
187 targetUnit.insert(mousePos + 1, std::to_string(ctx->hostIdx + 1));
188
189 auto conn = getSdBus();
190 auto method = conn->new_method_call(systemdService, systemdObjPath,
191 systemdInterface, "StartUnit");
192 method.append(targetUnit);
193 method.append("replace");
194
195 try
196 {
197 conn->call_noreply(method);
198 }
199 catch (const sdbusplus::exception::SdBusError& e)
200 {
201 phosphor::logging::log<phosphor::logging::level::ERR>(
202 "IPMI ipmiOemHostPowerStatus Failed in call method",
203 phosphor::logging::entry("ERROR=%s", e.what()));
204 return ipmi::responseUnspecifiedError();
205 }
206
207 return ipmi::responseSuccess(reqIana);
208}
209
Kumar Thangavel05d0ce92022-11-17 17:53:57 +0530210//----------------------------------------------------------------------
211// ipmiOemGetBiosFlashSize (CMD_OEM_GET_FLASH_SIZE)
212// This Function will return the bios flash size
213// netfn=0x38 and cmd=0x19 send the response back to the sender.
214//----------------------------------------------------------------------
215
216ipmi::RspType<IanaType, flashSize>
217 ipmiOemGetBiosFlashSize(ipmi::Context::ptr ctx, IanaType ianaReq,
218 uint8_t target)
219{
220 if (iana != ianaReq)
221 {
222 phosphor::logging::log<phosphor::logging::level::ERR>(
223 "Invalid IANA ID length received");
224 return ipmi::responseReqDataLenInvalid();
225 }
226
227 std::vector<uint8_t> respData;
228 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
229 std::vector<uint8_t> reqData(ianaReq.begin(), ianaReq.end());
230 reqData.emplace_back(target);
231
232 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
233 {
234 return ipmi::responseUnspecifiedError();
235 }
236
237 if (respData.size() != flashSizeRespLen)
238 {
239 phosphor::logging::log<phosphor::logging::level::ERR>(
240 "Invalid Response Data length received");
241 return ipmi::responseReqDataLenInvalid();
242 }
243
244 IanaType ianaResp;
245 std::copy_n(respData.begin(), ianaResp.size(), ianaResp.begin());
246
247 if (iana != ianaResp)
248 {
249 phosphor::logging::log<phosphor::logging::level::ERR>(
250 "Invalid IANA ID received");
251 return ipmi::responseInvalidCommand();
252 }
253
254 flashSize flashResp;
255 std::vector<uint8_t>::iterator respDataIter = respData.begin();
256 std::advance(respDataIter, ianaResp.size());
257 std::copy_n(respDataIter, flashResp.size(), flashResp.begin());
258
259 // sending the success response.
260 return ipmi::responseSuccess(ianaResp, flashResp);
261}
262
Jayashree Dhanapal6c931e42022-12-05 13:09:24 +0530263//----------------------------------------------------------------------
264// ipmiOemClearCmos (CMD_OEM_CLEAR_CMOS)
265// This Function will clear the CMOS.
266// netfn=0x38 and cmd=0x25
267//----------------------------------------------------------------------
268ipmi::RspType<IanaType> ipmiOemClearCmos(ipmi::Context::ptr ctx,
269 IanaType ianaReq)
270{
271 if (iana != ianaReq)
272 {
273 phosphor::logging::log<phosphor::logging::level::ERR>(
274 "Invalid request of IANA ID length received");
275 return ipmi::responseReqDataLenInvalid();
276 }
277
278 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
279
280 std::vector<uint8_t> respData;
281 std::vector<uint8_t> reqData(ianaReq.begin(), ianaReq.end());
282
283 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
284 {
285 return ipmi::responseUnspecifiedError();
286 }
287
288 if (respData.size() != iana.size())
289 {
290 return ipmi::responseReqDataLenInvalid();
291 }
292
293 IanaType resp;
294 std::copy_n(respData.begin(), resp.size(), resp.begin());
295
296 if (iana != resp)
297 {
298 phosphor::logging::log<phosphor::logging::level::ERR>(
299 "Invalid response of IANA ID received");
300 return ipmi::responseUnspecifiedError();
301 }
302
303 // sending the success response.
304 return ipmi::responseSuccess(resp);
305}
306
Willy Tue39f9392022-06-15 13:24:20 -0700307[[maybe_unused]] static void registerBICFunctions(void)
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +0530308{
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +0530309 phosphor::logging::log<phosphor::logging::level::INFO>(
310 "Registering BIC commands");
311
312 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
Bonnie Lo25b79bf2022-12-16 15:41:48 +0800313 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_BIC_INFO),
314 ipmi::Privilege::User, ipmiOemBicHandler);
315 ipmi::registerHandler(
316 ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
317 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_SEND_POST_BUFFER_TO_BMC),
318 ipmi::Privilege::User, ipmiOemPostCodeHandler);
319 ipmi::registerHandler(
320 ipmi::prioOemBase, ipmi::netFnOemFive,
321 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_GET_BIC_GPIO_STATE),
322 ipmi::Privilege::User, ipmiOemGetBicGpioState);
Bonnie Lo41027b92022-12-16 16:21:08 +0800323 ipmi::registerHandler(
324 ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
325 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_SET_HOST_POWER_STATE),
326 ipmi::Privilege::User, ipmiOemSetHostPowerState);
Kumar Thangavel05d0ce92022-11-17 17:53:57 +0530327 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
328 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_GET_FLASH_SIZE),
329 ipmi::Privilege::User, ipmiOemGetBiosFlashSize);
Jayashree Dhanapal6c931e42022-12-05 13:09:24 +0530330 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
331 static_cast<Cmd>(fb_bic_cmds::CMD_OEM_CLEAR_CMOS),
332 ipmi::Privilege::User, ipmiOemClearCmos);
Kumar Thangavel41ad4ff2020-06-11 10:31:07 +0530333 return;
334}
335
336} // namespace ipmi