blob: 7482e1cb6a5415e6cf16a5b6715dfd5f3101a4e8 [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
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +053050size_t getSelectorPosition();
Vijay Khemkae7d23d02019-03-08 13:13:40 -080051static void registerOEMFunctions() __attribute__((constructor));
52sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
53static constexpr size_t maxFRUStringLength = 0x3F;
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053054constexpr uint8_t cmdSetSystemGuid = 0xEF;
Vijay Khemkae7d23d02019-03-08 13:13:40 -080055
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +053056constexpr uint8_t cmdSetQDimmInfo = 0x12;
57constexpr uint8_t cmdGetQDimmInfo = 0x13;
58
Vijay Khemka63c99be2020-05-27 19:14:35 -070059int plat_udbg_get_post_desc(uint8_t, uint8_t*, uint8_t, uint8_t*, uint8_t*,
60 uint8_t*);
61int plat_udbg_get_gpio_desc(uint8_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*,
62 uint8_t*);
63ipmi_ret_t plat_udbg_get_frame_data(uint8_t, uint8_t, uint8_t*, uint8_t*,
64 uint8_t*);
65ipmi_ret_t plat_udbg_control_panel(uint8_t, uint8_t, uint8_t, uint8_t*,
66 uint8_t*);
67int sendMeCmd(uint8_t, uint8_t, std::vector<uint8_t>&, std::vector<uint8_t>&);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -070068
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053069int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
70 std::vector<uint8_t>&);
71
Vijay Khemkafeaa9812019-08-27 15:08:08 -070072nlohmann::json oemData __attribute__((init_priority(101)));
Vijay Khemka1b6fae32019-03-25 17:43:01 -070073
Vijay Khemkaf2246ce2020-05-27 14:26:35 -070074static constexpr size_t GUID_SIZE = 16;
75// TODO Make offset and location runtime configurable to ensure we
76// can make each define their own locations.
77static constexpr off_t OFFSET_SYS_GUID = 0x17F0;
78static constexpr const char* FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom";
79
Vijay Khemka1b6fae32019-03-25 17:43:01 -070080enum class LanParam : uint8_t
81{
82 INPROGRESS = 0,
83 AUTHSUPPORT = 1,
84 AUTHENABLES = 2,
85 IP = 3,
86 IPSRC = 4,
87 MAC = 5,
88 SUBNET = 6,
89 GATEWAY = 12,
90 VLAN = 20,
91 CIPHER_SUITE_COUNT = 22,
92 CIPHER_SUITE_ENTRIES = 23,
93 IPV6 = 59,
94};
95
Vijay Khemkaa7231892019-10-11 11:35:05 -070096namespace network
97{
98
99constexpr auto ROOT = "/xyz/openbmc_project/network";
100constexpr auto SERVICE = "xyz.openbmc_project.Network";
101constexpr auto IPV4_TYPE = "ipv4";
102constexpr auto IPV6_TYPE = "ipv6";
103constexpr auto IPV4_PREFIX = "169.254";
104constexpr auto IPV6_PREFIX = "fe80";
105constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
106constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
107
Vijay Khemka63c99be2020-05-27 19:14:35 -0700108bool isLinkLocalIP(const std::string& address)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700109{
110 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0;
111}
112
Vijay Khemka63c99be2020-05-27 19:14:35 -0700113DbusObjectInfo getIPObject(sdbusplus::bus::bus& bus,
114 const std::string& interface,
115 const std::string& serviceRoot,
116 const std::string& match)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700117{
118 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
119
120 if (objectTree.empty())
121 {
122 log<level::ERR>("No Object has implemented the IP interface",
123 entry("INTERFACE=%s", interface.c_str()));
124 }
125
126 DbusObjectInfo objectInfo;
127
Vijay Khemka63c99be2020-05-27 19:14:35 -0700128 for (auto& object : objectTree)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700129 {
130 auto variant =
131 ipmi::getDbusProperty(bus, object.second.begin()->first,
132 object.first, IP_INTERFACE, "Address");
133
134 objectInfo = std::make_pair(object.first, object.second.begin()->first);
135
136 // if LinkLocalIP found look for Non-LinkLocalIP
137 if (isLinkLocalIP(std::get<std::string>(variant)))
138 {
139 continue;
140 }
141 else
142 {
143 break;
144 }
145 }
146 return objectInfo;
147}
148
149} // namespace network
150
Jayashree-Df0cf6652020-11-30 11:03:30 +0530151namespace boot
152{
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530153using BootSource =
154 sdbusplus::xyz::openbmc_project::Control::Boot::server::Source::Sources;
155using BootMode =
156 sdbusplus::xyz::openbmc_project::Control::Boot::server::Mode::Modes;
157using BootType =
158 sdbusplus::xyz::openbmc_project::Control::Boot::server::Type::Types;
Jayashree-Df0cf6652020-11-30 11:03:30 +0530159
Jayashree-Df0cf6652020-11-30 11:03:30 +0530160using IpmiValue = uint8_t;
161
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530162std::map<IpmiValue, BootSource> sourceIpmiToDbus = {
163 {0x0f, BootSource::Default}, {0x00, BootSource::RemovableMedia},
164 {0x01, BootSource::Network}, {0x02, BootSource::Disk},
165 {0x03, BootSource::ExternalMedia}, {0x09, BootSource::Network}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530166
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530167std::map<IpmiValue, BootMode> modeIpmiToDbus = {{0x06, BootMode::Setup},
168 {0x00, BootMode::Regular}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530169
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530170std::map<IpmiValue, BootType> typeIpmiToDbus = {{0x00, BootType::Legacy},
171 {0x01, BootType::EFI}};
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530172
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530173std::map<std::optional<BootSource>, IpmiValue> sourceDbusToIpmi = {
174 {BootSource::Default, 0x0f},
175 {BootSource::RemovableMedia, 0x00},
176 {BootSource::Network, 0x01},
177 {BootSource::Disk, 0x02},
178 {BootSource::ExternalMedia, 0x03}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530179
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530180std::map<std::optional<BootMode>, IpmiValue> modeDbusToIpmi = {
181 {BootMode::Setup, 0x06}, {BootMode::Regular, 0x00}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530182
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530183std::map<std::optional<BootType>, IpmiValue> typeDbusToIpmi = {
184 {BootType::Legacy, 0x00}, {BootType::EFI, 0x01}};
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530185
Jayashree-Df0cf6652020-11-30 11:03:30 +0530186static constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
187static constexpr auto bootSourceIntf =
188 "xyz.openbmc_project.Control.Boot.Source";
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530189static constexpr auto bootTypeIntf = "xyz.openbmc_project.Control.Boot.Type";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530190static constexpr auto bootSourceProp = "BootSource";
191static constexpr auto bootModeProp = "BootMode";
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530192static constexpr auto bootTypeProp = "BootType";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530193
Jayashree-Df0cf6652020-11-30 11:03:30 +0530194std::tuple<std::string, std::string> objPath(size_t id)
195{
196 std::string hostName = "host" + std::to_string(id);
197 std::string bootObjPath =
198 "/xyz/openbmc_project/control/" + hostName + "/boot";
199 return std::make_tuple(std::move(bootObjPath), std::move(hostName));
200}
201
202} // namespace boot
203
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700204//----------------------------------------------------------------------
205// Helper functions for storing oem data
206//----------------------------------------------------------------------
207
208void flushOemData()
209{
210 std::ofstream file(JSON_OEM_DATA_FILE);
211 file << oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -0700212 file.close();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700213 return;
214}
215
Vijay Khemka63c99be2020-05-27 19:14:35 -0700216std::string bytesToStr(uint8_t* byte, int len)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700217{
218 std::stringstream ss;
219 int i;
220
221 ss << std::hex;
222 for (i = 0; i < len; i++)
223 {
224 ss << std::setw(2) << std::setfill('0') << (int)byte[i];
225 }
226
227 return ss.str();
228}
229
Vijay Khemka63c99be2020-05-27 19:14:35 -0700230int strToBytes(std::string& str, uint8_t* data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700231{
232 std::string sstr;
Willy Tue39f9392022-06-15 13:24:20 -0700233 size_t i;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700234
235 for (i = 0; i < (str.length()) / 2; i++)
236 {
237 sstr = str.substr(i * 2, 2);
238 data[i] = (uint8_t)std::strtol(sstr.c_str(), NULL, 16);
239 }
240 return i;
241}
242
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530243int readDimmType(std::string& data, uint8_t param)
244{
245 nlohmann::json dimmObj;
246 /* Get dimm type names stored in json file */
247 std::ifstream file(JSON_DIMM_TYPE_FILE);
248 if (file)
249 {
250 file >> dimmObj;
251 file.close();
252 }
253 else
254 {
255 phosphor::logging::log<phosphor::logging::level::ERR>(
256 "DIMM type names file not found",
257 phosphor::logging::entry("DIMM_TYPE_FILE=%s", JSON_DIMM_TYPE_FILE));
258 return -1;
259 }
260
261 std::string dimmKey = "dimm_type" + std::to_string(param);
262 auto obj = dimmObj[dimmKey]["short_name"];
263 data = obj;
264 return 0;
265}
266
Vijay Khemka63c99be2020-05-27 19:14:35 -0700267ipmi_ret_t getNetworkData(uint8_t lan_param, char* data)
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700268{
269 ipmi_ret_t rc = IPMI_CC_OK;
270 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
271
272 const std::string ethdevice = "eth0";
273
274 switch (static_cast<LanParam>(lan_param))
275 {
Vijay Khemkad1194022020-05-27 18:58:33 -0700276 case LanParam::IP:
277 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700278 auto ethIP = ethdevice + "/" + ipmi::network::IPV4_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700279 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700280 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700281 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
282
283 auto properties = ipmi::getAllDbusProperties(
284 bus, ipObjectInfo.second, ipObjectInfo.first,
285 ipmi::network::IP_INTERFACE);
286
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500287 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700288
289 std::strcpy(data, ipaddress.c_str());
290 }
291 break;
292
Vijay Khemkad1194022020-05-27 18:58:33 -0700293 case LanParam::IPV6:
294 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700295 auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700296 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700297 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700298 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
299
300 auto properties = ipmi::getAllDbusProperties(
301 bus, ipObjectInfo.second, ipObjectInfo.first,
302 ipmi::network::IP_INTERFACE);
303
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500304 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700305
306 std::strcpy(data, ipaddress.c_str());
307 }
308 break;
309
Vijay Khemkad1194022020-05-27 18:58:33 -0700310 case LanParam::MAC:
311 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700312 std::string macAddress;
313 auto macObjectInfo =
314 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
315 ipmi::network::ROOT, ethdevice);
316
317 auto variant = ipmi::getDbusProperty(
318 bus, macObjectInfo.second, macObjectInfo.first,
319 ipmi::network::MAC_INTERFACE, "MACAddress");
320
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500321 macAddress = std::get<std::string>(variant);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700322
323 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
324 (data), (data + 1), (data + 2), (data + 3), (data + 4),
325 (data + 5));
326 std::strcpy(data, macAddress.c_str());
327 }
328 break;
329
330 default:
331 rc = IPMI_CC_PARM_OUT_OF_RANGE;
332 }
333 return rc;
334}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800335
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530336bool isMultiHostPlatform()
337{
338 bool platform;
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530339 if (hostInstances == "0")
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530340 {
341 platform = false;
342 }
343 else
344 {
345 platform = true;
346 }
347 return platform;
348}
349
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800350// return code: 0 successful
Vijay Khemka63c99be2020-05-27 19:14:35 -0700351int8_t getFruData(std::string& data, std::string& name)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800352{
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530353 size_t pos;
354 static constexpr const auto depth = 0;
355 std::vector<std::string> paths;
356 std::string machinePath;
357 std::string baseBoard = "Baseboard";
358
359 bool platform = isMultiHostPlatform();
360 if (platform == true)
361 {
362 pos = getSelectorPosition();
363 }
364
365 sd_bus* bus = NULL;
366 int ret = sd_bus_default_system(&bus);
367 if (ret < 0)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800368 {
369 phosphor::logging::log<phosphor::logging::level::ERR>(
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530370 "Failed to connect to system bus",
371 phosphor::logging::entry("ERRNO=0x%X", -ret));
372 sd_bus_unref(bus);
373 return -1;
374 }
375 sdbusplus::bus::bus dbus(bus);
376 auto mapperCall = dbus.new_method_call("xyz.openbmc_project.ObjectMapper",
377 "/xyz/openbmc_project/object_mapper",
378 "xyz.openbmc_project.ObjectMapper",
379 "GetSubTreePaths");
380 static constexpr std::array<const char*, 1> interface = {
381 "xyz.openbmc_project.Inventory.Decorator.Asset"};
382 mapperCall.append("/xyz/openbmc_project/inventory/", depth, interface);
383
384 try
385 {
386 auto reply = dbus.call(mapperCall);
387 reply.read(paths);
388 }
389 catch (sdbusplus::exception_t& e)
390 {
391 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800392 return -1;
393 }
394
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530395 for (const auto& path : paths)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800396 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530397 if (platform == true)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800398 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530399 if (pos == BMC_POS)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800400 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530401 machinePath = baseBoard;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800402 }
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530403 else
404 {
405 machinePath = "_" + std::to_string(pos);
406 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800407 }
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530408 else
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800409 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530410 machinePath = baseBoard;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800411 }
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530412
413 auto found = path.find(machinePath);
Patrick Williams123cbcc2022-06-24 06:13:59 -0500414 if (found == std::string::npos)
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530415 {
416 continue;
417 }
418
419 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
420 std::string service = getService(
421 *dbus, "xyz.openbmc_project.Inventory.Decorator.Asset", path);
422
423 auto Value = ipmi::getDbusProperty(
424 *dbus, service, path,
425 "xyz.openbmc_project.Inventory.Decorator.Asset", name);
426
427 data = std::get<std::string>(Value);
428 return 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800429 }
430 return -1;
431}
432
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530433int8_t sysConfig(std::vector<std::string>& data, size_t pos)
434{
435 nlohmann::json sysObj;
436 std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(pos);
437 std::string result, typeName;
438 uint8_t res[MAX_BUF];
439
440 /* Get sysConfig data stored in json file */
441 std::ifstream file(JSON_OEM_DATA_FILE);
442 if (file)
443 {
444 file >> sysObj;
445 file.close();
446 }
447 else
448 {
449 phosphor::logging::log<phosphor::logging::level::ERR>(
450 "oemData file not found",
451 phosphor::logging::entry("OEM_DATA_FILE=%s", JSON_OEM_DATA_FILE));
452 return -1;
453 }
454
455 if (sysObj.find(dimmInfo) == sysObj.end())
456 {
457 phosphor::logging::log<phosphor::logging::level::ERR>(
458 "sysconfig key not available",
459 phosphor::logging::entry("SYS_JSON_KEY=%s", dimmInfo.c_str()));
460 return -1;
461 }
462 /* Get dimm type names stored in json file */
463 nlohmann::json dimmObj;
464 std::ifstream dimmFile(JSON_DIMM_TYPE_FILE);
465 if (file)
466 {
467 dimmFile >> dimmObj;
468 dimmFile.close();
469 }
470 else
471 {
472 phosphor::logging::log<phosphor::logging::level::ERR>(
473 "DIMM type names file not found",
474 phosphor::logging::entry("DIMM_TYPE_FILE=%s", JSON_DIMM_TYPE_FILE));
475 return -1;
476 }
477 std::vector<std::string> a;
478 for (auto& j : dimmObj.items())
479 {
480 std::string name = j.key();
481 a.push_back(name);
482 }
483
484 uint8_t len = a.size();
485 for (uint8_t ii = 0; ii < len; ii++)
486 {
487 std::string indKey = std::to_string(ii);
488 std::string speedSize = sysObj[dimmInfo][indKey][DIMM_SPEED];
489 strToBytes(speedSize, res);
490 auto speed = (res[1] << 8 | res[0]);
491 size_t dimmSize = ((res[3] << 8 | res[2]) / 1000);
492
493 if (dimmSize == 0)
494 {
495 std::cerr << "Dimm information not available for slot_" +
496 std::to_string(ii)
497 << std::endl;
498 continue;
499 }
500 std::string type = sysObj[dimmInfo][indKey][DIMM_TYPE];
501 std::string dualInlineMem = sysObj[dimmInfo][indKey][KEY_DIMM_TYPE];
502 strToBytes(type, res);
503 size_t dimmType = res[0];
504 if (dimmVenMap.find(dimmType) == dimmVenMap.end())
505 {
506 typeName = "unknown";
507 }
508 else
509 {
510 typeName = dimmVenMap[dimmType];
511 }
512 result = dualInlineMem + "/" + typeName + "/" + std::to_string(speed) +
513 "MHz" + "/" + std::to_string(dimmSize) + "GB";
514 data.push_back(result);
515 }
516 return 0;
517}
518
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800519typedef struct
520{
521 uint8_t cur_power_state;
522 uint8_t last_power_event;
523 uint8_t misc_power_state;
524 uint8_t front_panel_button_cap_status;
525} ipmi_get_chassis_status_t;
526
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800527//----------------------------------------------------------------------
528// Get Debug Frame Info
529//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700530ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800531 ipmi_request_t request,
532 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700533 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800534{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700535 uint8_t* req = reinterpret_cast<uint8_t*>(request);
536 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800537 uint8_t num_frames = 3;
538
539 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
540 res[SIZE_IANA_ID] = num_frames;
541 *data_len = SIZE_IANA_ID + 1;
542
543 return IPMI_CC_OK;
544}
545
546//----------------------------------------------------------------------
547// Get Debug Updated Frames
548//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700549ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800550 ipmi_request_t request,
551 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700552 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800553{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700554 uint8_t* req = reinterpret_cast<uint8_t*>(request);
555 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800556 uint8_t num_updates = 3;
557 *data_len = 4;
558
559 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
560 res[SIZE_IANA_ID] = num_updates;
561 *data_len = SIZE_IANA_ID + num_updates + 1;
562 res[SIZE_IANA_ID + 1] = 1; // info page update
563 res[SIZE_IANA_ID + 2] = 2; // cri sel update
564 res[SIZE_IANA_ID + 3] = 3; // cri sensor update
565
566 return IPMI_CC_OK;
567}
568
569//----------------------------------------------------------------------
570// Get Debug POST Description
571//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700572ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800573 ipmi_request_t request,
574 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700575 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800576{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700577 uint8_t* req = reinterpret_cast<uint8_t*>(request);
578 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800579 uint8_t index = 0;
580 uint8_t next = 0;
581 uint8_t end = 0;
582 uint8_t phase = 0;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700583 uint8_t descLen = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800584 int ret;
585
586 index = req[3];
587 phase = req[4];
588
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700589 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800590 if (ret)
591 {
592 memcpy(res, req, SIZE_IANA_ID); // IANA ID
593 *data_len = SIZE_IANA_ID;
594 return IPMI_CC_UNSPECIFIED_ERROR;
595 }
596
597 memcpy(res, req, SIZE_IANA_ID); // IANA ID
598 res[3] = index;
599 res[4] = next;
600 res[5] = phase;
601 res[6] = end;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700602 res[7] = descLen;
603 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800604
605 return IPMI_CC_OK;
606}
607
608//----------------------------------------------------------------------
609// Get Debug GPIO Description
610//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700611ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800612 ipmi_request_t request,
613 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700614 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800615{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700616 uint8_t* req = reinterpret_cast<uint8_t*>(request);
617 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800618
Vijay Khemka38183d62019-08-28 16:19:33 -0700619 uint8_t index = 0;
620 uint8_t next = 0;
621 uint8_t level = 0;
622 uint8_t pinDef = 0;
623 uint8_t descLen = 0;
624 int ret;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800625
Vijay Khemka38183d62019-08-28 16:19:33 -0700626 index = req[3];
627
628 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen,
629 &res[8]);
630 if (ret)
631 {
632 memcpy(res, req, SIZE_IANA_ID); // IANA ID
633 *data_len = SIZE_IANA_ID;
634 return IPMI_CC_UNSPECIFIED_ERROR;
635 }
636
637 memcpy(res, req, SIZE_IANA_ID); // IANA ID
638 res[3] = index;
639 res[4] = next;
640 res[5] = level;
641 res[6] = pinDef;
642 res[7] = descLen;
643 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800644
645 return IPMI_CC_OK;
646}
647
648//----------------------------------------------------------------------
649// Get Debug Frame Data
650//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700651ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800652 ipmi_request_t request,
653 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700654 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800655{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700656 uint8_t* req = reinterpret_cast<uint8_t*>(request);
657 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800658 uint8_t frame;
659 uint8_t page;
660 uint8_t next;
661 uint8_t count;
662 int ret;
663
664 frame = req[3];
665 page = req[4];
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800666
667 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]);
668 if (ret)
669 {
670 memcpy(res, req, SIZE_IANA_ID); // IANA ID
671 *data_len = SIZE_IANA_ID;
672 return IPMI_CC_UNSPECIFIED_ERROR;
673 }
674
675 memcpy(res, req, SIZE_IANA_ID); // IANA ID
676 res[3] = frame;
677 res[4] = page;
678 res[5] = next;
679 res[6] = count;
680 *data_len = SIZE_IANA_ID + 4 + count;
681
682 return IPMI_CC_OK;
683}
684
685//----------------------------------------------------------------------
686// Get Debug Control Panel
687//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700688ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800689 ipmi_request_t request,
690 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700691 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800692{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700693 uint8_t* req = reinterpret_cast<uint8_t*>(request);
694 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800695
696 uint8_t panel;
697 uint8_t operation;
698 uint8_t item;
699 uint8_t count;
700 ipmi_ret_t ret;
701
702 panel = req[3];
703 operation = req[4];
704 item = req[5];
705
706 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]);
707
708 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
709 *data_len = SIZE_IANA_ID + count;
710
711 return ret;
712}
713
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800714//----------------------------------------------------------------------
715// Set Dimm Info (CMD_OEM_SET_DIMM_INFO)
716//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700717ipmi_ret_t ipmiOemSetDimmInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
718 ipmi_response_t, ipmi_data_len_t data_len,
719 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800720{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700721 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700722
723 uint8_t index = req[0];
724 uint8_t type = req[1];
725 uint16_t speed;
726 uint32_t size;
727
728 memcpy(&speed, &req[2], 2);
729 memcpy(&size, &req[4], 4);
730
731 std::stringstream ss;
732 ss << std::hex;
733 ss << std::setw(2) << std::setfill('0') << (int)index;
734
735 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index;
736 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type;
737 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed;
738 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size;
739
740 flushOemData();
741
742 *data_len = 0;
743
744 return IPMI_CC_OK;
745}
746
747//----------------------------------------------------------------------
748// Get Board ID (CMD_OEM_GET_BOARD_ID)
749//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700750ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
751 ipmi_response_t, ipmi_data_len_t data_len,
752 ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700753{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700754 /* TODO: Needs to implement this after GPIO implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800755 *data_len = 0;
756
757 return IPMI_CC_OK;
758}
759
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800760/* Helper functions to set boot order */
Jayashree-Df0cf6652020-11-30 11:03:30 +0530761void setBootOrder(std::string bootObjPath, uint8_t* data,
762 std::string bootOrderKey)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800763{
Jayashree-Df0cf6652020-11-30 11:03:30 +0530764 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
765
766 // SETTING BOOT MODE PROPERTY
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530767 uint8_t bootModeBit = data[0] & 0x06;
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530768 auto bootValue = ipmi::boot::modeIpmiToDbus.at(bootModeBit);
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530769
Jayashree-Df0cf6652020-11-30 11:03:30 +0530770 std::string bootOption =
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530771 sdbusplus::message::convert_to_string<boot::BootMode>(bootValue);
Jayashree-Df0cf6652020-11-30 11:03:30 +0530772
773 std::string service =
774 getService(*dbus, ipmi::boot::bootModeIntf, bootObjPath);
775 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf,
776 ipmi::boot::bootModeProp, bootOption);
777
778 // SETTING BOOT SOURCE PROPERTY
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530779 auto bootOrder = ipmi::boot::sourceIpmiToDbus.at(data[1]);
Jayashree-Df0cf6652020-11-30 11:03:30 +0530780 std::string bootSource =
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530781 sdbusplus::message::convert_to_string<boot::BootSource>(bootOrder);
Jayashree-Df0cf6652020-11-30 11:03:30 +0530782
783 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath);
784 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf,
785 ipmi::boot::bootSourceProp, bootSource);
786
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530787 // SETTING BOOT TYPE PROPERTY
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530788 uint8_t bootTypeBit = data[0] & 0x01;
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530789 auto bootTypeVal = ipmi::boot::typeIpmiToDbus.at(bootTypeBit);
790
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530791 std::string bootType =
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530792 sdbusplus::message::convert_to_string<boot::BootType>(bootTypeVal);
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530793
794 service = getService(*dbus, ipmi::boot::bootTypeIntf, bootObjPath);
795
796 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootTypeIntf,
797 ipmi::boot::bootTypeProp, bootType);
798
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800799 nlohmann::json bootMode;
800 uint8_t mode = data[0];
801 int i;
802
803 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false);
804 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false);
805 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false);
806 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false);
Jayashree-Df0cf6652020-11-30 11:03:30 +0530807 oemData[bootOrderKey][KEY_BOOT_MODE] = bootMode;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800808
809 /* Initialize boot sequence array */
Jayashree-Df0cf6652020-11-30 11:03:30 +0530810 oemData[bootOrderKey][KEY_BOOT_SEQ] = {};
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800811 for (i = 1; i < SIZE_BOOT_ORDER; i++)
812 {
813 if (data[i] >= BOOT_SEQ_ARRAY_SIZE)
Jayashree-Df0cf6652020-11-30 11:03:30 +0530814 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = "NA";
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800815 else
Jayashree-Df0cf6652020-11-30 11:03:30 +0530816 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = bootSeq[data[i]];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800817 }
818
819 flushOemData();
820}
821
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800822//----------------------------------------------------------------------
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700823// Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
824//----------------------------------------------------------------------
Jayashree-Df0cf6652020-11-30 11:03:30 +0530825ipmi::RspType<std::vector<uint8_t>>
826 ipmiOemSetBootOrder(ipmi::Context::ptr ctx, std::vector<uint8_t> data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700827{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700828
Jayashree-Df0cf6652020-11-30 11:03:30 +0530829 uint8_t bootSeq[SIZE_BOOT_ORDER];
830 size_t len = data.size();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700831
832 if (len != SIZE_BOOT_ORDER)
833 {
834 phosphor::logging::log<phosphor::logging::level::ERR>(
835 "Invalid Boot order length received");
Jayashree-Df0cf6652020-11-30 11:03:30 +0530836 return ipmi::responseReqDataLenInvalid();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700837 }
838
Jayashree-Df0cf6652020-11-30 11:03:30 +0530839 std::copy(std::begin(data), std::end(data), bootSeq);
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530840 std::optional<size_t> hostId = findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700841
Jayashree-Df0cf6652020-11-30 11:03:30 +0530842 if (!hostId)
843 {
844 phosphor::logging::log<phosphor::logging::level::ERR>(
845 "Invalid Host Id received");
846 return ipmi::responseInvalidCommand();
847 }
848 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
849
850 setBootOrder(bootObjPath, bootSeq, hostName);
851
852 return ipmi::responseSuccess(data);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700853}
854
855//----------------------------------------------------------------------
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800856// Get Boot Order (CMD_OEM_GET_BOOT_ORDER)
857//----------------------------------------------------------------------
Jayashree-Df0cf6652020-11-30 11:03:30 +0530858ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>
859 ipmiOemGetBootOrder(ipmi::Context::ptr ctx)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800860{
Jayashree-Df0cf6652020-11-30 11:03:30 +0530861 uint8_t bootSeq[SIZE_BOOT_ORDER];
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700862 uint8_t mode = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800863
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530864 std::optional<size_t> hostId = findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700865
Jayashree-Df0cf6652020-11-30 11:03:30 +0530866 if (!hostId)
867 {
868 phosphor::logging::log<phosphor::logging::level::ERR>(
869 "Invalid Host Id received");
870 return ipmi::responseInvalidCommand();
871 }
872 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
873
Jayashree-Df0cf6652020-11-30 11:03:30 +0530874 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
875
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530876 // GETTING PROPERTY OF MODE INTERFACE
877
Jayashree-Df0cf6652020-11-30 11:03:30 +0530878 std::string service =
879 getService(*dbus, ipmi::boot::bootModeIntf, bootObjPath);
880 Value variant =
881 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf,
882 ipmi::boot::bootModeProp);
883
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530884 auto bootMode = sdbusplus::message::convert_from_string<boot::BootMode>(
Jayashree-Df0cf6652020-11-30 11:03:30 +0530885 std::get<std::string>(variant));
886
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530887 uint8_t bootOption = ipmi::boot::modeDbusToIpmi.at(bootMode);
Jayashree-Df0cf6652020-11-30 11:03:30 +0530888
889 // GETTING PROPERTY OF SOURCE INTERFACE
890
891 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath);
892 variant =
893 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf,
894 ipmi::boot::bootSourceProp);
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530895
896 auto bootSource = sdbusplus::message::convert_from_string<boot::BootSource>(
Jayashree-Df0cf6652020-11-30 11:03:30 +0530897 std::get<std::string>(variant));
898
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530899 uint8_t bootOrder = ipmi::boot::sourceDbusToIpmi.at(bootSource);
900
901 // GETTING PROPERTY OF TYPE INTERFACE
902
903 service = getService(*dbus, ipmi::boot::bootTypeIntf, bootObjPath);
904 variant =
905 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootTypeIntf,
906 ipmi::boot::bootTypeProp);
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530907
908 auto bootType = sdbusplus::message::convert_from_string<boot::BootType>(
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530909 std::get<std::string>(variant));
910
911 uint8_t bootTypeVal = ipmi::boot::typeDbusToIpmi.at(bootType);
912
913 uint8_t bootVal = bootOption | bootTypeVal;
Jayashree-Df0cf6652020-11-30 11:03:30 +0530914
915 if (oemData.find(hostName) == oemData.end())
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800916 {
917 /* Return default boot order 0100090203ff */
918 uint8_t defaultBoot[SIZE_BOOT_ORDER] = {
Willy Tue39f9392022-06-15 13:24:20 -0700919 BOOT_MODE_UEFI,
920 static_cast<uint8_t>(bootMap["USB_DEV"]),
921 static_cast<uint8_t>(bootMap["NET_IPV6"]),
922 static_cast<uint8_t>(bootMap["SATA_HDD"]),
923 static_cast<uint8_t>(bootMap["SATA_CD"]),
924 0xff};
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700925
Jayashree-Df0cf6652020-11-30 11:03:30 +0530926 memcpy(bootSeq, defaultBoot, SIZE_BOOT_ORDER);
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800927 phosphor::logging::log<phosphor::logging::level::INFO>(
928 "Set default boot order");
Jayashree-Df0cf6652020-11-30 11:03:30 +0530929 setBootOrder(bootObjPath, defaultBoot, hostName);
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800930 }
931 else
932 {
Jayashree-Df0cf6652020-11-30 11:03:30 +0530933 nlohmann::json bootMode = oemData[hostName][KEY_BOOT_MODE];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800934 if (bootMode["UEFI"])
935 mode |= BOOT_MODE_UEFI;
936 if (bootMode["CMOS_CLR"])
937 mode |= BOOT_MODE_CMOS_CLR;
938 if (bootMode["BOOT_FLAG"])
939 mode |= BOOT_MODE_BOOT_FLAG;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700940
Jayashree-Df0cf6652020-11-30 11:03:30 +0530941 bootSeq[0] = mode;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800942
Jayashree-Df0cf6652020-11-30 11:03:30 +0530943 for (int i = 1; i < SIZE_BOOT_ORDER; i++)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800944 {
Jayashree-Df0cf6652020-11-30 11:03:30 +0530945 std::string seqStr = oemData[hostName][KEY_BOOT_SEQ][i - 1];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800946 if (bootMap.find(seqStr) != bootMap.end())
Jayashree-Df0cf6652020-11-30 11:03:30 +0530947 bootSeq[i] = bootMap[seqStr];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800948 else
Jayashree-Df0cf6652020-11-30 11:03:30 +0530949 bootSeq[i] = 0xff;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800950 }
951 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800952
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530953 return ipmi::responseSuccess(bootVal, bootOrder, bootSeq[2], bootSeq[3],
Jayashree-Df0cf6652020-11-30 11:03:30 +0530954 bootSeq[4], bootSeq[5]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800955}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800956// Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO)
957//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700958ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t, ipmi_cmd_t,
959 ipmi_request_t request, ipmi_response_t,
960 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800961{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700962 machineConfigInfo_t* req = reinterpret_cast<machineConfigInfo_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700963 uint8_t len = *data_len;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800964
965 *data_len = 0;
966
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700967 if (len < sizeof(machineConfigInfo_t))
968 {
969 phosphor::logging::log<phosphor::logging::level::ERR>(
970 "Invalid machine configuration length received");
971 return IPMI_CC_REQ_DATA_LEN_INVALID;
972 }
973
Vijay Khemka63c99be2020-05-27 19:14:35 -0700974 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700975 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN";
976 else
977 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] =
978 chassisType[req->chassis_type];
979
Vijay Khemka63c99be2020-05-27 19:14:35 -0700980 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700981 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN";
982 else
983 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type];
984
985 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt;
986 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt;
987 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt;
988 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt;
989
Vijay Khemka63c99be2020-05-27 19:14:35 -0700990 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700991 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN";
992 else
993 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type];
994
995 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {};
996 int i = 0;
997 if (req->pcie_card_loc & BIT_0)
998 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1";
999 if (req->pcie_card_loc & BIT_1)
1000 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2";
1001 if (req->pcie_card_loc & BIT_2)
1002 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3";
1003 if (req->pcie_card_loc & BIT_3)
1004 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4";
1005
Vijay Khemka63c99be2020-05-27 19:14:35 -07001006 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001007 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN";
1008 else
1009 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] =
1010 pcieType[req->slot1_pcie_type];
1011
Vijay Khemka63c99be2020-05-27 19:14:35 -07001012 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001013 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN";
1014 else
1015 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] =
1016 pcieType[req->slot2_pcie_type];
1017
Vijay Khemka63c99be2020-05-27 19:14:35 -07001018 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001019 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN";
1020 else
1021 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] =
1022 pcieType[req->slot3_pcie_type];
1023
Vijay Khemka63c99be2020-05-27 19:14:35 -07001024 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001025 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN";
1026 else
1027 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] =
1028 pcieType[req->slot4_pcie_type];
1029
1030 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt;
1031
1032 flushOemData();
1033
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001034 return IPMI_CC_OK;
1035}
1036
1037//----------------------------------------------------------------------
1038// Set POST start (CMD_OEM_SET_POST_START)
1039//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001040ipmi_ret_t ipmiOemSetPostStart(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1041 ipmi_response_t, ipmi_data_len_t data_len,
1042 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001043{
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001044 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event");
1045
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001046 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001047 *data_len = 0;
1048 return IPMI_CC_OK;
1049}
1050
1051//----------------------------------------------------------------------
1052// Set POST End (CMD_OEM_SET_POST_END)
1053//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001054ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1055 ipmi_response_t, ipmi_data_len_t data_len,
1056 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001057{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001058 struct timespec ts;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001059
1060 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event");
1061
1062 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001063
1064 // Timestamp post end time.
1065 clock_gettime(CLOCK_REALTIME, &ts);
1066 oemData[KEY_TS_SLED] = ts.tv_sec;
1067 flushOemData();
1068
1069 // Sync time with system
1070 // TODO: Add code for syncing time
1071
1072 return IPMI_CC_OK;
1073}
1074
1075//----------------------------------------------------------------------
1076// Set PPIN Info (CMD_OEM_SET_PPIN_INFO)
1077//----------------------------------------------------------------------
1078// Inform BMC about PPIN data of 8 bytes for each CPU
1079//
1080// Request:
1081// Byte 1:8 – CPU0 PPIN data
1082// Optional:
1083// Byte 9:16 – CPU1 PPIN data
1084//
1085// Response:
1086// Byte 1 – Completion Code
Willy Tue39f9392022-06-15 13:24:20 -07001087ipmi_ret_t ipmiOemSetPPINInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
1088 ipmi_response_t, ipmi_data_len_t data_len,
1089 ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001090{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001091 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001092 std::string ppinStr;
1093 int len;
1094
1095 if (*data_len > SIZE_CPU_PPIN * 2)
1096 len = SIZE_CPU_PPIN * 2;
1097 else
1098 len = *data_len;
1099 *data_len = 0;
1100
1101 ppinStr = bytesToStr(req, len);
1102 oemData[KEY_PPIN_INFO] = ppinStr.c_str();
1103 flushOemData();
1104
1105 return IPMI_CC_OK;
1106}
1107
1108//----------------------------------------------------------------------
1109// Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER)
1110//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001111ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1112 ipmi_response_t, ipmi_data_len_t data_len,
1113 ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001114{
1115 /* Do nothing, return success */
1116 *data_len = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001117 return IPMI_CC_OK;
1118}
1119
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001120// Helper function to set guid at offset in EEPROM
Willy Tue39f9392022-06-15 13:24:20 -07001121[[maybe_unused]] static int setGUID(off_t offset, uint8_t* guid)
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001122{
1123 int fd = -1;
1124 ssize_t len;
1125 int ret = 0;
1126
1127 errno = 0;
1128
1129 // Check if file is present
1130 if (access(FRU_EEPROM, F_OK) == -1)
1131 {
1132 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl;
1133 return errno;
1134 }
1135
1136 // Open the file
1137 fd = open(FRU_EEPROM, O_WRONLY);
1138 if (fd == -1)
1139 {
1140 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl;
1141 return errno;
1142 }
1143
1144 // seek to the offset
1145 lseek(fd, offset, SEEK_SET);
1146
1147 // Write bytes to location
1148 len = write(fd, guid, GUID_SIZE);
1149 if (len != GUID_SIZE)
1150 {
1151 phosphor::logging::log<phosphor::logging::level::ERR>(
1152 "GUID write data to EEPROM failed");
1153 ret = errno;
1154 }
1155
1156 close(fd);
1157 return ret;
1158}
1159
1160//----------------------------------------------------------------------
1161// Set System GUID (CMD_OEM_SET_SYSTEM_GUID)
1162//----------------------------------------------------------------------
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301163#if BIC_ENABLED
Willy Tue39f9392022-06-15 13:24:20 -07001164ipmi::RspType<> ipmiOemSetSystemGuid(ipmi::Context::ptr ctx, uint8_t,
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301165 std::vector<uint8_t> reqData)
1166{
1167 std::vector<uint8_t> respData;
1168
1169 if (reqData.size() != GUID_SIZE) // 16bytes
1170 {
1171
1172 return ipmi::responseReqDataLenInvalid();
1173 }
1174
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301175 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
1176
1177 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
1178 return ipmi::responseUnspecifiedError();
1179
1180 return ipmi::responseSuccess();
1181}
1182
1183#else
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001184ipmi_ret_t ipmiOemSetSystemGuid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1185 ipmi_request_t request,
1186 ipmi_response_t response,
1187 ipmi_data_len_t data_len,
1188 ipmi_context_t context)
1189{
1190 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1191
1192 if (*data_len != GUID_SIZE) // 16bytes
1193 {
1194 *data_len = 0;
1195 return IPMI_CC_REQ_DATA_LEN_INVALID;
1196 }
1197
1198 *data_len = 0;
1199
1200 if (setGUID(OFFSET_SYS_GUID, req))
1201 {
1202 return IPMI_CC_UNSPECIFIED_ERROR;
1203 }
1204 return IPMI_CC_OK;
1205}
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301206#endif
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001207
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001208//----------------------------------------------------------------------
1209// Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO)
1210//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001211ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1212 ipmi_response_t, ipmi_data_len_t data_len,
1213 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001214{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001215 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001216 *data_len = 0;
1217 return IPMI_CC_OK;
1218}
1219
1220//----------------------------------------------------------------------
1221// Set PPR (CMD_OEM_SET_PPR)
1222//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001223ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
1224 ipmi_response_t, ipmi_data_len_t data_len,
1225 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001226{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001227 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001228 uint8_t pprCnt, pprAct, pprIndex;
1229 uint8_t selParam = req[0];
1230 uint8_t len = *data_len;
1231 std::stringstream ss;
1232 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001233
1234 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001235
1236 switch (selParam)
1237 {
1238 case PPR_ACTION:
1239 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) ==
1240 oemData[KEY_PPR].end())
1241 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1242
1243 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1244 if (pprCnt == 0)
1245 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1246
1247 pprAct = req[1];
1248 /* Check if ppr is enabled or disabled */
1249 if (!(pprAct & 0x80))
1250 pprAct = 0;
1251
1252 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct;
1253 break;
1254 case PPR_ROW_COUNT:
1255 if (req[1] > 100)
1256 return IPMI_CC_PARM_OUT_OF_RANGE;
1257
1258 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1];
1259 break;
1260 case PPR_ROW_ADDR:
1261 pprIndex = req[1];
1262 if (pprIndex > 100)
1263 return IPMI_CC_PARM_OUT_OF_RANGE;
1264
1265 if (len < PPR_ROW_ADDR_LEN + 1)
1266 {
1267 phosphor::logging::log<phosphor::logging::level::ERR>(
1268 "Invalid PPR Row Address length received");
1269 return IPMI_CC_REQ_DATA_LEN_INVALID;
1270 }
1271
1272 ss << std::hex;
1273 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1274
1275 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1276
1277 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN);
1278 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str();
1279 break;
1280 case PPR_HISTORY_DATA:
1281 pprIndex = req[1];
1282 if (pprIndex > 100)
1283 return IPMI_CC_PARM_OUT_OF_RANGE;
1284
1285 if (len < PPR_HST_DATA_LEN + 1)
1286 {
1287 phosphor::logging::log<phosphor::logging::level::ERR>(
1288 "Invalid PPR history data length received");
1289 return IPMI_CC_REQ_DATA_LEN_INVALID;
1290 }
1291
1292 ss << std::hex;
1293 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1294
1295 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1296
1297 str = bytesToStr(&req[1], PPR_HST_DATA_LEN);
1298 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str();
1299 break;
1300 default:
1301 return IPMI_CC_PARM_OUT_OF_RANGE;
1302 break;
1303 }
1304
1305 flushOemData();
1306
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001307 return IPMI_CC_OK;
1308}
1309
1310//----------------------------------------------------------------------
1311// Get PPR (CMD_OEM_GET_PPR)
1312//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001313ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
1314 ipmi_response_t response, ipmi_data_len_t data_len,
1315 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001316{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001317 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1318 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001319 uint8_t pprCnt, pprIndex;
1320 uint8_t selParam = req[0];
1321 std::stringstream ss;
1322 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001323
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001324 /* Any failure will return zero length data */
1325 *data_len = 0;
1326
1327 switch (selParam)
1328 {
1329 case PPR_ACTION:
1330 res[0] = 0;
1331 *data_len = 1;
1332
1333 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1334 oemData[KEY_PPR].end())
1335 {
1336 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1337 if (pprCnt != 0)
1338 {
1339 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) !=
1340 oemData[KEY_PPR].end())
1341 {
1342 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION];
1343 }
1344 }
1345 }
1346 break;
1347 case PPR_ROW_COUNT:
1348 res[0] = 0;
1349 *data_len = 1;
1350 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1351 oemData[KEY_PPR].end())
1352 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1353 break;
1354 case PPR_ROW_ADDR:
1355 pprIndex = req[1];
1356 if (pprIndex > 100)
1357 return IPMI_CC_PARM_OUT_OF_RANGE;
1358
1359 ss << std::hex;
1360 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1361
1362 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1363 return IPMI_CC_PARM_OUT_OF_RANGE;
1364
1365 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) ==
1366 oemData[KEY_PPR][ss.str()].end())
1367 return IPMI_CC_PARM_OUT_OF_RANGE;
1368
1369 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR];
1370 *data_len = strToBytes(str, res);
1371 break;
1372 case PPR_HISTORY_DATA:
1373 pprIndex = req[1];
1374 if (pprIndex > 100)
1375 return IPMI_CC_PARM_OUT_OF_RANGE;
1376
1377 ss << std::hex;
1378 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1379
1380 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1381 return IPMI_CC_PARM_OUT_OF_RANGE;
1382
1383 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) ==
1384 oemData[KEY_PPR][ss.str()].end())
1385 return IPMI_CC_PARM_OUT_OF_RANGE;
1386
1387 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA];
1388 *data_len = strToBytes(str, res);
1389 break;
1390 default:
1391 return IPMI_CC_PARM_OUT_OF_RANGE;
1392 break;
1393 }
1394
1395 return IPMI_CC_OK;
1396}
1397
1398/* FB OEM QC Commands */
1399
1400//----------------------------------------------------------------------
1401// Set Proc Info (CMD_OEM_Q_SET_PROC_INFO)
1402//----------------------------------------------------------------------
1403//"Request:
1404// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1405// Byte 4 – Processor Index, 0 base
1406// Byte 5 – Parameter Selector
1407// Byte 6..N – Configuration parameter data (see below for Parameters
1408// of Processor Information)
1409// Response:
1410// Byte 1 – Completion code
1411//
1412// Parameter#1: (Processor Product Name)
1413//
1414// Byte 1..48 –Product name(ASCII code)
1415// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1416//
1417// Param#2: Processor Basic Information
1418// Byte 1 – Core Number
1419// Byte 2 – Thread Number (LSB)
1420// Byte 3 – Thread Number (MSB)
1421// Byte 4 – Processor frequency in MHz (LSB)
1422// Byte 5 – Processor frequency in MHz (MSB)
1423// Byte 6..7 – Revision
1424//
Willy Tue39f9392022-06-15 13:24:20 -07001425ipmi_ret_t ipmiOemQSetProcInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
1426 ipmi_response_t, ipmi_data_len_t data_len,
1427 ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001428{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001429 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1430 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001431 std::stringstream ss;
1432 std::string str;
1433 uint8_t len = *data_len;
1434
1435 *data_len = 0;
1436
1437 /* check for requested data params */
1438 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1439 {
1440 phosphor::logging::log<phosphor::logging::level::ERR>(
1441 "Invalid parameter received");
1442 return IPMI_CC_PARM_OUT_OF_RANGE;
1443 }
1444
1445 len = len - 5; // Get Actual data length
1446
1447 ss << std::hex;
1448 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1449 oemData[KEY_Q_PROC_INFO][ss.str()][KEY_PROC_INDEX] = req->procIndex;
1450
1451 str = bytesToStr(req->data, len);
1452 oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]] = str.c_str();
1453 flushOemData();
1454
1455 return IPMI_CC_OK;
1456}
1457
1458//----------------------------------------------------------------------
1459// Get Proc Info (CMD_OEM_Q_GET_PROC_INFO)
1460//----------------------------------------------------------------------
1461// Request:
1462// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1463// Byte 4 – Processor Index, 0 base
1464// Byte 5 – Parameter Selector
1465// Response:
1466// Byte 1 – Completion code
1467// Byte 2..N – Configuration Parameter Data (see below for Parameters
1468// of Processor Information)
1469//
1470// Parameter#1: (Processor Product Name)
1471//
1472// Byte 1..48 –Product name(ASCII code)
1473// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1474//
1475// Param#2: Processor Basic Information
1476// Byte 1 – Core Number
1477// Byte 2 – Thread Number (LSB)
1478// Byte 3 – Thread Number (MSB)
1479// Byte 4 – Processor frequency in MHz (LSB)
1480// Byte 5 – Processor frequency in MHz (MSB)
1481// Byte 6..7 – Revision
1482//
Willy Tue39f9392022-06-15 13:24:20 -07001483ipmi_ret_t ipmiOemQGetProcInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
1484 ipmi_response_t response,
1485 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001486{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001487 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1488 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
1489 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001490 std::stringstream ss;
1491 std::string str;
1492
1493 *data_len = 0;
1494
1495 /* check for requested data params */
1496 if (req->paramSel < 1 || req->paramSel >= numParam)
1497 {
1498 phosphor::logging::log<phosphor::logging::level::ERR>(
1499 "Invalid parameter received");
1500 return IPMI_CC_PARM_OUT_OF_RANGE;
1501 }
1502
1503 ss << std::hex;
1504 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1505
1506 if (oemData[KEY_Q_PROC_INFO].find(ss.str()) ==
1507 oemData[KEY_Q_PROC_INFO].end())
1508 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1509
1510 if (oemData[KEY_Q_PROC_INFO][ss.str()].find(cpuInfoKey[req->paramSel]) ==
1511 oemData[KEY_Q_PROC_INFO][ss.str()].end())
1512 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1513
1514 str = oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]];
1515 *data_len = strToBytes(str, res);
1516
1517 return IPMI_CC_OK;
1518}
1519
1520//----------------------------------------------------------------------
1521// Set Dimm Info (CMD_OEM_Q_SET_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//
1532// Param#1 (DIMM Location):
1533// Byte 1 – DIMM Present
1534// Byte 1 – DIMM Present
1535// 01h – Present
1536// FFh – Not Present
1537// Byte 2 – Node Number, 0 base
1538// Byte 3 – Channel Number , 0 base
1539// Byte 4 – DIMM Number , 0 base
1540//
1541// Param#2 (DIMM Type):
1542// Byte 1 – DIMM Type
1543// Bit [7:6]
1544// For DDR3
1545// 00 – Normal Voltage (1.5V)
1546// 01 – Ultra Low Voltage (1.25V)
1547// 10 – Low Voltage (1.35V)
1548// 11 – Reserved
1549// For DDR4
1550// 00 – Reserved
1551// 01 – Reserved
1552// 10 – Reserved
1553// 11 – Normal Voltage (1.2V)
1554// Bit [5:0]
1555// 0x00 – SDRAM
1556// 0x01 – DDR-1 RAM
1557// 0x02 – Rambus
1558// 0x03 – DDR-2 RAM
1559// 0x04 – FBDIMM
1560// 0x05 – DDR-3 RAM
1561// 0x06 – DDR-4 RAM
1562//
1563// Param#3 (DIMM Speed):
1564// Byte 1..2 – DIMM speed in MHz, LSB
1565// Byte 3..6 – DIMM size in Mbytes, LSB
1566//
1567// Param#4 (Module Part Number):
1568// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1569//
1570// Param#5 (Module Serial Number):
1571// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1572//
1573// Param#6 (Module Manufacturer ID):
1574// Byte 1 - Module Manufacturer ID, LSB
1575// Byte 2 - Module Manufacturer ID, MSB
1576//
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301577ipmi::RspType<> ipmiOemQSetDimmInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t,
1578 uint8_t, uint8_t dimmIndex,
1579 uint8_t paramSel,
1580 std::vector<uint8_t> request)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001581{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001582 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001583 std::stringstream ss;
1584 std::string str;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301585 uint8_t len = request.size();
1586 std::string dimmType;
1587 readDimmType(dimmType, dimmIndex);
1588 auto hostId = ipmi::boot::findHost(ctx->hostIdx);
1589 if (!hostId)
1590 {
1591 phosphor::logging::log<phosphor::logging::level::ERR>(
1592 "Invalid Host Id received");
1593 return ipmi::responseInvalidCommand();
1594 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001595
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301596 std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(*hostId);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001597
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301598 if (len < 3 || paramSel < 1 || paramSel >= numParam)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001599 {
1600 phosphor::logging::log<phosphor::logging::level::ERR>(
1601 "Invalid parameter received");
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301602 return ipmi::responseParmOutOfRange();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001603 }
1604
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001605 ss << std::hex;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301606 ss << (int)dimmIndex;
1607 oemData[dimmInfo][ss.str()][KEY_DIMM_INDEX] = dimmIndex;
1608 oemData[dimmInfo][ss.str()][KEY_DIMM_TYPE] = dimmType;
1609 str = bytesToStr(request.data(), len);
1610 oemData[dimmInfo][ss.str()][dimmInfoKey[paramSel]] = str.c_str();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001611 flushOemData();
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301612 return ipmi::responseSuccess();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001613}
1614
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001615// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
1616//----------------------------------------------------------------------
1617// Request:
1618// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1619// Byte 4 – DIMM Index, 0 base
1620// Byte 5 – Parameter Selector
1621// Byte 6..N – Configuration parameter data (see below for Parameters
1622// of DIMM Information)
1623// Response:
1624// Byte 1 – Completion code
1625// Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters
1626// of DIMM Information)
1627//
1628// Param#1 (DIMM Location):
1629// Byte 1 – DIMM Present
1630// Byte 1 – DIMM Present
1631// 01h – Present
1632// FFh – Not Present
1633// Byte 2 – Node Number, 0 base
1634// Byte 3 – Channel Number , 0 base
1635// Byte 4 – DIMM Number , 0 base
1636//
1637// Param#2 (DIMM Type):
1638// Byte 1 – DIMM Type
1639// Bit [7:6]
1640// For DDR3
1641// 00 – Normal Voltage (1.5V)
1642// 01 – Ultra Low Voltage (1.25V)
1643// 10 – Low Voltage (1.35V)
1644// 11 – Reserved
1645// For DDR4
1646// 00 – Reserved
1647// 01 – Reserved
1648// 10 – Reserved
1649// 11 – Normal Voltage (1.2V)
1650// Bit [5:0]
1651// 0x00 – SDRAM
1652// 0x01 – DDR-1 RAM
1653// 0x02 – Rambus
1654// 0x03 – DDR-2 RAM
1655// 0x04 – FBDIMM
1656// 0x05 – DDR-3 RAM
1657// 0x06 – DDR-4 RAM
1658//
1659// Param#3 (DIMM Speed):
1660// Byte 1..2 – DIMM speed in MHz, LSB
1661// Byte 3..6 – DIMM size in Mbytes, LSB
1662//
1663// Param#4 (Module Part Number):
1664// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1665//
1666// Param#5 (Module Serial Number):
1667// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1668//
1669// Param#6 (Module Manufacturer ID):
1670// Byte 1 - Module Manufacturer ID, LSB
1671// Byte 2 - Module Manufacturer ID, MSB
1672//
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301673ipmi::RspType<std::vector<uint8_t>>
1674 ipmiOemQGetDimmInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t, uint8_t,
1675 uint8_t dimmIndex, uint8_t paramSel)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001676{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001677 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301678 uint8_t res[MAX_BUF];
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001679 std::stringstream ss;
1680 std::string str;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301681 std::string dimmType;
1682 readDimmType(dimmType, dimmIndex);
1683 auto hostId = ipmi::boot::findHost(ctx->hostIdx);
1684 if (!hostId)
1685 {
1686 phosphor::logging::log<phosphor::logging::level::ERR>(
1687 "Invalid Host Id received");
1688 return ipmi::responseInvalidCommand();
1689 }
1690 std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(*hostId);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001691
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301692 if (paramSel < 1 || paramSel >= numParam)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001693 {
1694 phosphor::logging::log<phosphor::logging::level::ERR>(
1695 "Invalid parameter received");
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301696 return ipmi::responseParmOutOfRange();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001697 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001698 ss << std::hex;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301699 ss << (int)dimmIndex;
1700 oemData[dimmInfo][ss.str()][KEY_DIMM_TYPE] = dimmType;
1701 if (oemData[dimmInfo].find(ss.str()) == oemData[dimmInfo].end())
1702 return ipmi::responseCommandNotAvailable();
1703 if (oemData[dimmInfo][ss.str()].find(dimmInfoKey[paramSel]) ==
1704 oemData[dimmInfo][ss.str()].end())
1705 return ipmi::responseCommandNotAvailable();
1706 str = oemData[dimmInfo][ss.str()][dimmInfoKey[paramSel]];
1707 int data_length = strToBytes(str, res);
1708 std::vector<uint8_t> response(&res[0], &res[data_length]);
1709 return ipmi::responseSuccess(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001710}
1711
1712//----------------------------------------------------------------------
1713// Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO)
1714//----------------------------------------------------------------------
1715// BIOS issue this command to provide HDD information to BMC.
1716//
1717// BIOS just can get information by standard ATA / SMART command for
1718// OB SATA controller.
1719// BIOS can get
1720// 1. Serial Number
1721// 2. Model Name
1722// 3. HDD FW Version
1723// 4. HDD Capacity
1724// 5. HDD WWN
1725//
1726// Use Get HDD info Param #5 to know the MAX HDD info index.
1727//
1728// Request:
1729// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1730// Byte 4 –
1731// [7:4] Reserved
1732// [3:0] HDD Controller Type
1733// 0x00 – BIOS
1734// 0x01 – Expander
1735// 0x02 – LSI
1736// Byte 5 – HDD Info Index, 0 base
1737// Byte 6 – Parameter Selector
1738// Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD
1739// Information)
1740//
1741// Response:
1742// Byte 1 – Completion Code
1743//
1744// Param#0 (HDD Location):
1745// Byte 1 – Controller
1746// [7:3] Device Number
1747// [2:0] Function Number
1748// For Intel C610 series (Wellsburg)
1749// D31:F2 (0xFA) – SATA control 1
1750// D31:F5 (0xFD) – SATA control 2
1751// D17:F4 (0x8C) – sSata control
1752// Byte 2 – Port Number
1753// Byte 3 – Location (0xFF: No HDD Present)
1754// BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param
1755// #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if
1756// the HDD present. BMC or other people who know the HDD location has
1757// responsibility for update Location info
1758//
1759// Param#1 (Serial Number):
1760// Bytes 1..33: HDD Serial Number
1761//
1762// Param#2 (Model Name):
1763// Byte 1..33 – HDD Model Name
1764//
1765// Param#3 (HDD FW Version):
1766// Byte 1..17 –HDD FW version
1767//
1768// Param#4 (Capacity):
1769// Byte 1..4 –HDD Block Size, LSB
1770// Byte 5..12 - HDD Block Number, LSB
1771// HDD Capacity = HDD Block size * HDD BLock number (Unit Byte)
1772//
1773// Param#5 (Max HDD Quantity):
1774// Byte 1 - Max HDD Quantity
1775// Max supported port numbers in this PCH
1776//
1777// Param#6 (HDD Type)
1778// Byte 1 – HDD Type
1779// 0h – Reserved
1780// 1h – SAS
1781// 2h – SATA
1782// 3h – PCIE SSD (NVME)
1783//
1784// Param#7 (HDD WWN)
1785// Data 1...8: HDD World Wide Name, LSB
1786//
Willy Tue39f9392022-06-15 13:24:20 -07001787ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t, ipmi_cmd_t,
1788 ipmi_request_t request, ipmi_response_t,
1789 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001790{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001791 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1792 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001793 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1794 std::stringstream ss;
1795 std::string str;
1796 uint8_t len = *data_len;
1797
1798 *data_len = 0;
1799
1800 /* check for requested data params */
1801 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam ||
1802 ctrlType > 2)
1803 {
1804 phosphor::logging::log<phosphor::logging::level::ERR>(
1805 "Invalid parameter received");
1806 return IPMI_CC_PARM_OUT_OF_RANGE;
1807 }
1808
1809 len = len - 6; // Get Actual data length
1810
1811 ss << std::hex;
1812 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1813 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType;
1814 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] =
1815 req->hddIndex;
1816
1817 str = bytesToStr(req->data, len);
1818 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1819 [driveInfoKey[req->paramSel]] = str.c_str();
1820 flushOemData();
1821
1822 return IPMI_CC_OK;
1823}
1824
1825//----------------------------------------------------------------------
1826// Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO)
1827//----------------------------------------------------------------------
1828// BMC needs to check HDD presented or not first. If NOT presented, return
1829// completion code 0xD5.
1830//
1831// Request:
1832// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1833// Byte 4 –
1834//[7:4] Reserved
1835//[3:0] HDD Controller Type
1836// 0x00 – BIOS
1837// 0x01 – Expander
1838// 0x02 – LSI
1839// Byte 5 – HDD Index, 0 base
1840// Byte 6 – Parameter Selector (See Above Set HDD Information)
1841// Response:
1842// Byte 1 – Completion Code
1843// 0xD5 – Not support in current status (HDD Not Present)
1844// Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD
1845// Information)
1846//
Willy Tue39f9392022-06-15 13:24:20 -07001847ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001848 ipmi_request_t request,
1849 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -07001850 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001851{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001852 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1853 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
1854 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001855 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1856 std::stringstream ss;
1857 std::string str;
1858
1859 *data_len = 0;
1860
1861 /* check for requested data params */
1862 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2)
1863 {
1864 phosphor::logging::log<phosphor::logging::level::ERR>(
1865 "Invalid parameter received");
1866 return IPMI_CC_PARM_OUT_OF_RANGE;
1867 }
1868
1869 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) ==
1870 oemData[KEY_Q_DRIVE_INFO].end())
1871 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1872
1873 ss << std::hex;
1874 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1875
1876 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) ==
1877 oemData[KEY_Q_DRIVE_INFO].end())
1878 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1879
1880 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find(
1881 dimmInfoKey[req->paramSel]) ==
1882 oemData[KEY_Q_DRIVE_INFO][ss.str()].end())
1883 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1884
1885 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1886 [dimmInfoKey[req->paramSel]];
1887 *data_len = strToBytes(str, res);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001888
1889 return IPMI_CC_OK;
1890}
1891
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001892/* Helper function for sending DCMI commands to ME and getting response back */
1893ipmi::RspType<std::vector<uint8_t>> sendDCMICmd(uint8_t cmd,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001894 std::vector<uint8_t>& cmdData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001895{
1896 std::vector<uint8_t> respData;
1897
1898 /* Add group id as first byte to request for ME command */
1899 cmdData.insert(cmdData.begin(), groupDCMI);
1900
1901 if (sendMeCmd(ipmi::netFnGroup, cmd, cmdData, respData))
1902 return ipmi::responseUnspecifiedError();
1903
1904 /* Remove group id as first byte as it will be added by IPMID */
1905 respData.erase(respData.begin());
1906
1907 return ipmi::responseSuccess(std::move(respData));
1908}
1909
1910/* DCMI Command handellers. */
1911
1912ipmi::RspType<std::vector<uint8_t>>
1913 ipmiOemDCMIGetPowerReading(std::vector<uint8_t> reqData)
1914{
1915 return sendDCMICmd(ipmi::dcmi::cmdGetPowerReading, reqData);
1916}
1917
1918ipmi::RspType<std::vector<uint8_t>>
1919 ipmiOemDCMIGetPowerLimit(std::vector<uint8_t> reqData)
1920{
1921 return sendDCMICmd(ipmi::dcmi::cmdGetPowerLimit, reqData);
1922}
1923
1924ipmi::RspType<std::vector<uint8_t>>
1925 ipmiOemDCMISetPowerLimit(std::vector<uint8_t> reqData)
1926{
1927 return sendDCMICmd(ipmi::dcmi::cmdSetPowerLimit, reqData);
1928}
1929
1930ipmi::RspType<std::vector<uint8_t>>
1931 ipmiOemDCMIApplyPowerLimit(std::vector<uint8_t> reqData)
1932{
1933 return sendDCMICmd(ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
1934}
1935
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001936static void registerOEMFunctions(void)
1937{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001938 /* Get OEM data from json file */
1939 std::ifstream file(JSON_OEM_DATA_FILE);
1940 if (file)
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001941 {
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001942 file >> oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001943 file.close();
1944 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001945
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001946 phosphor::logging::log<phosphor::logging::level::INFO>(
1947 "Registering OEM commands");
Vijay Khemka7c0aea42020-03-05 13:31:53 -08001948
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001949 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO,
1950 NULL, ipmiOemDbgGetFrameInfo,
1951 PRIVILEGE_USER); // get debug frame info
1952 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ,
1953 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL,
1954 ipmiOemDbgGetUpdFrames,
1955 PRIVILEGE_USER); // get debug updated frames
1956 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC,
1957 NULL, ipmiOemDbgGetPostDesc,
1958 PRIVILEGE_USER); // get debug post description
1959 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC,
1960 NULL, ipmiOemDbgGetGpioDesc,
1961 PRIVILEGE_USER); // get debug gpio description
1962 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA,
1963 NULL, ipmiOemDbgGetFrameData,
1964 PRIVILEGE_USER); // get debug frame data
1965 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL,
1966 NULL, ipmiOemDbgGetCtrlPanel,
1967 PRIVILEGE_USER); // get debug control panel
1968 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL,
1969 ipmiOemSetDimmInfo,
1970 PRIVILEGE_USER); // Set Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001971 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL,
1972 ipmiOemGetBoardID,
1973 PRIVILEGE_USER); // Get Board ID
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001974 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL,
1975 ipmiOemSetMachineCfgInfo,
1976 PRIVILEGE_USER); // Set Machine Config Info
1977 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL,
1978 ipmiOemSetPostStart,
1979 PRIVILEGE_USER); // Set POST start
1980 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL,
1981 ipmiOemSetPostEnd,
1982 PRIVILEGE_USER); // Set POST End
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001983 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL,
1984 ipmiOemSetPPINInfo,
1985 PRIVILEGE_USER); // Set PPIN Info
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301986#if BIC_ENABLED
1987
1988 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1989 ipmi::cmdSetSystemGuid, ipmi::Privilege::User,
1990 ipmiOemSetSystemGuid);
1991#else
1992
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001993 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_SYSTEM_GUID, NULL,
1994 ipmiOemSetSystemGuid,
1995 PRIVILEGE_USER); // Set System GUID
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301996#endif
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001997 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL,
1998 ipmiOemSetAdrTrigger,
1999 PRIVILEGE_USER); // Set ADR Trigger
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002000 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL,
2001 ipmiOemSetBiosFlashInfo,
2002 PRIVILEGE_USER); // Set Bios Flash Info
2003 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr,
2004 PRIVILEGE_USER); // Set PPR
2005 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
2006 PRIVILEGE_USER); // Get PPR
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002007 /* FB OEM QC Commands */
2008 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_PROC_INFO, NULL,
2009 ipmiOemQSetProcInfo,
2010 PRIVILEGE_USER); // Set Proc Info
2011 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL,
2012 ipmiOemQGetProcInfo,
2013 PRIVILEGE_USER); // Get Proc Info
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05302014 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
2015 ipmi::cmdSetQDimmInfo, ipmi::Privilege::User,
2016 ipmiOemQSetDimmInfo); // Set Dimm Info
2017 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
2018 ipmi::cmdGetQDimmInfo, ipmi::Privilege::User,
2019 ipmiOemQGetDimmInfo); // Get Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002020 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
2021 ipmiOemQSetDriveInfo,
2022 PRIVILEGE_USER); // Set Drive Info
2023 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL,
2024 ipmiOemQGetDriveInfo,
2025 PRIVILEGE_USER); // Get Drive Info
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002026
2027 /* FB OEM DCMI Commands as per DCMI spec 1.5 Section 6 */
2028 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2029 ipmi::dcmi::cmdGetPowerReading,
2030 ipmi::Privilege::User,
2031 ipmiOemDCMIGetPowerReading); // Get Power Reading
2032
2033 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2034 ipmi::dcmi::cmdGetPowerLimit,
2035 ipmi::Privilege::User,
2036 ipmiOemDCMIGetPowerLimit); // Get Power Limit
2037
2038 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2039 ipmi::dcmi::cmdSetPowerLimit,
2040 ipmi::Privilege::Operator,
2041 ipmiOemDCMISetPowerLimit); // Set Power Limit
2042
2043 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2044 ipmi::dcmi::cmdActDeactivatePwrLimit,
2045 ipmi::Privilege::Operator,
2046 ipmiOemDCMIApplyPowerLimit); // Apply Power Limit
2047
Jayashree-Df0cf6652020-11-30 11:03:30 +05302048 /* FB OEM BOOT ORDER COMMANDS */
2049 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
2050 CMD_OEM_GET_BOOT_ORDER, ipmi::Privilege::User,
2051 ipmiOemGetBootOrder); // Get Boot Order
2052
2053 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
2054 CMD_OEM_SET_BOOT_ORDER, ipmi::Privilege::User,
2055 ipmiOemSetBootOrder); // Set Boot Order
2056
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002057 return;
2058}
2059
2060} // namespace ipmi