blob: dfd4985585f29686bac28664eca7369c8a445072 [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>
James Feist91244a62019-02-19 15:04:54 -080023#include <boost/container/flat_map.hpp>
Yong Li23737fe2019-02-19 08:49:55 +080024#include <boost/process/child.hpp>
25#include <boost/process/io.hpp>
Jason M. Bills64796042018-10-03 16:51:55 -070026#include <commandutils.hpp>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080027#include <iostream>
Vernon Mauery5480ef62019-03-20 13:43:11 -070028#include <ipmid/utils.hpp>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080029#include <oemcommands.hpp>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080030#include <phosphor-logging/log.hpp>
31#include <sdbusplus/bus.hpp>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080032#include <string>
James Feist91244a62019-02-19 15:04:54 -080033#include <variant>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080034#include <vector>
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080035
36namespace ipmi
37{
Jason M. Bills64796042018-10-03 16:51:55 -070038static void registerOEMFunctions() __attribute__((constructor));
Jason M. Bills6d9c83f2019-02-08 14:02:19 -080039sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
Jason M. Bills64796042018-10-03 16:51:55 -070040static constexpr size_t maxFRUStringLength = 0x3F;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080041
42// return code: 0 successful
43int8_t getChassisSerialNumber(sdbusplus::bus::bus& bus, std::string& serial)
44{
45 std::string objpath = "/xyz/openbmc_project/FruDevice";
46 std::string intf = "xyz.openbmc_project.FruDeviceManager";
47 std::string service = getService(bus, intf, objpath);
48 ObjectValueTree valueTree = getManagedObjects(bus, service, "/");
49 if (valueTree.empty())
50 {
51 phosphor::logging::log<phosphor::logging::level::ERR>(
52 "No object implements interface",
53 phosphor::logging::entry("INTF=%s", intf.c_str()));
54 return -1;
55 }
56
Jason M. Bills64796042018-10-03 16:51:55 -070057 for (const auto& item : valueTree)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080058 {
59 auto interface = item.second.find("xyz.openbmc_project.FruDevice");
60 if (interface == item.second.end())
61 {
62 continue;
63 }
64
65 auto property = interface->second.find("CHASSIS_SERIAL_NUMBER");
66 if (property == interface->second.end())
67 {
68 continue;
69 }
70
71 try
72 {
73 Value variant = property->second;
Jason M. Bills64796042018-10-03 16:51:55 -070074 std::string& result =
75 sdbusplus::message::variant_ns::get<std::string>(variant);
76 if (result.size() > maxFRUStringLength)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080077 {
78 phosphor::logging::log<phosphor::logging::level::ERR>(
79 "FRU serial number exceed maximum length");
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080080 return -1;
81 }
Jason M. Bills64796042018-10-03 16:51:55 -070082 serial = result;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080083 return 0;
84 }
Jason M. Bills64796042018-10-03 16:51:55 -070085 catch (sdbusplus::message::variant_ns::bad_variant_access& e)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080086 {
Jason M. Bills64796042018-10-03 16:51:55 -070087 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080088 return -1;
89 }
90 }
91 return -1;
92}
Jason M. Bills64796042018-10-03 16:51:55 -070093
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080094ipmi_ret_t ipmiOEMWildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
95 ipmi_request_t request, ipmi_response_t response,
Jason M. Bills64796042018-10-03 16:51:55 -070096 ipmi_data_len_t dataLen, ipmi_context_t context)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080097{
Jason M. Bills64796042018-10-03 16:51:55 -070098 printCommand(+netfn, +cmd);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +080099 // Status code.
100 ipmi_ret_t rc = IPMI_CC_INVALID;
Jason M. Bills64796042018-10-03 16:51:55 -0700101 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800102 return rc;
103}
104
105// Returns the Chassis Identifier (serial #)
106ipmi_ret_t ipmiOEMGetChassisIdentifier(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
107 ipmi_request_t request,
108 ipmi_response_t response,
Jason M. Bills64796042018-10-03 16:51:55 -0700109 ipmi_data_len_t dataLen,
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800110 ipmi_context_t context)
111{
112 std::string serial;
Jason M. Bills64796042018-10-03 16:51:55 -0700113 if (*dataLen != 0) // invalid request if there are extra parameters
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800114 {
Jason M. Bills64796042018-10-03 16:51:55 -0700115 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800116 return IPMI_CC_REQ_DATA_LEN_INVALID;
117 }
Jason M. Bills64796042018-10-03 16:51:55 -0700118 if (getChassisSerialNumber(dbus, serial) == 0)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800119 {
Jason M. Bills64796042018-10-03 16:51:55 -0700120 *dataLen = serial.size(); // length will never exceed response length
121 // as it is checked in getChassisSerialNumber
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800122 char* resp = static_cast<char*>(response);
Jason M. Bills64796042018-10-03 16:51:55 -0700123 serial.copy(resp, *dataLen);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800124 return IPMI_CC_OK;
125 }
Jason M. Bills64796042018-10-03 16:51:55 -0700126 *dataLen = 0;
127 return IPMI_CC_RESPONSE_ERROR;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800128}
129
130ipmi_ret_t ipmiOEMSetSystemGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
131 ipmi_request_t request,
132 ipmi_response_t response,
Jason M. Bills64796042018-10-03 16:51:55 -0700133 ipmi_data_len_t dataLen, ipmi_context_t context)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800134{
135 static constexpr size_t safeBufferLength = 50;
136 char buf[safeBufferLength] = {0};
137 GUIDData* Data = reinterpret_cast<GUIDData*>(request);
138
Jason M. Bills64796042018-10-03 16:51:55 -0700139 if (*dataLen != sizeof(GUIDData)) // 16bytes
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800140 {
Jason M. Bills64796042018-10-03 16:51:55 -0700141 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800142 return IPMI_CC_REQ_DATA_LEN_INVALID;
143 }
144
Jason M. Bills64796042018-10-03 16:51:55 -0700145 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800146
147 snprintf(
148 buf, safeBufferLength,
149 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
150 Data->timeLow4, Data->timeLow3, Data->timeLow2, Data->timeLow1,
151 Data->timeMid2, Data->timeMid1, Data->timeHigh2, Data->timeHigh1,
152 Data->clock2, Data->clock1, Data->node6, Data->node5, Data->node4,
153 Data->node3, Data->node2, Data->node1);
154 // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
155 std::string guid = buf;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800156
157 std::string objpath = "/xyz/openbmc_project/control/host0/systemGUID";
158 std::string intf = "xyz.openbmc_project.Common.UUID";
Jason M. Bills64796042018-10-03 16:51:55 -0700159 std::string service = getService(dbus, intf, objpath);
160 setDbusProperty(dbus, service, objpath, intf, "UUID", guid);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800161 return IPMI_CC_OK;
162}
163
164ipmi_ret_t ipmiOEMSetBIOSID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
165 ipmi_request_t request, ipmi_response_t response,
166 ipmi_data_len_t dataLen, ipmi_context_t context)
167{
168 DeviceInfo* data = reinterpret_cast<DeviceInfo*>(request);
169
Jason M. Bills64796042018-10-03 16:51:55 -0700170 if ((*dataLen < 2) || (*dataLen != (1 + data->biosIDLength)))
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800171 {
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800172 *dataLen = 0;
173 return IPMI_CC_REQ_DATA_LEN_INVALID;
174 }
Jason M. Bills64796042018-10-03 16:51:55 -0700175 std::string idString((char*)data->biosId, data->biosIDLength);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800176
Jason M. Bills64796042018-10-03 16:51:55 -0700177 std::string service = getService(dbus, biosIntf, biosObjPath);
178 setDbusProperty(dbus, service, biosObjPath, biosIntf, biosProp, idString);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800179 uint8_t* bytesWritten = static_cast<uint8_t*>(response);
180 *bytesWritten =
Jason M. Bills64796042018-10-03 16:51:55 -0700181 data->biosIDLength; // how many bytes are written into storage
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800182 *dataLen = 1;
183 return IPMI_CC_OK;
184}
185
186ipmi_ret_t ipmiOEMGetDeviceInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
187 ipmi_request_t request,
188 ipmi_response_t response,
189 ipmi_data_len_t dataLen, ipmi_context_t context)
190{
191 GetOemDeviceInfoReq* req = reinterpret_cast<GetOemDeviceInfoReq*>(request);
192 GetOemDeviceInfoRes* res = reinterpret_cast<GetOemDeviceInfoRes*>(response);
193
194 if (*dataLen == 0)
195 {
Jason M. Bills64796042018-10-03 16:51:55 -0700196 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800197 return IPMI_CC_REQ_DATA_LEN_INVALID;
198 }
199
200 size_t reqDataLen = *dataLen;
201 *dataLen = 0;
Jason M. Bills64796042018-10-03 16:51:55 -0700202 if (req->entityType > static_cast<uint8_t>(OEMDevEntityType::sdrVer))
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800203 {
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800204 return IPMI_CC_INVALID_FIELD_REQUEST;
205 }
206
207 // handle OEM command items
Jason M. Bills64796042018-10-03 16:51:55 -0700208 switch (OEMDevEntityType(req->entityType))
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800209 {
210 case OEMDevEntityType::biosId:
211 {
212 if (sizeof(GetOemDeviceInfoReq) != reqDataLen)
213 {
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800214 return IPMI_CC_REQ_DATA_LEN_INVALID;
215 }
216
Jason M. Bills64796042018-10-03 16:51:55 -0700217 std::string service = getService(dbus, biosIntf, biosObjPath);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800218 try
219 {
Jason M. Bills64796042018-10-03 16:51:55 -0700220 Value variant = getDbusProperty(dbus, service, biosObjPath,
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800221 biosIntf, biosProp);
Jason M. Bills64796042018-10-03 16:51:55 -0700222 std::string& idString =
223 sdbusplus::message::variant_ns::get<std::string>(variant);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800224 if (req->offset >= idString.size())
225 {
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800226 return IPMI_CC_PARM_OUT_OF_RANGE;
227 }
Jason M. Bills64796042018-10-03 16:51:55 -0700228 size_t length = 0;
229 if (req->countToRead > (idString.size() - req->offset))
230 {
231 length = idString.size() - req->offset;
232 }
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800233 else
234 {
Jason M. Bills64796042018-10-03 16:51:55 -0700235 length = req->countToRead;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800236 }
Jason M. Bills64796042018-10-03 16:51:55 -0700237 std::copy(idString.begin() + req->offset, idString.end(),
238 res->data);
239 res->resDatalen = length;
240 *dataLen = res->resDatalen + 1;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800241 }
Jason M. Bills64796042018-10-03 16:51:55 -0700242 catch (sdbusplus::message::variant_ns::bad_variant_access& e)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800243 {
Jason M. Bills64796042018-10-03 16:51:55 -0700244 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800245 return IPMI_CC_UNSPECIFIED_ERROR;
246 }
247 }
248 break;
249
250 case OEMDevEntityType::devVer:
251 case OEMDevEntityType::sdrVer:
252 // TODO:
253 return IPMI_CC_ILLEGAL_COMMAND;
254 default:
255 return IPMI_CC_INVALID_FIELD_REQUEST;
256 }
257 return IPMI_CC_OK;
258}
259
260ipmi_ret_t ipmiOEMGetAICFRU(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
261 ipmi_request_t request, ipmi_response_t response,
262 ipmi_data_len_t dataLen, ipmi_context_t context)
263{
264 if (*dataLen != 0)
265 {
Jason M. Bills64796042018-10-03 16:51:55 -0700266 *dataLen = 0;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800267 return IPMI_CC_REQ_DATA_LEN_INVALID;
268 }
269
270 *dataLen = 1;
271 uint8_t* res = reinterpret_cast<uint8_t*>(response);
272 // temporary fix. We don't support AIC FRU now. Just tell BIOS that no
273 // AIC is available so that BIOS will not timeout repeatly which leads to
274 // slow booting.
275 *res = 0; // Byte1=Count of SlotPosition/FruID records.
276 return IPMI_CC_OK;
277}
278
Jason M. Bills64796042018-10-03 16:51:55 -0700279ipmi_ret_t ipmiOEMGetPowerRestoreDelay(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
280 ipmi_request_t request,
281 ipmi_response_t response,
282 ipmi_data_len_t dataLen,
283 ipmi_context_t context)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800284{
Jason M. Bills64796042018-10-03 16:51:55 -0700285 GetPowerRestoreDelayRes* resp =
286 reinterpret_cast<GetPowerRestoreDelayRes*>(response);
287
288 if (*dataLen != 0)
289 {
290 *dataLen = 0;
291 return IPMI_CC_REQ_DATA_LEN_INVALID;
292 }
293
294 std::string service =
295 getService(dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath);
296 Value variant =
297 getDbusProperty(dbus, service, powerRestoreDelayObjPath,
298 powerRestoreDelayIntf, powerRestoreDelayProp);
299
300 uint16_t delay = sdbusplus::message::variant_ns::get<uint16_t>(variant);
301 resp->byteLSB = delay;
302 resp->byteMSB = delay >> 8;
303
304 *dataLen = sizeof(GetPowerRestoreDelayRes);
305
306 return IPMI_CC_OK;
Jia, Chunhuia835eaa2018-09-05 09:00:41 +0800307}
308
Jason M. Bills64796042018-10-03 16:51:55 -0700309ipmi_ret_t ipmiOEMSetPowerRestoreDelay(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
310 ipmi_request_t request,
311 ipmi_response_t response,
312 ipmi_data_len_t dataLen,
313 ipmi_context_t context)
314{
315 SetPowerRestoreDelayReq* data =
316 reinterpret_cast<SetPowerRestoreDelayReq*>(request);
317 uint16_t delay = 0;
318
319 if (*dataLen != sizeof(SetPowerRestoreDelayReq))
320 {
321 *dataLen = 0;
322 return IPMI_CC_REQ_DATA_LEN_INVALID;
323 }
324 delay = data->byteMSB;
325 delay = (delay << 8) | data->byteLSB;
326 std::string service =
327 getService(dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath);
328 setDbusProperty(dbus, service, powerRestoreDelayObjPath,
329 powerRestoreDelayIntf, powerRestoreDelayProp, delay);
330 *dataLen = 0;
331
332 return IPMI_CC_OK;
333}
334
335ipmi_ret_t ipmiOEMGetProcessorErrConfig(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
336 ipmi_request_t request,
337 ipmi_response_t response,
338 ipmi_data_len_t dataLen,
339 ipmi_context_t context)
340{
341 GetProcessorErrConfigRes* resp =
342 reinterpret_cast<GetProcessorErrConfigRes*>(response);
343
344 if (*dataLen != 0)
345 {
346 *dataLen = 0;
347 return IPMI_CC_REQ_DATA_LEN_INVALID;
348 }
349
350 std::string service =
351 getService(dbus, processorErrConfigIntf, processorErrConfigObjPath);
352 Value variant = getDbusProperty(dbus, service, processorErrConfigObjPath,
353 processorErrConfigIntf, "ResetCfg");
354 resp->resetCfg = sdbusplus::message::variant_ns::get<uint8_t>(variant);
355
356 std::vector<uint8_t> caterrStatus;
Kuiying Wangbc546672018-11-23 15:41:05 +0800357 sdbusplus::message::variant<std::vector<uint8_t>> message;
Jason M. Bills64796042018-10-03 16:51:55 -0700358
359 auto method =
360 dbus.new_method_call(service.c_str(), processorErrConfigObjPath,
361 "org.freedesktop.DBus.Properties", "Get");
362
363 method.append(processorErrConfigIntf, "CATERRStatus");
Kuiying Wangbc546672018-11-23 15:41:05 +0800364 auto reply = dbus.call(method);
Jason M. Bills64796042018-10-03 16:51:55 -0700365
366 try
367 {
Kuiying Wangbc546672018-11-23 15:41:05 +0800368 reply.read(message);
369 caterrStatus =
370 sdbusplus::message::variant_ns::get<std::vector<uint8_t>>(message);
Jason M. Bills64796042018-10-03 16:51:55 -0700371 }
372 catch (sdbusplus::exception_t&)
373 {
Kuiying Wangbc546672018-11-23 15:41:05 +0800374 phosphor::logging::log<phosphor::logging::level::ERR>(
Jason M. Bills64796042018-10-03 16:51:55 -0700375 "ipmiOEMGetProcessorErrConfig: error on dbus",
376 phosphor::logging::entry("PRORPERTY=CATERRStatus"),
377 phosphor::logging::entry("PATH=%s", processorErrConfigObjPath),
378 phosphor::logging::entry("INTERFACE=%s", processorErrConfigIntf));
379 return IPMI_CC_UNSPECIFIED_ERROR;
380 }
381
382 size_t len =
383 maxCPUNum <= caterrStatus.size() ? maxCPUNum : caterrStatus.size();
384 caterrStatus.resize(len);
385 std::copy(caterrStatus.begin(), caterrStatus.end(), resp->caterrStatus);
386 *dataLen = sizeof(GetProcessorErrConfigRes);
387
388 return IPMI_CC_OK;
389}
390
391ipmi_ret_t ipmiOEMSetProcessorErrConfig(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
392 ipmi_request_t request,
393 ipmi_response_t response,
394 ipmi_data_len_t dataLen,
395 ipmi_context_t context)
396{
397 SetProcessorErrConfigReq* req =
398 reinterpret_cast<SetProcessorErrConfigReq*>(request);
399
400 if (*dataLen != sizeof(SetProcessorErrConfigReq))
401 {
402 *dataLen = 0;
403 return IPMI_CC_REQ_DATA_LEN_INVALID;
404 }
405 std::string service =
406 getService(dbus, processorErrConfigIntf, processorErrConfigObjPath);
407 setDbusProperty(dbus, service, processorErrConfigObjPath,
408 processorErrConfigIntf, "ResetCfg", req->resetCfg);
409
410 setDbusProperty(dbus, service, processorErrConfigObjPath,
411 processorErrConfigIntf, "ResetErrorOccurrenceCounts",
412 req->resetErrorOccurrenceCounts);
413 *dataLen = 0;
414
415 return IPMI_CC_OK;
416}
417
Yong Li703922d2018-11-06 13:25:31 +0800418ipmi_ret_t ipmiOEMGetShutdownPolicy(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
419 ipmi_request_t request,
420 ipmi_response_t response,
421 ipmi_data_len_t dataLen,
422 ipmi_context_t context)
423{
424 GetOEMShutdownPolicyRes* resp =
425 reinterpret_cast<GetOEMShutdownPolicyRes*>(response);
426
427 if (*dataLen != 0)
428 {
429 phosphor::logging::log<phosphor::logging::level::ERR>(
Kuiying Wang45f04982018-12-26 09:23:08 +0800430 "oem_get_shutdown_policy: invalid input len!");
Yong Li703922d2018-11-06 13:25:31 +0800431 *dataLen = 0;
432 return IPMI_CC_REQ_DATA_LEN_INVALID;
433 }
434
435 *dataLen = 0;
436
437 try
438 {
439 std::string service =
440 getService(dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath);
441 Value variant = getDbusProperty(dbus, service, oemShutdownPolicyObjPath,
442 oemShutdownPolicyIntf,
443 oemShutdownPolicyObjPathProp);
444 resp->policy = sdbusplus::message::variant_ns::get<uint8_t>(variant);
445 // TODO needs to check if it is multi-node products,
446 // policy is only supported on node 3/4
447 resp->policySupport = shutdownPolicySupported;
448 }
449 catch (sdbusplus::exception_t& e)
450 {
451 phosphor::logging::log<phosphor::logging::level::ERR>(e.description());
452 return IPMI_CC_UNSPECIFIED_ERROR;
453 }
454
455 *dataLen = sizeof(GetOEMShutdownPolicyRes);
456 return IPMI_CC_OK;
457}
458
459ipmi_ret_t ipmiOEMSetShutdownPolicy(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
460 ipmi_request_t request,
461 ipmi_response_t response,
462 ipmi_data_len_t dataLen,
463 ipmi_context_t context)
464{
465 uint8_t* req = reinterpret_cast<uint8_t*>(request);
466
467 // TODO needs to check if it is multi-node products,
468 // policy is only supported on node 3/4
469 if (*dataLen != 1)
470 {
471 phosphor::logging::log<phosphor::logging::level::ERR>(
472 "oem_set_shutdown_policy: invalid input len!");
473 *dataLen = 0;
474 return IPMI_CC_REQ_DATA_LEN_INVALID;
475 }
476
477 *dataLen = 0;
478 if ((*req != noShutdownOnOCOT) && (*req != shutdownOnOCOT))
479 {
480 phosphor::logging::log<phosphor::logging::level::ERR>(
481 "oem_set_shutdown_policy: invalid input!");
482 return IPMI_CC_INVALID_FIELD_REQUEST;
483 }
484
485 try
486 {
487 std::string service =
488 getService(dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath);
489 setDbusProperty(dbus, service, oemShutdownPolicyObjPath,
490 oemShutdownPolicyIntf, oemShutdownPolicyObjPathProp,
491 *req);
492 }
493 catch (sdbusplus::exception_t& e)
494 {
495 phosphor::logging::log<phosphor::logging::level::ERR>(e.description());
496 return IPMI_CC_UNSPECIFIED_ERROR;
497 }
498
499 return IPMI_CC_OK;
500}
501
Kuiying Wang45f04982018-12-26 09:23:08 +0800502namespace ledAction
503{
504using namespace sdbusplus::xyz::openbmc_project::Led::server;
505std::map<Physical::Action, uint8_t> actionDbusToIpmi = {
506 {Physical::Action::Off, 0x00},
507 {Physical::Action::On, 0x10},
508 {Physical::Action::Blink, 0x01}};
509
510std::map<uint8_t, std::string> offsetObjPath = {
511 {2, statusAmberObjPath}, {4, statusGreenObjPath}, {6, identifyLEDObjPath}};
512
513} // namespace ledAction
514
515int8_t getLEDState(sdbusplus::bus::bus& bus, const std::string& intf,
516 const std::string& objPath, uint8_t& state)
517{
518 try
519 {
520 std::string service = getService(bus, intf, objPath);
521 Value stateValue =
522 getDbusProperty(bus, service, objPath, intf, "State");
523 std::string strState =
524 sdbusplus::message::variant_ns::get<std::string>(stateValue);
525 state = ledAction::actionDbusToIpmi.at(
526 sdbusplus::xyz::openbmc_project::Led::server::Physical::
527 convertActionFromString(strState));
528 }
529 catch (sdbusplus::exception::SdBusError& e)
530 {
531 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
532 return -1;
533 }
534 return 0;
535}
536
537ipmi_ret_t ipmiOEMGetLEDStatus(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
538 ipmi_request_t request, ipmi_response_t response,
539 ipmi_data_len_t dataLen, ipmi_context_t context)
540{
541 uint8_t* resp = reinterpret_cast<uint8_t*>(response);
542 // LED Status
543 //[1:0] = Reserved
544 //[3:2] = Status(Amber)
545 //[5:4] = Status(Green)
546 //[7:6] = System Identify
547 // Status definitions:
548 // 00b = Off
549 // 01b = Blink
550 // 10b = On
551 // 11b = invalid
552 if (*dataLen != 0)
553 {
554 phosphor::logging::log<phosphor::logging::level::ERR>(
555 "oem_get_led_status: invalid input len!");
556 *dataLen = 0;
557 return IPMI_CC_REQ_DATA_LEN_INVALID;
558 }
559
560 phosphor::logging::log<phosphor::logging::level::DEBUG>("GET led status");
561 *resp = 0;
562 *dataLen = 0;
563 for (auto it = ledAction::offsetObjPath.begin();
564 it != ledAction::offsetObjPath.end(); ++it)
565 {
566 uint8_t state = 0;
567 if (-1 == getLEDState(dbus, ledIntf, it->second, state))
568 {
569 phosphor::logging::log<phosphor::logging::level::ERR>(
570 "oem_get_led_status: fail to get ID LED status!");
571 return IPMI_CC_UNSPECIFIED_ERROR;
572 }
573 *resp |= state << it->first;
574 }
575
576 *dataLen = sizeof(*resp);
577 return IPMI_CC_OK;
578}
579
Yong Li23737fe2019-02-19 08:49:55 +0800580ipmi_ret_t ipmiOEMCfgHostSerialPortSpeed(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
581 ipmi_request_t request,
582 ipmi_response_t response,
583 ipmi_data_len_t dataLen,
584 ipmi_context_t context)
585{
586 CfgHostSerialReq* req = reinterpret_cast<CfgHostSerialReq*>(request);
587 uint8_t* resp = reinterpret_cast<uint8_t*>(response);
588
589 if (*dataLen == 0)
590 {
591 phosphor::logging::log<phosphor::logging::level::ERR>(
592 "CfgHostSerial: invalid input len!",
593 phosphor::logging::entry("LEN=%d", *dataLen));
594 return IPMI_CC_REQ_DATA_LEN_INVALID;
595 }
596
597 switch (req->command)
598 {
599 case getHostSerialCfgCmd:
600 {
601 if (*dataLen != 1)
602 {
603 phosphor::logging::log<phosphor::logging::level::ERR>(
604 "CfgHostSerial: invalid input len!");
605 *dataLen = 0;
606 return IPMI_CC_REQ_DATA_LEN_INVALID;
607 }
608
609 *dataLen = 0;
610
611 boost::process::ipstream is;
612 std::vector<std::string> data;
613 std::string line;
614 boost::process::child c1(fwGetEnvCmd, "-n", fwHostSerailCfgEnvName,
615 boost::process::std_out > is);
616
617 while (c1.running() && std::getline(is, line) && !line.empty())
618 {
619 data.push_back(line);
620 }
621
622 c1.wait();
623 if (c1.exit_code())
624 {
625 phosphor::logging::log<phosphor::logging::level::ERR>(
626 "CfgHostSerial:: error on execute",
627 phosphor::logging::entry("EXECUTE=%s", fwSetEnvCmd));
628 // Using the default value
629 *resp = 0;
630 }
631 else
632 {
633 if (data.size() != 1)
634 {
635 phosphor::logging::log<phosphor::logging::level::ERR>(
636 "CfgHostSerial:: error on read env");
637 return IPMI_CC_UNSPECIFIED_ERROR;
638 }
639 try
640 {
641 unsigned long tmp = std::stoul(data[0]);
642 if (tmp > std::numeric_limits<uint8_t>::max())
643 {
644 throw std::out_of_range("Out of range");
645 }
646 *resp = static_cast<uint8_t>(tmp);
647 }
648 catch (const std::invalid_argument& e)
649 {
650 phosphor::logging::log<phosphor::logging::level::ERR>(
651 "invalid config ",
652 phosphor::logging::entry("ERR=%s", e.what()));
653 return IPMI_CC_UNSPECIFIED_ERROR;
654 }
655 catch (const std::out_of_range& e)
656 {
657 phosphor::logging::log<phosphor::logging::level::ERR>(
658 "out_of_range config ",
659 phosphor::logging::entry("ERR=%s", e.what()));
660 return IPMI_CC_UNSPECIFIED_ERROR;
661 }
662 }
663
664 *dataLen = 1;
665 break;
666 }
667 case setHostSerialCfgCmd:
668 {
669 if (*dataLen != sizeof(CfgHostSerialReq))
670 {
671 phosphor::logging::log<phosphor::logging::level::ERR>(
672 "CfgHostSerial: invalid input len!");
673 *dataLen = 0;
674 return IPMI_CC_REQ_DATA_LEN_INVALID;
675 }
676
677 *dataLen = 0;
678
679 if (req->parameter > HostSerialCfgParamMax)
680 {
681 phosphor::logging::log<phosphor::logging::level::ERR>(
682 "CfgHostSerial: invalid input!");
683 return IPMI_CC_INVALID_FIELD_REQUEST;
684 }
685
686 boost::process::child c1(fwSetEnvCmd, fwHostSerailCfgEnvName,
687 std::to_string(req->parameter));
688
689 c1.wait();
690 if (c1.exit_code())
691 {
692 phosphor::logging::log<phosphor::logging::level::ERR>(
693 "CfgHostSerial:: error on execute",
694 phosphor::logging::entry("EXECUTE=%s", fwGetEnvCmd));
695 return IPMI_CC_UNSPECIFIED_ERROR;
696 }
697 break;
698 }
699 default:
700 phosphor::logging::log<phosphor::logging::level::ERR>(
701 "CfgHostSerial: invalid input!");
702 *dataLen = 0;
703 return IPMI_CC_INVALID_FIELD_REQUEST;
704 }
705
706 return IPMI_CC_OK;
707}
708
James Feist91244a62019-02-19 15:04:54 -0800709constexpr const char* thermalModeInterface =
710 "xyz.openbmc_project.Control.ThermalMode";
711constexpr const char* thermalModePath =
712 "/xyz/openbmc_project/control/thermal_mode";
713
714bool getFanProfileInterface(
715 sdbusplus::bus::bus& bus,
716 boost::container::flat_map<
717 std::string, std::variant<std::vector<std::string>, std::string>>& resp)
718{
719 auto call = bus.new_method_call(settingsBusName, thermalModePath, PROP_INTF,
720 "GetAll");
721 call.append(thermalModeInterface);
722 try
723 {
724 auto data = bus.call(call);
725 data.read(resp);
726 }
727 catch (sdbusplus::exception_t& e)
728 {
729 phosphor::logging::log<phosphor::logging::level::ERR>(
730 "getFanProfileInterface: can't get thermal mode!",
731 phosphor::logging::entry("ERR=%s", e.what()));
732 return false;
733 }
734 return true;
735}
736
737ipmi_ret_t ipmiOEMSetFanConfig(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
738 ipmi_request_t request, ipmi_response_t response,
739 ipmi_data_len_t dataLen, ipmi_context_t context)
740{
741
742 if (*dataLen < 2 || *dataLen > 7)
743 {
744 phosphor::logging::log<phosphor::logging::level::ERR>(
745 "ipmiOEMSetFanConfig: invalid input len!");
746 *dataLen = 0;
747 return IPMI_CC_REQ_DATA_LEN_INVALID;
748 }
749
750 // todo: tell bios to only send first 2 bytes
751
752 SetFanConfigReq* req = reinterpret_cast<SetFanConfigReq*>(request);
753 boost::container::flat_map<
754 std::string, std::variant<std::vector<std::string>, std::string>>
755 profileData;
756 if (!getFanProfileInterface(dbus, profileData))
757 {
758 return IPMI_CC_UNSPECIFIED_ERROR;
759 }
760
761 std::vector<std::string>* supported =
762 std::get_if<std::vector<std::string>>(&profileData["Supported"]);
763 if (supported == nullptr)
764 {
765 return IPMI_CC_INVALID_FIELD_REQUEST;
766 }
767 std::string mode;
768 if (req->flags &
769 (1 << static_cast<uint8_t>(setFanProfileFlags::setPerfAcousMode)))
770 {
771 bool performanceMode =
772 (req->flags & (1 << static_cast<uint8_t>(
773 setFanProfileFlags::performAcousSelect))) > 0;
774
775 if (performanceMode)
776 {
777
778 if (std::find(supported->begin(), supported->end(),
779 "Performance") != supported->end())
780 {
781 mode = "Performance";
782 }
783 }
784 else
785 {
786
787 if (std::find(supported->begin(), supported->end(), "Acoustic") !=
788 supported->end())
789 {
790 mode = "Acoustic";
791 }
792 }
793 if (mode.empty())
794 {
795 return IPMI_CC_INVALID_FIELD_REQUEST;
796 }
797 setDbusProperty(dbus, settingsBusName, thermalModePath,
798 thermalModeInterface, "Current", mode);
799 }
800
801 return IPMI_CC_OK;
802}
803
804ipmi_ret_t ipmiOEMGetFanConfig(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
805 ipmi_request_t request, ipmi_response_t response,
806 ipmi_data_len_t dataLen, ipmi_context_t context)
807{
808
809 if (*dataLen > 1)
810 {
811 phosphor::logging::log<phosphor::logging::level::ERR>(
812 "ipmiOEMGetFanConfig: invalid input len!");
813 *dataLen = 0;
814 return IPMI_CC_REQ_DATA_LEN_INVALID;
815 }
816
817 // todo: talk to bios about needing less information
818
819 GetFanConfigResp* resp = reinterpret_cast<GetFanConfigResp*>(response);
820 *dataLen = sizeof(GetFanConfigResp);
821
822 boost::container::flat_map<
823 std::string, std::variant<std::vector<std::string>, std::string>>
824 profileData;
825
826 if (!getFanProfileInterface(dbus, profileData))
827 {
828 return IPMI_CC_UNSPECIFIED_ERROR;
829 }
830
831 std::string* current = std::get_if<std::string>(&profileData["Current"]);
832
833 if (current == nullptr)
834 {
835 phosphor::logging::log<phosphor::logging::level::ERR>(
836 "ipmiOEMGetFanConfig: can't get current mode!");
837 return IPMI_CC_UNSPECIFIED_ERROR;
838 }
839 bool performance = (*current == "Performance");
840
841 if (performance)
842 {
843 resp->flags |= 1 << 2;
844 }
845
846 return IPMI_CC_OK;
847}
848
James Feist5f957ca2019-03-14 15:33:55 -0700849constexpr const char* cfmLimitSettingPath =
850 "/xyz/openbmc_project/control/cfm_limit";
851constexpr const char* cfmLimitIface = "xyz.openbmc_project.Control.CFMLimit";
James Feistfaa4f222019-03-21 16:21:55 -0700852constexpr const size_t legacyExitAirSensorNumber = 0x2e;
853
854static std::string getExitAirConfigPath()
855{
856
857 auto method =
858 dbus.new_method_call("xyz.openbmc_project.ObjectMapper",
859 "/xyz/openbmc_project/object_mapper",
860 "xyz.openbmc_project.ObjectMapper", "GetSubTree");
861
862 method.append(
863 "/", 0,
864 std::array<const char*, 1>{"xyz.openbmc_project.Configuration.Pid"});
865 std::string path;
866 GetSubTreeType resp;
867 try
868 {
869 auto reply = dbus.call(method);
870 reply.read(resp);
871 }
872 catch (sdbusplus::exception_t&)
873 {
874 phosphor::logging::log<phosphor::logging::level::ERR>(
875 "ipmiOEMGetFscParameter: mapper error");
876 };
877 auto config = std::find_if(resp.begin(), resp.end(), [](const auto& pair) {
878 return pair.first.find("Exit_Air") != std::string::npos;
879 });
880 if (config != resp.end())
881 {
882 path = std::move(config->first);
883 }
884 return path;
885}
James Feist5f957ca2019-03-14 15:33:55 -0700886
887ipmi_ret_t ipmiOEMSetFscParameter(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
888 ipmi_request_t request,
889 ipmi_response_t response,
890 ipmi_data_len_t dataLen,
891 ipmi_context_t context)
892{
893 constexpr const size_t disableLimiting = 0x0;
894
895 if (*dataLen < 2)
896 {
897 phosphor::logging::log<phosphor::logging::level::ERR>(
898 "ipmiOEMSetFscParameter: invalid input len!");
899 *dataLen = 0;
900 return IPMI_CC_REQ_DATA_LEN_INVALID;
901 }
902
903 uint8_t* req = static_cast<uint8_t*>(request);
904
James Feistfaa4f222019-03-21 16:21:55 -0700905 if (*req == static_cast<uint8_t>(setFscParamFlags::tcontrol))
906 {
907 if (*dataLen == 3 && req[1] == legacyExitAirSensorNumber)
908 {
909 *dataLen = 0;
910 std::string path = getExitAirConfigPath();
911 ipmi::setDbusProperty(dbus, "xyz.openbmc_project.EntityManager",
912 path, "xyz.openbmc_project.Configuration.Pid",
913 "SetPoint", static_cast<double>(req[2]));
914 return IPMI_CC_OK;
915 }
916 else if (*dataLen == 3)
917 {
918 *dataLen = 0;
919 return IPMI_CC_INVALID_FIELD_REQUEST;
920 }
921 else
922 {
923 *dataLen = 0;
924 return IPMI_CC_REQ_DATA_LEN_INVALID;
925 }
926 }
927 else if (*req == static_cast<uint8_t>(setFscParamFlags::cfm))
James Feist5f957ca2019-03-14 15:33:55 -0700928 {
929 if (*dataLen != 3)
930 {
931 phosphor::logging::log<phosphor::logging::level::ERR>(
932 "ipmiOEMSetFscParameter: invalid input len!");
933 *dataLen = 0;
934 return IPMI_CC_REQ_DATA_LEN_INVALID;
935 }
936 *dataLen = 0;
937
938 uint16_t cfm = req[1] | (static_cast<uint16_t>(req[2]) << 8);
939
940 // must be greater than 50 based on eps
941 if (cfm < 50 && cfm != disableLimiting)
942 {
943 return IPMI_CC_PARM_OUT_OF_RANGE;
944 }
945
946 try
947 {
948 ipmi::setDbusProperty(dbus, settingsBusName, cfmLimitSettingPath,
949 cfmLimitIface, "Limit",
950 static_cast<double>(cfm));
951 }
952 catch (sdbusplus::exception_t& e)
953 {
954 phosphor::logging::log<phosphor::logging::level::ERR>(
955 "ipmiOEMSetFscParameter: can't set cfm setting!",
956 phosphor::logging::entry("ERR=%s", e.what()));
957 return IPMI_CC_UNSPECIFIED_ERROR;
958 }
959 return IPMI_CC_OK;
960 }
961 else
962 {
963 // todo other command parts possibly
964 // tcontrol is handled in peci now
965 // fan speed offset not implemented yet
966 // domain pwm limit not implemented
967 *dataLen = 0;
968 return IPMI_CC_PARM_OUT_OF_RANGE;
969 }
970}
971
972ipmi_ret_t ipmiOEMGetFscParameter(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
973 ipmi_request_t request,
974 ipmi_response_t response,
975 ipmi_data_len_t dataLen,
976 ipmi_context_t context)
977{
James Feistfaa4f222019-03-21 16:21:55 -0700978 constexpr uint8_t legacyDefaultExitAirLimit = -128;
James Feist5f957ca2019-03-14 15:33:55 -0700979
980 if (*dataLen < 1)
981 {
982 phosphor::logging::log<phosphor::logging::level::ERR>(
983 "ipmiOEMGetFscParameter: invalid input len!");
984 *dataLen = 0;
985 return IPMI_CC_REQ_DATA_LEN_INVALID;
986 }
987
988 uint8_t* req = static_cast<uint8_t*>(request);
989
James Feistfaa4f222019-03-21 16:21:55 -0700990 if (*req == static_cast<uint8_t>(setFscParamFlags::tcontrol))
991 {
992 if (*dataLen != 2)
993 {
994 phosphor::logging::log<phosphor::logging::level::ERR>(
995 "ipmiOEMGetFscParameter: invalid input len!");
996 *dataLen = 0;
997 return IPMI_CC_REQ_DATA_LEN_INVALID;
998 }
999
1000 if (req[1] != legacyExitAirSensorNumber)
1001 {
1002 return IPMI_CC_PARM_OUT_OF_RANGE;
1003 }
1004 uint8_t setpoint = legacyDefaultExitAirLimit;
1005 std::string path = getExitAirConfigPath();
1006 if (path.size())
1007 {
1008 Value val = ipmi::getDbusProperty(
1009 dbus, "xyz.openbmc_project.EntityManager", path,
1010 "xyz.openbmc_project.Configuration.Pid", "SetPoint");
1011 setpoint = std::floor(std::get<double>(val) + 0.5);
1012 }
1013
1014 // old implementation used to return the "default" and current, we
1015 // don't make the default readily available so just make both the
1016 // same
1017 auto resp = static_cast<uint8_t*>(response);
1018 resp[0] = setpoint;
1019 resp[1] = setpoint;
1020
1021 *dataLen = 2;
1022 return IPMI_CC_OK;
1023 }
1024 else if (*req == static_cast<uint8_t>(setFscParamFlags::cfm))
James Feist5f957ca2019-03-14 15:33:55 -07001025 {
1026
1027 /*
1028 DataLen should be 1, but host is sending us an extra bit. As the
1029 previous behavior didn't seem to prevent this, ignore the check for now.
1030
1031 if (*dataLen != 1)
1032 {
1033 phosphor::logging::log<phosphor::logging::level::ERR>(
1034 "ipmiOEMGetFscParameter: invalid input len!");
1035 *dataLen = 0;
1036 return IPMI_CC_REQ_DATA_LEN_INVALID;
1037 }
1038 */
1039 Value cfmLimit;
1040 Value cfmMaximum;
1041 try
1042 {
1043 cfmLimit = ipmi::getDbusProperty(dbus, settingsBusName,
1044 cfmLimitSettingPath, cfmLimitIface,
1045 "Limit");
1046 cfmMaximum = ipmi::getDbusProperty(
1047 dbus, "xyz.openbmc_project.ExitAirTempSensor",
1048 "/xyz/openbmc_project/control/MaxCFM", cfmLimitIface, "Limit");
1049 }
1050 catch (sdbusplus::exception_t& e)
1051 {
1052 phosphor::logging::log<phosphor::logging::level::ERR>(
1053 "ipmiOEMSetFscParameter: can't get cfm setting!",
1054 phosphor::logging::entry("ERR=%s", e.what()));
1055 *dataLen = 0;
1056 return IPMI_CC_UNSPECIFIED_ERROR;
1057 }
1058
1059 auto cfmLim = std::get_if<double>(&cfmLimit);
1060 if (cfmLim == nullptr ||
1061 *cfmLim > std::numeric_limits<uint16_t>::max() || *cfmLim < 0)
1062 {
1063 phosphor::logging::log<phosphor::logging::level::ERR>(
1064 "ipmiOEMSetFscParameter: cfm limit out of range!");
1065 *dataLen = 0;
1066 return IPMI_CC_UNSPECIFIED_ERROR;
1067 }
1068
1069 auto cfmMax = std::get_if<double>(&cfmMaximum);
1070 if (cfmMax == nullptr ||
1071 *cfmMax > std::numeric_limits<uint16_t>::max() || *cfmMax < 0)
1072 {
1073 phosphor::logging::log<phosphor::logging::level::ERR>(
1074 "ipmiOEMSetFscParameter: cfm max out of range!");
1075 *dataLen = 0;
1076 return IPMI_CC_UNSPECIFIED_ERROR;
1077 }
1078 *cfmLim = std::floor(*cfmLim + 0.5);
1079 *cfmMax = std::floor(*cfmMax + 0.5);
1080 uint16_t resp = static_cast<uint16_t>(*cfmLim);
1081 uint16_t* ptr = static_cast<uint16_t*>(response);
1082 ptr[0] = resp;
1083 resp = static_cast<uint16_t>(*cfmMax);
1084 ptr[1] = resp;
1085
1086 *dataLen = 4;
1087
1088 return IPMI_CC_OK;
1089 }
1090 else
1091 {
1092 // todo other command parts possibly
James Feist5f957ca2019-03-14 15:33:55 -07001093 // fan speed offset not implemented yet
1094 // domain pwm limit not implemented
1095 *dataLen = 0;
James Feistfaa4f222019-03-21 16:21:55 -07001096
James Feist5f957ca2019-03-14 15:33:55 -07001097 return IPMI_CC_PARM_OUT_OF_RANGE;
1098 }
1099}
1100
Jason M. Bills64796042018-10-03 16:51:55 -07001101static void registerOEMFunctions(void)
Jia, Chunhuia835eaa2018-09-05 09:00:41 +08001102{
1103 phosphor::logging::log<phosphor::logging::level::INFO>(
1104 "Registering OEM commands");
Jason M. Bills64796042018-10-03 16:51:55 -07001105 ipmiPrintAndRegister(netfnIntcOEMGeneral, IPMI_CMD_WILDCARD, NULL,
1106 ipmiOEMWildcard,
1107 PRIVILEGE_USER); // wildcard default handler
1108 ipmiPrintAndRegister(netfunIntelAppOEM, IPMI_CMD_WILDCARD, NULL,
1109 ipmiOEMWildcard,
1110 PRIVILEGE_USER); // wildcard default handler
1111 ipmiPrintAndRegister(
1112 netfnIntcOEMGeneral,
1113 static_cast<ipmi_cmd_t>(
1114 IPMINetfnIntelOEMGeneralCmd::cmdGetChassisIdentifier),
1115 NULL, ipmiOEMGetChassisIdentifier,
1116 PRIVILEGE_USER); // get chassis identifier
1117 ipmiPrintAndRegister(
1118 netfnIntcOEMGeneral,
1119 static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdSetSystemGUID),
1120 NULL, ipmiOEMSetSystemGUID,
1121 PRIVILEGE_ADMIN); // set system guid
1122 ipmiPrintAndRegister(
1123 netfnIntcOEMGeneral,
1124 static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdSetBIOSID),
1125 NULL, ipmiOEMSetBIOSID, PRIVILEGE_ADMIN);
1126 ipmiPrintAndRegister(netfnIntcOEMGeneral,
1127 static_cast<ipmi_cmd_t>(
1128 IPMINetfnIntelOEMGeneralCmd::cmdGetOEMDeviceInfo),
1129 NULL, ipmiOEMGetDeviceInfo, PRIVILEGE_USER);
1130 ipmiPrintAndRegister(
1131 netfnIntcOEMGeneral,
1132 static_cast<ipmi_cmd_t>(
1133 IPMINetfnIntelOEMGeneralCmd::cmdGetAICSlotFRUIDSlotPosRecords),
1134 NULL, ipmiOEMGetAICFRU, PRIVILEGE_USER);
1135 ipmiPrintAndRegister(
1136 netfnIntcOEMGeneral,
1137 static_cast<ipmi_cmd_t>(
1138 IPMINetfnIntelOEMGeneralCmd::cmdSetPowerRestoreDelay),
1139 NULL, ipmiOEMSetPowerRestoreDelay, PRIVILEGE_OPERATOR);
1140 ipmiPrintAndRegister(
1141 netfnIntcOEMGeneral,
1142 static_cast<ipmi_cmd_t>(
1143 IPMINetfnIntelOEMGeneralCmd::cmdGetPowerRestoreDelay),
1144 NULL, ipmiOEMGetPowerRestoreDelay, PRIVILEGE_USER);
1145 ipmiPrintAndRegister(
1146 netfnIntcOEMGeneral,
1147 static_cast<ipmi_cmd_t>(
1148 IPMINetfnIntelOEMGeneralCmd::cmdGetProcessorErrConfig),
1149 NULL, ipmiOEMGetProcessorErrConfig, PRIVILEGE_USER);
1150 ipmiPrintAndRegister(
1151 netfnIntcOEMGeneral,
1152 static_cast<ipmi_cmd_t>(
1153 IPMINetfnIntelOEMGeneralCmd::cmdSetProcessorErrConfig),
1154 NULL, ipmiOEMSetProcessorErrConfig, PRIVILEGE_ADMIN);
Yong Li703922d2018-11-06 13:25:31 +08001155 ipmiPrintAndRegister(netfnIntcOEMGeneral,
1156 static_cast<ipmi_cmd_t>(
1157 IPMINetfnIntelOEMGeneralCmd::cmdSetShutdownPolicy),
1158 NULL, ipmiOEMSetShutdownPolicy, PRIVILEGE_ADMIN);
1159 ipmiPrintAndRegister(netfnIntcOEMGeneral,
1160 static_cast<ipmi_cmd_t>(
1161 IPMINetfnIntelOEMGeneralCmd::cmdGetShutdownPolicy),
1162 NULL, ipmiOEMGetShutdownPolicy, PRIVILEGE_ADMIN);
James Feist91244a62019-02-19 15:04:54 -08001163
1164 ipmiPrintAndRegister(
1165 netfnIntcOEMGeneral,
1166 static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdSetFanConfig),
1167 NULL, ipmiOEMSetFanConfig, PRIVILEGE_USER);
1168
1169 ipmiPrintAndRegister(
1170 netfnIntcOEMGeneral,
1171 static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdGetFanConfig),
1172 NULL, ipmiOEMGetFanConfig, PRIVILEGE_USER);
1173
James Feist5f957ca2019-03-14 15:33:55 -07001174 ipmiPrintAndRegister(netfnIntcOEMGeneral,
1175 static_cast<ipmi_cmd_t>(
1176 IPMINetfnIntelOEMGeneralCmd::cmdSetFscParameter),
1177 NULL, ipmiOEMSetFscParameter, PRIVILEGE_USER);
1178
1179 ipmiPrintAndRegister(netfnIntcOEMGeneral,
1180 static_cast<ipmi_cmd_t>(
1181 IPMINetfnIntelOEMGeneralCmd::cmdGetFscParameter),
1182 NULL, ipmiOEMGetFscParameter, PRIVILEGE_USER);
1183
Kuiying Wang45f04982018-12-26 09:23:08 +08001184 ipmiPrintAndRegister(
1185 netfnIntcOEMGeneral,
1186 static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdGetLEDStatus),
1187 NULL, ipmiOEMGetLEDStatus, PRIVILEGE_ADMIN);
Yong Li23737fe2019-02-19 08:49:55 +08001188 ipmiPrintAndRegister(
1189 netfnIntcOEMPlatform,
1190 static_cast<ipmi_cmd_t>(
1191 IPMINetfnIntelOEMPlatformCmd::cmdCfgHostSerialPortSpeed),
1192 NULL, ipmiOEMCfgHostSerialPortSpeed, PRIVILEGE_ADMIN);
Jia, Chunhuia835eaa2018-09-05 09:00:41 +08001193 return;
1194}
1195
1196} // namespace ipmi