blob: 6d9af87e551139638c068aff97c336230058df69 [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
Cosmo Chou99d42b62024-08-15 10:42:47 +080020#include <boost/crc.hpp>
Patrick Williams2405ae92023-05-10 07:50:09 -050021#include <commandutils.hpp>
22#include <ipmid/api-types.hpp>
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 <nlohmann/json.hpp>
26#include <oemcommands.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080027#include <phosphor-logging/log.hpp>
28#include <sdbusplus/bus.hpp>
Patrick Williams2405ae92023-05-10 07:50:09 -050029#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
30#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
31#include <xyz/openbmc_project/Control/Boot/Type/server.hpp>
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053032
Vijay Khemka63c99be2020-05-27 19:14:35 -070033#include <array>
34#include <cstring>
35#include <fstream>
36#include <iomanip>
37#include <iostream>
Patrick Williams2405ae92023-05-10 07:50:09 -050038#include <regex>
Vijay Khemka63c99be2020-05-27 19:14:35 -070039#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 Pasupathie1ff81f2022-11-21 17:54:46 +053050void getSelectorPosition(size_t& position);
Vijay Khemkae7d23d02019-03-08 13:13:40 -080051static void registerOEMFunctions() __attribute__((constructor));
Patrick Williamscd315e02022-07-22 19:26:52 -050052sdbusplus::bus_t dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
Vijay Khemkae7d23d02019-03-08 13:13:40 -080053static 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
Cosmo Chou7ab87bb2024-06-28 10:47:44 +080059constexpr ipmi_ret_t ccInvalidParam = 0x80;
60
Vijay Khemka63c99be2020-05-27 19:14:35 -070061int plat_udbg_get_post_desc(uint8_t, uint8_t*, uint8_t, uint8_t*, uint8_t*,
62 uint8_t*);
63int plat_udbg_get_gpio_desc(uint8_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*,
64 uint8_t*);
Patrick Williams5e589482024-07-13 16:18:13 -050065int plat_udbg_get_frame_data(uint8_t, uint8_t, uint8_t*, uint8_t*, uint8_t*);
Vijay Khemka63c99be2020-05-27 19:14:35 -070066ipmi_ret_t plat_udbg_control_panel(uint8_t, uint8_t, uint8_t, uint8_t*,
67 uint8_t*);
68int sendMeCmd(uint8_t, uint8_t, std::vector<uint8_t>&, std::vector<uint8_t>&);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -070069
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053070int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
71 std::vector<uint8_t>&);
72
Vijay Khemkafeaa9812019-08-27 15:08:08 -070073nlohmann::json oemData __attribute__((init_priority(101)));
Vijay Khemka1b6fae32019-03-25 17:43:01 -070074
Cosmo Chou99d42b62024-08-15 10:42:47 +080075constexpr const char* certPath = "/mnt/data/host/bios-rootcert";
76
Vijay Khemkaf2246ce2020-05-27 14:26:35 -070077static constexpr size_t GUID_SIZE = 16;
78// TODO Make offset and location runtime configurable to ensure we
79// can make each define their own locations.
80static constexpr off_t OFFSET_SYS_GUID = 0x17F0;
81static constexpr const char* FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom";
Delphine CC Chiu7bb45922023-04-10 13:34:04 +080082void flushOemData();
Vijay Khemkaf2246ce2020-05-27 14:26:35 -070083
Vijay Khemka1b6fae32019-03-25 17:43:01 -070084enum class LanParam : uint8_t
85{
86 INPROGRESS = 0,
87 AUTHSUPPORT = 1,
88 AUTHENABLES = 2,
89 IP = 3,
90 IPSRC = 4,
91 MAC = 5,
92 SUBNET = 6,
93 GATEWAY = 12,
94 VLAN = 20,
95 CIPHER_SUITE_COUNT = 22,
96 CIPHER_SUITE_ENTRIES = 23,
97 IPV6 = 59,
98};
99
Vijay Khemkaa7231892019-10-11 11:35:05 -0700100namespace network
101{
102
103constexpr auto ROOT = "/xyz/openbmc_project/network";
104constexpr auto SERVICE = "xyz.openbmc_project.Network";
105constexpr auto IPV4_TYPE = "ipv4";
106constexpr auto IPV6_TYPE = "ipv6";
107constexpr auto IPV4_PREFIX = "169.254";
108constexpr auto IPV6_PREFIX = "fe80";
109constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
110constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
Potin Lai8d1a81e2022-12-20 11:13:45 +0800111constexpr auto IPV4_PROTOCOL = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
112constexpr auto IPV6_PROTOCOL = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
Vijay Khemkaa7231892019-10-11 11:35:05 -0700113
Vijay Khemka63c99be2020-05-27 19:14:35 -0700114bool isLinkLocalIP(const std::string& address)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700115{
116 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0;
117}
118
Patrick Williamscd315e02022-07-22 19:26:52 -0500119DbusObjectInfo getIPObject(sdbusplus::bus_t& bus, const std::string& interface,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700120 const std::string& serviceRoot,
Potin Lai8d1a81e2022-12-20 11:13:45 +0800121 const std::string& protocol,
122 const std::string& ethdev)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700123{
Potin Lai8d1a81e2022-12-20 11:13:45 +0800124 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, ethdev);
Vijay Khemkaa7231892019-10-11 11:35:05 -0700125
126 if (objectTree.empty())
127 {
128 log<level::ERR>("No Object has implemented the IP interface",
129 entry("INTERFACE=%s", interface.c_str()));
130 }
131
132 DbusObjectInfo objectInfo;
133
Vijay Khemka63c99be2020-05-27 19:14:35 -0700134 for (auto& object : objectTree)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700135 {
Patrick Williams2405ae92023-05-10 07:50:09 -0500136 auto variant = ipmi::getDbusProperty(bus, object.second.begin()->first,
137 object.first, IP_INTERFACE,
138 "Type");
Potin Lai8d1a81e2022-12-20 11:13:45 +0800139 if (std::get<std::string>(variant) != protocol)
140 {
141 continue;
142 }
143
144 variant = ipmi::getDbusProperty(bus, object.second.begin()->first,
145 object.first, IP_INTERFACE, "Address");
Vijay Khemkaa7231892019-10-11 11:35:05 -0700146
147 objectInfo = std::make_pair(object.first, object.second.begin()->first);
148
149 // if LinkLocalIP found look for Non-LinkLocalIP
150 if (isLinkLocalIP(std::get<std::string>(variant)))
151 {
152 continue;
153 }
154 else
155 {
156 break;
157 }
158 }
159 return objectInfo;
160}
161
162} // namespace network
163
Jayashree-Df0cf6652020-11-30 11:03:30 +0530164namespace boot
165{
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530166using BootSource =
167 sdbusplus::xyz::openbmc_project::Control::Boot::server::Source::Sources;
168using BootMode =
169 sdbusplus::xyz::openbmc_project::Control::Boot::server::Mode::Modes;
170using BootType =
171 sdbusplus::xyz::openbmc_project::Control::Boot::server::Type::Types;
Jayashree-Df0cf6652020-11-30 11:03:30 +0530172
Jayashree-Df0cf6652020-11-30 11:03:30 +0530173using IpmiValue = uint8_t;
174
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530175std::map<IpmiValue, BootSource> sourceIpmiToDbus = {
176 {0x0f, BootSource::Default}, {0x00, BootSource::RemovableMedia},
177 {0x01, BootSource::Network}, {0x02, BootSource::Disk},
Delphine CC Chiu7bb45922023-04-10 13:34:04 +0800178 {0x03, BootSource::ExternalMedia}, {0x04, BootSource::RemovableMedia},
179 {0x09, BootSource::Network}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530180
Delphine CC Chiuc0f918b2023-03-22 14:48:04 +0800181std::map<IpmiValue, BootMode> modeIpmiToDbus = {{0x04, BootMode::Setup},
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530182 {0x00, BootMode::Regular}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530183
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530184std::map<IpmiValue, BootType> typeIpmiToDbus = {{0x00, BootType::Legacy},
185 {0x01, BootType::EFI}};
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530186
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530187std::map<std::optional<BootSource>, IpmiValue> sourceDbusToIpmi = {
188 {BootSource::Default, 0x0f},
189 {BootSource::RemovableMedia, 0x00},
190 {BootSource::Network, 0x01},
191 {BootSource::Disk, 0x02},
192 {BootSource::ExternalMedia, 0x03}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530193
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530194std::map<std::optional<BootMode>, IpmiValue> modeDbusToIpmi = {
Delphine CC Chiuc0f918b2023-03-22 14:48:04 +0800195 {BootMode::Setup, 0x04}, {BootMode::Regular, 0x00}};
Jayashree-Df0cf6652020-11-30 11:03:30 +0530196
Jayashree Dhanapal77ee4892022-04-08 16:53:51 +0530197std::map<std::optional<BootType>, IpmiValue> typeDbusToIpmi = {
198 {BootType::Legacy, 0x00}, {BootType::EFI, 0x01}};
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530199
Delphine CC Chiuc0f918b2023-03-22 14:48:04 +0800200static constexpr auto bootEnableIntf = "xyz.openbmc_project.Object.Enable";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530201static constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
202static constexpr auto bootSourceIntf =
203 "xyz.openbmc_project.Control.Boot.Source";
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530204static constexpr auto bootTypeIntf = "xyz.openbmc_project.Control.Boot.Type";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530205static constexpr auto bootSourceProp = "BootSource";
206static constexpr auto bootModeProp = "BootMode";
Jayashree Dhanapal778147d2022-03-30 16:48:53 +0530207static constexpr auto bootTypeProp = "BootType";
Delphine CC Chiuc0f918b2023-03-22 14:48:04 +0800208static constexpr auto bootEnableProp = "Enabled";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530209
Jayashree-Df0cf6652020-11-30 11:03:30 +0530210std::tuple<std::string, std::string> objPath(size_t id)
211{
212 std::string hostName = "host" + std::to_string(id);
Patrick Williams2405ae92023-05-10 07:50:09 -0500213 std::string bootObjPath = "/xyz/openbmc_project/control/" + hostName +
214 "/boot";
Jayashree-Df0cf6652020-11-30 11:03:30 +0530215 return std::make_tuple(std::move(bootObjPath), std::move(hostName));
216}
217
Delphine CC Chiu7bb45922023-04-10 13:34:04 +0800218/* Helper functions to set boot order */
219void setBootOrder(std::string bootObjPath, const std::vector<uint8_t>& bootSeq,
220 std::string bootOrderKey)
221{
222 if (bootSeq.size() != SIZE_BOOT_ORDER)
223 {
224 phosphor::logging::log<phosphor::logging::level::ERR>(
225 "Invalid Boot order length received");
226 return;
227 }
228
229 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
230
231 uint8_t mode = bootSeq.front();
232
233 // SETTING BOOT MODE PROPERTY
234 uint8_t bootModeBit = mode & 0x04;
235 auto bootValue = ipmi::boot::modeIpmiToDbus.at(bootModeBit);
236
237 std::string bootOption =
238 sdbusplus::message::convert_to_string<boot::BootMode>(bootValue);
239
240 std::string service = getService(*dbus, ipmi::boot::bootModeIntf,
241 bootObjPath);
242 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf,
243 ipmi::boot::bootModeProp, bootOption);
244
245 // SETTING BOOT SOURCE PROPERTY
246 auto bootOrder = ipmi::boot::sourceIpmiToDbus.at(bootSeq.at(1));
247 std::string bootSource =
248 sdbusplus::message::convert_to_string<boot::BootSource>(bootOrder);
249
250 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath);
251 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf,
252 ipmi::boot::bootSourceProp, bootSource);
253
254 // SETTING BOOT TYPE PROPERTY
255 uint8_t bootTypeBit = mode & 0x01;
256 auto bootTypeVal = ipmi::boot::typeIpmiToDbus.at(bootTypeBit);
257
258 std::string bootType =
259 sdbusplus::message::convert_to_string<boot::BootType>(bootTypeVal);
260
261 service = getService(*dbus, ipmi::boot::bootTypeIntf, bootObjPath);
262
263 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootTypeIntf,
264 ipmi::boot::bootTypeProp, bootType);
265
266 // Set the valid bit to boot enabled property
267 service = getService(*dbus, ipmi::boot::bootEnableIntf, bootObjPath);
268
269 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootEnableIntf,
270 ipmi::boot::bootEnableProp,
271 (mode & BOOT_MODE_BOOT_FLAG) ? true : false);
272
273 nlohmann::json bootMode;
274
275 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI) ? true : false;
276 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR) ? true : false;
277 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT) ? true : false;
278 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG) ? true : false;
279 oemData[bootOrderKey][KEY_BOOT_MODE] = bootMode;
280
281 /* Initialize boot sequence array */
282 oemData[bootOrderKey][KEY_BOOT_SEQ] = {};
283 for (size_t i = 1; i < SIZE_BOOT_ORDER; i++)
284 {
285 if (bootSeq.at(i) >= BOOT_SEQ_ARRAY_SIZE)
286 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = "NA";
287 else
288 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] =
289 bootSeqDefine[bootSeq.at(i)];
290 }
291
292 flushOemData();
293}
294
295void getBootOrder(std::string bootObjPath, std::vector<uint8_t>& bootSeq,
296 std::string hostName)
297{
298 if (oemData.find(hostName) == oemData.end())
299 {
300 /* Return default boot order 0100090203ff */
301 bootSeq.push_back(BOOT_MODE_UEFI);
302 bootSeq.push_back(static_cast<uint8_t>(bootMap["USB_DEV"]));
303 bootSeq.push_back(static_cast<uint8_t>(bootMap["NET_IPV6"]));
304 bootSeq.push_back(static_cast<uint8_t>(bootMap["SATA_HDD"]));
305 bootSeq.push_back(static_cast<uint8_t>(bootMap["SATA_CD"]));
306 bootSeq.push_back(0xff);
307
308 phosphor::logging::log<phosphor::logging::level::INFO>(
309 "Set default boot order");
310 setBootOrder(bootObjPath, bootSeq, hostName);
311 return;
312 }
313
314 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
315
316 // GETTING PROPERTY OF MODE INTERFACE
317
318 std::string service = getService(*dbus, ipmi::boot::bootModeIntf,
319 bootObjPath);
320 Value variant = getDbusProperty(*dbus, service, bootObjPath,
321 ipmi::boot::bootModeIntf,
322 ipmi::boot::bootModeProp);
323
324 auto bootMode = sdbusplus::message::convert_from_string<boot::BootMode>(
325 std::get<std::string>(variant));
326
327 uint8_t bootOption = ipmi::boot::modeDbusToIpmi.at(bootMode);
328
329 // GETTING PROPERTY OF TYPE INTERFACE
330
331 service = getService(*dbus, ipmi::boot::bootTypeIntf, bootObjPath);
332 variant = getDbusProperty(*dbus, service, bootObjPath,
333 ipmi::boot::bootTypeIntf,
334 ipmi::boot::bootTypeProp);
335
336 auto bootType = sdbusplus::message::convert_from_string<boot::BootType>(
337 std::get<std::string>(variant));
338
339 // Get the valid bit to boot enabled property
340 service = getService(*dbus, ipmi::boot::bootEnableIntf, bootObjPath);
341 variant = getDbusProperty(*dbus, service, bootObjPath,
342 ipmi::boot::bootEnableIntf,
343 ipmi::boot::bootEnableProp);
344
345 bool validFlag = std::get<bool>(variant);
346
347 uint8_t bootTypeVal = ipmi::boot::typeDbusToIpmi.at(bootType);
348
349 bootSeq.push_back(bootOption | bootTypeVal);
350
351 if (validFlag)
352 {
353 bootSeq.front() |= BOOT_MODE_BOOT_FLAG;
354 }
355
356 nlohmann::json bootModeJson = oemData[hostName][KEY_BOOT_MODE];
357 if (bootModeJson["CMOS_CLR"])
358 bootSeq.front() |= BOOT_MODE_CMOS_CLR;
359
360 for (int i = 1; i < SIZE_BOOT_ORDER; i++)
361 {
362 std::string seqStr = oemData[hostName][KEY_BOOT_SEQ][i - 1];
363 if (bootMap.find(seqStr) != bootMap.end())
364 bootSeq.push_back(bootMap[seqStr]);
365 else
366 bootSeq.push_back(0xff);
367 }
368}
369
Jayashree-Df0cf6652020-11-30 11:03:30 +0530370} // namespace boot
371
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700372//----------------------------------------------------------------------
373// Helper functions for storing oem data
374//----------------------------------------------------------------------
375
376void flushOemData()
377{
378 std::ofstream file(JSON_OEM_DATA_FILE);
379 file << oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -0700380 file.close();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700381 return;
382}
383
Vijay Khemka63c99be2020-05-27 19:14:35 -0700384std::string bytesToStr(uint8_t* byte, int len)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700385{
386 std::stringstream ss;
387 int i;
388
389 ss << std::hex;
390 for (i = 0; i < len; i++)
391 {
392 ss << std::setw(2) << std::setfill('0') << (int)byte[i];
393 }
394
395 return ss.str();
396}
397
Vijay Khemka63c99be2020-05-27 19:14:35 -0700398int strToBytes(std::string& str, uint8_t* data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700399{
400 std::string sstr;
Willy Tue39f9392022-06-15 13:24:20 -0700401 size_t i;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700402
403 for (i = 0; i < (str.length()) / 2; i++)
404 {
405 sstr = str.substr(i * 2, 2);
406 data[i] = (uint8_t)std::strtol(sstr.c_str(), NULL, 16);
407 }
408 return i;
409}
410
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530411int readDimmType(std::string& data, uint8_t param)
412{
413 nlohmann::json dimmObj;
414 /* Get dimm type names stored in json file */
415 std::ifstream file(JSON_DIMM_TYPE_FILE);
416 if (file)
417 {
418 file >> dimmObj;
419 file.close();
420 }
421 else
422 {
423 phosphor::logging::log<phosphor::logging::level::ERR>(
424 "DIMM type names file not found",
425 phosphor::logging::entry("DIMM_TYPE_FILE=%s", JSON_DIMM_TYPE_FILE));
426 return -1;
427 }
428
429 std::string dimmKey = "dimm_type" + std::to_string(param);
430 auto obj = dimmObj[dimmKey]["short_name"];
431 data = obj;
432 return 0;
433}
434
Vijay Khemka63c99be2020-05-27 19:14:35 -0700435ipmi_ret_t getNetworkData(uint8_t lan_param, char* data)
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700436{
437 ipmi_ret_t rc = IPMI_CC_OK;
Patrick Williamscd315e02022-07-22 19:26:52 -0500438 sdbusplus::bus_t bus(ipmid_get_sd_bus_connection());
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700439
440 const std::string ethdevice = "eth0";
441
442 switch (static_cast<LanParam>(lan_param))
443 {
Vijay Khemkad1194022020-05-27 18:58:33 -0700444 case LanParam::IP:
445 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700446 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700447 auto ipObjectInfo = ipmi::network::getIPObject(
Potin Lai8d1a81e2022-12-20 11:13:45 +0800448 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT,
449 ipmi::network::IPV4_PROTOCOL, ethdevice);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700450
451 auto properties = ipmi::getAllDbusProperties(
452 bus, ipObjectInfo.second, ipObjectInfo.first,
453 ipmi::network::IP_INTERFACE);
454
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500455 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700456
457 std::strcpy(data, ipaddress.c_str());
458 }
459 break;
460
Vijay Khemkad1194022020-05-27 18:58:33 -0700461 case LanParam::IPV6:
462 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700463 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700464 auto ipObjectInfo = ipmi::network::getIPObject(
Potin Lai8d1a81e2022-12-20 11:13:45 +0800465 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT,
466 ipmi::network::IPV6_PROTOCOL, ethdevice);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700467
468 auto properties = ipmi::getAllDbusProperties(
469 bus, ipObjectInfo.second, ipObjectInfo.first,
470 ipmi::network::IP_INTERFACE);
471
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500472 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700473
474 std::strcpy(data, ipaddress.c_str());
475 }
476 break;
477
Vijay Khemkad1194022020-05-27 18:58:33 -0700478 case LanParam::MAC:
479 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700480 std::string macAddress;
481 auto macObjectInfo =
482 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
483 ipmi::network::ROOT, ethdevice);
484
485 auto variant = ipmi::getDbusProperty(
486 bus, macObjectInfo.second, macObjectInfo.first,
487 ipmi::network::MAC_INTERFACE, "MACAddress");
488
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500489 macAddress = std::get<std::string>(variant);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700490
491 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
492 (data), (data + 1), (data + 2), (data + 3), (data + 4),
493 (data + 5));
494 std::strcpy(data, macAddress.c_str());
495 }
496 break;
497
498 default:
499 rc = IPMI_CC_PARM_OUT_OF_RANGE;
500 }
501 return rc;
502}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800503
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530504bool isMultiHostPlatform()
505{
506 bool platform;
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530507 if (hostInstances == "0")
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530508 {
509 platform = false;
510 }
511 else
512 {
513 platform = true;
514 }
515 return platform;
516}
517
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800518// return code: 0 successful
Vijay Khemka63c99be2020-05-27 19:14:35 -0700519int8_t getFruData(std::string& data, std::string& name)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800520{
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530521 size_t pos;
522 static constexpr const auto depth = 0;
523 std::vector<std::string> paths;
524 std::string machinePath;
525 std::string baseBoard = "Baseboard";
526
527 bool platform = isMultiHostPlatform();
528 if (platform == true)
529 {
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530530 getSelectorPosition(pos);
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530531 }
532
533 sd_bus* bus = NULL;
534 int ret = sd_bus_default_system(&bus);
535 if (ret < 0)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800536 {
537 phosphor::logging::log<phosphor::logging::level::ERR>(
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530538 "Failed to connect to system bus",
539 phosphor::logging::entry("ERRNO=0x%X", -ret));
540 sd_bus_unref(bus);
541 return -1;
542 }
Patrick Williamscd315e02022-07-22 19:26:52 -0500543 sdbusplus::bus_t dbus(bus);
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530544 auto mapperCall = dbus.new_method_call("xyz.openbmc_project.ObjectMapper",
545 "/xyz/openbmc_project/object_mapper",
546 "xyz.openbmc_project.ObjectMapper",
547 "GetSubTreePaths");
548 static constexpr std::array<const char*, 1> interface = {
549 "xyz.openbmc_project.Inventory.Decorator.Asset"};
550 mapperCall.append("/xyz/openbmc_project/inventory/", depth, interface);
551
552 try
553 {
554 auto reply = dbus.call(mapperCall);
555 reply.read(paths);
556 }
557 catch (sdbusplus::exception_t& e)
558 {
559 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800560 return -1;
561 }
562
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530563 for (const auto& path : paths)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800564 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530565 if (platform == true)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800566 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530567 if (pos == BMC_POS)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800568 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530569 machinePath = baseBoard;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800570 }
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530571 else
572 {
573 machinePath = "_" + std::to_string(pos);
574 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800575 }
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530576 else
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800577 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530578 machinePath = baseBoard;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800579 }
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530580
581 auto found = path.find(machinePath);
Patrick Williams123cbcc2022-06-24 06:13:59 -0500582 if (found == std::string::npos)
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530583 {
584 continue;
585 }
586
587 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
588 std::string service = getService(
589 *dbus, "xyz.openbmc_project.Inventory.Decorator.Asset", path);
590
591 auto Value = ipmi::getDbusProperty(
592 *dbus, service, path,
593 "xyz.openbmc_project.Inventory.Decorator.Asset", name);
594
595 data = std::get<std::string>(Value);
596 return 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800597 }
598 return -1;
599}
600
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530601int8_t sysConfig(std::vector<std::string>& data, size_t pos)
602{
603 nlohmann::json sysObj;
604 std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(pos);
605 std::string result, typeName;
606 uint8_t res[MAX_BUF];
607
608 /* Get sysConfig data stored in json file */
609 std::ifstream file(JSON_OEM_DATA_FILE);
610 if (file)
611 {
612 file >> sysObj;
613 file.close();
614 }
615 else
616 {
617 phosphor::logging::log<phosphor::logging::level::ERR>(
618 "oemData file not found",
619 phosphor::logging::entry("OEM_DATA_FILE=%s", JSON_OEM_DATA_FILE));
620 return -1;
621 }
622
623 if (sysObj.find(dimmInfo) == sysObj.end())
624 {
625 phosphor::logging::log<phosphor::logging::level::ERR>(
626 "sysconfig key not available",
627 phosphor::logging::entry("SYS_JSON_KEY=%s", dimmInfo.c_str()));
628 return -1;
629 }
630 /* Get dimm type names stored in json file */
631 nlohmann::json dimmObj;
632 std::ifstream dimmFile(JSON_DIMM_TYPE_FILE);
633 if (file)
634 {
635 dimmFile >> dimmObj;
636 dimmFile.close();
637 }
638 else
639 {
640 phosphor::logging::log<phosphor::logging::level::ERR>(
641 "DIMM type names file not found",
642 phosphor::logging::entry("DIMM_TYPE_FILE=%s", JSON_DIMM_TYPE_FILE));
643 return -1;
644 }
645 std::vector<std::string> a;
646 for (auto& j : dimmObj.items())
647 {
648 std::string name = j.key();
649 a.push_back(name);
650 }
651
652 uint8_t len = a.size();
653 for (uint8_t ii = 0; ii < len; ii++)
654 {
655 std::string indKey = std::to_string(ii);
656 std::string speedSize = sysObj[dimmInfo][indKey][DIMM_SPEED];
657 strToBytes(speedSize, res);
658 auto speed = (res[1] << 8 | res[0]);
659 size_t dimmSize = ((res[3] << 8 | res[2]) / 1000);
660
661 if (dimmSize == 0)
662 {
663 std::cerr << "Dimm information not available for slot_" +
664 std::to_string(ii)
665 << std::endl;
666 continue;
667 }
668 std::string type = sysObj[dimmInfo][indKey][DIMM_TYPE];
669 std::string dualInlineMem = sysObj[dimmInfo][indKey][KEY_DIMM_TYPE];
670 strToBytes(type, res);
671 size_t dimmType = res[0];
672 if (dimmVenMap.find(dimmType) == dimmVenMap.end())
673 {
674 typeName = "unknown";
675 }
676 else
677 {
678 typeName = dimmVenMap[dimmType];
679 }
680 result = dualInlineMem + "/" + typeName + "/" + std::to_string(speed) +
681 "MHz" + "/" + std::to_string(dimmSize) + "GB";
682 data.push_back(result);
683 }
684 return 0;
685}
686
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +0530687int8_t procInfo(std::string& result, size_t pos)
688{
689 std::vector<char> data;
690 uint8_t res[MAX_BUF];
691 std::string procIndex = "00";
692 nlohmann::json proObj;
693 std::string procInfo = KEY_Q_PROC_INFO + std::to_string(pos);
694 /* Get processor data stored in json file */
695 std::ifstream file(JSON_OEM_DATA_FILE);
696 if (file)
697 {
698 file >> proObj;
699 file.close();
700 }
701 else
702 {
703 phosphor::logging::log<phosphor::logging::level::ERR>(
704 "oemData file not found",
705 phosphor::logging::entry("OEM_DATA_FILE=%s", JSON_OEM_DATA_FILE));
706 return -1;
707 }
708 if (proObj.find(procInfo) == proObj.end())
709 {
710 phosphor::logging::log<phosphor::logging::level::ERR>(
711 "processor info key not available",
712 phosphor::logging::entry("PROC_JSON_KEY=%s", procInfo.c_str()));
713 return -1;
714 }
715 std::string procName = proObj[procInfo][procIndex][KEY_PROC_NAME];
716 std::string basicInfo = proObj[procInfo][procIndex][KEY_BASIC_INFO];
717 // Processor Product Name
718 strToBytes(procName, res);
719 data.assign(reinterpret_cast<char*>(&res),
720 reinterpret_cast<char*>(&res) + sizeof(res));
721
722 std::string s(data.begin(), data.end());
723 std::regex regex(" ");
724 std::vector<std::string> productName(
725 std::sregex_token_iterator(s.begin(), s.end(), regex, -1),
726 std::sregex_token_iterator());
727
728 // Processor core and frequency
729 strToBytes(basicInfo, res);
730 uint16_t coreNum = res[0];
731 double procFrequency = (float)(res[4] << 8 | res[3]) / 1000;
732 result = "CPU:" + productName[2] + "/" + std::to_string(procFrequency) +
733 "GHz" + "/" + std::to_string(coreNum) + "c";
734 return 0;
735}
736
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800737typedef struct
738{
739 uint8_t cur_power_state;
740 uint8_t last_power_event;
741 uint8_t misc_power_state;
742 uint8_t front_panel_button_cap_status;
743} ipmi_get_chassis_status_t;
744
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800745//----------------------------------------------------------------------
746// Get Debug Frame Info
747//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700748ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800749 ipmi_request_t request,
750 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700751 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800752{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700753 uint8_t* req = reinterpret_cast<uint8_t*>(request);
754 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Peter Yinb340aa22024-07-08 16:07:55 +0800755 uint8_t num_frames = debugCardFrameSize;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800756
757 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
758 res[SIZE_IANA_ID] = num_frames;
759 *data_len = SIZE_IANA_ID + 1;
760
761 return IPMI_CC_OK;
762}
763
764//----------------------------------------------------------------------
765// Get Debug Updated Frames
766//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700767ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800768 ipmi_request_t request,
769 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700770 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800771{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700772 uint8_t* req = reinterpret_cast<uint8_t*>(request);
773 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800774 uint8_t num_updates = 3;
775 *data_len = 4;
776
777 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
778 res[SIZE_IANA_ID] = num_updates;
779 *data_len = SIZE_IANA_ID + num_updates + 1;
780 res[SIZE_IANA_ID + 1] = 1; // info page update
781 res[SIZE_IANA_ID + 2] = 2; // cri sel update
782 res[SIZE_IANA_ID + 3] = 3; // cri sensor update
783
784 return IPMI_CC_OK;
785}
786
787//----------------------------------------------------------------------
788// Get Debug POST Description
789//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700790ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800791 ipmi_request_t request,
792 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700793 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800794{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700795 uint8_t* req = reinterpret_cast<uint8_t*>(request);
796 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800797 uint8_t index = 0;
798 uint8_t next = 0;
799 uint8_t end = 0;
800 uint8_t phase = 0;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700801 uint8_t descLen = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800802 int ret;
803
804 index = req[3];
805 phase = req[4];
806
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700807 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800808 if (ret)
809 {
810 memcpy(res, req, SIZE_IANA_ID); // IANA ID
811 *data_len = SIZE_IANA_ID;
812 return IPMI_CC_UNSPECIFIED_ERROR;
813 }
814
815 memcpy(res, req, SIZE_IANA_ID); // IANA ID
816 res[3] = index;
817 res[4] = next;
818 res[5] = phase;
819 res[6] = end;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700820 res[7] = descLen;
821 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800822
823 return IPMI_CC_OK;
824}
825
826//----------------------------------------------------------------------
827// Get Debug GPIO Description
828//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700829ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800830 ipmi_request_t request,
831 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700832 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800833{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700834 uint8_t* req = reinterpret_cast<uint8_t*>(request);
835 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800836
Vijay Khemka38183d62019-08-28 16:19:33 -0700837 uint8_t index = 0;
838 uint8_t next = 0;
839 uint8_t level = 0;
840 uint8_t pinDef = 0;
841 uint8_t descLen = 0;
842 int ret;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800843
Vijay Khemka38183d62019-08-28 16:19:33 -0700844 index = req[3];
845
846 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen,
847 &res[8]);
848 if (ret)
849 {
850 memcpy(res, req, SIZE_IANA_ID); // IANA ID
851 *data_len = SIZE_IANA_ID;
852 return IPMI_CC_UNSPECIFIED_ERROR;
853 }
854
855 memcpy(res, req, SIZE_IANA_ID); // IANA ID
856 res[3] = index;
857 res[4] = next;
858 res[5] = level;
859 res[6] = pinDef;
860 res[7] = descLen;
861 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800862
863 return IPMI_CC_OK;
864}
865
866//----------------------------------------------------------------------
867// Get Debug Frame Data
868//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700869ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800870 ipmi_request_t request,
871 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700872 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800873{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700874 uint8_t* req = reinterpret_cast<uint8_t*>(request);
875 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800876 uint8_t frame;
877 uint8_t page;
878 uint8_t next;
879 uint8_t count;
880 int ret;
881
882 frame = req[3];
883 page = req[4];
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800884
885 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]);
886 if (ret)
887 {
888 memcpy(res, req, SIZE_IANA_ID); // IANA ID
889 *data_len = SIZE_IANA_ID;
890 return IPMI_CC_UNSPECIFIED_ERROR;
891 }
892
893 memcpy(res, req, SIZE_IANA_ID); // IANA ID
894 res[3] = frame;
895 res[4] = page;
896 res[5] = next;
897 res[6] = count;
898 *data_len = SIZE_IANA_ID + 4 + count;
899
900 return IPMI_CC_OK;
901}
902
903//----------------------------------------------------------------------
904// Get Debug Control Panel
905//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700906ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800907 ipmi_request_t request,
908 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -0700909 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800910{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700911 uint8_t* req = reinterpret_cast<uint8_t*>(request);
912 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800913
914 uint8_t panel;
915 uint8_t operation;
916 uint8_t item;
917 uint8_t count;
918 ipmi_ret_t ret;
919
920 panel = req[3];
921 operation = req[4];
922 item = req[5];
923
924 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]);
925
926 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
927 *data_len = SIZE_IANA_ID + count;
928
929 return ret;
930}
931
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800932//----------------------------------------------------------------------
933// Set Dimm Info (CMD_OEM_SET_DIMM_INFO)
934//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700935ipmi_ret_t ipmiOemSetDimmInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
936 ipmi_response_t, ipmi_data_len_t data_len,
937 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800938{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700939 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700940
941 uint8_t index = req[0];
942 uint8_t type = req[1];
943 uint16_t speed;
944 uint32_t size;
945
946 memcpy(&speed, &req[2], 2);
947 memcpy(&size, &req[4], 4);
948
949 std::stringstream ss;
950 ss << std::hex;
951 ss << std::setw(2) << std::setfill('0') << (int)index;
952
953 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index;
954 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type;
955 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed;
956 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size;
957
958 flushOemData();
959
960 *data_len = 0;
961
962 return IPMI_CC_OK;
963}
964
965//----------------------------------------------------------------------
966// Get Board ID (CMD_OEM_GET_BOARD_ID)
967//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -0700968ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
969 ipmi_response_t, ipmi_data_len_t data_len,
970 ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700971{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700972 /* TODO: Needs to implement this after GPIO implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800973 *data_len = 0;
974
975 return IPMI_CC_OK;
976}
977
Bonnie Lo4ae63e72023-02-09 15:27:54 +0800978//----------------------------------------------------------------------
979// Get port 80 record (CMD_OEM_GET_80PORT_RECORD)
980//----------------------------------------------------------------------
981ipmi::RspType<std::vector<uint8_t>>
982 ipmiOemGet80PortRecord(ipmi::Context::ptr ctx)
983{
984 auto postCodeService = "xyz.openbmc_project.State.Boot.PostCode" +
985 std::to_string(ctx->hostIdx + 1);
986 auto postCodeObjPath = "/xyz/openbmc_project/State/Boot/PostCode" +
987 std::to_string(ctx->hostIdx + 1);
988 constexpr auto postCodeInterface =
989 "xyz.openbmc_project.State.Boot.PostCode";
990 const static uint16_t lastestPostCodeIndex = 1;
991 constexpr const auto maxPostCodeLen =
992 224; // The length must be lower than IPMB limitation
993 size_t startIndex = 0;
994
995 std::vector<std::tuple<uint64_t, std::vector<uint8_t>>> postCodes;
996 std::vector<uint8_t> resData;
997
998 auto conn = getSdBus();
999 /* Get the post codes by calling GetPostCodes method */
Patrick Williams2405ae92023-05-10 07:50:09 -05001000 auto msg = conn->new_method_call(postCodeService.c_str(),
1001 postCodeObjPath.c_str(), postCodeInterface,
1002 "GetPostCodes");
Bonnie Lo4ae63e72023-02-09 15:27:54 +08001003 msg.append(lastestPostCodeIndex);
1004
1005 try
1006 {
1007 auto reply = conn->call(msg);
1008 reply.read(postCodes);
1009 }
1010 catch (const sdbusplus::exception::SdBusError& e)
1011 {
1012 phosphor::logging::log<phosphor::logging::level::ERR>(
1013 "IPMI Get80PortRecord Failed in call method",
1014 phosphor::logging::entry("ERROR=%s", e.what()));
1015 return ipmi::responseUnspecifiedError();
1016 }
1017
1018 /* Get post code data */
1019 for (size_t i = 0; i < postCodes.size(); ++i)
1020 {
1021 uint64_t primaryPostCode = std::get<uint64_t>(postCodes[i]);
1022 for (int j = postCodeSize - 1; j >= 0; --j)
1023 {
1024 uint8_t postCode =
1025 ((primaryPostCode >> (sizeof(uint64_t) * j)) & 0xFF);
1026 resData.emplace_back(postCode);
1027 }
1028 }
1029
1030 std::vector<uint8_t> response;
1031 if (resData.size() > maxPostCodeLen)
1032 {
1033 startIndex = resData.size() - maxPostCodeLen;
1034 }
1035
1036 response.assign(resData.begin() + startIndex, resData.end());
1037
1038 return ipmi::responseSuccess(response);
1039}
1040
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001041//----------------------------------------------------------------------
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001042// Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
1043//----------------------------------------------------------------------
Jayashree-Df0cf6652020-11-30 11:03:30 +05301044ipmi::RspType<std::vector<uint8_t>>
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001045 ipmiOemSetBootOrder(ipmi::Context::ptr ctx, std::vector<uint8_t> bootSeq)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001046{
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001047 size_t len = bootSeq.size();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001048
1049 if (len != SIZE_BOOT_ORDER)
1050 {
1051 phosphor::logging::log<phosphor::logging::level::ERR>(
1052 "Invalid Boot order length received");
Jayashree-Df0cf6652020-11-30 11:03:30 +05301053 return ipmi::responseReqDataLenInvalid();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001054 }
1055
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +05301056 std::optional<size_t> hostId = findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001057
Jayashree-Df0cf6652020-11-30 11:03:30 +05301058 if (!hostId)
1059 {
1060 phosphor::logging::log<phosphor::logging::level::ERR>(
1061 "Invalid Host Id received");
1062 return ipmi::responseInvalidCommand();
1063 }
1064 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
1065
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001066 ipmi::boot::setBootOrder(bootObjPath, bootSeq, hostName);
Jayashree-Df0cf6652020-11-30 11:03:30 +05301067
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001068 return ipmi::responseSuccess(bootSeq);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001069}
1070
1071//----------------------------------------------------------------------
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001072// Get Boot Order (CMD_OEM_GET_BOOT_ORDER)
1073//----------------------------------------------------------------------
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001074ipmi::RspType<std::vector<uint8_t>> ipmiOemGetBootOrder(ipmi::Context::ptr ctx)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001075{
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001076 std::vector<uint8_t> bootSeq;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001077
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +05301078 std::optional<size_t> hostId = findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001079
Jayashree-Df0cf6652020-11-30 11:03:30 +05301080 if (!hostId)
1081 {
1082 phosphor::logging::log<phosphor::logging::level::ERR>(
1083 "Invalid Host Id received");
1084 return ipmi::responseInvalidCommand();
1085 }
1086 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
1087
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001088 ipmi::boot::getBootOrder(bootObjPath, bootSeq, hostName);
Jayashree-Df0cf6652020-11-30 11:03:30 +05301089
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001090 return ipmi::responseSuccess(bootSeq);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001091}
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001092// Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO)
1093//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001094ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t, ipmi_cmd_t,
1095 ipmi_request_t request, ipmi_response_t,
1096 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001097{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001098 machineConfigInfo_t* req = reinterpret_cast<machineConfigInfo_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001099 uint8_t len = *data_len;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001100
1101 *data_len = 0;
1102
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001103 if (len < sizeof(machineConfigInfo_t))
1104 {
1105 phosphor::logging::log<phosphor::logging::level::ERR>(
1106 "Invalid machine configuration length received");
1107 return IPMI_CC_REQ_DATA_LEN_INVALID;
1108 }
1109
Vijay Khemka63c99be2020-05-27 19:14:35 -07001110 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001111 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN";
1112 else
1113 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] =
1114 chassisType[req->chassis_type];
1115
Vijay Khemka63c99be2020-05-27 19:14:35 -07001116 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001117 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN";
1118 else
1119 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type];
1120
1121 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt;
1122 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt;
1123 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt;
1124 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt;
1125
Vijay Khemka63c99be2020-05-27 19:14:35 -07001126 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001127 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN";
1128 else
1129 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type];
1130
1131 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {};
1132 int i = 0;
1133 if (req->pcie_card_loc & BIT_0)
1134 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1";
1135 if (req->pcie_card_loc & BIT_1)
1136 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2";
1137 if (req->pcie_card_loc & BIT_2)
1138 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3";
1139 if (req->pcie_card_loc & BIT_3)
1140 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4";
1141
Vijay Khemka63c99be2020-05-27 19:14:35 -07001142 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001143 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN";
1144 else
1145 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] =
1146 pcieType[req->slot1_pcie_type];
1147
Vijay Khemka63c99be2020-05-27 19:14:35 -07001148 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001149 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN";
1150 else
1151 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] =
1152 pcieType[req->slot2_pcie_type];
1153
Vijay Khemka63c99be2020-05-27 19:14:35 -07001154 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001155 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN";
1156 else
1157 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] =
1158 pcieType[req->slot3_pcie_type];
1159
Vijay Khemka63c99be2020-05-27 19:14:35 -07001160 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001161 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN";
1162 else
1163 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] =
1164 pcieType[req->slot4_pcie_type];
1165
1166 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt;
1167
1168 flushOemData();
1169
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001170 return IPMI_CC_OK;
1171}
1172
1173//----------------------------------------------------------------------
1174// Set POST start (CMD_OEM_SET_POST_START)
1175//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001176ipmi_ret_t ipmiOemSetPostStart(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1177 ipmi_response_t, ipmi_data_len_t data_len,
1178 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001179{
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001180 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event");
1181
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001182 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001183 *data_len = 0;
1184 return IPMI_CC_OK;
1185}
1186
1187//----------------------------------------------------------------------
1188// Set POST End (CMD_OEM_SET_POST_END)
1189//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001190ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1191 ipmi_response_t, ipmi_data_len_t data_len,
1192 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001193{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001194 struct timespec ts;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001195
1196 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event");
1197
1198 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001199
1200 // Timestamp post end time.
1201 clock_gettime(CLOCK_REALTIME, &ts);
1202 oemData[KEY_TS_SLED] = ts.tv_sec;
1203 flushOemData();
1204
1205 // Sync time with system
1206 // TODO: Add code for syncing time
1207
1208 return IPMI_CC_OK;
1209}
1210
1211//----------------------------------------------------------------------
1212// Set PPIN Info (CMD_OEM_SET_PPIN_INFO)
1213//----------------------------------------------------------------------
1214// Inform BMC about PPIN data of 8 bytes for each CPU
1215//
1216// Request:
1217// Byte 1:8 – CPU0 PPIN data
1218// Optional:
1219// Byte 9:16 – CPU1 PPIN data
1220//
1221// Response:
1222// Byte 1 – Completion Code
Willy Tue39f9392022-06-15 13:24:20 -07001223ipmi_ret_t ipmiOemSetPPINInfo(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 Khemka1d4a0692019-04-09 15:20:28 -07001226{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001227 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001228 std::string ppinStr;
1229 int len;
1230
1231 if (*data_len > SIZE_CPU_PPIN * 2)
1232 len = SIZE_CPU_PPIN * 2;
1233 else
1234 len = *data_len;
1235 *data_len = 0;
1236
1237 ppinStr = bytesToStr(req, len);
1238 oemData[KEY_PPIN_INFO] = ppinStr.c_str();
1239 flushOemData();
1240
1241 return IPMI_CC_OK;
1242}
1243
1244//----------------------------------------------------------------------
1245// Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER)
1246//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001247ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1248 ipmi_response_t, ipmi_data_len_t data_len,
1249 ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001250{
1251 /* Do nothing, return success */
1252 *data_len = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001253 return IPMI_CC_OK;
1254}
1255
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001256// Helper function to set guid at offset in EEPROM
Willy Tue39f9392022-06-15 13:24:20 -07001257[[maybe_unused]] static int setGUID(off_t offset, uint8_t* guid)
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001258{
1259 int fd = -1;
1260 ssize_t len;
1261 int ret = 0;
cchouxb2ae88b2023-09-13 00:35:36 +08001262 std::string eepromPath = FRU_EEPROM;
1263
1264 // find the eeprom path of MB FRU
1265 auto device = getMbFruDevice();
1266 if (device)
1267 {
1268 auto [bus, address] = *device;
1269 std::stringstream ss;
1270 ss << "/sys/bus/i2c/devices/" << static_cast<int>(bus) << "-"
1271 << std::setw(4) << std::setfill('0') << std::hex
1272 << static_cast<int>(address) << "/eeprom";
1273 eepromPath = ss.str();
1274 }
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001275
1276 errno = 0;
1277
1278 // Check if file is present
cchouxb2ae88b2023-09-13 00:35:36 +08001279 if (access(eepromPath.c_str(), F_OK) == -1)
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001280 {
cchouxb2ae88b2023-09-13 00:35:36 +08001281 std::cerr << "Unable to access: " << eepromPath << std::endl;
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001282 return errno;
1283 }
1284
1285 // Open the file
cchouxb2ae88b2023-09-13 00:35:36 +08001286 fd = open(eepromPath.c_str(), O_WRONLY);
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001287 if (fd == -1)
1288 {
cchouxb2ae88b2023-09-13 00:35:36 +08001289 std::cerr << "Unable to open: " << eepromPath << std::endl;
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001290 return errno;
1291 }
1292
1293 // seek to the offset
1294 lseek(fd, offset, SEEK_SET);
1295
1296 // Write bytes to location
1297 len = write(fd, guid, GUID_SIZE);
1298 if (len != GUID_SIZE)
1299 {
1300 phosphor::logging::log<phosphor::logging::level::ERR>(
1301 "GUID write data to EEPROM failed");
1302 ret = errno;
1303 }
1304
1305 close(fd);
1306 return ret;
1307}
1308
1309//----------------------------------------------------------------------
1310// Set System GUID (CMD_OEM_SET_SYSTEM_GUID)
1311//----------------------------------------------------------------------
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301312#if BIC_ENABLED
Bonnie Lo3f671272022-10-12 15:46:45 +08001313ipmi::RspType<> ipmiOemSetSystemGuid(ipmi::Context::ptr ctx,
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301314 std::vector<uint8_t> reqData)
1315{
1316 std::vector<uint8_t> respData;
1317
1318 if (reqData.size() != GUID_SIZE) // 16bytes
1319 {
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301320 return ipmi::responseReqDataLenInvalid();
1321 }
1322
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301323 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
1324
1325 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
1326 return ipmi::responseUnspecifiedError();
1327
1328 return ipmi::responseSuccess();
1329}
1330
1331#else
Potin Laid5353ca2022-08-11 04:52:11 +00001332ipmi_ret_t ipmiOemSetSystemGuid(ipmi_netfn_t, ipmi_cmd_t,
1333 ipmi_request_t request, ipmi_response_t,
1334 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001335{
1336 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1337
1338 if (*data_len != GUID_SIZE) // 16bytes
1339 {
1340 *data_len = 0;
1341 return IPMI_CC_REQ_DATA_LEN_INVALID;
1342 }
1343
1344 *data_len = 0;
1345
1346 if (setGUID(OFFSET_SYS_GUID, req))
1347 {
1348 return IPMI_CC_UNSPECIFIED_ERROR;
1349 }
1350 return IPMI_CC_OK;
1351}
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301352#endif
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001353
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001354//----------------------------------------------------------------------
1355// Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO)
1356//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001357ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1358 ipmi_response_t, ipmi_data_len_t data_len,
1359 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001360{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001361 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001362 *data_len = 0;
1363 return IPMI_CC_OK;
1364}
1365
1366//----------------------------------------------------------------------
1367// Set PPR (CMD_OEM_SET_PPR)
1368//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001369ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
1370 ipmi_response_t, ipmi_data_len_t data_len,
1371 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001372{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001373 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001374 uint8_t pprCnt, pprAct, pprIndex;
1375 uint8_t selParam = req[0];
1376 uint8_t len = *data_len;
1377 std::stringstream ss;
1378 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001379
1380 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001381
1382 switch (selParam)
1383 {
1384 case PPR_ACTION:
1385 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) ==
1386 oemData[KEY_PPR].end())
1387 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1388
1389 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1390 if (pprCnt == 0)
1391 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1392
1393 pprAct = req[1];
1394 /* Check if ppr is enabled or disabled */
1395 if (!(pprAct & 0x80))
1396 pprAct = 0;
1397
1398 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct;
1399 break;
1400 case PPR_ROW_COUNT:
1401 if (req[1] > 100)
1402 return IPMI_CC_PARM_OUT_OF_RANGE;
1403
1404 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1];
1405 break;
1406 case PPR_ROW_ADDR:
1407 pprIndex = req[1];
1408 if (pprIndex > 100)
1409 return IPMI_CC_PARM_OUT_OF_RANGE;
1410
1411 if (len < PPR_ROW_ADDR_LEN + 1)
1412 {
1413 phosphor::logging::log<phosphor::logging::level::ERR>(
1414 "Invalid PPR Row Address length received");
1415 return IPMI_CC_REQ_DATA_LEN_INVALID;
1416 }
1417
1418 ss << std::hex;
1419 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1420
1421 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1422
1423 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN);
1424 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str();
1425 break;
1426 case PPR_HISTORY_DATA:
1427 pprIndex = req[1];
1428 if (pprIndex > 100)
1429 return IPMI_CC_PARM_OUT_OF_RANGE;
1430
1431 if (len < PPR_HST_DATA_LEN + 1)
1432 {
1433 phosphor::logging::log<phosphor::logging::level::ERR>(
1434 "Invalid PPR history data length received");
1435 return IPMI_CC_REQ_DATA_LEN_INVALID;
1436 }
1437
1438 ss << std::hex;
1439 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1440
1441 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1442
1443 str = bytesToStr(&req[1], PPR_HST_DATA_LEN);
1444 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str();
1445 break;
1446 default:
1447 return IPMI_CC_PARM_OUT_OF_RANGE;
1448 break;
1449 }
1450
1451 flushOemData();
1452
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001453 return IPMI_CC_OK;
1454}
1455
1456//----------------------------------------------------------------------
1457// Get PPR (CMD_OEM_GET_PPR)
1458//----------------------------------------------------------------------
Willy Tue39f9392022-06-15 13:24:20 -07001459ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
1460 ipmi_response_t response, ipmi_data_len_t data_len,
1461 ipmi_context_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001462{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001463 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1464 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001465 uint8_t pprCnt, pprIndex;
1466 uint8_t selParam = req[0];
1467 std::stringstream ss;
1468 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001469
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001470 /* Any failure will return zero length data */
1471 *data_len = 0;
1472
1473 switch (selParam)
1474 {
1475 case PPR_ACTION:
1476 res[0] = 0;
1477 *data_len = 1;
1478
1479 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1480 oemData[KEY_PPR].end())
1481 {
1482 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1483 if (pprCnt != 0)
1484 {
1485 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) !=
1486 oemData[KEY_PPR].end())
1487 {
1488 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION];
1489 }
1490 }
1491 }
1492 break;
1493 case PPR_ROW_COUNT:
1494 res[0] = 0;
1495 *data_len = 1;
1496 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1497 oemData[KEY_PPR].end())
1498 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1499 break;
1500 case PPR_ROW_ADDR:
1501 pprIndex = req[1];
1502 if (pprIndex > 100)
1503 return IPMI_CC_PARM_OUT_OF_RANGE;
1504
1505 ss << std::hex;
1506 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1507
1508 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1509 return IPMI_CC_PARM_OUT_OF_RANGE;
1510
1511 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) ==
1512 oemData[KEY_PPR][ss.str()].end())
1513 return IPMI_CC_PARM_OUT_OF_RANGE;
1514
1515 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR];
1516 *data_len = strToBytes(str, res);
1517 break;
1518 case PPR_HISTORY_DATA:
1519 pprIndex = req[1];
1520 if (pprIndex > 100)
1521 return IPMI_CC_PARM_OUT_OF_RANGE;
1522
1523 ss << std::hex;
1524 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1525
1526 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1527 return IPMI_CC_PARM_OUT_OF_RANGE;
1528
1529 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) ==
1530 oemData[KEY_PPR][ss.str()].end())
1531 return IPMI_CC_PARM_OUT_OF_RANGE;
1532
1533 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA];
1534 *data_len = strToBytes(str, res);
1535 break;
1536 default:
1537 return IPMI_CC_PARM_OUT_OF_RANGE;
1538 break;
1539 }
1540
1541 return IPMI_CC_OK;
1542}
1543
1544/* FB OEM QC Commands */
1545
1546//----------------------------------------------------------------------
1547// Set Proc Info (CMD_OEM_Q_SET_PROC_INFO)
1548//----------------------------------------------------------------------
1549//"Request:
1550// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1551// Byte 4 – Processor Index, 0 base
1552// Byte 5 – Parameter Selector
1553// Byte 6..N – Configuration parameter data (see below for Parameters
1554// of Processor Information)
1555// Response:
1556// Byte 1 – Completion code
1557//
1558// Parameter#1: (Processor Product Name)
1559//
1560// Byte 1..48 –Product name(ASCII code)
1561// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1562//
1563// Param#2: Processor Basic Information
1564// Byte 1 – Core Number
1565// Byte 2 – Thread Number (LSB)
1566// Byte 3 – Thread Number (MSB)
1567// Byte 4 – Processor frequency in MHz (LSB)
1568// Byte 5 – Processor frequency in MHz (MSB)
1569// Byte 6..7 – Revision
1570//
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301571
1572ipmi::RspType<> ipmiOemQSetProcInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t,
1573 uint8_t, uint8_t procIndex,
1574 uint8_t paramSel,
1575 std::vector<uint8_t> request)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001576{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001577 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001578 std::stringstream ss;
1579 std::string str;
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301580 uint8_t len = request.size();
1581 auto hostId = findHost(ctx->hostIdx);
1582 if (!hostId)
1583 {
1584 phosphor::logging::log<phosphor::logging::level::ERR>(
1585 "Invalid Host Id received");
1586 return ipmi::responseInvalidCommand();
1587 }
1588 std::string procInfo = KEY_Q_PROC_INFO + std::to_string(*hostId);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001589 /* check for requested data params */
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301590 if (len < 5 || paramSel < 1 || paramSel >= numParam)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001591 {
1592 phosphor::logging::log<phosphor::logging::level::ERR>(
1593 "Invalid parameter received");
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301594 return ipmi::responseParmOutOfRange();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001595 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001596 ss << std::hex;
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301597 ss << std::setw(2) << std::setfill('0') << (int)procIndex;
1598 oemData[procInfo][ss.str()][KEY_PROC_INDEX] = procIndex;
1599 str = bytesToStr(request.data(), len);
1600 oemData[procInfo][ss.str()][cpuInfoKey[paramSel]] = str.c_str();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001601 flushOemData();
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301602 return ipmi::responseSuccess();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001603}
1604
1605//----------------------------------------------------------------------
1606// Get Proc Info (CMD_OEM_Q_GET_PROC_INFO)
1607//----------------------------------------------------------------------
1608// Request:
1609// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1610// Byte 4 – Processor Index, 0 base
1611// Byte 5 – Parameter Selector
1612// Response:
1613// Byte 1 – Completion code
1614// Byte 2..N – Configuration Parameter Data (see below for Parameters
1615// of Processor Information)
1616//
1617// Parameter#1: (Processor Product Name)
1618//
1619// Byte 1..48 –Product name(ASCII code)
1620// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1621//
1622// Param#2: Processor Basic Information
1623// Byte 1 – Core Number
1624// Byte 2 – Thread Number (LSB)
1625// Byte 3 – Thread Number (MSB)
1626// Byte 4 – Processor frequency in MHz (LSB)
1627// Byte 5 – Processor frequency in MHz (MSB)
1628// Byte 6..7 – Revision
1629//
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301630
1631ipmi::RspType<std::vector<uint8_t>>
1632 ipmiOemQGetProcInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t, uint8_t,
1633 uint8_t procIndex, uint8_t paramSel)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001634{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001635 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001636 std::stringstream ss;
1637 std::string str;
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301638 uint8_t res[MAX_BUF];
1639 auto hostId = findHost(ctx->hostIdx);
1640 if (!hostId)
1641 {
1642 phosphor::logging::log<phosphor::logging::level::ERR>(
1643 "Invalid Host Id received");
1644 return ipmi::responseInvalidCommand();
1645 }
1646 std::string procInfo = KEY_Q_PROC_INFO + std::to_string(*hostId);
1647 if (paramSel < 1 || paramSel >= numParam)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001648 {
1649 phosphor::logging::log<phosphor::logging::level::ERR>(
1650 "Invalid parameter received");
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301651 return ipmi::responseParmOutOfRange();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001652 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001653 ss << std::hex;
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301654 ss << std::setw(2) << std::setfill('0') << (int)procIndex;
1655 if (oemData[procInfo].find(ss.str()) == oemData[procInfo].end())
1656 return ipmi::responseCommandNotAvailable();
1657 if (oemData[procInfo][ss.str()].find(cpuInfoKey[paramSel]) ==
1658 oemData[procInfo][ss.str()].end())
1659 return ipmi::responseCommandNotAvailable();
1660 str = oemData[procInfo][ss.str()][cpuInfoKey[paramSel]];
1661 int dataLen = strToBytes(str, res);
1662 std::vector<uint8_t> response(&res[0], &res[dataLen]);
1663 return ipmi::responseSuccess(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001664}
1665
1666//----------------------------------------------------------------------
1667// Set Dimm Info (CMD_OEM_Q_SET_DIMM_INFO)
1668//----------------------------------------------------------------------
1669// Request:
1670// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1671// Byte 4 – DIMM Index, 0 base
1672// Byte 5 – Parameter Selector
1673// Byte 6..N – Configuration parameter data (see below for Parameters
1674// of DIMM Information)
1675// Response:
1676// Byte 1 – Completion code
1677//
1678// Param#1 (DIMM Location):
1679// Byte 1 – DIMM Present
1680// Byte 1 – DIMM Present
1681// 01h – Present
1682// FFh – Not Present
1683// Byte 2 – Node Number, 0 base
1684// Byte 3 – Channel Number , 0 base
1685// Byte 4 – DIMM Number , 0 base
1686//
1687// Param#2 (DIMM Type):
1688// Byte 1 – DIMM Type
1689// Bit [7:6]
1690// For DDR3
1691// 00 – Normal Voltage (1.5V)
1692// 01 – Ultra Low Voltage (1.25V)
1693// 10 – Low Voltage (1.35V)
1694// 11 – Reserved
1695// For DDR4
1696// 00 – Reserved
1697// 01 – Reserved
1698// 10 – Reserved
1699// 11 – Normal Voltage (1.2V)
1700// Bit [5:0]
1701// 0x00 – SDRAM
1702// 0x01 – DDR-1 RAM
1703// 0x02 – Rambus
1704// 0x03 – DDR-2 RAM
1705// 0x04 – FBDIMM
1706// 0x05 – DDR-3 RAM
1707// 0x06 – DDR-4 RAM
1708//
1709// Param#3 (DIMM Speed):
1710// Byte 1..2 – DIMM speed in MHz, LSB
1711// Byte 3..6 – DIMM size in Mbytes, LSB
1712//
1713// Param#4 (Module Part Number):
1714// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1715//
1716// Param#5 (Module Serial Number):
1717// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1718//
1719// Param#6 (Module Manufacturer ID):
1720// Byte 1 - Module Manufacturer ID, LSB
1721// Byte 2 - Module Manufacturer ID, MSB
1722//
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301723ipmi::RspType<> ipmiOemQSetDimmInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t,
1724 uint8_t, uint8_t dimmIndex,
1725 uint8_t paramSel,
1726 std::vector<uint8_t> request)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001727{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001728 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001729 std::stringstream ss;
1730 std::string str;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301731 uint8_t len = request.size();
1732 std::string dimmType;
1733 readDimmType(dimmType, dimmIndex);
Patrick Williams6d9e9a72022-07-18 10:30:50 -05001734 auto hostId = findHost(ctx->hostIdx);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301735 if (!hostId)
1736 {
1737 phosphor::logging::log<phosphor::logging::level::ERR>(
1738 "Invalid Host Id received");
1739 return ipmi::responseInvalidCommand();
1740 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001741
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301742 std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(*hostId);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001743
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301744 if (len < 3 || paramSel < 1 || paramSel >= numParam)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001745 {
1746 phosphor::logging::log<phosphor::logging::level::ERR>(
1747 "Invalid parameter received");
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301748 return ipmi::responseParmOutOfRange();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001749 }
1750
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001751 ss << std::hex;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301752 ss << (int)dimmIndex;
1753 oemData[dimmInfo][ss.str()][KEY_DIMM_INDEX] = dimmIndex;
1754 oemData[dimmInfo][ss.str()][KEY_DIMM_TYPE] = dimmType;
1755 str = bytesToStr(request.data(), len);
1756 oemData[dimmInfo][ss.str()][dimmInfoKey[paramSel]] = str.c_str();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001757 flushOemData();
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301758 return ipmi::responseSuccess();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001759}
1760
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001761// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
1762//----------------------------------------------------------------------
1763// Request:
1764// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1765// Byte 4 – DIMM Index, 0 base
1766// Byte 5 – Parameter Selector
1767// Byte 6..N – Configuration parameter data (see below for Parameters
1768// of DIMM Information)
1769// Response:
1770// Byte 1 – Completion code
1771// Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters
1772// of DIMM Information)
1773//
1774// Param#1 (DIMM Location):
1775// Byte 1 – DIMM Present
1776// Byte 1 – DIMM Present
1777// 01h – Present
1778// FFh – Not Present
1779// Byte 2 – Node Number, 0 base
1780// Byte 3 – Channel Number , 0 base
1781// Byte 4 – DIMM Number , 0 base
1782//
1783// Param#2 (DIMM Type):
1784// Byte 1 – DIMM Type
1785// Bit [7:6]
1786// For DDR3
1787// 00 – Normal Voltage (1.5V)
1788// 01 – Ultra Low Voltage (1.25V)
1789// 10 – Low Voltage (1.35V)
1790// 11 – Reserved
1791// For DDR4
1792// 00 – Reserved
1793// 01 – Reserved
1794// 10 – Reserved
1795// 11 – Normal Voltage (1.2V)
1796// Bit [5:0]
1797// 0x00 – SDRAM
1798// 0x01 – DDR-1 RAM
1799// 0x02 – Rambus
1800// 0x03 – DDR-2 RAM
1801// 0x04 – FBDIMM
1802// 0x05 – DDR-3 RAM
1803// 0x06 – DDR-4 RAM
1804//
1805// Param#3 (DIMM Speed):
1806// Byte 1..2 – DIMM speed in MHz, LSB
1807// Byte 3..6 – DIMM size in Mbytes, LSB
1808//
1809// Param#4 (Module Part Number):
1810// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1811//
1812// Param#5 (Module Serial Number):
1813// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1814//
1815// Param#6 (Module Manufacturer ID):
1816// Byte 1 - Module Manufacturer ID, LSB
1817// Byte 2 - Module Manufacturer ID, MSB
1818//
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301819ipmi::RspType<std::vector<uint8_t>>
1820 ipmiOemQGetDimmInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t, uint8_t,
1821 uint8_t dimmIndex, uint8_t paramSel)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001822{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001823 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301824 uint8_t res[MAX_BUF];
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001825 std::stringstream ss;
1826 std::string str;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301827 std::string dimmType;
1828 readDimmType(dimmType, dimmIndex);
Patrick Williams6d9e9a72022-07-18 10:30:50 -05001829 auto hostId = findHost(ctx->hostIdx);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301830 if (!hostId)
1831 {
1832 phosphor::logging::log<phosphor::logging::level::ERR>(
1833 "Invalid Host Id received");
1834 return ipmi::responseInvalidCommand();
1835 }
1836 std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(*hostId);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001837
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301838 if (paramSel < 1 || paramSel >= numParam)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001839 {
1840 phosphor::logging::log<phosphor::logging::level::ERR>(
1841 "Invalid parameter received");
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301842 return ipmi::responseParmOutOfRange();
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001843 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001844 ss << std::hex;
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301845 ss << (int)dimmIndex;
1846 oemData[dimmInfo][ss.str()][KEY_DIMM_TYPE] = dimmType;
1847 if (oemData[dimmInfo].find(ss.str()) == oemData[dimmInfo].end())
1848 return ipmi::responseCommandNotAvailable();
1849 if (oemData[dimmInfo][ss.str()].find(dimmInfoKey[paramSel]) ==
1850 oemData[dimmInfo][ss.str()].end())
1851 return ipmi::responseCommandNotAvailable();
1852 str = oemData[dimmInfo][ss.str()][dimmInfoKey[paramSel]];
1853 int data_length = strToBytes(str, res);
1854 std::vector<uint8_t> response(&res[0], &res[data_length]);
1855 return ipmi::responseSuccess(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001856}
1857
1858//----------------------------------------------------------------------
1859// Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO)
1860//----------------------------------------------------------------------
1861// BIOS issue this command to provide HDD information to BMC.
1862//
1863// BIOS just can get information by standard ATA / SMART command for
1864// OB SATA controller.
1865// BIOS can get
1866// 1. Serial Number
1867// 2. Model Name
1868// 3. HDD FW Version
1869// 4. HDD Capacity
1870// 5. HDD WWN
1871//
1872// Use Get HDD info Param #5 to know the MAX HDD info index.
1873//
1874// Request:
1875// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1876// Byte 4 –
1877// [7:4] Reserved
1878// [3:0] HDD Controller Type
1879// 0x00 – BIOS
1880// 0x01 – Expander
1881// 0x02 – LSI
1882// Byte 5 – HDD Info Index, 0 base
1883// Byte 6 – Parameter Selector
1884// Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD
1885// Information)
1886//
1887// Response:
1888// Byte 1 – Completion Code
1889//
1890// Param#0 (HDD Location):
1891// Byte 1 – Controller
1892// [7:3] Device Number
1893// [2:0] Function Number
1894// For Intel C610 series (Wellsburg)
1895// D31:F2 (0xFA) – SATA control 1
1896// D31:F5 (0xFD) – SATA control 2
1897// D17:F4 (0x8C) – sSata control
1898// Byte 2 – Port Number
1899// Byte 3 – Location (0xFF: No HDD Present)
1900// BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param
1901// #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if
1902// the HDD present. BMC or other people who know the HDD location has
1903// responsibility for update Location info
1904//
1905// Param#1 (Serial Number):
1906// Bytes 1..33: HDD Serial Number
1907//
1908// Param#2 (Model Name):
1909// Byte 1..33 – HDD Model Name
1910//
1911// Param#3 (HDD FW Version):
1912// Byte 1..17 –HDD FW version
1913//
1914// Param#4 (Capacity):
1915// Byte 1..4 –HDD Block Size, LSB
1916// Byte 5..12 - HDD Block Number, LSB
1917// HDD Capacity = HDD Block size * HDD BLock number (Unit Byte)
1918//
1919// Param#5 (Max HDD Quantity):
1920// Byte 1 - Max HDD Quantity
1921// Max supported port numbers in this PCH
1922//
1923// Param#6 (HDD Type)
1924// Byte 1 – HDD Type
1925// 0h – Reserved
1926// 1h – SAS
1927// 2h – SATA
1928// 3h – PCIE SSD (NVME)
1929//
1930// Param#7 (HDD WWN)
1931// Data 1...8: HDD World Wide Name, LSB
1932//
Willy Tue39f9392022-06-15 13:24:20 -07001933ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t, ipmi_cmd_t,
1934 ipmi_request_t request, ipmi_response_t,
1935 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001936{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001937 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1938 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001939 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1940 std::stringstream ss;
1941 std::string str;
1942 uint8_t len = *data_len;
1943
1944 *data_len = 0;
1945
1946 /* check for requested data params */
1947 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam ||
1948 ctrlType > 2)
1949 {
1950 phosphor::logging::log<phosphor::logging::level::ERR>(
1951 "Invalid parameter received");
1952 return IPMI_CC_PARM_OUT_OF_RANGE;
1953 }
1954
1955 len = len - 6; // Get Actual data length
1956
1957 ss << std::hex;
1958 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1959 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType;
1960 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] =
1961 req->hddIndex;
1962
1963 str = bytesToStr(req->data, len);
1964 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1965 [driveInfoKey[req->paramSel]] = str.c_str();
1966 flushOemData();
1967
1968 return IPMI_CC_OK;
1969}
1970
1971//----------------------------------------------------------------------
1972// Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO)
1973//----------------------------------------------------------------------
1974// BMC needs to check HDD presented or not first. If NOT presented, return
1975// completion code 0xD5.
1976//
1977// Request:
1978// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1979// Byte 4 –
1980//[7:4] Reserved
1981//[3:0] HDD Controller Type
1982// 0x00 – BIOS
1983// 0x01 – Expander
1984// 0x02 – LSI
1985// Byte 5 – HDD Index, 0 base
1986// Byte 6 – Parameter Selector (See Above Set HDD Information)
1987// Response:
1988// Byte 1 – Completion Code
1989// 0xD5 – Not support in current status (HDD Not Present)
1990// Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD
1991// Information)
1992//
Willy Tue39f9392022-06-15 13:24:20 -07001993ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t, ipmi_cmd_t,
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001994 ipmi_request_t request,
1995 ipmi_response_t response,
Willy Tue39f9392022-06-15 13:24:20 -07001996 ipmi_data_len_t data_len, ipmi_context_t)
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001997{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001998 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1999 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
2000 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002001 uint8_t ctrlType = req->hddCtrlType & 0x0f;
2002 std::stringstream ss;
2003 std::string str;
2004
2005 *data_len = 0;
2006
2007 /* check for requested data params */
2008 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2)
2009 {
2010 phosphor::logging::log<phosphor::logging::level::ERR>(
2011 "Invalid parameter received");
2012 return IPMI_CC_PARM_OUT_OF_RANGE;
2013 }
2014
2015 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) ==
2016 oemData[KEY_Q_DRIVE_INFO].end())
2017 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
2018
2019 ss << std::hex;
2020 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
2021
2022 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) ==
2023 oemData[KEY_Q_DRIVE_INFO].end())
2024 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
2025
2026 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find(
2027 dimmInfoKey[req->paramSel]) ==
2028 oemData[KEY_Q_DRIVE_INFO][ss.str()].end())
2029 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
2030
2031 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
2032 [dimmInfoKey[req->paramSel]];
2033 *data_len = strToBytes(str, res);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002034
2035 return IPMI_CC_OK;
2036}
2037
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302038/* Helper function for sending DCMI commands to ME/BIC and
2039 * getting response back
2040 */
2041ipmi::RspType<std::vector<uint8_t>>
2042 sendDCMICmd([[maybe_unused]] ipmi::Context::ptr ctx,
2043 [[maybe_unused]] uint8_t cmd, std::vector<uint8_t>& cmdData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002044{
2045 std::vector<uint8_t> respData;
2046
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302047#if BIC_ENABLED
2048
2049 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
2050
2051 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, cmdData, respData))
2052 {
2053 return ipmi::responseUnspecifiedError();
2054 }
2055
2056#else
2057
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002058 /* Add group id as first byte to request for ME command */
2059 cmdData.insert(cmdData.begin(), groupDCMI);
2060
2061 if (sendMeCmd(ipmi::netFnGroup, cmd, cmdData, respData))
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302062 {
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002063 return ipmi::responseUnspecifiedError();
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302064 }
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002065
2066 /* Remove group id as first byte as it will be added by IPMID */
2067 respData.erase(respData.begin());
2068
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302069#endif
2070
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002071 return ipmi::responseSuccess(std::move(respData));
2072}
2073
2074/* DCMI Command handellers. */
2075
2076ipmi::RspType<std::vector<uint8_t>>
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302077 ipmiOemDCMIGetPowerReading(ipmi::Context::ptr ctx,
2078 std::vector<uint8_t> reqData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002079{
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302080 return sendDCMICmd(ctx, ipmi::dcmi::cmdGetPowerReading, reqData);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002081}
2082
2083ipmi::RspType<std::vector<uint8_t>>
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302084 ipmiOemDCMIGetPowerLimit(ipmi::Context::ptr ctx,
2085 std::vector<uint8_t> reqData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002086{
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302087 return sendDCMICmd(ctx, ipmi::dcmi::cmdGetPowerLimit, reqData);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002088}
2089
2090ipmi::RspType<std::vector<uint8_t>>
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302091 ipmiOemDCMISetPowerLimit(ipmi::Context::ptr ctx,
2092 std::vector<uint8_t> reqData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002093{
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302094 return sendDCMICmd(ctx, ipmi::dcmi::cmdSetPowerLimit, reqData);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002095}
2096
2097ipmi::RspType<std::vector<uint8_t>>
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302098 ipmiOemDCMIApplyPowerLimit(ipmi::Context::ptr ctx,
2099 std::vector<uint8_t> reqData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002100{
Logananth Sundararaje4d6fe72022-08-23 20:36:31 +05302101 return sendDCMICmd(ctx, ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002102}
2103
Cosmo Chou99d42b62024-08-15 10:42:47 +08002104// Https Boot related functions
2105ipmi::RspType<std::vector<uint8_t>>
2106 ipmiOemGetHttpsData([[maybe_unused]] ipmi::Context::ptr ctx,
2107 std::vector<uint8_t> reqData)
2108{
2109 if (reqData.size() < sizeof(HttpsDataReq))
2110 return ipmi::responseReqDataLenInvalid();
2111
2112 const auto* pReq = reinterpret_cast<const HttpsDataReq*>(reqData.data());
2113 std::error_code ec;
2114 auto fileSize = std::filesystem::file_size(certPath, ec);
2115 if (ec)
2116 return ipmi::responseUnspecifiedError();
2117
2118 if (pReq->offset >= fileSize)
2119 return ipmi::responseInvalidFieldRequest();
2120
2121 std::ifstream file(certPath, std::ios::binary);
2122 if (!file)
2123 return ipmi::responseUnspecifiedError();
2124
2125 auto readLen = std::min<uint16_t>(pReq->length, fileSize - pReq->offset);
2126 std::vector<uint8_t> resData(readLen + 1);
2127 resData[0] = readLen;
2128 file.seekg(pReq->offset);
2129 file.read(reinterpret_cast<char*>(resData.data() + 1), readLen);
2130
2131 return ipmi::responseSuccess(resData);
2132}
2133
2134ipmi::RspType<std::vector<uint8_t>>
2135 ipmiOemGetHttpsAttr([[maybe_unused]] ipmi::Context::ptr ctx,
2136 std::vector<uint8_t> reqData)
2137{
2138 if (reqData.size() < sizeof(HttpsBootAttr))
2139 return ipmi::responseReqDataLenInvalid();
2140
2141 std::vector<uint8_t> resData;
2142
2143 switch (static_cast<HttpsBootAttr>(reqData[0]))
2144 {
2145 case HttpsBootAttr::certSize:
2146 {
2147 std::error_code ec;
2148 auto fileSize = std::filesystem::file_size(certPath, ec);
2149 if (ec || fileSize > std::numeric_limits<uint16_t>::max())
2150 return ipmi::responseUnspecifiedError();
2151
2152 uint16_t size = static_cast<uint16_t>(fileSize);
2153 resData.resize(sizeof(uint16_t));
2154 std::memcpy(resData.data(), &size, sizeof(uint16_t));
2155 break;
2156 }
2157 case HttpsBootAttr::certCrc:
2158 {
2159 std::ifstream file(certPath, std::ios::binary);
2160 if (!file)
2161 return ipmi::responseUnspecifiedError();
2162
2163 boost::crc_32_type result;
2164 char data[1024];
2165 while (file.read(data, sizeof(data)))
2166 result.process_bytes(data, file.gcount());
2167 if (file.gcount() > 0)
2168 result.process_bytes(data, file.gcount());
2169
2170 uint32_t crc = result.checksum();
2171 resData.resize(sizeof(uint32_t));
2172 std::memcpy(resData.data(), &crc, sizeof(uint32_t));
2173 break;
2174 }
2175 default:
2176 return ipmi::responseInvalidFieldRequest();
2177 }
2178
2179 return ipmi::responseSuccess(resData);
2180}
2181
Cosmo Chou7ab87bb2024-06-28 10:47:44 +08002182// OEM Crashdump related functions
2183static ipmi_ret_t setDumpState(CrdState& currState, CrdState newState)
2184{
2185 switch (newState)
2186 {
2187 case CrdState::waitData:
2188 if (currState == CrdState::packing)
2189 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
2190 break;
2191 case CrdState::packing:
2192 if (currState != CrdState::waitData)
2193 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
2194 break;
2195 case CrdState::free:
2196 break;
2197 default:
2198 return IPMI_CC_UNSPECIFIED_ERROR;
2199 }
2200 currState = newState;
2201
2202 return IPMI_CC_OK;
2203}
2204
2205static ipmi_ret_t handleMcaBank(const CrashDumpHdr& hdr,
2206 std::span<const uint8_t> data,
2207 CrdState& currState, std::stringstream& ss)
2208{
2209 if (data.size() < sizeof(CrdMcaBank))
2210 return IPMI_CC_REQ_DATA_LEN_INVALID;
2211
2212 ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
2213 if (res)
2214 return res;
2215
2216 const auto* pBank = reinterpret_cast<const CrdMcaBank*>(data.data());
2217 ss << std::format(" Bank ID : 0x{:02X}, Core ID : 0x{:02X}\n",
2218 hdr.bankHdr.bankId, hdr.bankHdr.coreId);
2219 ss << std::format(" MCA_CTRL : 0x{:016X}\n", pBank->mcaCtrl);
2220 ss << std::format(" MCA_STATUS : 0x{:016X}\n", pBank->mcaSts);
2221 ss << std::format(" MCA_ADDR : 0x{:016X}\n", pBank->mcaAddr);
2222 ss << std::format(" MCA_MISC0 : 0x{:016X}\n", pBank->mcaMisc0);
2223 ss << std::format(" MCA_CTRL_MASK : 0x{:016X}\n", pBank->mcaCtrlMask);
2224 ss << std::format(" MCA_CONFIG : 0x{:016X}\n", pBank->mcaConfig);
2225 ss << std::format(" MCA_IPID : 0x{:016X}\n", pBank->mcaIpid);
2226 ss << std::format(" MCA_SYND : 0x{:016X}\n", pBank->mcaSynd);
2227 ss << std::format(" MCA_DESTAT : 0x{:016X}\n", pBank->mcaDestat);
2228 ss << std::format(" MCA_DEADDR : 0x{:016X}\n", pBank->mcaDeaddr);
2229 ss << std::format(" MCA_MISC1 : 0x{:016X}\n", pBank->mcaMisc1);
2230 ss << "\n";
2231
2232 return IPMI_CC_OK;
2233}
2234
2235template <typename T>
2236static ipmi_ret_t handleVirtualBank(std::span<const uint8_t> data,
2237 CrdState& currState, std::stringstream& ss)
2238{
2239 if (data.size() < sizeof(T))
2240 return IPMI_CC_REQ_DATA_LEN_INVALID;
2241
2242 const auto* pBank = reinterpret_cast<const T*>(data.data());
2243
2244 if (data.size() < sizeof(T) + sizeof(BankCorePair) * pBank->mcaCount)
2245 return IPMI_CC_REQ_DATA_LEN_INVALID;
2246
2247 ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
2248 if (res)
2249 return res;
2250
2251 ss << " Virtual Bank\n";
2252 ss << std::format(" S5_RESET_STATUS : 0x{:08X}\n", pBank->s5ResetSts);
2253 ss << std::format(" PM_BREAKEVENT : 0x{:08X}\n", pBank->breakevent);
2254 if constexpr (std::is_same_v<T, CrdVirtualBankV3>)
2255 {
2256 ss << std::format(" WARMCOLDRSTSTATUS : 0x{:08X}\n", pBank->rstSts);
2257 }
2258 ss << std::format(" PROCESSOR NUMBER : 0x{:04X}\n", pBank->procNum);
2259 ss << std::format(" APIC ID : 0x{:08X}\n", pBank->apicId);
2260 ss << std::format(" EAX : 0x{:08X}\n", pBank->eax);
2261 ss << std::format(" EBX : 0x{:08X}\n", pBank->ebx);
2262 ss << std::format(" ECX : 0x{:08X}\n", pBank->ecx);
2263 ss << std::format(" EDX : 0x{:08X}\n", pBank->edx);
2264 ss << " VALID LIST : ";
2265 for (size_t i = 0; i < pBank->mcaCount; i++)
2266 {
2267 ss << std::format("(0x{:02X},0x{:02X}) ", pBank->mcaList[i].bankId,
2268 pBank->mcaList[i].coreId);
2269 }
2270 ss << "\n\n";
2271
2272 return IPMI_CC_OK;
2273}
2274
2275static ipmi_ret_t handleCpuWdtBank(std::span<const uint8_t> data,
2276 CrdState& currState, std::stringstream& ss)
2277{
2278 if (data.size() < sizeof(CrdCpuWdtBank))
2279 return IPMI_CC_REQ_DATA_LEN_INVALID;
2280
2281 ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
2282 if (res)
2283 return res;
2284
2285 const auto* pBank = reinterpret_cast<const CrdCpuWdtBank*>(data.data());
2286 for (size_t i = 0; i < ccmNum; i++)
2287 {
2288 ss << std::format(" [CCM{}]\n", i);
2289 ss << std::format(" HwAssertStsHi : 0x{:08X}\n",
2290 pBank->hwAssertStsHi[i]);
2291 ss << std::format(" HwAssertStsLo : 0x{:08X}\n",
2292 pBank->hwAssertStsLo[i]);
2293 ss << std::format(" OrigWdtAddrLogHi : 0x{:08X}\n",
2294 pBank->origWdtAddrLogHi[i]);
2295 ss << std::format(" OrigWdtAddrLogLo : 0x{:08X}\n",
2296 pBank->origWdtAddrLogLo[i]);
2297 ss << std::format(" HwAssertMskHi : 0x{:08X}\n",
2298 pBank->hwAssertMskHi[i]);
2299 ss << std::format(" HwAssertMskLo : 0x{:08X}\n",
2300 pBank->hwAssertMskLo[i]);
2301 ss << std::format(" OrigWdtAddrLogStat : 0x{:08X}\n",
2302 pBank->origWdtAddrLogStat[i]);
2303 }
2304 ss << "\n";
2305
2306 return IPMI_CC_OK;
2307}
2308
2309template <size_t N>
2310static ipmi_ret_t handleHwAssertBank(const char* name,
2311 std::span<const uint8_t> data,
2312 CrdState& currState, std::stringstream& ss)
2313{
2314 if (data.size() < sizeof(CrdHwAssertBank<N>))
2315 return IPMI_CC_REQ_DATA_LEN_INVALID;
2316
2317 ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
2318 if (res)
2319 return res;
2320
2321 const CrdHwAssertBank<N>* pBank =
2322 reinterpret_cast<const CrdHwAssertBank<N>*>(data.data());
2323
2324 for (size_t i = 0; i < N; i++)
2325 {
2326 ss << std::format(" [{}{}]\n", name, i);
2327 ss << std::format(" HwAssertStsHi : 0x{:08X}\n",
2328 pBank->hwAssertStsHi[i]);
2329 ss << std::format(" HwAssertStsLo : 0x{:08X}\n",
2330 pBank->hwAssertStsLo[i]);
2331 ss << std::format(" HwAssertMskHi : 0x{:08X}\n",
2332 pBank->hwAssertMskHi[i]);
2333 ss << std::format(" HwAssertMskLo : 0x{:08X}\n",
2334 pBank->hwAssertMskLo[i]);
2335 }
2336 ss << "\n";
2337
2338 return IPMI_CC_OK;
2339}
2340
2341static ipmi_ret_t handlePcieAerBank(std::span<const uint8_t> data,
2342 CrdState& currState, std::stringstream& ss)
2343{
2344 if (data.size() < sizeof(CrdPcieAerBank))
2345 return IPMI_CC_REQ_DATA_LEN_INVALID;
2346
2347 ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
2348 if (res)
2349 return res;
2350
2351 const auto* pBank = reinterpret_cast<const CrdPcieAerBank*>(data.data());
2352 ss << std::format(" [Bus{} Dev{} Fun{}]\n", pBank->bus, pBank->dev,
2353 pBank->fun);
2354 ss << std::format(" Command : 0x{:04X}\n",
2355 pBank->cmd);
2356 ss << std::format(" Status : 0x{:04X}\n",
2357 pBank->sts);
2358 ss << std::format(" Slot : 0x{:04X}\n",
2359 pBank->slot);
2360 ss << std::format(" Secondary Bus : 0x{:02X}\n",
2361 pBank->secondBus);
2362 ss << std::format(" Vendor ID : 0x{:04X}\n",
2363 pBank->vendorId);
2364 ss << std::format(" Device ID : 0x{:04X}\n",
2365 pBank->devId);
2366 ss << std::format(" Class Code : 0x{:02X}{:04X}\n",
2367 pBank->classCodeHi, pBank->classCodeLo);
2368 ss << std::format(" Bridge: Secondary Status : 0x{:04X}\n",
2369 pBank->secondSts);
2370 ss << std::format(" Bridge: Control : 0x{:04X}\n",
2371 pBank->ctrl);
2372 ss << std::format(" Uncorrectable Error Status : 0x{:08X}\n",
2373 pBank->uncorrErrSts);
2374 ss << std::format(" Uncorrectable Error Mask : 0x{:08X}\n",
2375 pBank->uncorrErrMsk);
2376 ss << std::format(" Uncorrectable Error Severity : 0x{:08X}\n",
2377 pBank->uncorrErrSeverity);
2378 ss << std::format(" Correctable Error Status : 0x{:08X}\n",
2379 pBank->corrErrSts);
2380 ss << std::format(" Correctable Error Mask : 0x{:08X}\n",
2381 pBank->corrErrMsk);
2382 ss << std::format(" Header Log DW0 : 0x{:08X}\n",
2383 pBank->hdrLogDw0);
2384 ss << std::format(" Header Log DW1 : 0x{:08X}\n",
2385 pBank->hdrLogDw1);
2386 ss << std::format(" Header Log DW2 : 0x{:08X}\n",
2387 pBank->hdrLogDw2);
2388 ss << std::format(" Header Log DW3 : 0x{:08X}\n",
2389 pBank->hdrLogDw3);
2390 ss << std::format(" Root Error Status : 0x{:08X}\n",
2391 pBank->rootErrSts);
2392 ss << std::format(" Correctable Error Source ID : 0x{:04X}\n",
2393 pBank->corrErrSrcId);
2394 ss << std::format(" Error Source ID : 0x{:04X}\n",
2395 pBank->errSrcId);
2396 ss << std::format(" Lane Error Status : 0x{:08X}\n",
2397 pBank->laneErrSts);
2398 ss << "\n";
2399
2400 return IPMI_CC_OK;
2401}
2402
2403static ipmi_ret_t handleWdtRegBank(std::span<const uint8_t> data,
2404 CrdState& currState, std::stringstream& ss)
2405{
2406 if (data.size() < sizeof(CrdWdtRegBank))
2407 return IPMI_CC_REQ_DATA_LEN_INVALID;
2408
2409 const auto* pBank = reinterpret_cast<const CrdWdtRegBank*>(data.data());
2410 if (data.size() < sizeof(CrdWdtRegBank) + sizeof(uint32_t) * pBank->count)
2411 return IPMI_CC_REQ_DATA_LEN_INVALID;
2412
2413 ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
2414 if (res)
2415 return res;
2416
2417 ss << std::format(" [NBIO{}] {}\n", pBank->nbio, pBank->name);
2418 ss << std::format(" Address: 0x{:08X}\n", pBank->addr);
2419 ss << std::format(" Data Count: {}\n", pBank->count);
2420 ss << " Data:\n";
2421 for (size_t i = 0; i < pBank->count; i++)
2422 {
2423 ss << std::format(" {}: 0x{:08X}\n", i, pBank->data[i]);
2424 }
2425 ss << "\n";
2426
2427 return IPMI_CC_OK;
2428}
2429
2430static ipmi_ret_t handleCrdHdrBank(std::span<const uint8_t> data,
2431 CrdState& currState, std::stringstream& ss)
2432{
2433 if (data.size() < sizeof(CrdHdrBank))
2434 return IPMI_CC_REQ_DATA_LEN_INVALID;
2435
2436 ipmi_ret_t res = setDumpState(currState, CrdState::waitData);
2437 if (res)
2438 return res;
2439
2440 const auto* pBank = reinterpret_cast<const CrdHdrBank*>(data.data());
2441 ss << " Crashdump Header\n";
2442 ss << std::format(" CPU PPIN : 0x{:016X}\n", pBank->ppin);
2443 ss << std::format(" UCODE VERSION : 0x{:08X}\n", pBank->ucodeVer);
2444 ss << std::format(" PMIO 80h : 0x{:08X}\n", pBank->pmio);
2445 ss << std::format(
2446 " BIT0 - SMN Parity/SMN Timeouts PSP/SMU Parity and ECC/SMN On-Package Link Error : {}\n",
2447 pBank->pmio & 0x1);
2448 ss << std::format(" BIT2 - PSP Parity and ECC : {}\n",
2449 (pBank->pmio & 0x4) >> 2);
2450 ss << std::format(" BIT3 - SMN Timeouts SMU : {}\n",
2451 (pBank->pmio & 0x8) >> 3);
2452 ss << std::format(" BIT4 - SMN Off-Package Link Packet Error : {}\n",
2453 (pBank->pmio & 0x10) >> 4);
2454 ss << "\n";
2455
2456 return IPMI_CC_OK;
2457}
2458
2459static std::string getFilename(const std::filesystem::path& dir,
2460 const std::string& prefix)
2461{
2462 std::vector<int> indices;
2463 std::regex pattern(prefix + "(\\d+)\\.txt");
2464
2465 for (const auto& entry : std::filesystem::directory_iterator(dir))
2466 {
2467 std::string filename = entry.path().filename().string();
2468 std::smatch match;
2469 if (std::regex_match(filename, match, pattern))
2470 indices.push_back(std::stoi(match[1]));
2471 }
2472
2473 std::sort(indices.rbegin(), indices.rend());
2474 while (indices.size() > 2) // keep 3 files, so remove if more than 2
2475 {
2476 std::filesystem::remove(
2477 dir / (prefix + std::to_string(indices.back()) + ".txt"));
2478 indices.pop_back();
2479 }
2480
2481 int nextIndex = indices.empty() ? 1 : indices.front() + 1;
2482 return prefix + std::to_string(nextIndex) + ".txt";
2483}
2484
2485static ipmi_ret_t handleCtrlBank(std::span<const uint8_t> data,
2486 CrdState& currState, std::stringstream& ss)
2487{
2488 if (data.empty())
2489 return IPMI_CC_REQ_DATA_LEN_INVALID;
2490
2491 switch (static_cast<CrdCtrl>(data[0]))
2492 {
2493 case CrdCtrl::getState:
2494 break;
2495 case CrdCtrl::finish:
2496 {
2497 ipmi_ret_t res = setDumpState(currState, CrdState::packing);
2498 if (res)
2499 return res;
2500
2501 const std::filesystem::path dumpDir = "/var/lib/fb-ipmi-oem";
2502 std::string filename = getFilename(dumpDir, "crashdump_");
2503 std::ofstream outFile(dumpDir / filename);
2504 if (!outFile.is_open())
2505 return IPMI_CC_UNSPECIFIED_ERROR;
2506
2507 auto now = std::chrono::system_clock::to_time_t(
2508 std::chrono::system_clock::now());
2509 outFile << "Crash Dump generated at: "
2510 << std::put_time(std::localtime(&now), "%Y-%m-%d %H:%M:%S")
2511 << "\n\n";
2512 outFile << ss.str();
2513 outFile.close();
2514 ss.str("");
2515 ss.clear();
2516 setDumpState(currState, CrdState::free);
2517 break;
2518 }
2519 default:
2520 return ccInvalidParam;
2521 }
2522
2523 return IPMI_CC_OK;
2524}
2525
2526ipmi::RspType<std::vector<uint8_t>>
2527 ipmiOemCrashdump([[maybe_unused]] ipmi::Context::ptr ctx,
2528 std::vector<uint8_t> reqData)
2529{
2530 static CrdState dumpState = CrdState::free;
2531 static std::stringstream ss;
2532
2533 if (reqData.size() < sizeof(CrashDumpHdr))
2534 return ipmi::responseReqDataLenInvalid();
2535
2536 const auto* pHdr = reinterpret_cast<const CrashDumpHdr*>(reqData.data());
2537 std::span<const uint8_t> bData{reqData.data() + sizeof(CrashDumpHdr),
2538 reqData.size() - sizeof(CrashDumpHdr)};
2539 ipmi_ret_t res;
2540
2541 switch (pHdr->bankHdr.bankType)
2542 {
2543 case BankType::mca:
2544 res = handleMcaBank(*pHdr, bData, dumpState, ss);
2545 break;
2546 case BankType::virt:
2547 if (pHdr->bankHdr.version >= 3)
2548 {
2549 res = handleVirtualBank<CrdVirtualBankV3>(bData, dumpState, ss);
2550 break;
2551 }
2552 res = handleVirtualBank<CrdVirtualBankV2>(bData, dumpState, ss);
2553 break;
2554 case BankType::cpuWdt:
2555 res = handleCpuWdtBank(bData, dumpState, ss);
2556 break;
2557 case BankType::tcdx:
2558 res = handleHwAssertBank<tcdxNum>("TCDX", bData, dumpState, ss);
2559 break;
2560 case BankType::cake:
2561 res = handleHwAssertBank<cakeNum>("CAKE", bData, dumpState, ss);
2562 break;
2563 case BankType::pie0:
2564 res = handleHwAssertBank<pie0Num>("PIE", bData, dumpState, ss);
2565 break;
2566 case BankType::iom:
2567 res = handleHwAssertBank<iomNum>("IOM", bData, dumpState, ss);
2568 break;
2569 case BankType::ccix:
2570 res = handleHwAssertBank<ccixNum>("CCIX", bData, dumpState, ss);
2571 break;
2572 case BankType::cs:
2573 res = handleHwAssertBank<csNum>("CS", bData, dumpState, ss);
2574 break;
2575 case BankType::pcieAer:
2576 res = handlePcieAerBank(bData, dumpState, ss);
2577 break;
2578 case BankType::wdtReg:
2579 res = handleWdtRegBank(bData, dumpState, ss);
2580 break;
2581 case BankType::ctrl:
2582 res = handleCtrlBank(bData, dumpState, ss);
2583 if (res == IPMI_CC_OK &&
2584 static_cast<CrdCtrl>(bData[0]) == CrdCtrl::getState)
2585 {
2586 return ipmi::responseSuccess(
2587 std::vector<uint8_t>{static_cast<uint8_t>(dumpState)});
2588 }
2589 break;
2590 case BankType::crdHdr:
2591 res = handleCrdHdrBank(bData, dumpState, ss);
2592 break;
2593 default:
2594 return ipmi::responseInvalidFieldRequest();
2595 }
2596
2597 return ipmi::response(res);
2598}
2599
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002600static void registerOEMFunctions(void)
2601{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002602 /* Get OEM data from json file */
2603 std::ifstream file(JSON_OEM_DATA_FILE);
2604 if (file)
Vijay Khemkafeaa9812019-08-27 15:08:08 -07002605 {
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002606 file >> oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -07002607 file.close();
2608 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002609
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002610 phosphor::logging::log<phosphor::logging::level::INFO>(
2611 "Registering OEM commands");
Vijay Khemka7c0aea42020-03-05 13:31:53 -08002612
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002613 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO,
2614 NULL, ipmiOemDbgGetFrameInfo,
2615 PRIVILEGE_USER); // get debug frame info
2616 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ,
2617 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL,
2618 ipmiOemDbgGetUpdFrames,
2619 PRIVILEGE_USER); // get debug updated frames
2620 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC,
2621 NULL, ipmiOemDbgGetPostDesc,
2622 PRIVILEGE_USER); // get debug post description
2623 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC,
2624 NULL, ipmiOemDbgGetGpioDesc,
2625 PRIVILEGE_USER); // get debug gpio description
2626 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA,
2627 NULL, ipmiOemDbgGetFrameData,
2628 PRIVILEGE_USER); // get debug frame data
2629 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL,
2630 NULL, ipmiOemDbgGetCtrlPanel,
2631 PRIVILEGE_USER); // get debug control panel
2632 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL,
2633 ipmiOemSetDimmInfo,
2634 PRIVILEGE_USER); // Set Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002635 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL,
2636 ipmiOemGetBoardID,
2637 PRIVILEGE_USER); // Get Board ID
Bonnie Lo4ae63e72023-02-09 15:27:54 +08002638 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnOemOne,
2639 CMD_OEM_GET_80PORT_RECORD, ipmi::Privilege::User,
2640 ipmiOemGet80PortRecord); // Get 80 Port Record
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002641 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL,
2642 ipmiOemSetMachineCfgInfo,
2643 PRIVILEGE_USER); // Set Machine Config Info
2644 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL,
2645 ipmiOemSetPostStart,
2646 PRIVILEGE_USER); // Set POST start
2647 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL,
2648 ipmiOemSetPostEnd,
2649 PRIVILEGE_USER); // Set POST End
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002650 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL,
2651 ipmiOemSetPPINInfo,
2652 PRIVILEGE_USER); // Set PPIN Info
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05302653#if BIC_ENABLED
2654
2655 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
2656 ipmi::cmdSetSystemGuid, ipmi::Privilege::User,
2657 ipmiOemSetSystemGuid);
2658#else
2659
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07002660 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_SYSTEM_GUID, NULL,
2661 ipmiOemSetSystemGuid,
2662 PRIVILEGE_USER); // Set System GUID
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05302663#endif
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002664 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL,
2665 ipmiOemSetAdrTrigger,
2666 PRIVILEGE_USER); // Set ADR Trigger
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002667 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL,
2668 ipmiOemSetBiosFlashInfo,
2669 PRIVILEGE_USER); // Set Bios Flash Info
2670 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr,
2671 PRIVILEGE_USER); // Set PPR
2672 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
2673 PRIVILEGE_USER); // Get PPR
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002674 /* FB OEM QC Commands */
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05302675 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
2676 CMD_OEM_Q_SET_PROC_INFO, ipmi::Privilege::User,
2677 ipmiOemQSetProcInfo); // Set Proc Info
2678 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
2679 CMD_OEM_Q_GET_PROC_INFO, ipmi::Privilege::User,
2680 ipmiOemQGetProcInfo); // Get Proc Info
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05302681 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
2682 ipmi::cmdSetQDimmInfo, ipmi::Privilege::User,
2683 ipmiOemQSetDimmInfo); // Set Dimm Info
2684 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
2685 ipmi::cmdGetQDimmInfo, ipmi::Privilege::User,
2686 ipmiOemQGetDimmInfo); // Get Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07002687 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
2688 ipmiOemQSetDriveInfo,
2689 PRIVILEGE_USER); // Set Drive Info
2690 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL,
2691 ipmiOemQGetDriveInfo,
2692 PRIVILEGE_USER); // Get Drive Info
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07002693
2694 /* FB OEM DCMI Commands as per DCMI spec 1.5 Section 6 */
2695 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2696 ipmi::dcmi::cmdGetPowerReading,
2697 ipmi::Privilege::User,
2698 ipmiOemDCMIGetPowerReading); // Get Power Reading
2699
2700 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2701 ipmi::dcmi::cmdGetPowerLimit,
2702 ipmi::Privilege::User,
2703 ipmiOemDCMIGetPowerLimit); // Get Power Limit
2704
2705 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2706 ipmi::dcmi::cmdSetPowerLimit,
2707 ipmi::Privilege::Operator,
2708 ipmiOemDCMISetPowerLimit); // Set Power Limit
2709
2710 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
2711 ipmi::dcmi::cmdActDeactivatePwrLimit,
2712 ipmi::Privilege::Operator,
2713 ipmiOemDCMIApplyPowerLimit); // Apply Power Limit
2714
Jayashree-Df0cf6652020-11-30 11:03:30 +05302715 /* FB OEM BOOT ORDER COMMANDS */
2716 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
2717 CMD_OEM_GET_BOOT_ORDER, ipmi::Privilege::User,
2718 ipmiOemGetBootOrder); // Get Boot Order
2719
2720 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
2721 CMD_OEM_SET_BOOT_ORDER, ipmi::Privilege::User,
2722 ipmiOemSetBootOrder); // Set Boot Order
2723
Cosmo Chou7ab87bb2024-06-28 10:47:44 +08002724 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
Cosmo Chou99d42b62024-08-15 10:42:47 +08002725 CMD_OEM_GET_HTTPS_BOOT_DATA, ipmi::Privilege::User,
2726 ipmiOemGetHttpsData);
2727
2728 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
2729 CMD_OEM_GET_HTTPS_BOOT_ATTR, ipmi::Privilege::User,
2730 ipmiOemGetHttpsAttr);
2731
2732 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
Cosmo Chou7ab87bb2024-06-28 10:47:44 +08002733 CMD_OEM_CRASHDUMP, ipmi::Privilege::User,
2734 ipmiOemCrashdump);
2735
Vijay Khemkae7d23d02019-03-08 13:13:40 -08002736 return;
2737}
2738
2739} // namespace ipmi