blob: 724d8e5f26ec90aa4ab24345b57474b0025f37c2 [file] [log] [blame]
Jia, Chunhuia835eaa2018-09-05 09:00:41 +08001/*
2// Copyright (c) 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
Jason M. Bills64796042018-10-03 16:51:55 -070017#include "xyz/openbmc_project/Common/error.hpp"
Kuiying Wang45f04982018-12-26 09:23:08 +080018#include "xyz/openbmc_project/Led/Physical/server.hpp"
Jason M. Bills64796042018-10-03 16:51:55 -070019
Jason M. Bills6d9c83f2019-02-08 14:02:19 -080020#include <ipmid/api.h>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080021
22#include <array>
Jason M. Bills64796042018-10-03 16:51:55 -070023#include <commandutils.hpp>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080024#include <iostream>
25#include <oemcommands.hpp>
Jason M. Bills3f7c5e42018-10-03 14:00:41 -070026#include <phosphor-ipmi-host/utils.hpp>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080027#include <phosphor-logging/log.hpp>
28#include <sdbusplus/bus.hpp>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080029#include <string>
30#include <vector>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080031
32namespace ipmi
33{
Jason M. Bills64796042018-10-03 16:51:55 -070034static void registerOEMFunctions() __attribute__((constructor));
Jason M. Bills6d9c83f2019-02-08 14:02:19 -080035sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
Jason M. Bills64796042018-10-03 16:51:55 -070036static constexpr size_t maxFRUStringLength = 0x3F;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080037
38// return code: 0 successful
39int8_t getChassisSerialNumber(sdbusplus::bus::bus& bus, std::string& serial)
40{
41 std::string objpath = "/xyz/openbmc_project/FruDevice";
42 std::string intf = "xyz.openbmc_project.FruDeviceManager";
43 std::string service = getService(bus, intf, objpath);
44 ObjectValueTree valueTree = getManagedObjects(bus, service, "/");
45 if (valueTree.empty())
46 {
47 phosphor::logging::log<phosphor::logging::level::ERR>(
48 "No object implements interface",
49 phosphor::logging::entry("INTF=%s", intf.c_str()));
50 return -1;
51 }
52
Jason M. Bills64796042018-10-03 16:51:55 -070053 for (const auto& item : valueTree)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080054 {
55 auto interface = item.second.find("xyz.openbmc_project.FruDevice");
56 if (interface == item.second.end())
57 {
58 continue;
59 }
60
61 auto property = interface->second.find("CHASSIS_SERIAL_NUMBER");
62 if (property == interface->second.end())
63 {
64 continue;
65 }
66
67 try
68 {
69 Value variant = property->second;
Jason M. Bills64796042018-10-03 16:51:55 -070070 std::string& result =
71 sdbusplus::message::variant_ns::get<std::string>(variant);
72 if (result.size() > maxFRUStringLength)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080073 {
74 phosphor::logging::log<phosphor::logging::level::ERR>(
75 "FRU serial number exceed maximum length");
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080076 return -1;
77 }
Jason M. Bills64796042018-10-03 16:51:55 -070078 serial = result;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080079 return 0;
80 }
Jason M. Bills64796042018-10-03 16:51:55 -070081 catch (sdbusplus::message::variant_ns::bad_variant_access& e)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080082 {
Jason M. Bills64796042018-10-03 16:51:55 -070083 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080084 return -1;
85 }
86 }
87 return -1;
88}
Jason M. Bills64796042018-10-03 16:51:55 -070089
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080090ipmi_ret_t ipmiOEMWildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
91 ipmi_request_t request, ipmi_response_t response,
Jason M. Bills64796042018-10-03 16:51:55 -070092 ipmi_data_len_t dataLen, ipmi_context_t context)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080093{
Jason M. Bills64796042018-10-03 16:51:55 -070094 printCommand(+netfn, +cmd);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080095 // Status code.
96 ipmi_ret_t rc = IPMI_CC_INVALID;
Jason M. Bills64796042018-10-03 16:51:55 -070097 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080098 return rc;
99}
100
101// Returns the Chassis Identifier (serial #)
102ipmi_ret_t ipmiOEMGetChassisIdentifier(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
103 ipmi_request_t request,
104 ipmi_response_t response,
Jason M. Bills64796042018-10-03 16:51:55 -0700105 ipmi_data_len_t dataLen,
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800106 ipmi_context_t context)
107{
108 std::string serial;
Jason M. Bills64796042018-10-03 16:51:55 -0700109 if (*dataLen != 0) // invalid request if there are extra parameters
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800110 {
Jason M. Bills64796042018-10-03 16:51:55 -0700111 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800112 return IPMI_CC_REQ_DATA_LEN_INVALID;
113 }
Jason M. Bills64796042018-10-03 16:51:55 -0700114 if (getChassisSerialNumber(dbus, serial) == 0)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800115 {
Jason M. Bills64796042018-10-03 16:51:55 -0700116 *dataLen = serial.size(); // length will never exceed response length
117 // as it is checked in getChassisSerialNumber
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800118 char* resp = static_cast<char*>(response);
Jason M. Bills64796042018-10-03 16:51:55 -0700119 serial.copy(resp, *dataLen);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800120 return IPMI_CC_OK;
121 }
Jason M. Bills64796042018-10-03 16:51:55 -0700122 *dataLen = 0;
123 return IPMI_CC_RESPONSE_ERROR;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800124}
125
126ipmi_ret_t ipmiOEMSetSystemGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
127 ipmi_request_t request,
128 ipmi_response_t response,
Jason M. Bills64796042018-10-03 16:51:55 -0700129 ipmi_data_len_t dataLen, ipmi_context_t context)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800130{
131 static constexpr size_t safeBufferLength = 50;
132 char buf[safeBufferLength] = {0};
133 GUIDData* Data = reinterpret_cast<GUIDData*>(request);
134
Jason M. Bills64796042018-10-03 16:51:55 -0700135 if (*dataLen != sizeof(GUIDData)) // 16bytes
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800136 {
Jason M. Bills64796042018-10-03 16:51:55 -0700137 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800138 return IPMI_CC_REQ_DATA_LEN_INVALID;
139 }
140
Jason M. Bills64796042018-10-03 16:51:55 -0700141 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800142
143 snprintf(
144 buf, safeBufferLength,
145 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
146 Data->timeLow4, Data->timeLow3, Data->timeLow2, Data->timeLow1,
147 Data->timeMid2, Data->timeMid1, Data->timeHigh2, Data->timeHigh1,
148 Data->clock2, Data->clock1, Data->node6, Data->node5, Data->node4,
149 Data->node3, Data->node2, Data->node1);
150 // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
151 std::string guid = buf;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800152
153 std::string objpath = "/xyz/openbmc_project/control/host0/systemGUID";
154 std::string intf = "xyz.openbmc_project.Common.UUID";
Jason M. Bills64796042018-10-03 16:51:55 -0700155 std::string service = getService(dbus, intf, objpath);
156 setDbusProperty(dbus, service, objpath, intf, "UUID", guid);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800157 return IPMI_CC_OK;
158}
159
160ipmi_ret_t ipmiOEMSetBIOSID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
161 ipmi_request_t request, ipmi_response_t response,
162 ipmi_data_len_t dataLen, ipmi_context_t context)
163{
164 DeviceInfo* data = reinterpret_cast<DeviceInfo*>(request);
165
Jason M. Bills64796042018-10-03 16:51:55 -0700166 if ((*dataLen < 2) || (*dataLen != (1 + data->biosIDLength)))
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800167 {
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800168 *dataLen = 0;
169 return IPMI_CC_REQ_DATA_LEN_INVALID;
170 }
Jason M. Bills64796042018-10-03 16:51:55 -0700171 std::string idString((char*)data->biosId, data->biosIDLength);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800172
Jason M. Bills64796042018-10-03 16:51:55 -0700173 std::string service = getService(dbus, biosIntf, biosObjPath);
174 setDbusProperty(dbus, service, biosObjPath, biosIntf, biosProp, idString);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800175 uint8_t* bytesWritten = static_cast<uint8_t*>(response);
176 *bytesWritten =
Jason M. Bills64796042018-10-03 16:51:55 -0700177 data->biosIDLength; // how many bytes are written into storage
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800178 *dataLen = 1;
179 return IPMI_CC_OK;
180}
181
182ipmi_ret_t ipmiOEMGetDeviceInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
183 ipmi_request_t request,
184 ipmi_response_t response,
185 ipmi_data_len_t dataLen, ipmi_context_t context)
186{
187 GetOemDeviceInfoReq* req = reinterpret_cast<GetOemDeviceInfoReq*>(request);
188 GetOemDeviceInfoRes* res = reinterpret_cast<GetOemDeviceInfoRes*>(response);
189
190 if (*dataLen == 0)
191 {
Jason M. Bills64796042018-10-03 16:51:55 -0700192 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800193 return IPMI_CC_REQ_DATA_LEN_INVALID;
194 }
195
196 size_t reqDataLen = *dataLen;
197 *dataLen = 0;
Jason M. Bills64796042018-10-03 16:51:55 -0700198 if (req->entityType > static_cast<uint8_t>(OEMDevEntityType::sdrVer))
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800199 {
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800200 return IPMI_CC_INVALID_FIELD_REQUEST;
201 }
202
203 // handle OEM command items
Jason M. Bills64796042018-10-03 16:51:55 -0700204 switch (OEMDevEntityType(req->entityType))
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800205 {
206 case OEMDevEntityType::biosId:
207 {
208 if (sizeof(GetOemDeviceInfoReq) != reqDataLen)
209 {
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800210 return IPMI_CC_REQ_DATA_LEN_INVALID;
211 }
212
Jason M. Bills64796042018-10-03 16:51:55 -0700213 std::string service = getService(dbus, biosIntf, biosObjPath);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800214 try
215 {
Jason M. Bills64796042018-10-03 16:51:55 -0700216 Value variant = getDbusProperty(dbus, service, biosObjPath,
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800217 biosIntf, biosProp);
Jason M. Bills64796042018-10-03 16:51:55 -0700218 std::string& idString =
219 sdbusplus::message::variant_ns::get<std::string>(variant);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800220 if (req->offset >= idString.size())
221 {
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800222 return IPMI_CC_PARM_OUT_OF_RANGE;
223 }
Jason M. Bills64796042018-10-03 16:51:55 -0700224 size_t length = 0;
225 if (req->countToRead > (idString.size() - req->offset))
226 {
227 length = idString.size() - req->offset;
228 }
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800229 else
230 {
Jason M. Bills64796042018-10-03 16:51:55 -0700231 length = req->countToRead;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800232 }
Jason M. Bills64796042018-10-03 16:51:55 -0700233 std::copy(idString.begin() + req->offset, idString.end(),
234 res->data);
235 res->resDatalen = length;
236 *dataLen = res->resDatalen + 1;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800237 }
Jason M. Bills64796042018-10-03 16:51:55 -0700238 catch (sdbusplus::message::variant_ns::bad_variant_access& e)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800239 {
Jason M. Bills64796042018-10-03 16:51:55 -0700240 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800241 return IPMI_CC_UNSPECIFIED_ERROR;
242 }
243 }
244 break;
245
246 case OEMDevEntityType::devVer:
247 case OEMDevEntityType::sdrVer:
248 // TODO:
249 return IPMI_CC_ILLEGAL_COMMAND;
250 default:
251 return IPMI_CC_INVALID_FIELD_REQUEST;
252 }
253 return IPMI_CC_OK;
254}
255
256ipmi_ret_t ipmiOEMGetAICFRU(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
257 ipmi_request_t request, ipmi_response_t response,
258 ipmi_data_len_t dataLen, ipmi_context_t context)
259{
260 if (*dataLen != 0)
261 {
Jason M. Bills64796042018-10-03 16:51:55 -0700262 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800263 return IPMI_CC_REQ_DATA_LEN_INVALID;
264 }
265
266 *dataLen = 1;
267 uint8_t* res = reinterpret_cast<uint8_t*>(response);
268 // temporary fix. We don't support AIC FRU now. Just tell BIOS that no
269 // AIC is available so that BIOS will not timeout repeatly which leads to
270 // slow booting.
271 *res = 0; // Byte1=Count of SlotPosition/FruID records.
272 return IPMI_CC_OK;
273}
274
Jason M. Bills64796042018-10-03 16:51:55 -0700275ipmi_ret_t ipmiOEMGetPowerRestoreDelay(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
276 ipmi_request_t request,
277 ipmi_response_t response,
278 ipmi_data_len_t dataLen,
279 ipmi_context_t context)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800280{
Jason M. Bills64796042018-10-03 16:51:55 -0700281 GetPowerRestoreDelayRes* resp =
282 reinterpret_cast<GetPowerRestoreDelayRes*>(response);
283
284 if (*dataLen != 0)
285 {
286 *dataLen = 0;
287 return IPMI_CC_REQ_DATA_LEN_INVALID;
288 }
289
290 std::string service =
291 getService(dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath);
292 Value variant =
293 getDbusProperty(dbus, service, powerRestoreDelayObjPath,
294 powerRestoreDelayIntf, powerRestoreDelayProp);
295
296 uint16_t delay = sdbusplus::message::variant_ns::get<uint16_t>(variant);
297 resp->byteLSB = delay;
298 resp->byteMSB = delay >> 8;
299
300 *dataLen = sizeof(GetPowerRestoreDelayRes);
301
302 return IPMI_CC_OK;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800303}
304
Jason M. Bills64796042018-10-03 16:51:55 -0700305ipmi_ret_t ipmiOEMSetPowerRestoreDelay(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
306 ipmi_request_t request,
307 ipmi_response_t response,
308 ipmi_data_len_t dataLen,
309 ipmi_context_t context)
310{
311 SetPowerRestoreDelayReq* data =
312 reinterpret_cast<SetPowerRestoreDelayReq*>(request);
313 uint16_t delay = 0;
314
315 if (*dataLen != sizeof(SetPowerRestoreDelayReq))
316 {
317 *dataLen = 0;
318 return IPMI_CC_REQ_DATA_LEN_INVALID;
319 }
320 delay = data->byteMSB;
321 delay = (delay << 8) | data->byteLSB;
322 std::string service =
323 getService(dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath);
324 setDbusProperty(dbus, service, powerRestoreDelayObjPath,
325 powerRestoreDelayIntf, powerRestoreDelayProp, delay);
326 *dataLen = 0;
327
328 return IPMI_CC_OK;
329}
330
331ipmi_ret_t ipmiOEMGetProcessorErrConfig(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
332 ipmi_request_t request,
333 ipmi_response_t response,
334 ipmi_data_len_t dataLen,
335 ipmi_context_t context)
336{
337 GetProcessorErrConfigRes* resp =
338 reinterpret_cast<GetProcessorErrConfigRes*>(response);
339
340 if (*dataLen != 0)
341 {
342 *dataLen = 0;
343 return IPMI_CC_REQ_DATA_LEN_INVALID;
344 }
345
346 std::string service =
347 getService(dbus, processorErrConfigIntf, processorErrConfigObjPath);
348 Value variant = getDbusProperty(dbus, service, processorErrConfigObjPath,
349 processorErrConfigIntf, "ResetCfg");
350 resp->resetCfg = sdbusplus::message::variant_ns::get<uint8_t>(variant);
351
352 std::vector<uint8_t> caterrStatus;
Kuiying Wangbc546672018-11-23 15:41:05 +0800353 sdbusplus::message::variant<std::vector<uint8_t>> message;
Jason M. Bills64796042018-10-03 16:51:55 -0700354
355 auto method =
356 dbus.new_method_call(service.c_str(), processorErrConfigObjPath,
357 "org.freedesktop.DBus.Properties", "Get");
358
359 method.append(processorErrConfigIntf, "CATERRStatus");
Kuiying Wangbc546672018-11-23 15:41:05 +0800360 auto reply = dbus.call(method);
Jason M. Bills64796042018-10-03 16:51:55 -0700361
362 try
363 {
Kuiying Wangbc546672018-11-23 15:41:05 +0800364 reply.read(message);
365 caterrStatus =
366 sdbusplus::message::variant_ns::get<std::vector<uint8_t>>(message);
Jason M. Bills64796042018-10-03 16:51:55 -0700367 }
368 catch (sdbusplus::exception_t&)
369 {
Kuiying Wangbc546672018-11-23 15:41:05 +0800370 phosphor::logging::log<phosphor::logging::level::ERR>(
Jason M. Bills64796042018-10-03 16:51:55 -0700371 "ipmiOEMGetProcessorErrConfig: error on dbus",
372 phosphor::logging::entry("PRORPERTY=CATERRStatus"),
373 phosphor::logging::entry("PATH=%s", processorErrConfigObjPath),
374 phosphor::logging::entry("INTERFACE=%s", processorErrConfigIntf));
375 return IPMI_CC_UNSPECIFIED_ERROR;
376 }
377
378 size_t len =
379 maxCPUNum <= caterrStatus.size() ? maxCPUNum : caterrStatus.size();
380 caterrStatus.resize(len);
381 std::copy(caterrStatus.begin(), caterrStatus.end(), resp->caterrStatus);
382 *dataLen = sizeof(GetProcessorErrConfigRes);
383
384 return IPMI_CC_OK;
385}
386
387ipmi_ret_t ipmiOEMSetProcessorErrConfig(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
388 ipmi_request_t request,
389 ipmi_response_t response,
390 ipmi_data_len_t dataLen,
391 ipmi_context_t context)
392{
393 SetProcessorErrConfigReq* req =
394 reinterpret_cast<SetProcessorErrConfigReq*>(request);
395
396 if (*dataLen != sizeof(SetProcessorErrConfigReq))
397 {
398 *dataLen = 0;
399 return IPMI_CC_REQ_DATA_LEN_INVALID;
400 }
401 std::string service =
402 getService(dbus, processorErrConfigIntf, processorErrConfigObjPath);
403 setDbusProperty(dbus, service, processorErrConfigObjPath,
404 processorErrConfigIntf, "ResetCfg", req->resetCfg);
405
406 setDbusProperty(dbus, service, processorErrConfigObjPath,
407 processorErrConfigIntf, "ResetErrorOccurrenceCounts",
408 req->resetErrorOccurrenceCounts);
409 *dataLen = 0;
410
411 return IPMI_CC_OK;
412}
413
Yong Li703922d2018-11-06 13:25:31 +0800414ipmi_ret_t ipmiOEMGetShutdownPolicy(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
415 ipmi_request_t request,
416 ipmi_response_t response,
417 ipmi_data_len_t dataLen,
418 ipmi_context_t context)
419{
420 GetOEMShutdownPolicyRes* resp =
421 reinterpret_cast<GetOEMShutdownPolicyRes*>(response);
422
423 if (*dataLen != 0)
424 {
425 phosphor::logging::log<phosphor::logging::level::ERR>(
Kuiying Wang45f04982018-12-26 09:23:08 +0800426 "oem_get_shutdown_policy: invalid input len!");
Yong Li703922d2018-11-06 13:25:31 +0800427 *dataLen = 0;
428 return IPMI_CC_REQ_DATA_LEN_INVALID;
429 }
430
431 *dataLen = 0;
432
433 try
434 {
435 std::string service =
436 getService(dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath);
437 Value variant = getDbusProperty(dbus, service, oemShutdownPolicyObjPath,
438 oemShutdownPolicyIntf,
439 oemShutdownPolicyObjPathProp);
440 resp->policy = sdbusplus::message::variant_ns::get<uint8_t>(variant);
441 // TODO needs to check if it is multi-node products,
442 // policy is only supported on node 3/4
443 resp->policySupport = shutdownPolicySupported;
444 }
445 catch (sdbusplus::exception_t& e)
446 {
447 phosphor::logging::log<phosphor::logging::level::ERR>(e.description());
448 return IPMI_CC_UNSPECIFIED_ERROR;
449 }
450
451 *dataLen = sizeof(GetOEMShutdownPolicyRes);
452 return IPMI_CC_OK;
453}
454
455ipmi_ret_t ipmiOEMSetShutdownPolicy(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
456 ipmi_request_t request,
457 ipmi_response_t response,
458 ipmi_data_len_t dataLen,
459 ipmi_context_t context)
460{
461 uint8_t* req = reinterpret_cast<uint8_t*>(request);
462
463 // TODO needs to check if it is multi-node products,
464 // policy is only supported on node 3/4
465 if (*dataLen != 1)
466 {
467 phosphor::logging::log<phosphor::logging::level::ERR>(
468 "oem_set_shutdown_policy: invalid input len!");
469 *dataLen = 0;
470 return IPMI_CC_REQ_DATA_LEN_INVALID;
471 }
472
473 *dataLen = 0;
474 if ((*req != noShutdownOnOCOT) && (*req != shutdownOnOCOT))
475 {
476 phosphor::logging::log<phosphor::logging::level::ERR>(
477 "oem_set_shutdown_policy: invalid input!");
478 return IPMI_CC_INVALID_FIELD_REQUEST;
479 }
480
481 try
482 {
483 std::string service =
484 getService(dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath);
485 setDbusProperty(dbus, service, oemShutdownPolicyObjPath,
486 oemShutdownPolicyIntf, oemShutdownPolicyObjPathProp,
487 *req);
488 }
489 catch (sdbusplus::exception_t& e)
490 {
491 phosphor::logging::log<phosphor::logging::level::ERR>(e.description());
492 return IPMI_CC_UNSPECIFIED_ERROR;
493 }
494
495 return IPMI_CC_OK;
496}
497
Kuiying Wang45f04982018-12-26 09:23:08 +0800498namespace ledAction
499{
500using namespace sdbusplus::xyz::openbmc_project::Led::server;
501std::map<Physical::Action, uint8_t> actionDbusToIpmi = {
502 {Physical::Action::Off, 0x00},
503 {Physical::Action::On, 0x10},
504 {Physical::Action::Blink, 0x01}};
505
506std::map<uint8_t, std::string> offsetObjPath = {
507 {2, statusAmberObjPath}, {4, statusGreenObjPath}, {6, identifyLEDObjPath}};
508
509} // namespace ledAction
510
511int8_t getLEDState(sdbusplus::bus::bus& bus, const std::string& intf,
512 const std::string& objPath, uint8_t& state)
513{
514 try
515 {
516 std::string service = getService(bus, intf, objPath);
517 Value stateValue =
518 getDbusProperty(bus, service, objPath, intf, "State");
519 std::string strState =
520 sdbusplus::message::variant_ns::get<std::string>(stateValue);
521 state = ledAction::actionDbusToIpmi.at(
522 sdbusplus::xyz::openbmc_project::Led::server::Physical::
523 convertActionFromString(strState));
524 }
525 catch (sdbusplus::exception::SdBusError& e)
526 {
527 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
528 return -1;
529 }
530 return 0;
531}
532
533ipmi_ret_t ipmiOEMGetLEDStatus(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
534 ipmi_request_t request, ipmi_response_t response,
535 ipmi_data_len_t dataLen, ipmi_context_t context)
536{
537 uint8_t* resp = reinterpret_cast<uint8_t*>(response);
538 // LED Status
539 //[1:0] = Reserved
540 //[3:2] = Status(Amber)
541 //[5:4] = Status(Green)
542 //[7:6] = System Identify
543 // Status definitions:
544 // 00b = Off
545 // 01b = Blink
546 // 10b = On
547 // 11b = invalid
548 if (*dataLen != 0)
549 {
550 phosphor::logging::log<phosphor::logging::level::ERR>(
551 "oem_get_led_status: invalid input len!");
552 *dataLen = 0;
553 return IPMI_CC_REQ_DATA_LEN_INVALID;
554 }
555
556 phosphor::logging::log<phosphor::logging::level::DEBUG>("GET led status");
557 *resp = 0;
558 *dataLen = 0;
559 for (auto it = ledAction::offsetObjPath.begin();
560 it != ledAction::offsetObjPath.end(); ++it)
561 {
562 uint8_t state = 0;
563 if (-1 == getLEDState(dbus, ledIntf, it->second, state))
564 {
565 phosphor::logging::log<phosphor::logging::level::ERR>(
566 "oem_get_led_status: fail to get ID LED status!");
567 return IPMI_CC_UNSPECIFIED_ERROR;
568 }
569 *resp |= state << it->first;
570 }
571
572 *dataLen = sizeof(*resp);
573 return IPMI_CC_OK;
574}
575
Jason M. Bills64796042018-10-03 16:51:55 -0700576static void registerOEMFunctions(void)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800577{
578 phosphor::logging::log<phosphor::logging::level::INFO>(
579 "Registering OEM commands");
Jason M. Bills64796042018-10-03 16:51:55 -0700580 ipmiPrintAndRegister(netfnIntcOEMGeneral, IPMI_CMD_WILDCARD, NULL,
581 ipmiOEMWildcard,
582 PRIVILEGE_USER); // wildcard default handler
583 ipmiPrintAndRegister(netfunIntelAppOEM, IPMI_CMD_WILDCARD, NULL,
584 ipmiOEMWildcard,
585 PRIVILEGE_USER); // wildcard default handler
586 ipmiPrintAndRegister(
587 netfnIntcOEMGeneral,
588 static_cast<ipmi_cmd_t>(
589 IPMINetfnIntelOEMGeneralCmd::cmdGetChassisIdentifier),
590 NULL, ipmiOEMGetChassisIdentifier,
591 PRIVILEGE_USER); // get chassis identifier
592 ipmiPrintAndRegister(
593 netfnIntcOEMGeneral,
594 static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdSetSystemGUID),
595 NULL, ipmiOEMSetSystemGUID,
596 PRIVILEGE_ADMIN); // set system guid
597 ipmiPrintAndRegister(
598 netfnIntcOEMGeneral,
599 static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdSetBIOSID),
600 NULL, ipmiOEMSetBIOSID, PRIVILEGE_ADMIN);
601 ipmiPrintAndRegister(netfnIntcOEMGeneral,
602 static_cast<ipmi_cmd_t>(
603 IPMINetfnIntelOEMGeneralCmd::cmdGetOEMDeviceInfo),
604 NULL, ipmiOEMGetDeviceInfo, PRIVILEGE_USER);
605 ipmiPrintAndRegister(
606 netfnIntcOEMGeneral,
607 static_cast<ipmi_cmd_t>(
608 IPMINetfnIntelOEMGeneralCmd::cmdGetAICSlotFRUIDSlotPosRecords),
609 NULL, ipmiOEMGetAICFRU, PRIVILEGE_USER);
610 ipmiPrintAndRegister(
611 netfnIntcOEMGeneral,
612 static_cast<ipmi_cmd_t>(
613 IPMINetfnIntelOEMGeneralCmd::cmdSetPowerRestoreDelay),
614 NULL, ipmiOEMSetPowerRestoreDelay, PRIVILEGE_OPERATOR);
615 ipmiPrintAndRegister(
616 netfnIntcOEMGeneral,
617 static_cast<ipmi_cmd_t>(
618 IPMINetfnIntelOEMGeneralCmd::cmdGetPowerRestoreDelay),
619 NULL, ipmiOEMGetPowerRestoreDelay, PRIVILEGE_USER);
620 ipmiPrintAndRegister(
621 netfnIntcOEMGeneral,
622 static_cast<ipmi_cmd_t>(
623 IPMINetfnIntelOEMGeneralCmd::cmdGetProcessorErrConfig),
624 NULL, ipmiOEMGetProcessorErrConfig, PRIVILEGE_USER);
625 ipmiPrintAndRegister(
626 netfnIntcOEMGeneral,
627 static_cast<ipmi_cmd_t>(
628 IPMINetfnIntelOEMGeneralCmd::cmdSetProcessorErrConfig),
629 NULL, ipmiOEMSetProcessorErrConfig, PRIVILEGE_ADMIN);
Yong Li703922d2018-11-06 13:25:31 +0800630 ipmiPrintAndRegister(netfnIntcOEMGeneral,
631 static_cast<ipmi_cmd_t>(
632 IPMINetfnIntelOEMGeneralCmd::cmdSetShutdownPolicy),
633 NULL, ipmiOEMSetShutdownPolicy, PRIVILEGE_ADMIN);
634 ipmiPrintAndRegister(netfnIntcOEMGeneral,
635 static_cast<ipmi_cmd_t>(
636 IPMINetfnIntelOEMGeneralCmd::cmdGetShutdownPolicy),
637 NULL, ipmiOEMGetShutdownPolicy, PRIVILEGE_ADMIN);
Kuiying Wang45f04982018-12-26 09:23:08 +0800638 ipmiPrintAndRegister(
639 netfnIntcOEMGeneral,
640 static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdGetLEDStatus),
641 NULL, ipmiOEMGetLEDStatus, PRIVILEGE_ADMIN);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800642 return;
643}
644
645} // namespace ipmi