blob: ba2b6e0fa498bd5edd058bceb443d8f2d8eacf88 [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"
Vijay Khemkae7d23d02019-03-08 13:13:40 -080019
Patrick Williams2405ae92023-05-10 07:50:09 -050020#include <commandutils.hpp>
21#include <ipmid/api-types.hpp>
Vijay Khemka63c99be2020-05-27 19:14:35 -070022#include <ipmid/api.hpp>
Vijay Khemka1b6fae32019-03-25 17:43:01 -070023#include <ipmid/utils.hpp>
Vijay Khemka63c99be2020-05-27 19:14:35 -070024#include <nlohmann/json.hpp>
25#include <oemcommands.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080026#include <phosphor-logging/log.hpp>
27#include <sdbusplus/bus.hpp>
Patrick Williams2405ae92023-05-10 07:50:09 -050028#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
29#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
30#include <xyz/openbmc_project/Control/Boot/Type/server.hpp>
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053031
Vijay Khemka63c99be2020-05-27 19:14:35 -070032#include <array>
33#include <cstring>
34#include <fstream>
35#include <iomanip>
36#include <iostream>
Patrick Williams2405ae92023-05-10 07:50:09 -050037#include <regex>
Vijay Khemka63c99be2020-05-27 19:14:35 -070038#include <sstream>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080039#include <string>
40#include <vector>
41
42#define SIZE_IANA_ID 3
43
44namespace ipmi
45{
Vijay Khemkaa7231892019-10-11 11:35:05 -070046
47using namespace phosphor::logging;
48
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +053049void getSelectorPosition(size_t& position);
Vijay Khemkae7d23d02019-03-08 13:13:40 -080050static void registerOEMFunctions() __attribute__((constructor));
Patrick Williamscd315e02022-07-22 19:26:52 -050051sdbusplus::bus_t dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
Vijay Khemkae7d23d02019-03-08 13:13:40 -080052static 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
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +053055constexpr uint8_t cmdSetQDimmInfo = 0x12;
56constexpr uint8_t cmdGetQDimmInfo = 0x13;
57
Vijay Khemka63c99be2020-05-27 19:14:35 -070058int plat_udbg_get_post_desc(uint8_t, uint8_t*, uint8_t, uint8_t*, uint8_t*,
59 uint8_t*);
60int plat_udbg_get_gpio_desc(uint8_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*,
61 uint8_t*);
Patrick Williams5e589482024-07-13 16:18:13 -050062int plat_udbg_get_frame_data(uint8_t, uint8_t, uint8_t*, uint8_t*, uint8_t*);
Vijay Khemka63c99be2020-05-27 19:14:35 -070063ipmi_ret_t plat_udbg_control_panel(uint8_t, uint8_t, uint8_t, uint8_t*,
64 uint8_t*);
65int sendMeCmd(uint8_t, uint8_t, std::vector<uint8_t>&, std::vector<uint8_t>&);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -070066
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053067int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
68 std::vector<uint8_t>&);
69
Vijay Khemkafeaa9812019-08-27 15:08:08 -070070nlohmann::json oemData __attribute__((init_priority(101)));
Vijay Khemka1b6fae32019-03-25 17:43:01 -070071
Vijay Khemkaf2246ce2020-05-27 14:26:35 -070072static constexpr size_t GUID_SIZE = 16;
73// TODO Make offset and location runtime configurable to ensure we
74// can make each define their own locations.
75static constexpr off_t OFFSET_SYS_GUID = 0x17F0;
76static constexpr const char* FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom";
Delphine CC Chiu7bb45922023-04-10 13:34:04 +080077void flushOemData();
Vijay Khemkaf2246ce2020-05-27 14:26:35 -070078
Vijay Khemka1b6fae32019-03-25 17:43:01 -070079enum class LanParam : uint8_t
80{
81 INPROGRESS = 0,
82 AUTHSUPPORT = 1,
83 AUTHENABLES = 2,
84 IP = 3,
85 IPSRC = 4,
86 MAC = 5,
87 SUBNET = 6,
88 GATEWAY = 12,
89 VLAN = 20,
90 CIPHER_SUITE_COUNT = 22,
91 CIPHER_SUITE_ENTRIES = 23,
92 IPV6 = 59,
93};
94
Vijay Khemkaa7231892019-10-11 11:35:05 -070095namespace network
96{
97
98constexpr auto ROOT = "/xyz/openbmc_project/network";
99constexpr auto SERVICE = "xyz.openbmc_project.Network";
100constexpr auto IPV4_TYPE = "ipv4";
101constexpr auto IPV6_TYPE = "ipv6";
102constexpr auto IPV4_PREFIX = "169.254";
103constexpr auto IPV6_PREFIX = "fe80";
104constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
105constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
Potin Lai8d1a81e2022-12-20 11:13:45 +0800106constexpr auto IPV4_PROTOCOL = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
107constexpr auto IPV6_PROTOCOL = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
Vijay Khemkaa7231892019-10-11 11:35:05 -0700108
Vijay Khemka63c99be2020-05-27 19:14:35 -0700109bool isLinkLocalIP(const std::string& address)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700110{
111 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0;
112}
113
Patrick Williamscd315e02022-07-22 19:26:52 -0500114DbusObjectInfo getIPObject(sdbusplus::bus_t& bus, const std::string& interface,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700115 const std::string& serviceRoot,
Potin Lai8d1a81e2022-12-20 11:13:45 +0800116 const std::string& protocol,
117 const std::string& ethdev)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700118{
Potin Lai8d1a81e2022-12-20 11:13:45 +0800119 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, ethdev);
Vijay Khemkaa7231892019-10-11 11:35:05 -0700120
121 if (objectTree.empty())
122 {
123 log<level::ERR>("No Object has implemented the IP interface",
124 entry("INTERFACE=%s", interface.c_str()));
125 }
126
127 DbusObjectInfo objectInfo;
128
Vijay Khemka63c99be2020-05-27 19:14:35 -0700129 for (auto& object : objectTree)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700130 {
Patrick Williams2405ae92023-05-10 07:50:09 -0500131 auto variant = ipmi::getDbusProperty(bus, object.second.begin()->first,
132 object.first, IP_INTERFACE,
133 "Type");
Potin Lai8d1a81e2022-12-20 11:13:45 +0800134 if (std::get<std::string>(variant) != protocol)
135 {
136 continue;
137 }
138
139 variant = ipmi::getDbusProperty(bus, object.second.begin()->first,
140 object.first, IP_INTERFACE, "Address");
Vijay Khemkaa7231892019-10-11 11:35:05 -0700141
142 objectInfo = std::make_pair(object.first, object.second.begin()->first);
143
144 // if LinkLocalIP found look for Non-LinkLocalIP
145 if (isLinkLocalIP(std::get<std::string>(variant)))
146 {
147 continue;
148 }
149 else
150 {
151 break;
152 }
153 }
154 return objectInfo;
155}
156
157} // namespace network
158
Jayashree-Df0cf6652020-11-30 11:03:30 +0530159namespace boot
160{
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530161using BootSource =
162 sdbusplus::xyz::openbmc_project::Control::Boot::server::Source::Sources;
163using BootMode =
164 sdbusplus::xyz::openbmc_project::Control::Boot::server::Mode::Modes;
165using BootType =
166 sdbusplus::xyz::openbmc_project::Control::Boot::server::Type::Types;
Jayashree-Df0cf6652020-11-30 11:03:30 +0530167
Jayashree-Df0cf6652020-11-30 11:03:30 +0530168using IpmiValue = uint8_t;
169
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530170std::map<IpmiValue, BootSource> sourceIpmiToDbus = {
171 {0x0f, BootSource::Default}, {0x00, BootSource::RemovableMedia},
172 {0x01, BootSource::Network}, {0x02, BootSource::Disk},
Delphine CC Chiu7bb45922023-04-10 13:34:04 +0800173 {0x03, BootSource::ExternalMedia}, {0x04, BootSource::RemovableMedia},
174 {0x09, BootSource::Network}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530175
Delphine CC Chiuc0f918b2023-03-22 14:48:04 +0800176std::map<IpmiValue, BootMode> modeIpmiToDbus = {{0x04, BootMode::Setup},
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530177 {0x00, BootMode::Regular}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530178
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530179std::map<IpmiValue, BootType> typeIpmiToDbus = {{0x00, BootType::Legacy},
180 {0x01, BootType::EFI}};
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530181
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530182std::map<std::optional<BootSource>, IpmiValue> sourceDbusToIpmi = {
183 {BootSource::Default, 0x0f},
184 {BootSource::RemovableMedia, 0x00},
185 {BootSource::Network, 0x01},
186 {BootSource::Disk, 0x02},
187 {BootSource::ExternalMedia, 0x03}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530188
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530189std::map<std::optional<BootMode>, IpmiValue> modeDbusToIpmi = {
Delphine CC Chiuc0f918b2023-03-22 14:48:04 +0800190 {BootMode::Setup, 0x04}, {BootMode::Regular, 0x00}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530191
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530192std::map<std::optional<BootType>, IpmiValue> typeDbusToIpmi = {
193 {BootType::Legacy, 0x00}, {BootType::EFI, 0x01}};
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530194
Delphine CC Chiuc0f918b2023-03-22 14:48:04 +0800195static constexpr auto bootEnableIntf = "xyz.openbmc_project.Object.Enable";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530196static constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
197static constexpr auto bootSourceIntf =
198 "xyz.openbmc_project.Control.Boot.Source";
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530199static constexpr auto bootTypeIntf = "xyz.openbmc_project.Control.Boot.Type";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530200static constexpr auto bootSourceProp = "BootSource";
201static constexpr auto bootModeProp = "BootMode";
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530202static constexpr auto bootTypeProp = "BootType";
Delphine CC Chiuc0f918b2023-03-22 14:48:04 +0800203static constexpr auto bootEnableProp = "Enabled";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530204
Jayashree-Df0cf6652020-11-30 11:03:30 +0530205std::tuple<std::string, std::string> objPath(size_t id)
206{
207 std::string hostName = "host" + std::to_string(id);
Patrick Williams2405ae92023-05-10 07:50:09 -0500208 std::string bootObjPath = "/xyz/openbmc_project/control/" + hostName +
209 "/boot";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530210 return std::make_tuple(std::move(bootObjPath), std::move(hostName));
211}
212
Delphine CC Chiu7bb45922023-04-10 13:34:04 +0800213/* Helper functions to set boot order */
214void setBootOrder(std::string bootObjPath, const std::vector<uint8_t>& bootSeq,
215 std::string bootOrderKey)
216{
217 if (bootSeq.size() != SIZE_BOOT_ORDER)
218 {
219 phosphor::logging::log<phosphor::logging::level::ERR>(
220 "Invalid Boot order length received");
221 return;
222 }
223
224 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
225
226 uint8_t mode = bootSeq.front();
227
228 // SETTING BOOT MODE PROPERTY
229 uint8_t bootModeBit = mode & 0x04;
230 auto bootValue = ipmi::boot::modeIpmiToDbus.at(bootModeBit);
231
232 std::string bootOption =
233 sdbusplus::message::convert_to_string<boot::BootMode>(bootValue);
234
235 std::string service = getService(*dbus, ipmi::boot::bootModeIntf,
236 bootObjPath);
237 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf,
238 ipmi::boot::bootModeProp, bootOption);
239
240 // SETTING BOOT SOURCE PROPERTY
241 auto bootOrder = ipmi::boot::sourceIpmiToDbus.at(bootSeq.at(1));
242 std::string bootSource =
243 sdbusplus::message::convert_to_string<boot::BootSource>(bootOrder);
244
245 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath);
246 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf,
247 ipmi::boot::bootSourceProp, bootSource);
248
249 // SETTING BOOT TYPE PROPERTY
250 uint8_t bootTypeBit = mode & 0x01;
251 auto bootTypeVal = ipmi::boot::typeIpmiToDbus.at(bootTypeBit);
252
253 std::string bootType =
254 sdbusplus::message::convert_to_string<boot::BootType>(bootTypeVal);
255
256 service = getService(*dbus, ipmi::boot::bootTypeIntf, bootObjPath);
257
258 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootTypeIntf,
259 ipmi::boot::bootTypeProp, bootType);
260
261 // Set the valid bit to boot enabled property
262 service = getService(*dbus, ipmi::boot::bootEnableIntf, bootObjPath);
263
264 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootEnableIntf,
265 ipmi::boot::bootEnableProp,
266 (mode & BOOT_MODE_BOOT_FLAG) ? true : false);
267
268 nlohmann::json bootMode;
269
270 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI) ? true : false;
271 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR) ? true : false;
272 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT) ? true : false;
273 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG) ? true : false;
274 oemData[bootOrderKey][KEY_BOOT_MODE] = bootMode;
275
276 /* Initialize boot sequence array */
277 oemData[bootOrderKey][KEY_BOOT_SEQ] = {};
278 for (size_t i = 1; i < SIZE_BOOT_ORDER; i++)
279 {
280 if (bootSeq.at(i) >= BOOT_SEQ_ARRAY_SIZE)
281 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = "NA";
282 else
283 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] =
284 bootSeqDefine[bootSeq.at(i)];
285 }
286
287 flushOemData();
288}
289
290void getBootOrder(std::string bootObjPath, std::vector<uint8_t>& bootSeq,
291 std::string hostName)
292{
293 if (oemData.find(hostName) == oemData.end())
294 {
295 /* Return default boot order 0100090203ff */
296 bootSeq.push_back(BOOT_MODE_UEFI);
297 bootSeq.push_back(static_cast<uint8_t>(bootMap["USB_DEV"]));
298 bootSeq.push_back(static_cast<uint8_t>(bootMap["NET_IPV6"]));
299 bootSeq.push_back(static_cast<uint8_t>(bootMap["SATA_HDD"]));
300 bootSeq.push_back(static_cast<uint8_t>(bootMap["SATA_CD"]));
301 bootSeq.push_back(0xff);
302
303 phosphor::logging::log<phosphor::logging::level::INFO>(
304 "Set default boot order");
305 setBootOrder(bootObjPath, bootSeq, hostName);
306 return;
307 }
308
309 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
310
311 // GETTING PROPERTY OF MODE INTERFACE
312
313 std::string service = getService(*dbus, ipmi::boot::bootModeIntf,
314 bootObjPath);
315 Value variant = getDbusProperty(*dbus, service, bootObjPath,
316 ipmi::boot::bootModeIntf,
317 ipmi::boot::bootModeProp);
318
319 auto bootMode = sdbusplus::message::convert_from_string<boot::BootMode>(
320 std::get<std::string>(variant));
321
322 uint8_t bootOption = ipmi::boot::modeDbusToIpmi.at(bootMode);
323
324 // GETTING PROPERTY OF TYPE INTERFACE
325
326 service = getService(*dbus, ipmi::boot::bootTypeIntf, bootObjPath);
327 variant = getDbusProperty(*dbus, service, bootObjPath,
328 ipmi::boot::bootTypeIntf,
329 ipmi::boot::bootTypeProp);
330
331 auto bootType = sdbusplus::message::convert_from_string<boot::BootType>(
332 std::get<std::string>(variant));
333
334 // Get the valid bit to boot enabled property
335 service = getService(*dbus, ipmi::boot::bootEnableIntf, bootObjPath);
336 variant = getDbusProperty(*dbus, service, bootObjPath,
337 ipmi::boot::bootEnableIntf,
338 ipmi::boot::bootEnableProp);
339
340 bool validFlag = std::get<bool>(variant);
341
342 uint8_t bootTypeVal = ipmi::boot::typeDbusToIpmi.at(bootType);
343
344 bootSeq.push_back(bootOption | bootTypeVal);
345
346 if (validFlag)
347 {
348 bootSeq.front() |= BOOT_MODE_BOOT_FLAG;
349 }
350
351 nlohmann::json bootModeJson = oemData[hostName][KEY_BOOT_MODE];
352 if (bootModeJson["CMOS_CLR"])
353 bootSeq.front() |= BOOT_MODE_CMOS_CLR;
354
355 for (int i = 1; i < SIZE_BOOT_ORDER; i++)
356 {
357 std::string seqStr = oemData[hostName][KEY_BOOT_SEQ][i - 1];
358 if (bootMap.find(seqStr) != bootMap.end())
359 bootSeq.push_back(bootMap[seqStr]);
360 else
361 bootSeq.push_back(0xff);
362 }
363}
364
Jayashree-Df0cf6652020-11-30 11:03:30 +0530365} // namespace boot
366
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700367//----------------------------------------------------------------------
368// Helper functions for storing oem data
369//----------------------------------------------------------------------
370
371void flushOemData()
372{
373 std::ofstream file(JSON_OEM_DATA_FILE);
374 file << oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -0700375 file.close();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700376 return;
377}
378
Vijay Khemka63c99be2020-05-27 19:14:35 -0700379std::string bytesToStr(uint8_t* byte, int len)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700380{
381 std::stringstream ss;
382 int i;
383
384 ss << std::hex;
385 for (i = 0; i < len; i++)
386 {
387 ss << std::setw(2) << std::setfill('0') << (int)byte[i];
388 }
389
390 return ss.str();
391}
392
Vijay Khemka63c99be2020-05-27 19:14:35 -0700393int strToBytes(std::string& str, uint8_t* data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700394{
395 std::string sstr;
Willy Tue39f9392022-06-15 13:24:20 -0700396 size_t i;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700397
398 for (i = 0; i < (str.length()) / 2; i++)
399 {
400 sstr = str.substr(i * 2, 2);
401 data[i] = (uint8_t)std::strtol(sstr.c_str(), NULL, 16);
402 }
403 return i;
404}
405
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530406int readDimmType(std::string& data, uint8_t param)
407{
408 nlohmann::json dimmObj;
409 /* Get dimm type names stored in json file */
410 std::ifstream file(JSON_DIMM_TYPE_FILE);
411 if (file)
412 {
413 file >> dimmObj;
414 file.close();
415 }
416 else
417 {
418 phosphor::logging::log<phosphor::logging::level::ERR>(
419 "DIMM type names file not found",
420 phosphor::logging::entry("DIMM_TYPE_FILE=%s", JSON_DIMM_TYPE_FILE));
421 return -1;
422 }
423
424 std::string dimmKey = "dimm_type" + std::to_string(param);
425 auto obj = dimmObj[dimmKey]["short_name"];
426 data = obj;
427 return 0;
428}
429
Vijay Khemka63c99be2020-05-27 19:14:35 -0700430ipmi_ret_t getNetworkData(uint8_t lan_param, char* data)
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700431{
432 ipmi_ret_t rc = IPMI_CC_OK;
Patrick Williamscd315e02022-07-22 19:26:52 -0500433 sdbusplus::bus_t bus(ipmid_get_sd_bus_connection());
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700434
435 const std::string ethdevice = "eth0";
436
437 switch (static_cast<LanParam>(lan_param))
438 {
Vijay Khemkad1194022020-05-27 18:58:33 -0700439 case LanParam::IP:
440 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700441 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700442 auto ipObjectInfo = ipmi::network::getIPObject(
Potin Lai8d1a81e2022-12-20 11:13:45 +0800443 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT,
444 ipmi::network::IPV4_PROTOCOL, ethdevice);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700445
446 auto properties = ipmi::getAllDbusProperties(
447 bus, ipObjectInfo.second, ipObjectInfo.first,
448 ipmi::network::IP_INTERFACE);
449
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500450 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700451
452 std::strcpy(data, ipaddress.c_str());
453 }
454 break;
455
Vijay Khemkad1194022020-05-27 18:58:33 -0700456 case LanParam::IPV6:
457 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700458 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700459 auto ipObjectInfo = ipmi::network::getIPObject(
Potin Lai8d1a81e2022-12-20 11:13:45 +0800460 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT,
461 ipmi::network::IPV6_PROTOCOL, ethdevice);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700462
463 auto properties = ipmi::getAllDbusProperties(
464 bus, ipObjectInfo.second, ipObjectInfo.first,
465 ipmi::network::IP_INTERFACE);
466
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500467 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700468
469 std::strcpy(data, ipaddress.c_str());
470 }
471 break;
472
Vijay Khemkad1194022020-05-27 18:58:33 -0700473 case LanParam::MAC:
474 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700475 std::string macAddress;
476 auto macObjectInfo =
477 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
478 ipmi::network::ROOT, ethdevice);
479
480 auto variant = ipmi::getDbusProperty(
481 bus, macObjectInfo.second, macObjectInfo.first,
482 ipmi::network::MAC_INTERFACE, "MACAddress");
483
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500484 macAddress = std::get<std::string>(variant);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700485
486 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
487 (data), (data + 1), (data + 2), (data + 3), (data + 4),
488 (data + 5));
489 std::strcpy(data, macAddress.c_str());
490 }
491 break;
492
493 default:
494 rc = IPMI_CC_PARM_OUT_OF_RANGE;
495 }
496 return rc;
497}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800498
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530499bool isMultiHostPlatform()
500{
501 bool platform;
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530502 if (hostInstances == "0")
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530503 {
504 platform = false;
505 }
506 else
507 {
508 platform = true;
509 }
510 return platform;
511}
512
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800513// return code: 0 successful
Vijay Khemka63c99be2020-05-27 19:14:35 -0700514int8_t getFruData(std::string& data, std::string& name)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800515{
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530516 size_t pos;
517 static constexpr const auto depth = 0;
518 std::vector<std::string> paths;
519 std::string machinePath;
520 std::string baseBoard = "Baseboard";
521
522 bool platform = isMultiHostPlatform();
523 if (platform == true)
524 {
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530525 getSelectorPosition(pos);
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530526 }
527
528 sd_bus* bus = NULL;
529 int ret = sd_bus_default_system(&bus);
530 if (ret < 0)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800531 {
532 phosphor::logging::log<phosphor::logging::level::ERR>(
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530533 "Failed to connect to system bus",
534 phosphor::logging::entry("ERRNO=0x%X", -ret));
535 sd_bus_unref(bus);
536 return -1;
537 }
Patrick Williamscd315e02022-07-22 19:26:52 -0500538 sdbusplus::bus_t dbus(bus);
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530539 auto mapperCall = dbus.new_method_call("xyz.openbmc_project.ObjectMapper",
540 "/xyz/openbmc_project/object_mapper",
541 "xyz.openbmc_project.ObjectMapper",
542 "GetSubTreePaths");
543 static constexpr std::array<const char*, 1> interface = {
544 "xyz.openbmc_project.Inventory.Decorator.Asset"};
545 mapperCall.append("/xyz/openbmc_project/inventory/", depth, interface);
546
547 try
548 {
549 auto reply = dbus.call(mapperCall);
550 reply.read(paths);
551 }
552 catch (sdbusplus::exception_t& e)
553 {
554 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800555 return -1;
556 }
557
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530558 for (const auto& path : paths)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800559 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530560 if (platform == true)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800561 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530562 if (pos == BMC_POS)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800563 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530564 machinePath = baseBoard;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800565 }
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530566 else
567 {
568 machinePath = "_" + std::to_string(pos);
569 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800570 }
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530571 else
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800572 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530573 machinePath = baseBoard;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800574 }
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530575
576 auto found = path.find(machinePath);
Patrick Williams123cbcc2022-06-24 06:13:59 -0500577 if (found == std::string::npos)
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530578 {
579 continue;
580 }
581
582 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
583 std::string service = getService(
584 *dbus, "xyz.openbmc_project.Inventory.Decorator.Asset", path);
585
586 auto Value = ipmi::getDbusProperty(
587 *dbus, service, path,
588 "xyz.openbmc_project.Inventory.Decorator.Asset", name);
589
590 data = std::get<std::string>(Value);
591 return 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800592 }
593 return -1;
594}
595
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530596int8_t sysConfig(std::vector<std::string>& data, size_t pos)
597{
598 nlohmann::json sysObj;
599 std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(pos);
600 std::string result, typeName;
601 uint8_t res[MAX_BUF];
602
603 /* Get sysConfig data stored in json file */
604 std::ifstream file(JSON_OEM_DATA_FILE);
605 if (file)
606 {
607 file >> sysObj;
608 file.close();
609 }
610 else
611 {
612 phosphor::logging::log<phosphor::logging::level::ERR>(
613 "oemData file not found",
614 phosphor::logging::entry("OEM_DATA_FILE=%s", JSON_OEM_DATA_FILE));
615 return -1;
616 }
617
618 if (sysObj.find(dimmInfo) == sysObj.end())
619 {
620 phosphor::logging::log<phosphor::logging::level::ERR>(
621 "sysconfig key not available",
622 phosphor::logging::entry("SYS_JSON_KEY=%s", dimmInfo.c_str()));
623 return -1;
624 }
625 /* Get dimm type names stored in json file */
626 nlohmann::json dimmObj;
627 std::ifstream dimmFile(JSON_DIMM_TYPE_FILE);
628 if (file)
629 {
630 dimmFile >> dimmObj;
631 dimmFile.close();
632 }
633 else
634 {
635 phosphor::logging::log<phosphor::logging::level::ERR>(
636 "DIMM type names file not found",
637 phosphor::logging::entry("DIMM_TYPE_FILE=%s", JSON_DIMM_TYPE_FILE));
638 return -1;
639 }
640 std::vector<std::string> a;
641 for (auto& j : dimmObj.items())
642 {
643 std::string name = j.key();
644 a.push_back(name);
645 }
646
647 uint8_t len = a.size();
648 for (uint8_t ii = 0; ii < len; ii++)
649 {
650 std::string indKey = std::to_string(ii);
651 std::string speedSize = sysObj[dimmInfo][indKey][DIMM_SPEED];
652 strToBytes(speedSize, res);
653 auto speed = (res[1] << 8 | res[0]);
654 size_t dimmSize = ((res[3] << 8 | res[2]) / 1000);
655
656 if (dimmSize == 0)
657 {
658 std::cerr << "Dimm information not available for slot_" +
659 std::to_string(ii)
660 << std::endl;
661 continue;
662 }
663 std::string type = sysObj[dimmInfo][indKey][DIMM_TYPE];
664 std::string dualInlineMem = sysObj[dimmInfo][indKey][KEY_DIMM_TYPE];
665 strToBytes(type, res);
666 size_t dimmType = res[0];
667 if (dimmVenMap.find(dimmType) == dimmVenMap.end())
668 {
669 typeName = "unknown";
670 }
671 else
672 {
673 typeName = dimmVenMap[dimmType];
674 }
675 result = dualInlineMem + "/" + typeName + "/" + std::to_string(speed) +
676 "MHz" + "/" + std::to_string(dimmSize) + "GB";
677 data.push_back(result);
678 }
679 return 0;
680}
681
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +0530682int8_t procInfo(std::string& result, size_t pos)
683{
684 std::vector<char> data;
685 uint8_t res[MAX_BUF];
686 std::string procIndex = "00";
687 nlohmann::json proObj;
688 std::string procInfo = KEY_Q_PROC_INFO + std::to_string(pos);
689 /* Get processor data stored in json file */
690 std::ifstream file(JSON_OEM_DATA_FILE);
691 if (file)
692 {
693 file >> proObj;
694 file.close();
695 }
696 else
697 {
698 phosphor::logging::log<phosphor::logging::level::ERR>(
699 "oemData file not found",
700 phosphor::logging::entry("OEM_DATA_FILE=%s", JSON_OEM_DATA_FILE));
701 return -1;
702 }
703 if (proObj.find(procInfo) == proObj.end())
704 {
705 phosphor::logging::log<phosphor::logging::level::ERR>(
706 "processor info key not available",
707 phosphor::logging::entry("PROC_JSON_KEY=%s", procInfo.c_str()));
708 return -1;
709 }
710 std::string procName = proObj[procInfo][procIndex][KEY_PROC_NAME];
711 std::string basicInfo = proObj[procInfo][procIndex][KEY_BASIC_INFO];
712 // Processor Product Name
713 strToBytes(procName, res);
714 data.assign(reinterpret_cast<char*>(&res),
715 reinterpret_cast<char*>(&res) + sizeof(res));
716
717 std::string s(data.begin(), data.end());
718 std::regex regex(" ");
719 std::vector<std::string> productName(
720 std::sregex_token_iterator(s.begin(), s.end(), regex, -1),
721 std::sregex_token_iterator());
722
723 // Processor core and frequency
724 strToBytes(basicInfo, res);
725 uint16_t coreNum = res[0];
726 double procFrequency = (float)(res[4] << 8 | res[3]) / 1000;
727 result = "CPU:" + productName[2] + "/" + std::to_string(procFrequency) +
728 "GHz" + "/" + std::to_string(coreNum) + "c";
729 return 0;
730}
731
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800732typedef struct
733{
734 uint8_t cur_power_state;
735 uint8_t last_power_event;
736 uint8_t misc_power_state;
737 uint8_t front_panel_button_cap_status;
738} ipmi_get_chassis_status_t;
739
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800740//----------------------------------------------------------------------
741// Get Debug Frame Info
742//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700743ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800744 ipmi_request_t request,
745 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700746 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800747{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700748 uint8_t* req = reinterpret_cast<uint8_t*>(request);
749 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800750 uint8_t num_frames = 3;
751
752 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
753 res[SIZE_IANA_ID] = num_frames;
754 *data_len = SIZE_IANA_ID + 1;
755
756 return IPMI_CC_OK;
757}
758
759//----------------------------------------------------------------------
760// Get Debug Updated Frames
761//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700762ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800763 ipmi_request_t request,
764 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700765 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800766{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700767 uint8_t* req = reinterpret_cast<uint8_t*>(request);
768 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800769 uint8_t num_updates = 3;
770 *data_len = 4;
771
772 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
773 res[SIZE_IANA_ID] = num_updates;
774 *data_len = SIZE_IANA_ID + num_updates + 1;
775 res[SIZE_IANA_ID + 1] = 1; // info page update
776 res[SIZE_IANA_ID + 2] = 2; // cri sel update
777 res[SIZE_IANA_ID + 3] = 3; // cri sensor update
778
779 return IPMI_CC_OK;
780}
781
782//----------------------------------------------------------------------
783// Get Debug POST Description
784//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700785ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800786 ipmi_request_t request,
787 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700788 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800789{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700790 uint8_t* req = reinterpret_cast<uint8_t*>(request);
791 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800792 uint8_t index = 0;
793 uint8_t next = 0;
794 uint8_t end = 0;
795 uint8_t phase = 0;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700796 uint8_t descLen = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800797 int ret;
798
799 index = req[3];
800 phase = req[4];
801
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700802 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800803 if (ret)
804 {
805 memcpy(res, req, SIZE_IANA_ID); // IANA ID
806 *data_len = SIZE_IANA_ID;
807 return IPMI_CC_UNSPECIFIED_ERROR;
808 }
809
810 memcpy(res, req, SIZE_IANA_ID); // IANA ID
811 res[3] = index;
812 res[4] = next;
813 res[5] = phase;
814 res[6] = end;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700815 res[7] = descLen;
816 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800817
818 return IPMI_CC_OK;
819}
820
821//----------------------------------------------------------------------
822// Get Debug GPIO Description
823//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700824ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800825 ipmi_request_t request,
826 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700827 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800828{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700829 uint8_t* req = reinterpret_cast<uint8_t*>(request);
830 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800831
Vijay Khemka38183d62019-08-28 16:19:33 -0700832 uint8_t index = 0;
833 uint8_t next = 0;
834 uint8_t level = 0;
835 uint8_t pinDef = 0;
836 uint8_t descLen = 0;
837 int ret;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800838
Vijay Khemka38183d62019-08-28 16:19:33 -0700839 index = req[3];
840
841 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen,
842 &res[8]);
843 if (ret)
844 {
845 memcpy(res, req, SIZE_IANA_ID); // IANA ID
846 *data_len = SIZE_IANA_ID;
847 return IPMI_CC_UNSPECIFIED_ERROR;
848 }
849
850 memcpy(res, req, SIZE_IANA_ID); // IANA ID
851 res[3] = index;
852 res[4] = next;
853 res[5] = level;
854 res[6] = pinDef;
855 res[7] = descLen;
856 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800857
858 return IPMI_CC_OK;
859}
860
861//----------------------------------------------------------------------
862// Get Debug Frame Data
863//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700864ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800865 ipmi_request_t request,
866 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700867 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800868{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700869 uint8_t* req = reinterpret_cast<uint8_t*>(request);
870 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800871 uint8_t frame;
872 uint8_t page;
873 uint8_t next;
874 uint8_t count;
875 int ret;
876
877 frame = req[3];
878 page = req[4];
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800879
880 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]);
881 if (ret)
882 {
883 memcpy(res, req, SIZE_IANA_ID); // IANA ID
884 *data_len = SIZE_IANA_ID;
885 return IPMI_CC_UNSPECIFIED_ERROR;
886 }
887
888 memcpy(res, req, SIZE_IANA_ID); // IANA ID
889 res[3] = frame;
890 res[4] = page;
891 res[5] = next;
892 res[6] = count;
893 *data_len = SIZE_IANA_ID + 4 + count;
894
895 return IPMI_CC_OK;
896}
897
898//----------------------------------------------------------------------
899// Get Debug Control Panel
900//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700901ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800902 ipmi_request_t request,
903 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700904 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800905{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700906 uint8_t* req = reinterpret_cast<uint8_t*>(request);
907 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800908
909 uint8_t panel;
910 uint8_t operation;
911 uint8_t item;
912 uint8_t count;
913 ipmi_ret_t ret;
914
915 panel = req[3];
916 operation = req[4];
917 item = req[5];
918
919 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]);
920
921 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
922 *data_len = SIZE_IANA_ID + count;
923
924 return ret;
925}
926
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800927//----------------------------------------------------------------------
928// Set Dimm Info (CMD_OEM_SET_DIMM_INFO)
929//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700930ipmi_ret_t ipmiOemSetDimmInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
931 ipmi_response_t, ipmi_data_len_t data_len,
932 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800933{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700934 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700935
936 uint8_t index = req[0];
937 uint8_t type = req[1];
938 uint16_t speed;
939 uint32_t size;
940
941 memcpy(&speed, &req[2], 2);
942 memcpy(&size, &req[4], 4);
943
944 std::stringstream ss;
945 ss << std::hex;
946 ss << std::setw(2) << std::setfill('0') << (int)index;
947
948 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index;
949 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type;
950 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed;
951 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size;
952
953 flushOemData();
954
955 *data_len = 0;
956
957 return IPMI_CC_OK;
958}
959
960//----------------------------------------------------------------------
961// Get Board ID (CMD_OEM_GET_BOARD_ID)
962//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700963ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
964 ipmi_response_t, ipmi_data_len_t data_len,
965 ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700966{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700967 /* TODO: Needs to implement this after GPIO implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800968 *data_len = 0;
969
970 return IPMI_CC_OK;
971}
972
Bonnie Lo4ae63e72023-02-09 15:27:54 +0800973//----------------------------------------------------------------------
974// Get port 80 record (CMD_OEM_GET_80PORT_RECORD)
975//----------------------------------------------------------------------
976ipmi::RspType<std::vector<uint8_t>>
977 ipmiOemGet80PortRecord(ipmi::Context::ptr ctx)
978{
979 auto postCodeService = "xyz.openbmc_project.State.Boot.PostCode" +
980 std::to_string(ctx->hostIdx + 1);
981 auto postCodeObjPath = "/xyz/openbmc_project/State/Boot/PostCode" +
982 std::to_string(ctx->hostIdx + 1);
983 constexpr auto postCodeInterface =
984 "xyz.openbmc_project.State.Boot.PostCode";
985 const static uint16_t lastestPostCodeIndex = 1;
986 constexpr const auto maxPostCodeLen =
987 224; // The length must be lower than IPMB limitation
988 size_t startIndex = 0;
989
990 std::vector<std::tuple<uint64_t, std::vector<uint8_t>>> postCodes;
991 std::vector<uint8_t> resData;
992
993 auto conn = getSdBus();
994 /* Get the post codes by calling GetPostCodes method */
Patrick Williams2405ae92023-05-10 07:50:09 -0500995 auto msg = conn->new_method_call(postCodeService.c_str(),
996 postCodeObjPath.c_str(), postCodeInterface,
997 "GetPostCodes");
Bonnie Lo4ae63e72023-02-09 15:27:54 +0800998 msg.append(lastestPostCodeIndex);
999
1000 try
1001 {
1002 auto reply = conn->call(msg);
1003 reply.read(postCodes);
1004 }
1005 catch (const sdbusplus::exception::SdBusError& e)
1006 {
1007 phosphor::logging::log<phosphor::logging::level::ERR>(
1008 "IPMI Get80PortRecord Failed in call method",
1009 phosphor::logging::entry("ERROR=%s", e.what()));
1010 return ipmi::responseUnspecifiedError();
1011 }
1012
1013 /* Get post code data */
1014 for (size_t i = 0; i < postCodes.size(); ++i)
1015 {
1016 uint64_t primaryPostCode = std::get<uint64_t>(postCodes[i]);
1017 for (int j = postCodeSize - 1; j >= 0; --j)
1018 {
1019 uint8_t postCode =
1020 ((primaryPostCode >> (sizeof(uint64_t) * j)) & 0xFF);
1021 resData.emplace_back(postCode);
1022 }
1023 }
1024
1025 std::vector<uint8_t> response;
1026 if (resData.size() > maxPostCodeLen)
1027 {
1028 startIndex = resData.size() - maxPostCodeLen;
1029 }
1030
1031 response.assign(resData.begin() + startIndex, resData.end());
1032
1033 return ipmi::responseSuccess(response);
1034}
1035
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001036//----------------------------------------------------------------------
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001037// Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
1038//----------------------------------------------------------------------
Jayashree-Df0cf6652020-11-30 11:03:30 +05301039ipmi::RspType<std::vector<uint8_t>>
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001040 ipmiOemSetBootOrder(ipmi::Context::ptr ctx, std::vector<uint8_t> bootSeq)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001041{
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001042 size_t len = bootSeq.size();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001043
1044 if (len != SIZE_BOOT_ORDER)
1045 {
1046 phosphor::logging::log<phosphor::logging::level::ERR>(
1047 "Invalid Boot order length received");
Jayashree-Df0cf6652020-11-30 11:03:30 +05301048 return ipmi::responseReqDataLenInvalid();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001049 }
1050
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +05301051 std::optional<size_t> hostId = findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001052
Jayashree-Df0cf6652020-11-30 11:03:30 +05301053 if (!hostId)
1054 {
1055 phosphor::logging::log<phosphor::logging::level::ERR>(
1056 "Invalid Host Id received");
1057 return ipmi::responseInvalidCommand();
1058 }
1059 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
1060
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001061 ipmi::boot::setBootOrder(bootObjPath, bootSeq, hostName);
Jayashree-Df0cf6652020-11-30 11:03:30 +05301062
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001063 return ipmi::responseSuccess(bootSeq);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001064}
1065
1066//----------------------------------------------------------------------
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001067// Get Boot Order (CMD_OEM_GET_BOOT_ORDER)
1068//----------------------------------------------------------------------
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001069ipmi::RspType<std::vector<uint8_t>> ipmiOemGetBootOrder(ipmi::Context::ptr ctx)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001070{
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001071 std::vector<uint8_t> bootSeq;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001072
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +05301073 std::optional<size_t> hostId = findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001074
Jayashree-Df0cf6652020-11-30 11:03:30 +05301075 if (!hostId)
1076 {
1077 phosphor::logging::log<phosphor::logging::level::ERR>(
1078 "Invalid Host Id received");
1079 return ipmi::responseInvalidCommand();
1080 }
1081 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
1082
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001083 ipmi::boot::getBootOrder(bootObjPath, bootSeq, hostName);
Jayashree-Df0cf6652020-11-30 11:03:30 +05301084
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001085 return ipmi::responseSuccess(bootSeq);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001086}
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001087// Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO)
1088//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001089ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t, ipmi_cmd_t,
1090 ipmi_request_t request, ipmi_response_t,
1091 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001092{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001093 machineConfigInfo_t* req = reinterpret_cast<machineConfigInfo_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001094 uint8_t len = *data_len;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001095
1096 *data_len = 0;
1097
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001098 if (len < sizeof(machineConfigInfo_t))
1099 {
1100 phosphor::logging::log<phosphor::logging::level::ERR>(
1101 "Invalid machine configuration length received");
1102 return IPMI_CC_REQ_DATA_LEN_INVALID;
1103 }
1104
Vijay Khemka63c99be2020-05-27 19:14:35 -07001105 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001106 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN";
1107 else
1108 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] =
1109 chassisType[req->chassis_type];
1110
Vijay Khemka63c99be2020-05-27 19:14:35 -07001111 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001112 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN";
1113 else
1114 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type];
1115
1116 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt;
1117 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt;
1118 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt;
1119 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt;
1120
Vijay Khemka63c99be2020-05-27 19:14:35 -07001121 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001122 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN";
1123 else
1124 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type];
1125
1126 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {};
1127 int i = 0;
1128 if (req->pcie_card_loc & BIT_0)
1129 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1";
1130 if (req->pcie_card_loc & BIT_1)
1131 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2";
1132 if (req->pcie_card_loc & BIT_2)
1133 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3";
1134 if (req->pcie_card_loc & BIT_3)
1135 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4";
1136
Vijay Khemka63c99be2020-05-27 19:14:35 -07001137 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001138 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN";
1139 else
1140 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] =
1141 pcieType[req->slot1_pcie_type];
1142
Vijay Khemka63c99be2020-05-27 19:14:35 -07001143 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001144 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN";
1145 else
1146 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] =
1147 pcieType[req->slot2_pcie_type];
1148
Vijay Khemka63c99be2020-05-27 19:14:35 -07001149 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001150 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN";
1151 else
1152 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] =
1153 pcieType[req->slot3_pcie_type];
1154
Vijay Khemka63c99be2020-05-27 19:14:35 -07001155 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001156 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN";
1157 else
1158 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] =
1159 pcieType[req->slot4_pcie_type];
1160
1161 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt;
1162
1163 flushOemData();
1164
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001165 return IPMI_CC_OK;
1166}
1167
1168//----------------------------------------------------------------------
1169// Set POST start (CMD_OEM_SET_POST_START)
1170//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001171ipmi_ret_t ipmiOemSetPostStart(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1172 ipmi_response_t, ipmi_data_len_t data_len,
1173 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001174{
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001175 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event");
1176
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001177 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001178 *data_len = 0;
1179 return IPMI_CC_OK;
1180}
1181
1182//----------------------------------------------------------------------
1183// Set POST End (CMD_OEM_SET_POST_END)
1184//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001185ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1186 ipmi_response_t, ipmi_data_len_t data_len,
1187 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001188{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001189 struct timespec ts;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001190
1191 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event");
1192
1193 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001194
1195 // Timestamp post end time.
1196 clock_gettime(CLOCK_REALTIME, &ts);
1197 oemData[KEY_TS_SLED] = ts.tv_sec;
1198 flushOemData();
1199
1200 // Sync time with system
1201 // TODO: Add code for syncing time
1202
1203 return IPMI_CC_OK;
1204}
1205
1206//----------------------------------------------------------------------
1207// Set PPIN Info (CMD_OEM_SET_PPIN_INFO)
1208//----------------------------------------------------------------------
1209// Inform BMC about PPIN data of 8 bytes for each CPU
1210//
1211// Request:
1212// Byte 1:8 – CPU0 PPIN data
1213// Optional:
1214// Byte 9:16 – CPU1 PPIN data
1215//
1216// Response:
1217// Byte 1 – Completion Code
Willy Tue39f9392022-06-15 13:24:20 -07001218ipmi_ret_t ipmiOemSetPPINInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
1219 ipmi_response_t, ipmi_data_len_t data_len,
1220 ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001221{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001222 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001223 std::string ppinStr;
1224 int len;
1225
1226 if (*data_len > SIZE_CPU_PPIN * 2)
1227 len = SIZE_CPU_PPIN * 2;
1228 else
1229 len = *data_len;
1230 *data_len = 0;
1231
1232 ppinStr = bytesToStr(req, len);
1233 oemData[KEY_PPIN_INFO] = ppinStr.c_str();
1234 flushOemData();
1235
1236 return IPMI_CC_OK;
1237}
1238
1239//----------------------------------------------------------------------
1240// Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER)
1241//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001242ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1243 ipmi_response_t, ipmi_data_len_t data_len,
1244 ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001245{
1246 /* Do nothing, return success */
1247 *data_len = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001248 return IPMI_CC_OK;
1249}
1250
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001251// Helper function to set guid at offset in EEPROM
Willy Tue39f9392022-06-15 13:24:20 -07001252[[maybe_unused]] static int setGUID(off_t offset, uint8_t* guid)
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001253{
1254 int fd = -1;
1255 ssize_t len;
1256 int ret = 0;
cchouxb2ae88b2023-09-13 00:35:36 +08001257 std::string eepromPath = FRU_EEPROM;
1258
1259 // find the eeprom path of MB FRU
1260 auto device = getMbFruDevice();
1261 if (device)
1262 {
1263 auto [bus, address] = *device;
1264 std::stringstream ss;
1265 ss << "/sys/bus/i2c/devices/" << static_cast<int>(bus) << "-"
1266 << std::setw(4) << std::setfill('0') << std::hex
1267 << static_cast<int>(address) << "/eeprom";
1268 eepromPath = ss.str();
1269 }
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001270
1271 errno = 0;
1272
1273 // Check if file is present
cchouxb2ae88b2023-09-13 00:35:36 +08001274 if (access(eepromPath.c_str(), F_OK) == -1)
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001275 {
cchouxb2ae88b2023-09-13 00:35:36 +08001276 std::cerr << "Unable to access: " << eepromPath << std::endl;
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001277 return errno;
1278 }
1279
1280 // Open the file
cchouxb2ae88b2023-09-13 00:35:36 +08001281 fd = open(eepromPath.c_str(), O_WRONLY);
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001282 if (fd == -1)
1283 {
cchouxb2ae88b2023-09-13 00:35:36 +08001284 std::cerr << "Unable to open: " << eepromPath << std::endl;
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001285 return errno;
1286 }
1287
1288 // seek to the offset
1289 lseek(fd, offset, SEEK_SET);
1290
1291 // Write bytes to location
1292 len = write(fd, guid, GUID_SIZE);
1293 if (len != GUID_SIZE)
1294 {
1295 phosphor::logging::log<phosphor::logging::level::ERR>(
1296 "GUID write data to EEPROM failed");
1297 ret = errno;
1298 }
1299
1300 close(fd);
1301 return ret;
1302}
1303
1304//----------------------------------------------------------------------
1305// Set System GUID (CMD_OEM_SET_SYSTEM_GUID)
1306//----------------------------------------------------------------------
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301307#if BIC_ENABLED
Bonnie Lo3f671272022-10-12 15:46:45 +08001308ipmi::RspType<> ipmiOemSetSystemGuid(ipmi::Context::ptr ctx,
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301309 std::vector<uint8_t> reqData)
1310{
1311 std::vector<uint8_t> respData;
1312
1313 if (reqData.size() != GUID_SIZE) // 16bytes
1314 {
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301315 return ipmi::responseReqDataLenInvalid();
1316 }
1317
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301318 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
1319
1320 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
1321 return ipmi::responseUnspecifiedError();
1322
1323 return ipmi::responseSuccess();
1324}
1325
1326#else
Potin Laid5353ca2022-08-11 04:52:11 +00001327ipmi_ret_t ipmiOemSetSystemGuid(ipmi_netfn_t, ipmi_cmd_t,
1328 ipmi_request_t request, ipmi_response_t,
1329 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001330{
1331 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1332
1333 if (*data_len != GUID_SIZE) // 16bytes
1334 {
1335 *data_len = 0;
1336 return IPMI_CC_REQ_DATA_LEN_INVALID;
1337 }
1338
1339 *data_len = 0;
1340
1341 if (setGUID(OFFSET_SYS_GUID, req))
1342 {
1343 return IPMI_CC_UNSPECIFIED_ERROR;
1344 }
1345 return IPMI_CC_OK;
1346}
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301347#endif
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001348
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001349//----------------------------------------------------------------------
1350// Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO)
1351//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001352ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1353 ipmi_response_t, ipmi_data_len_t data_len,
1354 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001355{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001356 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001357 *data_len = 0;
1358 return IPMI_CC_OK;
1359}
1360
1361//----------------------------------------------------------------------
1362// Set PPR (CMD_OEM_SET_PPR)
1363//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001364ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
1365 ipmi_response_t, ipmi_data_len_t data_len,
1366 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001367{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001368 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001369 uint8_t pprCnt, pprAct, pprIndex;
1370 uint8_t selParam = req[0];
1371 uint8_t len = *data_len;
1372 std::stringstream ss;
1373 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001374
1375 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001376
1377 switch (selParam)
1378 {
1379 case PPR_ACTION:
1380 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) ==
1381 oemData[KEY_PPR].end())
1382 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1383
1384 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1385 if (pprCnt == 0)
1386 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1387
1388 pprAct = req[1];
1389 /* Check if ppr is enabled or disabled */
1390 if (!(pprAct & 0x80))
1391 pprAct = 0;
1392
1393 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct;
1394 break;
1395 case PPR_ROW_COUNT:
1396 if (req[1] > 100)
1397 return IPMI_CC_PARM_OUT_OF_RANGE;
1398
1399 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1];
1400 break;
1401 case PPR_ROW_ADDR:
1402 pprIndex = req[1];
1403 if (pprIndex > 100)
1404 return IPMI_CC_PARM_OUT_OF_RANGE;
1405
1406 if (len < PPR_ROW_ADDR_LEN + 1)
1407 {
1408 phosphor::logging::log<phosphor::logging::level::ERR>(
1409 "Invalid PPR Row Address length received");
1410 return IPMI_CC_REQ_DATA_LEN_INVALID;
1411 }
1412
1413 ss << std::hex;
1414 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1415
1416 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1417
1418 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN);
1419 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str();
1420 break;
1421 case PPR_HISTORY_DATA:
1422 pprIndex = req[1];
1423 if (pprIndex > 100)
1424 return IPMI_CC_PARM_OUT_OF_RANGE;
1425
1426 if (len < PPR_HST_DATA_LEN + 1)
1427 {
1428 phosphor::logging::log<phosphor::logging::level::ERR>(
1429 "Invalid PPR history data length received");
1430 return IPMI_CC_REQ_DATA_LEN_INVALID;
1431 }
1432
1433 ss << std::hex;
1434 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1435
1436 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1437
1438 str = bytesToStr(&req[1], PPR_HST_DATA_LEN);
1439 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str();
1440 break;
1441 default:
1442 return IPMI_CC_PARM_OUT_OF_RANGE;
1443 break;
1444 }
1445
1446 flushOemData();
1447
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001448 return IPMI_CC_OK;
1449}
1450
1451//----------------------------------------------------------------------
1452// Get PPR (CMD_OEM_GET_PPR)
1453//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001454ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
1455 ipmi_response_t response, ipmi_data_len_t data_len,
1456 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001457{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001458 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1459 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001460 uint8_t pprCnt, pprIndex;
1461 uint8_t selParam = req[0];
1462 std::stringstream ss;
1463 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001464
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001465 /* Any failure will return zero length data */
1466 *data_len = 0;
1467
1468 switch (selParam)
1469 {
1470 case PPR_ACTION:
1471 res[0] = 0;
1472 *data_len = 1;
1473
1474 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1475 oemData[KEY_PPR].end())
1476 {
1477 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1478 if (pprCnt != 0)
1479 {
1480 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) !=
1481 oemData[KEY_PPR].end())
1482 {
1483 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION];
1484 }
1485 }
1486 }
1487 break;
1488 case PPR_ROW_COUNT:
1489 res[0] = 0;
1490 *data_len = 1;
1491 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1492 oemData[KEY_PPR].end())
1493 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1494 break;
1495 case PPR_ROW_ADDR:
1496 pprIndex = req[1];
1497 if (pprIndex > 100)
1498 return IPMI_CC_PARM_OUT_OF_RANGE;
1499
1500 ss << std::hex;
1501 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1502
1503 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1504 return IPMI_CC_PARM_OUT_OF_RANGE;
1505
1506 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) ==
1507 oemData[KEY_PPR][ss.str()].end())
1508 return IPMI_CC_PARM_OUT_OF_RANGE;
1509
1510 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR];
1511 *data_len = strToBytes(str, res);
1512 break;
1513 case PPR_HISTORY_DATA:
1514 pprIndex = req[1];
1515 if (pprIndex > 100)
1516 return IPMI_CC_PARM_OUT_OF_RANGE;
1517
1518 ss << std::hex;
1519 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1520
1521 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1522 return IPMI_CC_PARM_OUT_OF_RANGE;
1523
1524 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) ==
1525 oemData[KEY_PPR][ss.str()].end())
1526 return IPMI_CC_PARM_OUT_OF_RANGE;
1527
1528 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA];
1529 *data_len = strToBytes(str, res);
1530 break;
1531 default:
1532 return IPMI_CC_PARM_OUT_OF_RANGE;
1533 break;
1534 }
1535
1536 return IPMI_CC_OK;
1537}
1538
1539/* FB OEM QC Commands */
1540
1541//----------------------------------------------------------------------
1542// Set Proc Info (CMD_OEM_Q_SET_PROC_INFO)
1543//----------------------------------------------------------------------
1544//"Request:
1545// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1546// Byte 4 – Processor Index, 0 base
1547// Byte 5 – Parameter Selector
1548// Byte 6..N – Configuration parameter data (see below for Parameters
1549// of Processor Information)
1550// Response:
1551// Byte 1 – Completion code
1552//
1553// Parameter#1: (Processor Product Name)
1554//
1555// Byte 1..48 –Product name(ASCII code)
1556// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1557//
1558// Param#2: Processor Basic Information
1559// Byte 1 – Core Number
1560// Byte 2 – Thread Number (LSB)
1561// Byte 3 – Thread Number (MSB)
1562// Byte 4 – Processor frequency in MHz (LSB)
1563// Byte 5 – Processor frequency in MHz (MSB)
1564// Byte 6..7 – Revision
1565//
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301566
1567ipmi::RspType<> ipmiOemQSetProcInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t,
1568 uint8_t, uint8_t procIndex,
1569 uint8_t paramSel,
1570 std::vector<uint8_t> request)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001571{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001572 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001573 std::stringstream ss;
1574 std::string str;
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301575 uint8_t len = request.size();
1576 auto hostId = findHost(ctx->hostIdx);
1577 if (!hostId)
1578 {
1579 phosphor::logging::log<phosphor::logging::level::ERR>(
1580 "Invalid Host Id received");
1581 return ipmi::responseInvalidCommand();
1582 }
1583 std::string procInfo = KEY_Q_PROC_INFO + std::to_string(*hostId);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001584 /* check for requested data params */
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301585 if (len < 5 || paramSel < 1 || paramSel >= numParam)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001586 {
1587 phosphor::logging::log<phosphor::logging::level::ERR>(
1588 "Invalid parameter received");
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301589 return ipmi::responseParmOutOfRange();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001590 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001591 ss << std::hex;
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301592 ss << std::setw(2) << std::setfill('0') << (int)procIndex;
1593 oemData[procInfo][ss.str()][KEY_PROC_INDEX] = procIndex;
1594 str = bytesToStr(request.data(), len);
1595 oemData[procInfo][ss.str()][cpuInfoKey[paramSel]] = str.c_str();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001596 flushOemData();
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301597 return ipmi::responseSuccess();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001598}
1599
1600//----------------------------------------------------------------------
1601// Get Proc Info (CMD_OEM_Q_GET_PROC_INFO)
1602//----------------------------------------------------------------------
1603// Request:
1604// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1605// Byte 4 – Processor Index, 0 base
1606// Byte 5 – Parameter Selector
1607// Response:
1608// Byte 1 – Completion code
1609// Byte 2..N – Configuration Parameter Data (see below for Parameters
1610// of Processor Information)
1611//
1612// Parameter#1: (Processor Product Name)
1613//
1614// Byte 1..48 –Product name(ASCII code)
1615// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1616//
1617// Param#2: Processor Basic Information
1618// Byte 1 – Core Number
1619// Byte 2 – Thread Number (LSB)
1620// Byte 3 – Thread Number (MSB)
1621// Byte 4 – Processor frequency in MHz (LSB)
1622// Byte 5 – Processor frequency in MHz (MSB)
1623// Byte 6..7 – Revision
1624//
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301625
1626ipmi::RspType<std::vector<uint8_t>>
1627 ipmiOemQGetProcInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t, uint8_t,
1628 uint8_t procIndex, uint8_t paramSel)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001629{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001630 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001631 std::stringstream ss;
1632 std::string str;
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301633 uint8_t res[MAX_BUF];
1634 auto hostId = findHost(ctx->hostIdx);
1635 if (!hostId)
1636 {
1637 phosphor::logging::log<phosphor::logging::level::ERR>(
1638 "Invalid Host Id received");
1639 return ipmi::responseInvalidCommand();
1640 }
1641 std::string procInfo = KEY_Q_PROC_INFO + std::to_string(*hostId);
1642 if (paramSel < 1 || paramSel >= numParam)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001643 {
1644 phosphor::logging::log<phosphor::logging::level::ERR>(
1645 "Invalid parameter received");
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301646 return ipmi::responseParmOutOfRange();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001647 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001648 ss << std::hex;
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301649 ss << std::setw(2) << std::setfill('0') << (int)procIndex;
1650 if (oemData[procInfo].find(ss.str()) == oemData[procInfo].end())
1651 return ipmi::responseCommandNotAvailable();
1652 if (oemData[procInfo][ss.str()].find(cpuInfoKey[paramSel]) ==
1653 oemData[procInfo][ss.str()].end())
1654 return ipmi::responseCommandNotAvailable();
1655 str = oemData[procInfo][ss.str()][cpuInfoKey[paramSel]];
1656 int dataLen = strToBytes(str, res);
1657 std::vector<uint8_t> response(&res[0], &res[dataLen]);
1658 return ipmi::responseSuccess(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001659}
1660
1661//----------------------------------------------------------------------
1662// Set Dimm Info (CMD_OEM_Q_SET_DIMM_INFO)
1663//----------------------------------------------------------------------
1664// Request:
1665// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1666// Byte 4 – DIMM Index, 0 base
1667// Byte 5 – Parameter Selector
1668// Byte 6..N – Configuration parameter data (see below for Parameters
1669// of DIMM Information)
1670// Response:
1671// Byte 1 – Completion code
1672//
1673// Param#1 (DIMM Location):
1674// Byte 1 – DIMM Present
1675// Byte 1 – DIMM Present
1676// 01h – Present
1677// FFh – Not Present
1678// Byte 2 – Node Number, 0 base
1679// Byte 3 – Channel Number , 0 base
1680// Byte 4 – DIMM Number , 0 base
1681//
1682// Param#2 (DIMM Type):
1683// Byte 1 – DIMM Type
1684// Bit [7:6]
1685// For DDR3
1686// 00 – Normal Voltage (1.5V)
1687// 01 – Ultra Low Voltage (1.25V)
1688// 10 – Low Voltage (1.35V)
1689// 11 – Reserved
1690// For DDR4
1691// 00 – Reserved
1692// 01 – Reserved
1693// 10 – Reserved
1694// 11 – Normal Voltage (1.2V)
1695// Bit [5:0]
1696// 0x00 – SDRAM
1697// 0x01 – DDR-1 RAM
1698// 0x02 – Rambus
1699// 0x03 – DDR-2 RAM
1700// 0x04 – FBDIMM
1701// 0x05 – DDR-3 RAM
1702// 0x06 – DDR-4 RAM
1703//
1704// Param#3 (DIMM Speed):
1705// Byte 1..2 – DIMM speed in MHz, LSB
1706// Byte 3..6 – DIMM size in Mbytes, LSB
1707//
1708// Param#4 (Module Part Number):
1709// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1710//
1711// Param#5 (Module Serial Number):
1712// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1713//
1714// Param#6 (Module Manufacturer ID):
1715// Byte 1 - Module Manufacturer ID, LSB
1716// Byte 2 - Module Manufacturer ID, MSB
1717//
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301718ipmi::RspType<> ipmiOemQSetDimmInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t,
1719 uint8_t, uint8_t dimmIndex,
1720 uint8_t paramSel,
1721 std::vector<uint8_t> request)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001722{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001723 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001724 std::stringstream ss;
1725 std::string str;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301726 uint8_t len = request.size();
1727 std::string dimmType;
1728 readDimmType(dimmType, dimmIndex);
Patrick Williams6d9e9a72022-07-18 10:30:50 -05001729 auto hostId = findHost(ctx->hostIdx);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301730 if (!hostId)
1731 {
1732 phosphor::logging::log<phosphor::logging::level::ERR>(
1733 "Invalid Host Id received");
1734 return ipmi::responseInvalidCommand();
1735 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001736
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301737 std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(*hostId);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001738
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301739 if (len < 3 || paramSel < 1 || paramSel >= numParam)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001740 {
1741 phosphor::logging::log<phosphor::logging::level::ERR>(
1742 "Invalid parameter received");
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301743 return ipmi::responseParmOutOfRange();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001744 }
1745
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001746 ss << std::hex;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301747 ss << (int)dimmIndex;
1748 oemData[dimmInfo][ss.str()][KEY_DIMM_INDEX] = dimmIndex;
1749 oemData[dimmInfo][ss.str()][KEY_DIMM_TYPE] = dimmType;
1750 str = bytesToStr(request.data(), len);
1751 oemData[dimmInfo][ss.str()][dimmInfoKey[paramSel]] = str.c_str();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001752 flushOemData();
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301753 return ipmi::responseSuccess();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001754}
1755
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001756// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
1757//----------------------------------------------------------------------
1758// Request:
1759// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1760// Byte 4 – DIMM Index, 0 base
1761// Byte 5 – Parameter Selector
1762// Byte 6..N – Configuration parameter data (see below for Parameters
1763// of DIMM Information)
1764// Response:
1765// Byte 1 – Completion code
1766// Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters
1767// of DIMM Information)
1768//
1769// Param#1 (DIMM Location):
1770// Byte 1 – DIMM Present
1771// Byte 1 – DIMM Present
1772// 01h – Present
1773// FFh – Not Present
1774// Byte 2 – Node Number, 0 base
1775// Byte 3 – Channel Number , 0 base
1776// Byte 4 – DIMM Number , 0 base
1777//
1778// Param#2 (DIMM Type):
1779// Byte 1 – DIMM Type
1780// Bit [7:6]
1781// For DDR3
1782// 00 – Normal Voltage (1.5V)
1783// 01 – Ultra Low Voltage (1.25V)
1784// 10 – Low Voltage (1.35V)
1785// 11 – Reserved
1786// For DDR4
1787// 00 – Reserved
1788// 01 – Reserved
1789// 10 – Reserved
1790// 11 – Normal Voltage (1.2V)
1791// Bit [5:0]
1792// 0x00 – SDRAM
1793// 0x01 – DDR-1 RAM
1794// 0x02 – Rambus
1795// 0x03 – DDR-2 RAM
1796// 0x04 – FBDIMM
1797// 0x05 – DDR-3 RAM
1798// 0x06 – DDR-4 RAM
1799//
1800// Param#3 (DIMM Speed):
1801// Byte 1..2 – DIMM speed in MHz, LSB
1802// Byte 3..6 – DIMM size in Mbytes, LSB
1803//
1804// Param#4 (Module Part Number):
1805// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1806//
1807// Param#5 (Module Serial Number):
1808// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1809//
1810// Param#6 (Module Manufacturer ID):
1811// Byte 1 - Module Manufacturer ID, LSB
1812// Byte 2 - Module Manufacturer ID, MSB
1813//
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301814ipmi::RspType<std::vector<uint8_t>>
1815 ipmiOemQGetDimmInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t, uint8_t,
1816 uint8_t dimmIndex, uint8_t paramSel)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001817{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001818 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301819 uint8_t res[MAX_BUF];
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001820 std::stringstream ss;
1821 std::string str;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301822 std::string dimmType;
1823 readDimmType(dimmType, dimmIndex);
Patrick Williams6d9e9a72022-07-18 10:30:50 -05001824 auto hostId = findHost(ctx->hostIdx);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301825 if (!hostId)
1826 {
1827 phosphor::logging::log<phosphor::logging::level::ERR>(
1828 "Invalid Host Id received");
1829 return ipmi::responseInvalidCommand();
1830 }
1831 std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(*hostId);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001832
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301833 if (paramSel < 1 || paramSel >= numParam)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001834 {
1835 phosphor::logging::log<phosphor::logging::level::ERR>(
1836 "Invalid parameter received");
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301837 return ipmi::responseParmOutOfRange();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001838 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001839 ss << std::hex;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301840 ss << (int)dimmIndex;
1841 oemData[dimmInfo][ss.str()][KEY_DIMM_TYPE] = dimmType;
1842 if (oemData[dimmInfo].find(ss.str()) == oemData[dimmInfo].end())
1843 return ipmi::responseCommandNotAvailable();
1844 if (oemData[dimmInfo][ss.str()].find(dimmInfoKey[paramSel]) ==
1845 oemData[dimmInfo][ss.str()].end())
1846 return ipmi::responseCommandNotAvailable();
1847 str = oemData[dimmInfo][ss.str()][dimmInfoKey[paramSel]];
1848 int data_length = strToBytes(str, res);
1849 std::vector<uint8_t> response(&res[0], &res[data_length]);
1850 return ipmi::responseSuccess(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001851}
1852
1853//----------------------------------------------------------------------
1854// Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO)
1855//----------------------------------------------------------------------
1856// BIOS issue this command to provide HDD information to BMC.
1857//
1858// BIOS just can get information by standard ATA / SMART command for
1859// OB SATA controller.
1860// BIOS can get
1861// 1. Serial Number
1862// 2. Model Name
1863// 3. HDD FW Version
1864// 4. HDD Capacity
1865// 5. HDD WWN
1866//
1867// Use Get HDD info Param #5 to know the MAX HDD info index.
1868//
1869// Request:
1870// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1871// Byte 4 –
1872// [7:4] Reserved
1873// [3:0] HDD Controller Type
1874// 0x00 – BIOS
1875// 0x01 – Expander
1876// 0x02 – LSI
1877// Byte 5 – HDD Info Index, 0 base
1878// Byte 6 – Parameter Selector
1879// Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD
1880// Information)
1881//
1882// Response:
1883// Byte 1 – Completion Code
1884//
1885// Param#0 (HDD Location):
1886// Byte 1 – Controller
1887// [7:3] Device Number
1888// [2:0] Function Number
1889// For Intel C610 series (Wellsburg)
1890// D31:F2 (0xFA) – SATA control 1
1891// D31:F5 (0xFD) – SATA control 2
1892// D17:F4 (0x8C) – sSata control
1893// Byte 2 – Port Number
1894// Byte 3 – Location (0xFF: No HDD Present)
1895// BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param
1896// #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if
1897// the HDD present. BMC or other people who know the HDD location has
1898// responsibility for update Location info
1899//
1900// Param#1 (Serial Number):
1901// Bytes 1..33: HDD Serial Number
1902//
1903// Param#2 (Model Name):
1904// Byte 1..33 – HDD Model Name
1905//
1906// Param#3 (HDD FW Version):
1907// Byte 1..17 –HDD FW version
1908//
1909// Param#4 (Capacity):
1910// Byte 1..4 –HDD Block Size, LSB
1911// Byte 5..12 - HDD Block Number, LSB
1912// HDD Capacity = HDD Block size * HDD BLock number (Unit Byte)
1913//
1914// Param#5 (Max HDD Quantity):
1915// Byte 1 - Max HDD Quantity
1916// Max supported port numbers in this PCH
1917//
1918// Param#6 (HDD Type)
1919// Byte 1 – HDD Type
1920// 0h – Reserved
1921// 1h – SAS
1922// 2h – SATA
1923// 3h – PCIE SSD (NVME)
1924//
1925// Param#7 (HDD WWN)
1926// Data 1...8: HDD World Wide Name, LSB
1927//
Willy Tue39f9392022-06-15 13:24:20 -07001928ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t, ipmi_cmd_t,
1929 ipmi_request_t request, ipmi_response_t,
1930 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001931{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001932 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1933 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001934 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1935 std::stringstream ss;
1936 std::string str;
1937 uint8_t len = *data_len;
1938
1939 *data_len = 0;
1940
1941 /* check for requested data params */
1942 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam ||
1943 ctrlType > 2)
1944 {
1945 phosphor::logging::log<phosphor::logging::level::ERR>(
1946 "Invalid parameter received");
1947 return IPMI_CC_PARM_OUT_OF_RANGE;
1948 }
1949
1950 len = len - 6; // Get Actual data length
1951
1952 ss << std::hex;
1953 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1954 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType;
1955 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] =
1956 req->hddIndex;
1957
1958 str = bytesToStr(req->data, len);
1959 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1960 [driveInfoKey[req->paramSel]] = str.c_str();
1961 flushOemData();
1962
1963 return IPMI_CC_OK;
1964}
1965
1966//----------------------------------------------------------------------
1967// Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO)
1968//----------------------------------------------------------------------
1969// BMC needs to check HDD presented or not first. If NOT presented, return
1970// completion code 0xD5.
1971//
1972// Request:
1973// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1974// Byte 4 –
1975//[7:4] Reserved
1976//[3:0] HDD Controller Type
1977// 0x00 – BIOS
1978// 0x01 – Expander
1979// 0x02 – LSI
1980// Byte 5 – HDD Index, 0 base
1981// Byte 6 – Parameter Selector (See Above Set HDD Information)
1982// Response:
1983// Byte 1 – Completion Code
1984// 0xD5 – Not support in current status (HDD Not Present)
1985// Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD
1986// Information)
1987//
Willy Tue39f9392022-06-15 13:24:20 -07001988ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001989 ipmi_request_t request,
1990 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -07001991 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001992{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001993 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1994 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
1995 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001996 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1997 std::stringstream ss;
1998 std::string str;
1999
2000 *data_len = 0;
2001
2002 /* check for requested data params */
2003 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2)
2004 {
2005 phosphor::logging::log<phosphor::logging::level::ERR>(
2006 "Invalid parameter received");
2007 return IPMI_CC_PARM_OUT_OF_RANGE;
2008 }
2009
2010 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) ==
2011 oemData[KEY_Q_DRIVE_INFO].end())
2012 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
2013
2014 ss << std::hex;
2015 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
2016
2017 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) ==
2018 oemData[KEY_Q_DRIVE_INFO].end())
2019 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
2020
2021 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find(
2022 dimmInfoKey[req->paramSel]) ==
2023 oemData[KEY_Q_DRIVE_INFO][ss.str()].end())
2024 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
2025
2026 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
2027 [dimmInfoKey[req->paramSel]];
2028 *data_len = strToBytes(str, res);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002029
2030 return IPMI_CC_OK;
2031}
2032
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302033/* Helper function for sending DCMI commands to ME/BIC and
2034 * getting response back
2035 */
2036ipmi::RspType<std::vector<uint8_t>>
2037 sendDCMICmd([[maybe_unused]] ipmi::Context::ptr ctx,
2038 [[maybe_unused]] uint8_t cmd, std::vector<uint8_t>& cmdData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002039{
2040 std::vector<uint8_t> respData;
2041
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302042#if BIC_ENABLED
2043
2044 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
2045
2046 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, cmdData, respData))
2047 {
2048 return ipmi::responseUnspecifiedError();
2049 }
2050
2051#else
2052
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002053 /* Add group id as first byte to request for ME command */
2054 cmdData.insert(cmdData.begin(), groupDCMI);
2055
2056 if (sendMeCmd(ipmi::netFnGroup, cmd, cmdData, respData))
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302057 {
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002058 return ipmi::responseUnspecifiedError();
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302059 }
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002060
2061 /* Remove group id as first byte as it will be added by IPMID */
2062 respData.erase(respData.begin());
2063
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302064#endif
2065
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002066 return ipmi::responseSuccess(std::move(respData));
2067}
2068
2069/* DCMI Command handellers. */
2070
2071ipmi::RspType<std::vector<uint8_t>>
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302072 ipmiOemDCMIGetPowerReading(ipmi::Context::ptr ctx,
2073 std::vector<uint8_t> reqData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002074{
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302075 return sendDCMICmd(ctx, ipmi::dcmi::cmdGetPowerReading, reqData);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002076}
2077
2078ipmi::RspType<std::vector<uint8_t>>
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302079 ipmiOemDCMIGetPowerLimit(ipmi::Context::ptr ctx,
2080 std::vector<uint8_t> reqData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002081{
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302082 return sendDCMICmd(ctx, ipmi::dcmi::cmdGetPowerLimit, reqData);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002083}
2084
2085ipmi::RspType<std::vector<uint8_t>>
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302086 ipmiOemDCMISetPowerLimit(ipmi::Context::ptr ctx,
2087 std::vector<uint8_t> reqData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002088{
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302089 return sendDCMICmd(ctx, ipmi::dcmi::cmdSetPowerLimit, reqData);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002090}
2091
2092ipmi::RspType<std::vector<uint8_t>>
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302093 ipmiOemDCMIApplyPowerLimit(ipmi::Context::ptr ctx,
2094 std::vector<uint8_t> reqData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002095{
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302096 return sendDCMICmd(ctx, ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002097}
2098
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002099static void registerOEMFunctions(void)
2100{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002101 /* Get OEM data from json file */
2102 std::ifstream file(JSON_OEM_DATA_FILE);
2103 if (file)
Vijay Khemkafeaa9812019-08-27 15:08:08 -07002104 {
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002105 file >> oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -07002106 file.close();
2107 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002108
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002109 phosphor::logging::log<phosphor::logging::level::INFO>(
2110 "Registering OEM commands");
Vijay Khemka7c0aea42020-03-05 13:31:53 -08002111
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002112 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO,
2113 NULL, ipmiOemDbgGetFrameInfo,
2114 PRIVILEGE_USER); // get debug frame info
2115 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ,
2116 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL,
2117 ipmiOemDbgGetUpdFrames,
2118 PRIVILEGE_USER); // get debug updated frames
2119 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC,
2120 NULL, ipmiOemDbgGetPostDesc,
2121 PRIVILEGE_USER); // get debug post description
2122 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC,
2123 NULL, ipmiOemDbgGetGpioDesc,
2124 PRIVILEGE_USER); // get debug gpio description
2125 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA,
2126 NULL, ipmiOemDbgGetFrameData,
2127 PRIVILEGE_USER); // get debug frame data
2128 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL,
2129 NULL, ipmiOemDbgGetCtrlPanel,
2130 PRIVILEGE_USER); // get debug control panel
2131 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL,
2132 ipmiOemSetDimmInfo,
2133 PRIVILEGE_USER); // Set Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002134 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL,
2135 ipmiOemGetBoardID,
2136 PRIVILEGE_USER); // Get Board ID
Bonnie Lo4ae63e72023-02-09 15:27:54 +08002137 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnOemOne,
2138 CMD_OEM_GET_80PORT_RECORD, ipmi::Privilege::User,
2139 ipmiOemGet80PortRecord); // Get 80 Port Record
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002140 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL,
2141 ipmiOemSetMachineCfgInfo,
2142 PRIVILEGE_USER); // Set Machine Config Info
2143 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL,
2144 ipmiOemSetPostStart,
2145 PRIVILEGE_USER); // Set POST start
2146 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL,
2147 ipmiOemSetPostEnd,
2148 PRIVILEGE_USER); // Set POST End
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002149 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL,
2150 ipmiOemSetPPINInfo,
2151 PRIVILEGE_USER); // Set PPIN Info
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05302152#if BIC_ENABLED
2153
2154 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
2155 ipmi::cmdSetSystemGuid, ipmi::Privilege::User,
2156 ipmiOemSetSystemGuid);
2157#else
2158
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07002159 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_SYSTEM_GUID, NULL,
2160 ipmiOemSetSystemGuid,
2161 PRIVILEGE_USER); // Set System GUID
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05302162#endif
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002163 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL,
2164 ipmiOemSetAdrTrigger,
2165 PRIVILEGE_USER); // Set ADR Trigger
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002166 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL,
2167 ipmiOemSetBiosFlashInfo,
2168 PRIVILEGE_USER); // Set Bios Flash Info
2169 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr,
2170 PRIVILEGE_USER); // Set PPR
2171 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
2172 PRIVILEGE_USER); // Get PPR
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002173 /* FB OEM QC Commands */
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05302174 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
2175 CMD_OEM_Q_SET_PROC_INFO, ipmi::Privilege::User,
2176 ipmiOemQSetProcInfo); // Set Proc Info
2177 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
2178 CMD_OEM_Q_GET_PROC_INFO, ipmi::Privilege::User,
2179 ipmiOemQGetProcInfo); // Get Proc Info
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05302180 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
2181 ipmi::cmdSetQDimmInfo, ipmi::Privilege::User,
2182 ipmiOemQSetDimmInfo); // Set Dimm Info
2183 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
2184 ipmi::cmdGetQDimmInfo, ipmi::Privilege::User,
2185 ipmiOemQGetDimmInfo); // Get Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002186 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
2187 ipmiOemQSetDriveInfo,
2188 PRIVILEGE_USER); // Set Drive Info
2189 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL,
2190 ipmiOemQGetDriveInfo,
2191 PRIVILEGE_USER); // Get Drive Info
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002192
2193 /* FB OEM DCMI Commands as per DCMI spec 1.5 Section 6 */
2194 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2195 ipmi::dcmi::cmdGetPowerReading,
2196 ipmi::Privilege::User,
2197 ipmiOemDCMIGetPowerReading); // Get Power Reading
2198
2199 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2200 ipmi::dcmi::cmdGetPowerLimit,
2201 ipmi::Privilege::User,
2202 ipmiOemDCMIGetPowerLimit); // Get Power Limit
2203
2204 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2205 ipmi::dcmi::cmdSetPowerLimit,
2206 ipmi::Privilege::Operator,
2207 ipmiOemDCMISetPowerLimit); // Set Power Limit
2208
2209 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2210 ipmi::dcmi::cmdActDeactivatePwrLimit,
2211 ipmi::Privilege::Operator,
2212 ipmiOemDCMIApplyPowerLimit); // Apply Power Limit
2213
Jayashree-Df0cf6652020-11-30 11:03:30 +05302214 /* FB OEM BOOT ORDER COMMANDS */
2215 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
2216 CMD_OEM_GET_BOOT_ORDER, ipmi::Privilege::User,
2217 ipmiOemGetBootOrder); // Get Boot Order
2218
2219 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
2220 CMD_OEM_SET_BOOT_ORDER, ipmi::Privilege::User,
2221 ipmiOemSetBootOrder); // Set Boot Order
2222
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002223 return;
2224}
2225
2226} // namespace ipmi