blob: adb9d6294c75c6d4755b8b1663b24c462cdf4755 [file] [log] [blame]
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001/*
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 "xyz/openbmc_project/Common/error.hpp"
Jayashree-Df0cf6652020-11-30 11:03:30 +053019#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
20#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
Jayashree Dhanapal778147d2022-03-30 16:48:53 +053021#include <xyz/openbmc_project/Control/Boot/Type/server.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080022
Vijay Khemka63c99be2020-05-27 19:14:35 -070023#include <ipmid/api.hpp>
Vijay Khemka1b6fae32019-03-25 17:43:01 -070024#include <ipmid/utils.hpp>
Vijay Khemka63c99be2020-05-27 19:14:35 -070025#include <commandutils.hpp>
26#include <nlohmann/json.hpp>
27#include <oemcommands.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080028#include <phosphor-logging/log.hpp>
29#include <sdbusplus/bus.hpp>
Vijay Khemka63c99be2020-05-27 19:14:35 -070030
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053031#include <ipmid/api.hpp>
32#include <ipmid/api-types.hpp>
33
Vijay Khemka63c99be2020-05-27 19:14:35 -070034#include <array>
35#include <cstring>
36#include <fstream>
37#include <iomanip>
38#include <iostream>
39#include <sstream>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080040#include <string>
41#include <vector>
42
43#define SIZE_IANA_ID 3
44
45namespace ipmi
46{
Vijay Khemkaa7231892019-10-11 11:35:05 -070047
48using namespace phosphor::logging;
49
Vijay Khemkae7d23d02019-03-08 13:13:40 -080050static void registerOEMFunctions() __attribute__((constructor));
51sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
52static constexpr size_t maxFRUStringLength = 0x3F;
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053053constexpr uint8_t cmdSetSystemGuid = 0xEF;
Vijay Khemkae7d23d02019-03-08 13:13:40 -080054
Vijay Khemka63c99be2020-05-27 19:14:35 -070055int plat_udbg_get_post_desc(uint8_t, uint8_t*, uint8_t, uint8_t*, uint8_t*,
56 uint8_t*);
57int plat_udbg_get_gpio_desc(uint8_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*,
58 uint8_t*);
59ipmi_ret_t plat_udbg_get_frame_data(uint8_t, uint8_t, uint8_t*, uint8_t*,
60 uint8_t*);
61ipmi_ret_t plat_udbg_control_panel(uint8_t, uint8_t, uint8_t, uint8_t*,
62 uint8_t*);
63int sendMeCmd(uint8_t, uint8_t, std::vector<uint8_t>&, std::vector<uint8_t>&);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -070064
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053065int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
66 std::vector<uint8_t>&);
67
Vijay Khemkafeaa9812019-08-27 15:08:08 -070068nlohmann::json oemData __attribute__((init_priority(101)));
Vijay Khemka1b6fae32019-03-25 17:43:01 -070069
Vijay Khemkaf2246ce2020-05-27 14:26:35 -070070static constexpr size_t GUID_SIZE = 16;
71// TODO Make offset and location runtime configurable to ensure we
72// can make each define their own locations.
73static constexpr off_t OFFSET_SYS_GUID = 0x17F0;
74static constexpr const char* FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom";
75
Vijay Khemka1b6fae32019-03-25 17:43:01 -070076enum class LanParam : uint8_t
77{
78 INPROGRESS = 0,
79 AUTHSUPPORT = 1,
80 AUTHENABLES = 2,
81 IP = 3,
82 IPSRC = 4,
83 MAC = 5,
84 SUBNET = 6,
85 GATEWAY = 12,
86 VLAN = 20,
87 CIPHER_SUITE_COUNT = 22,
88 CIPHER_SUITE_ENTRIES = 23,
89 IPV6 = 59,
90};
91
Vijay Khemkaa7231892019-10-11 11:35:05 -070092namespace network
93{
94
95constexpr auto ROOT = "/xyz/openbmc_project/network";
96constexpr auto SERVICE = "xyz.openbmc_project.Network";
97constexpr auto IPV4_TYPE = "ipv4";
98constexpr auto IPV6_TYPE = "ipv6";
99constexpr auto IPV4_PREFIX = "169.254";
100constexpr auto IPV6_PREFIX = "fe80";
101constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
102constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
103
Vijay Khemka63c99be2020-05-27 19:14:35 -0700104bool isLinkLocalIP(const std::string& address)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700105{
106 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0;
107}
108
Vijay Khemka63c99be2020-05-27 19:14:35 -0700109DbusObjectInfo getIPObject(sdbusplus::bus::bus& bus,
110 const std::string& interface,
111 const std::string& serviceRoot,
112 const std::string& match)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700113{
114 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
115
116 if (objectTree.empty())
117 {
118 log<level::ERR>("No Object has implemented the IP interface",
119 entry("INTERFACE=%s", interface.c_str()));
120 }
121
122 DbusObjectInfo objectInfo;
123
Vijay Khemka63c99be2020-05-27 19:14:35 -0700124 for (auto& object : objectTree)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700125 {
126 auto variant =
127 ipmi::getDbusProperty(bus, object.second.begin()->first,
128 object.first, IP_INTERFACE, "Address");
129
130 objectInfo = std::make_pair(object.first, object.second.begin()->first);
131
132 // if LinkLocalIP found look for Non-LinkLocalIP
133 if (isLinkLocalIP(std::get<std::string>(variant)))
134 {
135 continue;
136 }
137 else
138 {
139 break;
140 }
141 }
142 return objectInfo;
143}
144
145} // namespace network
146
Jayashree-Df0cf6652020-11-30 11:03:30 +0530147namespace boot
148{
149
150using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
151using IpmiValue = uint8_t;
152
153std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = {
154 {0x0f, Source::Sources::Default},
155 {0x00, Source::Sources::RemovableMedia},
156 {0x01, Source::Sources::Network},
157 {0x02, Source::Sources::Disk},
158 {0x03, Source::Sources::ExternalMedia},
159 {0x09, Source::Sources::Network}};
160
161std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
162 {0x06, Mode::Modes::Setup}, {0x00, Mode::Modes::Regular}};
163
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530164std::map<IpmiValue, Type::Types> typeIpmiToDbus = {{0x00, Type::Types::Legacy},
165 {0x01, Type::Types::EFI}};
166
Jayashree-Df0cf6652020-11-30 11:03:30 +0530167std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = {
168 {Source::Sources::Default, 0x0f},
169 {Source::Sources::RemovableMedia, 0x00},
170 {Source::Sources::Network, 0x01},
171 {Source::Sources::Disk, 0x02},
172 {Source::Sources::ExternalMedia, 0x03}};
173
174std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
175 {Mode::Modes::Setup, 0x06}, {Mode::Modes::Regular, 0x00}};
176
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530177std::map<Type::Types, IpmiValue> typeDbusToIpmi = {{Type::Types::Legacy, 0x00},
178 {Type::Types::EFI, 0x01}};
179
Jayashree-Df0cf6652020-11-30 11:03:30 +0530180static constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
181static constexpr auto bootSourceIntf =
182 "xyz.openbmc_project.Control.Boot.Source";
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530183static constexpr auto bootTypeIntf = "xyz.openbmc_project.Control.Boot.Type";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530184static constexpr auto bootSourceProp = "BootSource";
185static constexpr auto bootModeProp = "BootMode";
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530186static constexpr auto bootTypeProp = "BootType";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530187
188auto instances(std::string s)
189{
190 std::string delimiter = " ";
191 size_t pos = 0;
192 std::string token;
193 std::vector<std::string> host;
194
195 while ((pos = s.find(delimiter)) != std::string::npos)
196 {
197 token = s.substr(0, pos);
198 host.push_back(token);
199 s.erase(0, pos + delimiter.length());
200 }
201 host.push_back(s);
202
203 return host;
204}
205
206std::optional<size_t> findHost(size_t id)
207{
208 std::string str = INSTANCES;
209 size_t hostId;
210
211 if (INSTANCES == "0")
212 {
213 hostId = id;
214 }
215 else
216 {
217 static const auto hosts = instances(str);
218 std::string num = std::to_string(id + 1);
219 auto instance = std::lower_bound(hosts.begin(), hosts.end(), num);
220
221 if ((instance == hosts.end()) || (*instance != num))
222 {
223 return std::nullopt;
224 }
225 hostId = id + 1;
226 }
227
228 return hostId;
229}
230
231std::tuple<std::string, std::string> objPath(size_t id)
232{
233 std::string hostName = "host" + std::to_string(id);
234 std::string bootObjPath =
235 "/xyz/openbmc_project/control/" + hostName + "/boot";
236 return std::make_tuple(std::move(bootObjPath), std::move(hostName));
237}
238
239} // namespace boot
240
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700241//----------------------------------------------------------------------
242// Helper functions for storing oem data
243//----------------------------------------------------------------------
244
245void flushOemData()
246{
247 std::ofstream file(JSON_OEM_DATA_FILE);
248 file << oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -0700249 file.close();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700250 return;
251}
252
Vijay Khemka63c99be2020-05-27 19:14:35 -0700253std::string bytesToStr(uint8_t* byte, int len)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700254{
255 std::stringstream ss;
256 int i;
257
258 ss << std::hex;
259 for (i = 0; i < len; i++)
260 {
261 ss << std::setw(2) << std::setfill('0') << (int)byte[i];
262 }
263
264 return ss.str();
265}
266
Vijay Khemka63c99be2020-05-27 19:14:35 -0700267int strToBytes(std::string& str, uint8_t* data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700268{
269 std::string sstr;
270 int i;
271
272 for (i = 0; i < (str.length()) / 2; i++)
273 {
274 sstr = str.substr(i * 2, 2);
275 data[i] = (uint8_t)std::strtol(sstr.c_str(), NULL, 16);
276 }
277 return i;
278}
279
Vijay Khemka63c99be2020-05-27 19:14:35 -0700280ipmi_ret_t getNetworkData(uint8_t lan_param, char* data)
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700281{
282 ipmi_ret_t rc = IPMI_CC_OK;
283 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
284
285 const std::string ethdevice = "eth0";
286
287 switch (static_cast<LanParam>(lan_param))
288 {
Vijay Khemkad1194022020-05-27 18:58:33 -0700289 case LanParam::IP:
290 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700291 auto ethIP = ethdevice + "/" + ipmi::network::IPV4_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700292 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700293 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700294 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
295
296 auto properties = ipmi::getAllDbusProperties(
297 bus, ipObjectInfo.second, ipObjectInfo.first,
298 ipmi::network::IP_INTERFACE);
299
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500300 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700301
302 std::strcpy(data, ipaddress.c_str());
303 }
304 break;
305
Vijay Khemkad1194022020-05-27 18:58:33 -0700306 case LanParam::IPV6:
307 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700308 auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700309 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700310 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700311 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
312
313 auto properties = ipmi::getAllDbusProperties(
314 bus, ipObjectInfo.second, ipObjectInfo.first,
315 ipmi::network::IP_INTERFACE);
316
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500317 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700318
319 std::strcpy(data, ipaddress.c_str());
320 }
321 break;
322
Vijay Khemkad1194022020-05-27 18:58:33 -0700323 case LanParam::MAC:
324 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700325 std::string macAddress;
326 auto macObjectInfo =
327 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
328 ipmi::network::ROOT, ethdevice);
329
330 auto variant = ipmi::getDbusProperty(
331 bus, macObjectInfo.second, macObjectInfo.first,
332 ipmi::network::MAC_INTERFACE, "MACAddress");
333
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500334 macAddress = std::get<std::string>(variant);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700335
336 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
337 (data), (data + 1), (data + 2), (data + 3), (data + 4),
338 (data + 5));
339 std::strcpy(data, macAddress.c_str());
340 }
341 break;
342
343 default:
344 rc = IPMI_CC_PARM_OUT_OF_RANGE;
345 }
346 return rc;
347}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800348
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530349bool isMultiHostPlatform()
350{
351 bool platform;
352 if (INSTANCES == "0")
353 {
354 platform = false;
355 }
356 else
357 {
358 platform = true;
359 }
360 return platform;
361}
362
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800363// return code: 0 successful
Vijay Khemka63c99be2020-05-27 19:14:35 -0700364int8_t getFruData(std::string& data, std::string& name)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800365{
366 std::string objpath = "/xyz/openbmc_project/FruDevice";
367 std::string intf = "xyz.openbmc_project.FruDeviceManager";
368 std::string service = getService(dbus, intf, objpath);
369 ObjectValueTree valueTree = getManagedObjects(dbus, service, "/");
370 if (valueTree.empty())
371 {
372 phosphor::logging::log<phosphor::logging::level::ERR>(
373 "No object implements interface",
374 phosphor::logging::entry("INTF=%s", intf.c_str()));
375 return -1;
376 }
377
Vijay Khemka63c99be2020-05-27 19:14:35 -0700378 for (const auto& item : valueTree)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800379 {
380 auto interface = item.second.find("xyz.openbmc_project.FruDevice");
381 if (interface == item.second.end())
382 {
383 continue;
384 }
385
386 auto property = interface->second.find(name.c_str());
387 if (property == interface->second.end())
388 {
389 continue;
390 }
391
392 try
393 {
394 Value variant = property->second;
Vijay Khemka63c99be2020-05-27 19:14:35 -0700395 std::string& result = std::get<std::string>(variant);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800396 if (result.size() > maxFRUStringLength)
397 {
398 phosphor::logging::log<phosphor::logging::level::ERR>(
399 "FRU serial number exceed maximum length");
400 return -1;
401 }
402 data = result;
403 return 0;
404 }
Patrick Williams35d12542021-10-06 11:21:13 -0500405 catch (const std::bad_variant_access& e)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800406 {
407 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
408 return -1;
409 }
410 }
411 return -1;
412}
413
414typedef struct
415{
416 uint8_t cur_power_state;
417 uint8_t last_power_event;
418 uint8_t misc_power_state;
419 uint8_t front_panel_button_cap_status;
420} ipmi_get_chassis_status_t;
421
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800422//----------------------------------------------------------------------
423// Get Debug Frame Info
424//----------------------------------------------------------------------
425ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
426 ipmi_request_t request,
427 ipmi_response_t response,
428 ipmi_data_len_t data_len,
429 ipmi_context_t context)
430{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700431 uint8_t* req = reinterpret_cast<uint8_t*>(request);
432 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800433 uint8_t num_frames = 3;
434
435 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
436 res[SIZE_IANA_ID] = num_frames;
437 *data_len = SIZE_IANA_ID + 1;
438
439 return IPMI_CC_OK;
440}
441
442//----------------------------------------------------------------------
443// Get Debug Updated Frames
444//----------------------------------------------------------------------
445ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
446 ipmi_request_t request,
447 ipmi_response_t response,
448 ipmi_data_len_t data_len,
449 ipmi_context_t context)
450{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700451 uint8_t* req = reinterpret_cast<uint8_t*>(request);
452 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800453 uint8_t num_updates = 3;
454 *data_len = 4;
455
456 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
457 res[SIZE_IANA_ID] = num_updates;
458 *data_len = SIZE_IANA_ID + num_updates + 1;
459 res[SIZE_IANA_ID + 1] = 1; // info page update
460 res[SIZE_IANA_ID + 2] = 2; // cri sel update
461 res[SIZE_IANA_ID + 3] = 3; // cri sensor update
462
463 return IPMI_CC_OK;
464}
465
466//----------------------------------------------------------------------
467// Get Debug POST Description
468//----------------------------------------------------------------------
469ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
470 ipmi_request_t request,
471 ipmi_response_t response,
472 ipmi_data_len_t data_len,
473 ipmi_context_t context)
474{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700475 uint8_t* req = reinterpret_cast<uint8_t*>(request);
476 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800477 uint8_t index = 0;
478 uint8_t next = 0;
479 uint8_t end = 0;
480 uint8_t phase = 0;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700481 uint8_t descLen = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800482 int ret;
483
484 index = req[3];
485 phase = req[4];
486
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700487 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800488 if (ret)
489 {
490 memcpy(res, req, SIZE_IANA_ID); // IANA ID
491 *data_len = SIZE_IANA_ID;
492 return IPMI_CC_UNSPECIFIED_ERROR;
493 }
494
495 memcpy(res, req, SIZE_IANA_ID); // IANA ID
496 res[3] = index;
497 res[4] = next;
498 res[5] = phase;
499 res[6] = end;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700500 res[7] = descLen;
501 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800502
503 return IPMI_CC_OK;
504}
505
506//----------------------------------------------------------------------
507// Get Debug GPIO Description
508//----------------------------------------------------------------------
509ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
510 ipmi_request_t request,
511 ipmi_response_t response,
512 ipmi_data_len_t data_len,
513 ipmi_context_t context)
514{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700515 uint8_t* req = reinterpret_cast<uint8_t*>(request);
516 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800517
Vijay Khemka38183d62019-08-28 16:19:33 -0700518 uint8_t index = 0;
519 uint8_t next = 0;
520 uint8_t level = 0;
521 uint8_t pinDef = 0;
522 uint8_t descLen = 0;
523 int ret;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800524
Vijay Khemka38183d62019-08-28 16:19:33 -0700525 index = req[3];
526
527 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen,
528 &res[8]);
529 if (ret)
530 {
531 memcpy(res, req, SIZE_IANA_ID); // IANA ID
532 *data_len = SIZE_IANA_ID;
533 return IPMI_CC_UNSPECIFIED_ERROR;
534 }
535
536 memcpy(res, req, SIZE_IANA_ID); // IANA ID
537 res[3] = index;
538 res[4] = next;
539 res[5] = level;
540 res[6] = pinDef;
541 res[7] = descLen;
542 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800543
544 return IPMI_CC_OK;
545}
546
547//----------------------------------------------------------------------
548// Get Debug Frame Data
549//----------------------------------------------------------------------
550ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
551 ipmi_request_t request,
552 ipmi_response_t response,
553 ipmi_data_len_t data_len,
554 ipmi_context_t context)
555{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700556 uint8_t* req = reinterpret_cast<uint8_t*>(request);
557 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800558 uint8_t frame;
559 uint8_t page;
560 uint8_t next;
561 uint8_t count;
562 int ret;
563
564 frame = req[3];
565 page = req[4];
566 int fr = frame;
567 int pg = page;
568
569 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]);
570 if (ret)
571 {
572 memcpy(res, req, SIZE_IANA_ID); // IANA ID
573 *data_len = SIZE_IANA_ID;
574 return IPMI_CC_UNSPECIFIED_ERROR;
575 }
576
577 memcpy(res, req, SIZE_IANA_ID); // IANA ID
578 res[3] = frame;
579 res[4] = page;
580 res[5] = next;
581 res[6] = count;
582 *data_len = SIZE_IANA_ID + 4 + count;
583
584 return IPMI_CC_OK;
585}
586
587//----------------------------------------------------------------------
588// Get Debug Control Panel
589//----------------------------------------------------------------------
590ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
591 ipmi_request_t request,
592 ipmi_response_t response,
593 ipmi_data_len_t data_len,
594 ipmi_context_t context)
595{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700596 uint8_t* req = reinterpret_cast<uint8_t*>(request);
597 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800598
599 uint8_t panel;
600 uint8_t operation;
601 uint8_t item;
602 uint8_t count;
603 ipmi_ret_t ret;
604
605 panel = req[3];
606 operation = req[4];
607 item = req[5];
608
609 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]);
610
611 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
612 *data_len = SIZE_IANA_ID + count;
613
614 return ret;
615}
616
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800617//----------------------------------------------------------------------
618// Set Dimm Info (CMD_OEM_SET_DIMM_INFO)
619//----------------------------------------------------------------------
620ipmi_ret_t ipmiOemSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
621 ipmi_request_t request, ipmi_response_t response,
622 ipmi_data_len_t data_len, ipmi_context_t context)
623{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700624 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700625
626 uint8_t index = req[0];
627 uint8_t type = req[1];
628 uint16_t speed;
629 uint32_t size;
630
631 memcpy(&speed, &req[2], 2);
632 memcpy(&size, &req[4], 4);
633
634 std::stringstream ss;
635 ss << std::hex;
636 ss << std::setw(2) << std::setfill('0') << (int)index;
637
638 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index;
639 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type;
640 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed;
641 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size;
642
643 flushOemData();
644
645 *data_len = 0;
646
647 return IPMI_CC_OK;
648}
649
650//----------------------------------------------------------------------
651// Get Board ID (CMD_OEM_GET_BOARD_ID)
652//----------------------------------------------------------------------
653ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
654 ipmi_request_t request, ipmi_response_t response,
655 ipmi_data_len_t data_len, ipmi_context_t context)
656{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700657 uint8_t* req = reinterpret_cast<uint8_t*>(request);
658 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800659
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700660 /* TODO: Needs to implement this after GPIO implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800661 *data_len = 0;
662
663 return IPMI_CC_OK;
664}
665
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800666/* Helper functions to set boot order */
Jayashree-Df0cf6652020-11-30 11:03:30 +0530667void setBootOrder(std::string bootObjPath, uint8_t* data,
668 std::string bootOrderKey)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800669{
Jayashree-Df0cf6652020-11-30 11:03:30 +0530670
671 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
672
673 // SETTING BOOT MODE PROPERTY
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530674 uint8_t bootModeBit = data[0] & 0x06;
675 auto bootValue = ipmi::boot::modeIpmiToDbus.find(bootModeBit);
676
Jayashree-Df0cf6652020-11-30 11:03:30 +0530677 std::string bootOption =
678 ipmi::boot::Mode::convertModesToString((bootValue->second));
679
680 std::string service =
681 getService(*dbus, ipmi::boot::bootModeIntf, bootObjPath);
682 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf,
683 ipmi::boot::bootModeProp, bootOption);
684
685 // SETTING BOOT SOURCE PROPERTY
686 auto bootOrder = ipmi::boot::sourceIpmiToDbus.find((data[1]));
687 std::string bootSource =
688 ipmi::boot::Source::convertSourcesToString((bootOrder->second));
689
690 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath);
691 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf,
692 ipmi::boot::bootSourceProp, bootSource);
693
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530694 // SETTING BOOT TYPE PROPERTY
695
696 uint8_t bootTypeBit = data[0] & 0x01;
697 auto bootTypeVal = ipmi::boot::typeIpmiToDbus.find(bootTypeBit);
698 std::string bootType =
699 ipmi::boot::Type::convertTypesToString((bootTypeVal->second));
700
701 service = getService(*dbus, ipmi::boot::bootTypeIntf, bootObjPath);
702
703 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootTypeIntf,
704 ipmi::boot::bootTypeProp, bootType);
705
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800706 nlohmann::json bootMode;
707 uint8_t mode = data[0];
708 int i;
709
710 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false);
711 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false);
712 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false);
713 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false);
Jayashree-Df0cf6652020-11-30 11:03:30 +0530714 oemData[bootOrderKey][KEY_BOOT_MODE] = bootMode;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800715
716 /* Initialize boot sequence array */
Jayashree-Df0cf6652020-11-30 11:03:30 +0530717 oemData[bootOrderKey][KEY_BOOT_SEQ] = {};
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800718 for (i = 1; i < SIZE_BOOT_ORDER; i++)
719 {
720 if (data[i] >= BOOT_SEQ_ARRAY_SIZE)
Jayashree-Df0cf6652020-11-30 11:03:30 +0530721 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = "NA";
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800722 else
Jayashree-Df0cf6652020-11-30 11:03:30 +0530723 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = bootSeq[data[i]];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800724 }
725
726 flushOemData();
727}
728
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800729//----------------------------------------------------------------------
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700730// Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
731//----------------------------------------------------------------------
Jayashree-Df0cf6652020-11-30 11:03:30 +0530732ipmi::RspType<std::vector<uint8_t>>
733 ipmiOemSetBootOrder(ipmi::Context::ptr ctx, std::vector<uint8_t> data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700734{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700735
Jayashree-Df0cf6652020-11-30 11:03:30 +0530736 uint8_t bootSeq[SIZE_BOOT_ORDER];
737 size_t len = data.size();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700738
739 if (len != SIZE_BOOT_ORDER)
740 {
741 phosphor::logging::log<phosphor::logging::level::ERR>(
742 "Invalid Boot order length received");
Jayashree-Df0cf6652020-11-30 11:03:30 +0530743 return ipmi::responseReqDataLenInvalid();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700744 }
745
Jayashree-Df0cf6652020-11-30 11:03:30 +0530746 std::copy(std::begin(data), std::end(data), bootSeq);
747 std::optional<size_t> hostId = ipmi::boot::findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700748
Jayashree-Df0cf6652020-11-30 11:03:30 +0530749 if (!hostId)
750 {
751 phosphor::logging::log<phosphor::logging::level::ERR>(
752 "Invalid Host Id received");
753 return ipmi::responseInvalidCommand();
754 }
755 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
756
757 setBootOrder(bootObjPath, bootSeq, hostName);
758
759 return ipmi::responseSuccess(data);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700760}
761
762//----------------------------------------------------------------------
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800763// Get Boot Order (CMD_OEM_GET_BOOT_ORDER)
764//----------------------------------------------------------------------
Jayashree-Df0cf6652020-11-30 11:03:30 +0530765ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>
766 ipmiOemGetBootOrder(ipmi::Context::ptr ctx)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800767{
Jayashree-Df0cf6652020-11-30 11:03:30 +0530768 uint8_t bootSeq[SIZE_BOOT_ORDER];
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700769 uint8_t mode = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800770
Jayashree-Df0cf6652020-11-30 11:03:30 +0530771 std::optional<size_t> hostId = ipmi::boot::findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700772
Jayashree-Df0cf6652020-11-30 11:03:30 +0530773 if (!hostId)
774 {
775 phosphor::logging::log<phosphor::logging::level::ERR>(
776 "Invalid Host Id received");
777 return ipmi::responseInvalidCommand();
778 }
779 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
780
781 // GETTING PROPERTY OF MODE INTERFACE
782
783 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
784
785 std::string service =
786 getService(*dbus, ipmi::boot::bootModeIntf, bootObjPath);
787 Value variant =
788 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf,
789 ipmi::boot::bootModeProp);
790
791 auto bootMode = ipmi::boot::Mode::convertModesFromString(
792 std::get<std::string>(variant));
793
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530794 uint8_t bootOption = ipmi::boot::modeDbusToIpmi.at(bootMode);
Jayashree-Df0cf6652020-11-30 11:03:30 +0530795
796 // GETTING PROPERTY OF SOURCE INTERFACE
797
798 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath);
799 variant =
800 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf,
801 ipmi::boot::bootSourceProp);
802 auto bootSource = ipmi::boot::Source::convertSourcesFromString(
803 std::get<std::string>(variant));
804
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530805 uint8_t bootOrder = ipmi::boot::sourceDbusToIpmi.at(bootSource);
806
807 // GETTING PROPERTY OF TYPE INTERFACE
808
809 service = getService(*dbus, ipmi::boot::bootTypeIntf, bootObjPath);
810 variant =
811 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootTypeIntf,
812 ipmi::boot::bootTypeProp);
813 auto bootType = ipmi::boot::Type::convertTypesFromString(
814 std::get<std::string>(variant));
815
816 uint8_t bootTypeVal = ipmi::boot::typeDbusToIpmi.at(bootType);
817
818 uint8_t bootVal = bootOption | bootTypeVal;
Jayashree-Df0cf6652020-11-30 11:03:30 +0530819
820 if (oemData.find(hostName) == oemData.end())
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800821 {
822 /* Return default boot order 0100090203ff */
823 uint8_t defaultBoot[SIZE_BOOT_ORDER] = {
824 BOOT_MODE_UEFI, bootMap["USB_DEV"], bootMap["NET_IPV6"],
825 bootMap["SATA_HDD"], bootMap["SATA_CD"], 0xff};
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700826
Jayashree-Df0cf6652020-11-30 11:03:30 +0530827 memcpy(bootSeq, defaultBoot, SIZE_BOOT_ORDER);
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800828 phosphor::logging::log<phosphor::logging::level::INFO>(
829 "Set default boot order");
Jayashree-Df0cf6652020-11-30 11:03:30 +0530830 setBootOrder(bootObjPath, defaultBoot, hostName);
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800831 }
832 else
833 {
Jayashree-Df0cf6652020-11-30 11:03:30 +0530834 nlohmann::json bootMode = oemData[hostName][KEY_BOOT_MODE];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800835 if (bootMode["UEFI"])
836 mode |= BOOT_MODE_UEFI;
837 if (bootMode["CMOS_CLR"])
838 mode |= BOOT_MODE_CMOS_CLR;
839 if (bootMode["BOOT_FLAG"])
840 mode |= BOOT_MODE_BOOT_FLAG;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700841
Jayashree-Df0cf6652020-11-30 11:03:30 +0530842 bootSeq[0] = mode;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800843
Jayashree-Df0cf6652020-11-30 11:03:30 +0530844 for (int i = 1; i < SIZE_BOOT_ORDER; i++)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800845 {
Jayashree-Df0cf6652020-11-30 11:03:30 +0530846 std::string seqStr = oemData[hostName][KEY_BOOT_SEQ][i - 1];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800847 if (bootMap.find(seqStr) != bootMap.end())
Jayashree-Df0cf6652020-11-30 11:03:30 +0530848 bootSeq[i] = bootMap[seqStr];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800849 else
Jayashree-Df0cf6652020-11-30 11:03:30 +0530850 bootSeq[i] = 0xff;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800851 }
852 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800853
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530854 return ipmi::responseSuccess(bootVal, bootOrder, bootSeq[2], bootSeq[3],
Jayashree-Df0cf6652020-11-30 11:03:30 +0530855 bootSeq[4], bootSeq[5]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800856}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800857// Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO)
858//----------------------------------------------------------------------
859ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
860 ipmi_request_t request,
861 ipmi_response_t response,
862 ipmi_data_len_t data_len,
863 ipmi_context_t context)
864{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700865 machineConfigInfo_t* req = reinterpret_cast<machineConfigInfo_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700866 uint8_t len = *data_len;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800867
868 *data_len = 0;
869
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700870 if (len < sizeof(machineConfigInfo_t))
871 {
872 phosphor::logging::log<phosphor::logging::level::ERR>(
873 "Invalid machine configuration length received");
874 return IPMI_CC_REQ_DATA_LEN_INVALID;
875 }
876
Vijay Khemka63c99be2020-05-27 19:14:35 -0700877 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700878 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN";
879 else
880 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] =
881 chassisType[req->chassis_type];
882
Vijay Khemka63c99be2020-05-27 19:14:35 -0700883 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700884 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN";
885 else
886 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type];
887
888 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt;
889 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt;
890 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt;
891 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt;
892
Vijay Khemka63c99be2020-05-27 19:14:35 -0700893 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700894 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN";
895 else
896 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type];
897
898 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {};
899 int i = 0;
900 if (req->pcie_card_loc & BIT_0)
901 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1";
902 if (req->pcie_card_loc & BIT_1)
903 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2";
904 if (req->pcie_card_loc & BIT_2)
905 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3";
906 if (req->pcie_card_loc & BIT_3)
907 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4";
908
Vijay Khemka63c99be2020-05-27 19:14:35 -0700909 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700910 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN";
911 else
912 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] =
913 pcieType[req->slot1_pcie_type];
914
Vijay Khemka63c99be2020-05-27 19:14:35 -0700915 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700916 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN";
917 else
918 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] =
919 pcieType[req->slot2_pcie_type];
920
Vijay Khemka63c99be2020-05-27 19:14:35 -0700921 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700922 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN";
923 else
924 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] =
925 pcieType[req->slot3_pcie_type];
926
Vijay Khemka63c99be2020-05-27 19:14:35 -0700927 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700928 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN";
929 else
930 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] =
931 pcieType[req->slot4_pcie_type];
932
933 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt;
934
935 flushOemData();
936
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800937 return IPMI_CC_OK;
938}
939
940//----------------------------------------------------------------------
941// Set POST start (CMD_OEM_SET_POST_START)
942//----------------------------------------------------------------------
943ipmi_ret_t ipmiOemSetPostStart(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
944 ipmi_request_t request, ipmi_response_t response,
945 ipmi_data_len_t data_len, ipmi_context_t context)
946{
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800947 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event");
948
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700949 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800950 *data_len = 0;
951 return IPMI_CC_OK;
952}
953
954//----------------------------------------------------------------------
955// Set POST End (CMD_OEM_SET_POST_END)
956//----------------------------------------------------------------------
957ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
958 ipmi_request_t request, ipmi_response_t response,
959 ipmi_data_len_t data_len, ipmi_context_t context)
960{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700961 struct timespec ts;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800962
963 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event");
964
965 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700966
967 // Timestamp post end time.
968 clock_gettime(CLOCK_REALTIME, &ts);
969 oemData[KEY_TS_SLED] = ts.tv_sec;
970 flushOemData();
971
972 // Sync time with system
973 // TODO: Add code for syncing time
974
975 return IPMI_CC_OK;
976}
977
978//----------------------------------------------------------------------
979// Set PPIN Info (CMD_OEM_SET_PPIN_INFO)
980//----------------------------------------------------------------------
981// Inform BMC about PPIN data of 8 bytes for each CPU
982//
983// Request:
984// Byte 1:8 – CPU0 PPIN data
985// Optional:
986// Byte 9:16 – CPU1 PPIN data
987//
988// Response:
989// Byte 1 – Completion Code
990ipmi_ret_t ipmiOemSetPPINInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
991 ipmi_request_t request, ipmi_response_t response,
992 ipmi_data_len_t data_len, ipmi_context_t context)
993{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700994 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700995 std::string ppinStr;
996 int len;
997
998 if (*data_len > SIZE_CPU_PPIN * 2)
999 len = SIZE_CPU_PPIN * 2;
1000 else
1001 len = *data_len;
1002 *data_len = 0;
1003
1004 ppinStr = bytesToStr(req, len);
1005 oemData[KEY_PPIN_INFO] = ppinStr.c_str();
1006 flushOemData();
1007
1008 return IPMI_CC_OK;
1009}
1010
1011//----------------------------------------------------------------------
1012// Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER)
1013//----------------------------------------------------------------------
1014ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1015 ipmi_request_t request,
1016 ipmi_response_t response,
1017 ipmi_data_len_t data_len,
1018 ipmi_context_t context)
1019{
1020 /* Do nothing, return success */
1021 *data_len = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001022 return IPMI_CC_OK;
1023}
1024
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001025// Helper function to set guid at offset in EEPROM
1026static int setGUID(off_t offset, uint8_t* guid)
1027{
1028 int fd = -1;
1029 ssize_t len;
1030 int ret = 0;
1031
1032 errno = 0;
1033
1034 // Check if file is present
1035 if (access(FRU_EEPROM, F_OK) == -1)
1036 {
1037 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl;
1038 return errno;
1039 }
1040
1041 // Open the file
1042 fd = open(FRU_EEPROM, O_WRONLY);
1043 if (fd == -1)
1044 {
1045 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl;
1046 return errno;
1047 }
1048
1049 // seek to the offset
1050 lseek(fd, offset, SEEK_SET);
1051
1052 // Write bytes to location
1053 len = write(fd, guid, GUID_SIZE);
1054 if (len != GUID_SIZE)
1055 {
1056 phosphor::logging::log<phosphor::logging::level::ERR>(
1057 "GUID write data to EEPROM failed");
1058 ret = errno;
1059 }
1060
1061 close(fd);
1062 return ret;
1063}
1064
1065//----------------------------------------------------------------------
1066// Set System GUID (CMD_OEM_SET_SYSTEM_GUID)
1067//----------------------------------------------------------------------
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301068#if BIC_ENABLED
1069ipmi::RspType<> ipmiOemSetSystemGuid(ipmi::Context::ptr ctx, uint8_t cmdReq,
1070 std::vector<uint8_t> reqData)
1071{
1072 std::vector<uint8_t> respData;
1073
1074 if (reqData.size() != GUID_SIZE) // 16bytes
1075 {
1076
1077 return ipmi::responseReqDataLenInvalid();
1078 }
1079
1080 auto ptrReqData = reqData.insert(reqData.begin(), reqData.size());
1081
1082 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
1083
1084 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
1085 return ipmi::responseUnspecifiedError();
1086
1087 return ipmi::responseSuccess();
1088}
1089
1090#else
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001091ipmi_ret_t ipmiOemSetSystemGuid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1092 ipmi_request_t request,
1093 ipmi_response_t response,
1094 ipmi_data_len_t data_len,
1095 ipmi_context_t context)
1096{
1097 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1098
1099 if (*data_len != GUID_SIZE) // 16bytes
1100 {
1101 *data_len = 0;
1102 return IPMI_CC_REQ_DATA_LEN_INVALID;
1103 }
1104
1105 *data_len = 0;
1106
1107 if (setGUID(OFFSET_SYS_GUID, req))
1108 {
1109 return IPMI_CC_UNSPECIFIED_ERROR;
1110 }
1111 return IPMI_CC_OK;
1112}
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301113#endif
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001114
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001115//----------------------------------------------------------------------
1116// Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO)
1117//----------------------------------------------------------------------
1118ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1119 ipmi_request_t request,
1120 ipmi_response_t response,
1121 ipmi_data_len_t data_len,
1122 ipmi_context_t context)
1123{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001124 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001125 *data_len = 0;
1126 return IPMI_CC_OK;
1127}
1128
1129//----------------------------------------------------------------------
1130// Set PPR (CMD_OEM_SET_PPR)
1131//----------------------------------------------------------------------
1132ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1133 ipmi_request_t request, ipmi_response_t response,
1134 ipmi_data_len_t data_len, ipmi_context_t context)
1135{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001136 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001137 uint8_t pprCnt, pprAct, pprIndex;
1138 uint8_t selParam = req[0];
1139 uint8_t len = *data_len;
1140 std::stringstream ss;
1141 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001142
1143 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001144
1145 switch (selParam)
1146 {
1147 case PPR_ACTION:
1148 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) ==
1149 oemData[KEY_PPR].end())
1150 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1151
1152 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1153 if (pprCnt == 0)
1154 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1155
1156 pprAct = req[1];
1157 /* Check if ppr is enabled or disabled */
1158 if (!(pprAct & 0x80))
1159 pprAct = 0;
1160
1161 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct;
1162 break;
1163 case PPR_ROW_COUNT:
1164 if (req[1] > 100)
1165 return IPMI_CC_PARM_OUT_OF_RANGE;
1166
1167 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1];
1168 break;
1169 case PPR_ROW_ADDR:
1170 pprIndex = req[1];
1171 if (pprIndex > 100)
1172 return IPMI_CC_PARM_OUT_OF_RANGE;
1173
1174 if (len < PPR_ROW_ADDR_LEN + 1)
1175 {
1176 phosphor::logging::log<phosphor::logging::level::ERR>(
1177 "Invalid PPR Row Address length received");
1178 return IPMI_CC_REQ_DATA_LEN_INVALID;
1179 }
1180
1181 ss << std::hex;
1182 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1183
1184 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1185
1186 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN);
1187 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str();
1188 break;
1189 case PPR_HISTORY_DATA:
1190 pprIndex = req[1];
1191 if (pprIndex > 100)
1192 return IPMI_CC_PARM_OUT_OF_RANGE;
1193
1194 if (len < PPR_HST_DATA_LEN + 1)
1195 {
1196 phosphor::logging::log<phosphor::logging::level::ERR>(
1197 "Invalid PPR history data length received");
1198 return IPMI_CC_REQ_DATA_LEN_INVALID;
1199 }
1200
1201 ss << std::hex;
1202 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1203
1204 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1205
1206 str = bytesToStr(&req[1], PPR_HST_DATA_LEN);
1207 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str();
1208 break;
1209 default:
1210 return IPMI_CC_PARM_OUT_OF_RANGE;
1211 break;
1212 }
1213
1214 flushOemData();
1215
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001216 return IPMI_CC_OK;
1217}
1218
1219//----------------------------------------------------------------------
1220// Get PPR (CMD_OEM_GET_PPR)
1221//----------------------------------------------------------------------
1222ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1223 ipmi_request_t request, ipmi_response_t response,
1224 ipmi_data_len_t data_len, ipmi_context_t context)
1225{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001226 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1227 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001228 uint8_t pprCnt, pprIndex;
1229 uint8_t selParam = req[0];
1230 std::stringstream ss;
1231 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001232
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001233 /* Any failure will return zero length data */
1234 *data_len = 0;
1235
1236 switch (selParam)
1237 {
1238 case PPR_ACTION:
1239 res[0] = 0;
1240 *data_len = 1;
1241
1242 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1243 oemData[KEY_PPR].end())
1244 {
1245 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1246 if (pprCnt != 0)
1247 {
1248 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) !=
1249 oemData[KEY_PPR].end())
1250 {
1251 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION];
1252 }
1253 }
1254 }
1255 break;
1256 case PPR_ROW_COUNT:
1257 res[0] = 0;
1258 *data_len = 1;
1259 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1260 oemData[KEY_PPR].end())
1261 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1262 break;
1263 case PPR_ROW_ADDR:
1264 pprIndex = req[1];
1265 if (pprIndex > 100)
1266 return IPMI_CC_PARM_OUT_OF_RANGE;
1267
1268 ss << std::hex;
1269 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1270
1271 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1272 return IPMI_CC_PARM_OUT_OF_RANGE;
1273
1274 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) ==
1275 oemData[KEY_PPR][ss.str()].end())
1276 return IPMI_CC_PARM_OUT_OF_RANGE;
1277
1278 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR];
1279 *data_len = strToBytes(str, res);
1280 break;
1281 case PPR_HISTORY_DATA:
1282 pprIndex = req[1];
1283 if (pprIndex > 100)
1284 return IPMI_CC_PARM_OUT_OF_RANGE;
1285
1286 ss << std::hex;
1287 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1288
1289 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1290 return IPMI_CC_PARM_OUT_OF_RANGE;
1291
1292 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) ==
1293 oemData[KEY_PPR][ss.str()].end())
1294 return IPMI_CC_PARM_OUT_OF_RANGE;
1295
1296 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA];
1297 *data_len = strToBytes(str, res);
1298 break;
1299 default:
1300 return IPMI_CC_PARM_OUT_OF_RANGE;
1301 break;
1302 }
1303
1304 return IPMI_CC_OK;
1305}
1306
1307/* FB OEM QC Commands */
1308
1309//----------------------------------------------------------------------
1310// Set Proc Info (CMD_OEM_Q_SET_PROC_INFO)
1311//----------------------------------------------------------------------
1312//"Request:
1313// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1314// Byte 4 – Processor Index, 0 base
1315// Byte 5 – Parameter Selector
1316// Byte 6..N – Configuration parameter data (see below for Parameters
1317// of Processor Information)
1318// Response:
1319// Byte 1 – Completion code
1320//
1321// Parameter#1: (Processor Product Name)
1322//
1323// Byte 1..48 –Product name(ASCII code)
1324// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1325//
1326// Param#2: Processor Basic Information
1327// Byte 1 – Core Number
1328// Byte 2 – Thread Number (LSB)
1329// Byte 3 – Thread Number (MSB)
1330// Byte 4 – Processor frequency in MHz (LSB)
1331// Byte 5 – Processor frequency in MHz (MSB)
1332// Byte 6..7 – Revision
1333//
1334ipmi_ret_t ipmiOemQSetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1335 ipmi_request_t request, ipmi_response_t response,
1336 ipmi_data_len_t data_len, ipmi_context_t context)
1337{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001338 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1339 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001340 std::stringstream ss;
1341 std::string str;
1342 uint8_t len = *data_len;
1343
1344 *data_len = 0;
1345
1346 /* check for requested data params */
1347 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1348 {
1349 phosphor::logging::log<phosphor::logging::level::ERR>(
1350 "Invalid parameter received");
1351 return IPMI_CC_PARM_OUT_OF_RANGE;
1352 }
1353
1354 len = len - 5; // Get Actual data length
1355
1356 ss << std::hex;
1357 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1358 oemData[KEY_Q_PROC_INFO][ss.str()][KEY_PROC_INDEX] = req->procIndex;
1359
1360 str = bytesToStr(req->data, len);
1361 oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]] = str.c_str();
1362 flushOemData();
1363
1364 return IPMI_CC_OK;
1365}
1366
1367//----------------------------------------------------------------------
1368// Get Proc Info (CMD_OEM_Q_GET_PROC_INFO)
1369//----------------------------------------------------------------------
1370// Request:
1371// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1372// Byte 4 – Processor Index, 0 base
1373// Byte 5 – Parameter Selector
1374// Response:
1375// Byte 1 – Completion code
1376// Byte 2..N – Configuration Parameter Data (see below for Parameters
1377// of Processor Information)
1378//
1379// Parameter#1: (Processor Product Name)
1380//
1381// Byte 1..48 –Product name(ASCII code)
1382// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1383//
1384// Param#2: Processor Basic Information
1385// Byte 1 – Core Number
1386// Byte 2 – Thread Number (LSB)
1387// Byte 3 – Thread Number (MSB)
1388// Byte 4 – Processor frequency in MHz (LSB)
1389// Byte 5 – Processor frequency in MHz (MSB)
1390// Byte 6..7 – Revision
1391//
1392ipmi_ret_t ipmiOemQGetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1393 ipmi_request_t request, ipmi_response_t response,
1394 ipmi_data_len_t data_len, ipmi_context_t context)
1395{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001396 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1397 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
1398 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001399 std::stringstream ss;
1400 std::string str;
1401
1402 *data_len = 0;
1403
1404 /* check for requested data params */
1405 if (req->paramSel < 1 || req->paramSel >= numParam)
1406 {
1407 phosphor::logging::log<phosphor::logging::level::ERR>(
1408 "Invalid parameter received");
1409 return IPMI_CC_PARM_OUT_OF_RANGE;
1410 }
1411
1412 ss << std::hex;
1413 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1414
1415 if (oemData[KEY_Q_PROC_INFO].find(ss.str()) ==
1416 oemData[KEY_Q_PROC_INFO].end())
1417 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1418
1419 if (oemData[KEY_Q_PROC_INFO][ss.str()].find(cpuInfoKey[req->paramSel]) ==
1420 oemData[KEY_Q_PROC_INFO][ss.str()].end())
1421 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1422
1423 str = oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]];
1424 *data_len = strToBytes(str, res);
1425
1426 return IPMI_CC_OK;
1427}
1428
1429//----------------------------------------------------------------------
1430// Set Dimm Info (CMD_OEM_Q_SET_DIMM_INFO)
1431//----------------------------------------------------------------------
1432// Request:
1433// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1434// Byte 4 – DIMM Index, 0 base
1435// Byte 5 – Parameter Selector
1436// Byte 6..N – Configuration parameter data (see below for Parameters
1437// of DIMM Information)
1438// Response:
1439// Byte 1 – Completion code
1440//
1441// Param#1 (DIMM Location):
1442// Byte 1 – DIMM Present
1443// Byte 1 – DIMM Present
1444// 01h – Present
1445// FFh – Not Present
1446// Byte 2 – Node Number, 0 base
1447// Byte 3 – Channel Number , 0 base
1448// Byte 4 – DIMM Number , 0 base
1449//
1450// Param#2 (DIMM Type):
1451// Byte 1 – DIMM Type
1452// Bit [7:6]
1453// For DDR3
1454// 00 – Normal Voltage (1.5V)
1455// 01 – Ultra Low Voltage (1.25V)
1456// 10 – Low Voltage (1.35V)
1457// 11 – Reserved
1458// For DDR4
1459// 00 – Reserved
1460// 01 – Reserved
1461// 10 – Reserved
1462// 11 – Normal Voltage (1.2V)
1463// Bit [5:0]
1464// 0x00 – SDRAM
1465// 0x01 – DDR-1 RAM
1466// 0x02 – Rambus
1467// 0x03 – DDR-2 RAM
1468// 0x04 – FBDIMM
1469// 0x05 – DDR-3 RAM
1470// 0x06 – DDR-4 RAM
1471//
1472// Param#3 (DIMM Speed):
1473// Byte 1..2 – DIMM speed in MHz, LSB
1474// Byte 3..6 – DIMM size in Mbytes, LSB
1475//
1476// Param#4 (Module Part Number):
1477// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1478//
1479// Param#5 (Module Serial Number):
1480// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1481//
1482// Param#6 (Module Manufacturer ID):
1483// Byte 1 - Module Manufacturer ID, LSB
1484// Byte 2 - Module Manufacturer ID, MSB
1485//
1486ipmi_ret_t ipmiOemQSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1487 ipmi_request_t request, ipmi_response_t response,
1488 ipmi_data_len_t data_len, ipmi_context_t context)
1489{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001490 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1491 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001492 std::stringstream ss;
1493 std::string str;
1494 uint8_t len = *data_len;
1495
1496 *data_len = 0;
1497
1498 /* check for requested data params */
1499 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1500 {
1501 phosphor::logging::log<phosphor::logging::level::ERR>(
1502 "Invalid parameter received");
1503 return IPMI_CC_PARM_OUT_OF_RANGE;
1504 }
1505
1506 len = len - 5; // Get Actual data length
1507
1508 ss << std::hex;
1509 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1510 oemData[KEY_Q_DIMM_INFO][ss.str()][KEY_DIMM_INDEX] = req->dimmIndex;
1511
1512 str = bytesToStr(req->data, len);
1513 oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]] =
1514 str.c_str();
1515 flushOemData();
1516
1517 return IPMI_CC_OK;
1518}
1519
1520//----------------------------------------------------------------------
1521// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
1522//----------------------------------------------------------------------
1523// Request:
1524// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1525// Byte 4 – DIMM Index, 0 base
1526// Byte 5 – Parameter Selector
1527// Byte 6..N – Configuration parameter data (see below for Parameters
1528// of DIMM Information)
1529// Response:
1530// Byte 1 – Completion code
1531// Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters
1532// of DIMM Information)
1533//
1534// Param#1 (DIMM Location):
1535// Byte 1 – DIMM Present
1536// Byte 1 – DIMM Present
1537// 01h – Present
1538// FFh – Not Present
1539// Byte 2 – Node Number, 0 base
1540// Byte 3 – Channel Number , 0 base
1541// Byte 4 – DIMM Number , 0 base
1542//
1543// Param#2 (DIMM Type):
1544// Byte 1 – DIMM Type
1545// Bit [7:6]
1546// For DDR3
1547// 00 – Normal Voltage (1.5V)
1548// 01 – Ultra Low Voltage (1.25V)
1549// 10 – Low Voltage (1.35V)
1550// 11 – Reserved
1551// For DDR4
1552// 00 – Reserved
1553// 01 – Reserved
1554// 10 – Reserved
1555// 11 – Normal Voltage (1.2V)
1556// Bit [5:0]
1557// 0x00 – SDRAM
1558// 0x01 – DDR-1 RAM
1559// 0x02 – Rambus
1560// 0x03 – DDR-2 RAM
1561// 0x04 – FBDIMM
1562// 0x05 – DDR-3 RAM
1563// 0x06 – DDR-4 RAM
1564//
1565// Param#3 (DIMM Speed):
1566// Byte 1..2 – DIMM speed in MHz, LSB
1567// Byte 3..6 – DIMM size in Mbytes, LSB
1568//
1569// Param#4 (Module Part Number):
1570// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1571//
1572// Param#5 (Module Serial Number):
1573// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1574//
1575// Param#6 (Module Manufacturer ID):
1576// Byte 1 - Module Manufacturer ID, LSB
1577// Byte 2 - Module Manufacturer ID, MSB
1578//
1579ipmi_ret_t ipmiOemQGetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1580 ipmi_request_t request, ipmi_response_t response,
1581 ipmi_data_len_t data_len, ipmi_context_t context)
1582{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001583 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1584 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
1585 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001586 std::stringstream ss;
1587 std::string str;
1588
1589 *data_len = 0;
1590
1591 /* check for requested data params */
1592 if (req->paramSel < 1 || req->paramSel >= numParam)
1593 {
1594 phosphor::logging::log<phosphor::logging::level::ERR>(
1595 "Invalid parameter received");
1596 return IPMI_CC_PARM_OUT_OF_RANGE;
1597 }
1598
1599 ss << std::hex;
1600 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1601
1602 if (oemData[KEY_Q_DIMM_INFO].find(ss.str()) ==
1603 oemData[KEY_Q_DIMM_INFO].end())
1604 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1605
1606 if (oemData[KEY_Q_DIMM_INFO][ss.str()].find(dimmInfoKey[req->paramSel]) ==
1607 oemData[KEY_Q_DIMM_INFO][ss.str()].end())
1608 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1609
1610 str = oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]];
1611 *data_len = strToBytes(str, res);
1612
1613 return IPMI_CC_OK;
1614}
1615
1616//----------------------------------------------------------------------
1617// Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO)
1618//----------------------------------------------------------------------
1619// BIOS issue this command to provide HDD information to BMC.
1620//
1621// BIOS just can get information by standard ATA / SMART command for
1622// OB SATA controller.
1623// BIOS can get
1624// 1. Serial Number
1625// 2. Model Name
1626// 3. HDD FW Version
1627// 4. HDD Capacity
1628// 5. HDD WWN
1629//
1630// Use Get HDD info Param #5 to know the MAX HDD info index.
1631//
1632// Request:
1633// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1634// Byte 4 –
1635// [7:4] Reserved
1636// [3:0] HDD Controller Type
1637// 0x00 – BIOS
1638// 0x01 – Expander
1639// 0x02 – LSI
1640// Byte 5 – HDD Info Index, 0 base
1641// Byte 6 – Parameter Selector
1642// Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD
1643// Information)
1644//
1645// Response:
1646// Byte 1 – Completion Code
1647//
1648// Param#0 (HDD Location):
1649// Byte 1 – Controller
1650// [7:3] Device Number
1651// [2:0] Function Number
1652// For Intel C610 series (Wellsburg)
1653// D31:F2 (0xFA) – SATA control 1
1654// D31:F5 (0xFD) – SATA control 2
1655// D17:F4 (0x8C) – sSata control
1656// Byte 2 – Port Number
1657// Byte 3 – Location (0xFF: No HDD Present)
1658// BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param
1659// #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if
1660// the HDD present. BMC or other people who know the HDD location has
1661// responsibility for update Location info
1662//
1663// Param#1 (Serial Number):
1664// Bytes 1..33: HDD Serial Number
1665//
1666// Param#2 (Model Name):
1667// Byte 1..33 – HDD Model Name
1668//
1669// Param#3 (HDD FW Version):
1670// Byte 1..17 –HDD FW version
1671//
1672// Param#4 (Capacity):
1673// Byte 1..4 –HDD Block Size, LSB
1674// Byte 5..12 - HDD Block Number, LSB
1675// HDD Capacity = HDD Block size * HDD BLock number (Unit Byte)
1676//
1677// Param#5 (Max HDD Quantity):
1678// Byte 1 - Max HDD Quantity
1679// Max supported port numbers in this PCH
1680//
1681// Param#6 (HDD Type)
1682// Byte 1 – HDD Type
1683// 0h – Reserved
1684// 1h – SAS
1685// 2h – SATA
1686// 3h – PCIE SSD (NVME)
1687//
1688// Param#7 (HDD WWN)
1689// Data 1...8: HDD World Wide Name, LSB
1690//
1691ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1692 ipmi_request_t request,
1693 ipmi_response_t response,
1694 ipmi_data_len_t data_len,
1695 ipmi_context_t context)
1696{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001697 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1698 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001699 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1700 std::stringstream ss;
1701 std::string str;
1702 uint8_t len = *data_len;
1703
1704 *data_len = 0;
1705
1706 /* check for requested data params */
1707 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam ||
1708 ctrlType > 2)
1709 {
1710 phosphor::logging::log<phosphor::logging::level::ERR>(
1711 "Invalid parameter received");
1712 return IPMI_CC_PARM_OUT_OF_RANGE;
1713 }
1714
1715 len = len - 6; // Get Actual data length
1716
1717 ss << std::hex;
1718 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1719 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType;
1720 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] =
1721 req->hddIndex;
1722
1723 str = bytesToStr(req->data, len);
1724 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1725 [driveInfoKey[req->paramSel]] = str.c_str();
1726 flushOemData();
1727
1728 return IPMI_CC_OK;
1729}
1730
1731//----------------------------------------------------------------------
1732// Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO)
1733//----------------------------------------------------------------------
1734// BMC needs to check HDD presented or not first. If NOT presented, return
1735// completion code 0xD5.
1736//
1737// Request:
1738// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1739// Byte 4 –
1740//[7:4] Reserved
1741//[3:0] HDD Controller Type
1742// 0x00 – BIOS
1743// 0x01 – Expander
1744// 0x02 – LSI
1745// Byte 5 – HDD Index, 0 base
1746// Byte 6 – Parameter Selector (See Above Set HDD Information)
1747// Response:
1748// Byte 1 – Completion Code
1749// 0xD5 – Not support in current status (HDD Not Present)
1750// Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD
1751// Information)
1752//
1753ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1754 ipmi_request_t request,
1755 ipmi_response_t response,
1756 ipmi_data_len_t data_len,
1757 ipmi_context_t context)
1758{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001759 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1760 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
1761 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001762 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1763 std::stringstream ss;
1764 std::string str;
1765
1766 *data_len = 0;
1767
1768 /* check for requested data params */
1769 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2)
1770 {
1771 phosphor::logging::log<phosphor::logging::level::ERR>(
1772 "Invalid parameter received");
1773 return IPMI_CC_PARM_OUT_OF_RANGE;
1774 }
1775
1776 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) ==
1777 oemData[KEY_Q_DRIVE_INFO].end())
1778 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1779
1780 ss << std::hex;
1781 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1782
1783 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) ==
1784 oemData[KEY_Q_DRIVE_INFO].end())
1785 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1786
1787 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find(
1788 dimmInfoKey[req->paramSel]) ==
1789 oemData[KEY_Q_DRIVE_INFO][ss.str()].end())
1790 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1791
1792 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1793 [dimmInfoKey[req->paramSel]];
1794 *data_len = strToBytes(str, res);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001795
1796 return IPMI_CC_OK;
1797}
1798
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001799/* Helper function for sending DCMI commands to ME and getting response back */
1800ipmi::RspType<std::vector<uint8_t>> sendDCMICmd(uint8_t cmd,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001801 std::vector<uint8_t>& cmdData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001802{
1803 std::vector<uint8_t> respData;
1804
1805 /* Add group id as first byte to request for ME command */
1806 cmdData.insert(cmdData.begin(), groupDCMI);
1807
1808 if (sendMeCmd(ipmi::netFnGroup, cmd, cmdData, respData))
1809 return ipmi::responseUnspecifiedError();
1810
1811 /* Remove group id as first byte as it will be added by IPMID */
1812 respData.erase(respData.begin());
1813
1814 return ipmi::responseSuccess(std::move(respData));
1815}
1816
1817/* DCMI Command handellers. */
1818
1819ipmi::RspType<std::vector<uint8_t>>
1820 ipmiOemDCMIGetPowerReading(std::vector<uint8_t> reqData)
1821{
1822 return sendDCMICmd(ipmi::dcmi::cmdGetPowerReading, reqData);
1823}
1824
1825ipmi::RspType<std::vector<uint8_t>>
1826 ipmiOemDCMIGetPowerLimit(std::vector<uint8_t> reqData)
1827{
1828 return sendDCMICmd(ipmi::dcmi::cmdGetPowerLimit, reqData);
1829}
1830
1831ipmi::RspType<std::vector<uint8_t>>
1832 ipmiOemDCMISetPowerLimit(std::vector<uint8_t> reqData)
1833{
1834 return sendDCMICmd(ipmi::dcmi::cmdSetPowerLimit, reqData);
1835}
1836
1837ipmi::RspType<std::vector<uint8_t>>
1838 ipmiOemDCMIApplyPowerLimit(std::vector<uint8_t> reqData)
1839{
1840 return sendDCMICmd(ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
1841}
1842
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001843static void registerOEMFunctions(void)
1844{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001845 /* Get OEM data from json file */
1846 std::ifstream file(JSON_OEM_DATA_FILE);
1847 if (file)
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001848 {
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001849 file >> oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001850 file.close();
1851 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001852
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001853 phosphor::logging::log<phosphor::logging::level::INFO>(
1854 "Registering OEM commands");
Vijay Khemka7c0aea42020-03-05 13:31:53 -08001855
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001856 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO,
1857 NULL, ipmiOemDbgGetFrameInfo,
1858 PRIVILEGE_USER); // get debug frame info
1859 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ,
1860 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL,
1861 ipmiOemDbgGetUpdFrames,
1862 PRIVILEGE_USER); // get debug updated frames
1863 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC,
1864 NULL, ipmiOemDbgGetPostDesc,
1865 PRIVILEGE_USER); // get debug post description
1866 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC,
1867 NULL, ipmiOemDbgGetGpioDesc,
1868 PRIVILEGE_USER); // get debug gpio description
1869 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA,
1870 NULL, ipmiOemDbgGetFrameData,
1871 PRIVILEGE_USER); // get debug frame data
1872 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL,
1873 NULL, ipmiOemDbgGetCtrlPanel,
1874 PRIVILEGE_USER); // get debug control panel
1875 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL,
1876 ipmiOemSetDimmInfo,
1877 PRIVILEGE_USER); // Set Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001878 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL,
1879 ipmiOemGetBoardID,
1880 PRIVILEGE_USER); // Get Board ID
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001881 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL,
1882 ipmiOemSetMachineCfgInfo,
1883 PRIVILEGE_USER); // Set Machine Config Info
1884 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL,
1885 ipmiOemSetPostStart,
1886 PRIVILEGE_USER); // Set POST start
1887 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL,
1888 ipmiOemSetPostEnd,
1889 PRIVILEGE_USER); // Set POST End
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001890 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL,
1891 ipmiOemSetPPINInfo,
1892 PRIVILEGE_USER); // Set PPIN Info
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301893#if BIC_ENABLED
1894
1895 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1896 ipmi::cmdSetSystemGuid, ipmi::Privilege::User,
1897 ipmiOemSetSystemGuid);
1898#else
1899
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001900 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_SYSTEM_GUID, NULL,
1901 ipmiOemSetSystemGuid,
1902 PRIVILEGE_USER); // Set System GUID
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301903#endif
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001904 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL,
1905 ipmiOemSetAdrTrigger,
1906 PRIVILEGE_USER); // Set ADR Trigger
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001907 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL,
1908 ipmiOemSetBiosFlashInfo,
1909 PRIVILEGE_USER); // Set Bios Flash Info
1910 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr,
1911 PRIVILEGE_USER); // Set PPR
1912 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
1913 PRIVILEGE_USER); // Get PPR
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001914 /* FB OEM QC Commands */
1915 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_PROC_INFO, NULL,
1916 ipmiOemQSetProcInfo,
1917 PRIVILEGE_USER); // Set Proc Info
1918 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL,
1919 ipmiOemQGetProcInfo,
1920 PRIVILEGE_USER); // Get Proc Info
1921 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DIMM_INFO, NULL,
1922 ipmiOemQSetDimmInfo,
1923 PRIVILEGE_USER); // Set Dimm Info
1924 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DIMM_INFO, NULL,
1925 ipmiOemQGetDimmInfo,
1926 PRIVILEGE_USER); // Get Dimm Info
1927 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
1928 ipmiOemQSetDriveInfo,
1929 PRIVILEGE_USER); // Set Drive Info
1930 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL,
1931 ipmiOemQGetDriveInfo,
1932 PRIVILEGE_USER); // Get Drive Info
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001933
1934 /* FB OEM DCMI Commands as per DCMI spec 1.5 Section 6 */
1935 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1936 ipmi::dcmi::cmdGetPowerReading,
1937 ipmi::Privilege::User,
1938 ipmiOemDCMIGetPowerReading); // Get Power Reading
1939
1940 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1941 ipmi::dcmi::cmdGetPowerLimit,
1942 ipmi::Privilege::User,
1943 ipmiOemDCMIGetPowerLimit); // Get Power Limit
1944
1945 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1946 ipmi::dcmi::cmdSetPowerLimit,
1947 ipmi::Privilege::Operator,
1948 ipmiOemDCMISetPowerLimit); // Set Power Limit
1949
1950 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1951 ipmi::dcmi::cmdActDeactivatePwrLimit,
1952 ipmi::Privilege::Operator,
1953 ipmiOemDCMIApplyPowerLimit); // Apply Power Limit
1954
Jayashree-Df0cf6652020-11-30 11:03:30 +05301955 /* FB OEM BOOT ORDER COMMANDS */
1956 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1957 CMD_OEM_GET_BOOT_ORDER, ipmi::Privilege::User,
1958 ipmiOemGetBootOrder); // Get Boot Order
1959
1960 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1961 CMD_OEM_SET_BOOT_ORDER, ipmi::Privilege::User,
1962 ipmiOemSetBootOrder); // Set Boot Order
1963
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001964 return;
1965}
1966
1967} // namespace ipmi