blob: d4835f15f902f81240424f05895879eb01419ca3 [file] [log] [blame]
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001/*
2 * Copyright (c) 2018 Intel Corporation.
3 * Copyright (c) 2018-present Facebook.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "xyz/openbmc_project/Common/error.hpp"
Jayashree-Df0cf6652020-11-30 11:03:30 +053019#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
20#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080021
Vijay Khemka63c99be2020-05-27 19:14:35 -070022#include <ipmid/api.hpp>
Vijay Khemka1b6fae32019-03-25 17:43:01 -070023#include <ipmid/utils.hpp>
Vijay Khemka63c99be2020-05-27 19:14:35 -070024#include <commandutils.hpp>
25#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>
Vijay Khemka63c99be2020-05-27 19:14:35 -070029
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053030#include <ipmid/api.hpp>
31#include <ipmid/api-types.hpp>
32
Vijay Khemka63c99be2020-05-27 19:14:35 -070033#include <array>
34#include <cstring>
35#include <fstream>
36#include <iomanip>
37#include <iostream>
38#include <sstream>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080039#include <string>
40#include <vector>
41
42#define SIZE_IANA_ID 3
43
44namespace ipmi
45{
Vijay Khemkaa7231892019-10-11 11:35:05 -070046
47using namespace phosphor::logging;
48
Vijay Khemkae7d23d02019-03-08 13:13:40 -080049static void registerOEMFunctions() __attribute__((constructor));
50sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
51static constexpr size_t maxFRUStringLength = 0x3F;
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053052constexpr uint8_t cmdSetSystemGuid = 0xEF;
Vijay Khemkae7d23d02019-03-08 13:13:40 -080053
Vijay Khemka63c99be2020-05-27 19:14:35 -070054int plat_udbg_get_post_desc(uint8_t, uint8_t*, uint8_t, uint8_t*, uint8_t*,
55 uint8_t*);
56int plat_udbg_get_gpio_desc(uint8_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*,
57 uint8_t*);
58ipmi_ret_t plat_udbg_get_frame_data(uint8_t, uint8_t, uint8_t*, uint8_t*,
59 uint8_t*);
60ipmi_ret_t plat_udbg_control_panel(uint8_t, uint8_t, uint8_t, uint8_t*,
61 uint8_t*);
62int sendMeCmd(uint8_t, uint8_t, std::vector<uint8_t>&, std::vector<uint8_t>&);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -070063
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053064int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
65 std::vector<uint8_t>&);
66
Vijay Khemkafeaa9812019-08-27 15:08:08 -070067nlohmann::json oemData __attribute__((init_priority(101)));
Vijay Khemka1b6fae32019-03-25 17:43:01 -070068
Vijay Khemkaf2246ce2020-05-27 14:26:35 -070069static constexpr size_t GUID_SIZE = 16;
70// TODO Make offset and location runtime configurable to ensure we
71// can make each define their own locations.
72static constexpr off_t OFFSET_SYS_GUID = 0x17F0;
73static constexpr const char* FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom";
74
Vijay Khemka1b6fae32019-03-25 17:43:01 -070075enum class LanParam : uint8_t
76{
77 INPROGRESS = 0,
78 AUTHSUPPORT = 1,
79 AUTHENABLES = 2,
80 IP = 3,
81 IPSRC = 4,
82 MAC = 5,
83 SUBNET = 6,
84 GATEWAY = 12,
85 VLAN = 20,
86 CIPHER_SUITE_COUNT = 22,
87 CIPHER_SUITE_ENTRIES = 23,
88 IPV6 = 59,
89};
90
Vijay Khemkaa7231892019-10-11 11:35:05 -070091namespace network
92{
93
94constexpr auto ROOT = "/xyz/openbmc_project/network";
95constexpr auto SERVICE = "xyz.openbmc_project.Network";
96constexpr auto IPV4_TYPE = "ipv4";
97constexpr auto IPV6_TYPE = "ipv6";
98constexpr auto IPV4_PREFIX = "169.254";
99constexpr auto IPV6_PREFIX = "fe80";
100constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
101constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
102
Vijay Khemka63c99be2020-05-27 19:14:35 -0700103bool isLinkLocalIP(const std::string& address)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700104{
105 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0;
106}
107
Vijay Khemka63c99be2020-05-27 19:14:35 -0700108DbusObjectInfo getIPObject(sdbusplus::bus::bus& bus,
109 const std::string& interface,
110 const std::string& serviceRoot,
111 const std::string& match)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700112{
113 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
114
115 if (objectTree.empty())
116 {
117 log<level::ERR>("No Object has implemented the IP interface",
118 entry("INTERFACE=%s", interface.c_str()));
119 }
120
121 DbusObjectInfo objectInfo;
122
Vijay Khemka63c99be2020-05-27 19:14:35 -0700123 for (auto& object : objectTree)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700124 {
125 auto variant =
126 ipmi::getDbusProperty(bus, object.second.begin()->first,
127 object.first, IP_INTERFACE, "Address");
128
129 objectInfo = std::make_pair(object.first, object.second.begin()->first);
130
131 // if LinkLocalIP found look for Non-LinkLocalIP
132 if (isLinkLocalIP(std::get<std::string>(variant)))
133 {
134 continue;
135 }
136 else
137 {
138 break;
139 }
140 }
141 return objectInfo;
142}
143
144} // namespace network
145
Jayashree-Df0cf6652020-11-30 11:03:30 +0530146namespace boot
147{
148
149using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
150using IpmiValue = uint8_t;
151
152std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = {
153 {0x0f, Source::Sources::Default},
154 {0x00, Source::Sources::RemovableMedia},
155 {0x01, Source::Sources::Network},
156 {0x02, Source::Sources::Disk},
157 {0x03, Source::Sources::ExternalMedia},
158 {0x09, Source::Sources::Network}};
159
160std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
161 {0x06, Mode::Modes::Setup}, {0x00, Mode::Modes::Regular}};
162
163std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = {
164 {Source::Sources::Default, 0x0f},
165 {Source::Sources::RemovableMedia, 0x00},
166 {Source::Sources::Network, 0x01},
167 {Source::Sources::Disk, 0x02},
168 {Source::Sources::ExternalMedia, 0x03}};
169
170std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
171 {Mode::Modes::Setup, 0x06}, {Mode::Modes::Regular, 0x00}};
172
173static constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
174static constexpr auto bootSourceIntf =
175 "xyz.openbmc_project.Control.Boot.Source";
176static constexpr auto bootSourceProp = "BootSource";
177static constexpr auto bootModeProp = "BootMode";
178
179auto instances(std::string s)
180{
181 std::string delimiter = " ";
182 size_t pos = 0;
183 std::string token;
184 std::vector<std::string> host;
185
186 while ((pos = s.find(delimiter)) != std::string::npos)
187 {
188 token = s.substr(0, pos);
189 host.push_back(token);
190 s.erase(0, pos + delimiter.length());
191 }
192 host.push_back(s);
193
194 return host;
195}
196
197std::optional<size_t> findHost(size_t id)
198{
199 std::string str = INSTANCES;
200 size_t hostId;
201
202 if (INSTANCES == "0")
203 {
204 hostId = id;
205 }
206 else
207 {
208 static const auto hosts = instances(str);
209 std::string num = std::to_string(id + 1);
210 auto instance = std::lower_bound(hosts.begin(), hosts.end(), num);
211
212 if ((instance == hosts.end()) || (*instance != num))
213 {
214 return std::nullopt;
215 }
216 hostId = id + 1;
217 }
218
219 return hostId;
220}
221
222std::tuple<std::string, std::string> objPath(size_t id)
223{
224 std::string hostName = "host" + std::to_string(id);
225 std::string bootObjPath =
226 "/xyz/openbmc_project/control/" + hostName + "/boot";
227 return std::make_tuple(std::move(bootObjPath), std::move(hostName));
228}
229
230} // namespace boot
231
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700232//----------------------------------------------------------------------
233// Helper functions for storing oem data
234//----------------------------------------------------------------------
235
236void flushOemData()
237{
238 std::ofstream file(JSON_OEM_DATA_FILE);
239 file << oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -0700240 file.close();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700241 return;
242}
243
Vijay Khemka63c99be2020-05-27 19:14:35 -0700244std::string bytesToStr(uint8_t* byte, int len)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700245{
246 std::stringstream ss;
247 int i;
248
249 ss << std::hex;
250 for (i = 0; i < len; i++)
251 {
252 ss << std::setw(2) << std::setfill('0') << (int)byte[i];
253 }
254
255 return ss.str();
256}
257
Vijay Khemka63c99be2020-05-27 19:14:35 -0700258int strToBytes(std::string& str, uint8_t* data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700259{
260 std::string sstr;
261 int i;
262
263 for (i = 0; i < (str.length()) / 2; i++)
264 {
265 sstr = str.substr(i * 2, 2);
266 data[i] = (uint8_t)std::strtol(sstr.c_str(), NULL, 16);
267 }
268 return i;
269}
270
Vijay Khemka63c99be2020-05-27 19:14:35 -0700271ipmi_ret_t getNetworkData(uint8_t lan_param, char* data)
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700272{
273 ipmi_ret_t rc = IPMI_CC_OK;
274 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
275
276 const std::string ethdevice = "eth0";
277
278 switch (static_cast<LanParam>(lan_param))
279 {
Vijay Khemkad1194022020-05-27 18:58:33 -0700280 case LanParam::IP:
281 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700282 auto ethIP = ethdevice + "/" + ipmi::network::IPV4_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700283 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700284 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700285 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
286
287 auto properties = ipmi::getAllDbusProperties(
288 bus, ipObjectInfo.second, ipObjectInfo.first,
289 ipmi::network::IP_INTERFACE);
290
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500291 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700292
293 std::strcpy(data, ipaddress.c_str());
294 }
295 break;
296
Vijay Khemkad1194022020-05-27 18:58:33 -0700297 case LanParam::IPV6:
298 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700299 auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700300 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700301 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700302 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
303
304 auto properties = ipmi::getAllDbusProperties(
305 bus, ipObjectInfo.second, ipObjectInfo.first,
306 ipmi::network::IP_INTERFACE);
307
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500308 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700309
310 std::strcpy(data, ipaddress.c_str());
311 }
312 break;
313
Vijay Khemkad1194022020-05-27 18:58:33 -0700314 case LanParam::MAC:
315 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700316 std::string macAddress;
317 auto macObjectInfo =
318 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
319 ipmi::network::ROOT, ethdevice);
320
321 auto variant = ipmi::getDbusProperty(
322 bus, macObjectInfo.second, macObjectInfo.first,
323 ipmi::network::MAC_INTERFACE, "MACAddress");
324
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500325 macAddress = std::get<std::string>(variant);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700326
327 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
328 (data), (data + 1), (data + 2), (data + 3), (data + 4),
329 (data + 5));
330 std::strcpy(data, macAddress.c_str());
331 }
332 break;
333
334 default:
335 rc = IPMI_CC_PARM_OUT_OF_RANGE;
336 }
337 return rc;
338}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800339
340// return code: 0 successful
Vijay Khemka63c99be2020-05-27 19:14:35 -0700341int8_t getFruData(std::string& data, std::string& name)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800342{
343 std::string objpath = "/xyz/openbmc_project/FruDevice";
344 std::string intf = "xyz.openbmc_project.FruDeviceManager";
345 std::string service = getService(dbus, intf, objpath);
346 ObjectValueTree valueTree = getManagedObjects(dbus, service, "/");
347 if (valueTree.empty())
348 {
349 phosphor::logging::log<phosphor::logging::level::ERR>(
350 "No object implements interface",
351 phosphor::logging::entry("INTF=%s", intf.c_str()));
352 return -1;
353 }
354
Vijay Khemka63c99be2020-05-27 19:14:35 -0700355 for (const auto& item : valueTree)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800356 {
357 auto interface = item.second.find("xyz.openbmc_project.FruDevice");
358 if (interface == item.second.end())
359 {
360 continue;
361 }
362
363 auto property = interface->second.find(name.c_str());
364 if (property == interface->second.end())
365 {
366 continue;
367 }
368
369 try
370 {
371 Value variant = property->second;
Vijay Khemka63c99be2020-05-27 19:14:35 -0700372 std::string& result = std::get<std::string>(variant);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800373 if (result.size() > maxFRUStringLength)
374 {
375 phosphor::logging::log<phosphor::logging::level::ERR>(
376 "FRU serial number exceed maximum length");
377 return -1;
378 }
379 data = result;
380 return 0;
381 }
Vijay Khemka63c99be2020-05-27 19:14:35 -0700382 catch (std::bad_variant_access& e)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800383 {
384 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
385 return -1;
386 }
387 }
388 return -1;
389}
390
391typedef struct
392{
393 uint8_t cur_power_state;
394 uint8_t last_power_event;
395 uint8_t misc_power_state;
396 uint8_t front_panel_button_cap_status;
397} ipmi_get_chassis_status_t;
398
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800399//----------------------------------------------------------------------
400// Get Debug Frame Info
401//----------------------------------------------------------------------
402ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
403 ipmi_request_t request,
404 ipmi_response_t response,
405 ipmi_data_len_t data_len,
406 ipmi_context_t context)
407{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700408 uint8_t* req = reinterpret_cast<uint8_t*>(request);
409 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800410 uint8_t num_frames = 3;
411
412 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
413 res[SIZE_IANA_ID] = num_frames;
414 *data_len = SIZE_IANA_ID + 1;
415
416 return IPMI_CC_OK;
417}
418
419//----------------------------------------------------------------------
420// Get Debug Updated Frames
421//----------------------------------------------------------------------
422ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
423 ipmi_request_t request,
424 ipmi_response_t response,
425 ipmi_data_len_t data_len,
426 ipmi_context_t context)
427{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700428 uint8_t* req = reinterpret_cast<uint8_t*>(request);
429 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800430 uint8_t num_updates = 3;
431 *data_len = 4;
432
433 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
434 res[SIZE_IANA_ID] = num_updates;
435 *data_len = SIZE_IANA_ID + num_updates + 1;
436 res[SIZE_IANA_ID + 1] = 1; // info page update
437 res[SIZE_IANA_ID + 2] = 2; // cri sel update
438 res[SIZE_IANA_ID + 3] = 3; // cri sensor update
439
440 return IPMI_CC_OK;
441}
442
443//----------------------------------------------------------------------
444// Get Debug POST Description
445//----------------------------------------------------------------------
446ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
447 ipmi_request_t request,
448 ipmi_response_t response,
449 ipmi_data_len_t data_len,
450 ipmi_context_t context)
451{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700452 uint8_t* req = reinterpret_cast<uint8_t*>(request);
453 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800454 uint8_t index = 0;
455 uint8_t next = 0;
456 uint8_t end = 0;
457 uint8_t phase = 0;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700458 uint8_t descLen = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800459 int ret;
460
461 index = req[3];
462 phase = req[4];
463
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700464 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800465 if (ret)
466 {
467 memcpy(res, req, SIZE_IANA_ID); // IANA ID
468 *data_len = SIZE_IANA_ID;
469 return IPMI_CC_UNSPECIFIED_ERROR;
470 }
471
472 memcpy(res, req, SIZE_IANA_ID); // IANA ID
473 res[3] = index;
474 res[4] = next;
475 res[5] = phase;
476 res[6] = end;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700477 res[7] = descLen;
478 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800479
480 return IPMI_CC_OK;
481}
482
483//----------------------------------------------------------------------
484// Get Debug GPIO Description
485//----------------------------------------------------------------------
486ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
487 ipmi_request_t request,
488 ipmi_response_t response,
489 ipmi_data_len_t data_len,
490 ipmi_context_t context)
491{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700492 uint8_t* req = reinterpret_cast<uint8_t*>(request);
493 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800494
Vijay Khemka38183d62019-08-28 16:19:33 -0700495 uint8_t index = 0;
496 uint8_t next = 0;
497 uint8_t level = 0;
498 uint8_t pinDef = 0;
499 uint8_t descLen = 0;
500 int ret;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800501
Vijay Khemka38183d62019-08-28 16:19:33 -0700502 index = req[3];
503
504 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen,
505 &res[8]);
506 if (ret)
507 {
508 memcpy(res, req, SIZE_IANA_ID); // IANA ID
509 *data_len = SIZE_IANA_ID;
510 return IPMI_CC_UNSPECIFIED_ERROR;
511 }
512
513 memcpy(res, req, SIZE_IANA_ID); // IANA ID
514 res[3] = index;
515 res[4] = next;
516 res[5] = level;
517 res[6] = pinDef;
518 res[7] = descLen;
519 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800520
521 return IPMI_CC_OK;
522}
523
524//----------------------------------------------------------------------
525// Get Debug Frame Data
526//----------------------------------------------------------------------
527ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
528 ipmi_request_t request,
529 ipmi_response_t response,
530 ipmi_data_len_t data_len,
531 ipmi_context_t context)
532{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700533 uint8_t* req = reinterpret_cast<uint8_t*>(request);
534 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800535 uint8_t frame;
536 uint8_t page;
537 uint8_t next;
538 uint8_t count;
539 int ret;
540
541 frame = req[3];
542 page = req[4];
543 int fr = frame;
544 int pg = page;
545
546 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]);
547 if (ret)
548 {
549 memcpy(res, req, SIZE_IANA_ID); // IANA ID
550 *data_len = SIZE_IANA_ID;
551 return IPMI_CC_UNSPECIFIED_ERROR;
552 }
553
554 memcpy(res, req, SIZE_IANA_ID); // IANA ID
555 res[3] = frame;
556 res[4] = page;
557 res[5] = next;
558 res[6] = count;
559 *data_len = SIZE_IANA_ID + 4 + count;
560
561 return IPMI_CC_OK;
562}
563
564//----------------------------------------------------------------------
565// Get Debug Control Panel
566//----------------------------------------------------------------------
567ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
568 ipmi_request_t request,
569 ipmi_response_t response,
570 ipmi_data_len_t data_len,
571 ipmi_context_t context)
572{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700573 uint8_t* req = reinterpret_cast<uint8_t*>(request);
574 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800575
576 uint8_t panel;
577 uint8_t operation;
578 uint8_t item;
579 uint8_t count;
580 ipmi_ret_t ret;
581
582 panel = req[3];
583 operation = req[4];
584 item = req[5];
585
586 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]);
587
588 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
589 *data_len = SIZE_IANA_ID + count;
590
591 return ret;
592}
593
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800594//----------------------------------------------------------------------
595// Set Dimm Info (CMD_OEM_SET_DIMM_INFO)
596//----------------------------------------------------------------------
597ipmi_ret_t ipmiOemSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
598 ipmi_request_t request, ipmi_response_t response,
599 ipmi_data_len_t data_len, ipmi_context_t context)
600{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700601 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700602
603 uint8_t index = req[0];
604 uint8_t type = req[1];
605 uint16_t speed;
606 uint32_t size;
607
608 memcpy(&speed, &req[2], 2);
609 memcpy(&size, &req[4], 4);
610
611 std::stringstream ss;
612 ss << std::hex;
613 ss << std::setw(2) << std::setfill('0') << (int)index;
614
615 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index;
616 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type;
617 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed;
618 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size;
619
620 flushOemData();
621
622 *data_len = 0;
623
624 return IPMI_CC_OK;
625}
626
627//----------------------------------------------------------------------
628// Get Board ID (CMD_OEM_GET_BOARD_ID)
629//----------------------------------------------------------------------
630ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
631 ipmi_request_t request, ipmi_response_t response,
632 ipmi_data_len_t data_len, ipmi_context_t context)
633{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700634 uint8_t* req = reinterpret_cast<uint8_t*>(request);
635 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800636
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700637 /* TODO: Needs to implement this after GPIO implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800638 *data_len = 0;
639
640 return IPMI_CC_OK;
641}
642
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800643/* Helper functions to set boot order */
Jayashree-Df0cf6652020-11-30 11:03:30 +0530644void setBootOrder(std::string bootObjPath, uint8_t* data,
645 std::string bootOrderKey)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800646{
Jayashree-Df0cf6652020-11-30 11:03:30 +0530647
648 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
649
650 // SETTING BOOT MODE PROPERTY
651 auto bootValue = ipmi::boot::modeIpmiToDbus.find((data[0]));
652 std::string bootOption =
653 ipmi::boot::Mode::convertModesToString((bootValue->second));
654
655 std::string service =
656 getService(*dbus, ipmi::boot::bootModeIntf, bootObjPath);
657 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf,
658 ipmi::boot::bootModeProp, bootOption);
659
660 // SETTING BOOT SOURCE PROPERTY
661 auto bootOrder = ipmi::boot::sourceIpmiToDbus.find((data[1]));
662 std::string bootSource =
663 ipmi::boot::Source::convertSourcesToString((bootOrder->second));
664
665 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath);
666 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf,
667 ipmi::boot::bootSourceProp, bootSource);
668
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800669 nlohmann::json bootMode;
670 uint8_t mode = data[0];
671 int i;
672
673 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false);
674 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false);
675 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false);
676 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false);
Jayashree-Df0cf6652020-11-30 11:03:30 +0530677 oemData[bootOrderKey][KEY_BOOT_MODE] = bootMode;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800678
679 /* Initialize boot sequence array */
Jayashree-Df0cf6652020-11-30 11:03:30 +0530680 oemData[bootOrderKey][KEY_BOOT_SEQ] = {};
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800681 for (i = 1; i < SIZE_BOOT_ORDER; i++)
682 {
683 if (data[i] >= BOOT_SEQ_ARRAY_SIZE)
Jayashree-Df0cf6652020-11-30 11:03:30 +0530684 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = "NA";
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800685 else
Jayashree-Df0cf6652020-11-30 11:03:30 +0530686 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = bootSeq[data[i]];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800687 }
688
689 flushOemData();
690}
691
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800692//----------------------------------------------------------------------
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700693// Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
694//----------------------------------------------------------------------
Jayashree-Df0cf6652020-11-30 11:03:30 +0530695ipmi::RspType<std::vector<uint8_t>>
696 ipmiOemSetBootOrder(ipmi::Context::ptr ctx, std::vector<uint8_t> data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700697{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700698
Jayashree-Df0cf6652020-11-30 11:03:30 +0530699 uint8_t bootSeq[SIZE_BOOT_ORDER];
700 size_t len = data.size();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700701
702 if (len != SIZE_BOOT_ORDER)
703 {
704 phosphor::logging::log<phosphor::logging::level::ERR>(
705 "Invalid Boot order length received");
Jayashree-Df0cf6652020-11-30 11:03:30 +0530706 return ipmi::responseReqDataLenInvalid();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700707 }
708
Jayashree-Df0cf6652020-11-30 11:03:30 +0530709 std::copy(std::begin(data), std::end(data), bootSeq);
710 std::optional<size_t> hostId = ipmi::boot::findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700711
Jayashree-Df0cf6652020-11-30 11:03:30 +0530712 if (!hostId)
713 {
714 phosphor::logging::log<phosphor::logging::level::ERR>(
715 "Invalid Host Id received");
716 return ipmi::responseInvalidCommand();
717 }
718 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
719
720 setBootOrder(bootObjPath, bootSeq, hostName);
721
722 return ipmi::responseSuccess(data);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700723}
724
725//----------------------------------------------------------------------
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800726// Get Boot Order (CMD_OEM_GET_BOOT_ORDER)
727//----------------------------------------------------------------------
Jayashree-Df0cf6652020-11-30 11:03:30 +0530728ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>
729 ipmiOemGetBootOrder(ipmi::Context::ptr ctx)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800730{
Jayashree-Df0cf6652020-11-30 11:03:30 +0530731 uint8_t bootOption, bootOrder;
732 uint8_t bootSeq[SIZE_BOOT_ORDER];
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700733 uint8_t mode = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800734
Jayashree-Df0cf6652020-11-30 11:03:30 +0530735 std::optional<size_t> hostId = ipmi::boot::findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700736
Jayashree-Df0cf6652020-11-30 11:03:30 +0530737 if (!hostId)
738 {
739 phosphor::logging::log<phosphor::logging::level::ERR>(
740 "Invalid Host Id received");
741 return ipmi::responseInvalidCommand();
742 }
743 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
744
745 // GETTING PROPERTY OF MODE INTERFACE
746
747 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
748
749 std::string service =
750 getService(*dbus, ipmi::boot::bootModeIntf, bootObjPath);
751 Value variant =
752 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf,
753 ipmi::boot::bootModeProp);
754
755 auto bootMode = ipmi::boot::Mode::convertModesFromString(
756 std::get<std::string>(variant));
757
758 bootOption = ipmi::boot::modeDbusToIpmi.at(bootMode);
759
760 // GETTING PROPERTY OF SOURCE INTERFACE
761
762 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath);
763 variant =
764 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf,
765 ipmi::boot::bootSourceProp);
766 auto bootSource = ipmi::boot::Source::convertSourcesFromString(
767 std::get<std::string>(variant));
768
769 bootOrder = ipmi::boot::sourceDbusToIpmi.at(bootSource);
770
771 if (oemData.find(hostName) == oemData.end())
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800772 {
773 /* Return default boot order 0100090203ff */
774 uint8_t defaultBoot[SIZE_BOOT_ORDER] = {
775 BOOT_MODE_UEFI, bootMap["USB_DEV"], bootMap["NET_IPV6"],
776 bootMap["SATA_HDD"], bootMap["SATA_CD"], 0xff};
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700777
Jayashree-Df0cf6652020-11-30 11:03:30 +0530778 memcpy(bootSeq, defaultBoot, SIZE_BOOT_ORDER);
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800779 phosphor::logging::log<phosphor::logging::level::INFO>(
780 "Set default boot order");
Jayashree-Df0cf6652020-11-30 11:03:30 +0530781 setBootOrder(bootObjPath, defaultBoot, hostName);
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800782 }
783 else
784 {
Jayashree-Df0cf6652020-11-30 11:03:30 +0530785 nlohmann::json bootMode = oemData[hostName][KEY_BOOT_MODE];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800786 if (bootMode["UEFI"])
787 mode |= BOOT_MODE_UEFI;
788 if (bootMode["CMOS_CLR"])
789 mode |= BOOT_MODE_CMOS_CLR;
790 if (bootMode["BOOT_FLAG"])
791 mode |= BOOT_MODE_BOOT_FLAG;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700792
Jayashree-Df0cf6652020-11-30 11:03:30 +0530793 bootSeq[0] = mode;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800794
Jayashree-Df0cf6652020-11-30 11:03:30 +0530795 for (int i = 1; i < SIZE_BOOT_ORDER; i++)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800796 {
Jayashree-Df0cf6652020-11-30 11:03:30 +0530797 std::string seqStr = oemData[hostName][KEY_BOOT_SEQ][i - 1];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800798 if (bootMap.find(seqStr) != bootMap.end())
Jayashree-Df0cf6652020-11-30 11:03:30 +0530799 bootSeq[i] = bootMap[seqStr];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800800 else
Jayashree-Df0cf6652020-11-30 11:03:30 +0530801 bootSeq[i] = 0xff;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800802 }
803 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800804
Jayashree-Df0cf6652020-11-30 11:03:30 +0530805 return ipmi::responseSuccess(bootOption, bootOrder, bootSeq[2], bootSeq[3],
806 bootSeq[4], bootSeq[5]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800807}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800808// Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO)
809//----------------------------------------------------------------------
810ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
811 ipmi_request_t request,
812 ipmi_response_t response,
813 ipmi_data_len_t data_len,
814 ipmi_context_t context)
815{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700816 machineConfigInfo_t* req = reinterpret_cast<machineConfigInfo_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700817 uint8_t len = *data_len;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800818
819 *data_len = 0;
820
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700821 if (len < sizeof(machineConfigInfo_t))
822 {
823 phosphor::logging::log<phosphor::logging::level::ERR>(
824 "Invalid machine configuration length received");
825 return IPMI_CC_REQ_DATA_LEN_INVALID;
826 }
827
Vijay Khemka63c99be2020-05-27 19:14:35 -0700828 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700829 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN";
830 else
831 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] =
832 chassisType[req->chassis_type];
833
Vijay Khemka63c99be2020-05-27 19:14:35 -0700834 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700835 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN";
836 else
837 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type];
838
839 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt;
840 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt;
841 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt;
842 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt;
843
Vijay Khemka63c99be2020-05-27 19:14:35 -0700844 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700845 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN";
846 else
847 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type];
848
849 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {};
850 int i = 0;
851 if (req->pcie_card_loc & BIT_0)
852 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1";
853 if (req->pcie_card_loc & BIT_1)
854 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2";
855 if (req->pcie_card_loc & BIT_2)
856 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3";
857 if (req->pcie_card_loc & BIT_3)
858 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4";
859
Vijay Khemka63c99be2020-05-27 19:14:35 -0700860 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700861 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN";
862 else
863 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] =
864 pcieType[req->slot1_pcie_type];
865
Vijay Khemka63c99be2020-05-27 19:14:35 -0700866 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700867 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN";
868 else
869 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] =
870 pcieType[req->slot2_pcie_type];
871
Vijay Khemka63c99be2020-05-27 19:14:35 -0700872 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700873 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN";
874 else
875 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] =
876 pcieType[req->slot3_pcie_type];
877
Vijay Khemka63c99be2020-05-27 19:14:35 -0700878 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700879 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN";
880 else
881 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] =
882 pcieType[req->slot4_pcie_type];
883
884 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt;
885
886 flushOemData();
887
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800888 return IPMI_CC_OK;
889}
890
891//----------------------------------------------------------------------
892// Set POST start (CMD_OEM_SET_POST_START)
893//----------------------------------------------------------------------
894ipmi_ret_t ipmiOemSetPostStart(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
895 ipmi_request_t request, ipmi_response_t response,
896 ipmi_data_len_t data_len, ipmi_context_t context)
897{
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800898 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event");
899
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700900 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800901 *data_len = 0;
902 return IPMI_CC_OK;
903}
904
905//----------------------------------------------------------------------
906// Set POST End (CMD_OEM_SET_POST_END)
907//----------------------------------------------------------------------
908ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
909 ipmi_request_t request, ipmi_response_t response,
910 ipmi_data_len_t data_len, ipmi_context_t context)
911{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700912 struct timespec ts;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800913
914 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event");
915
916 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700917
918 // Timestamp post end time.
919 clock_gettime(CLOCK_REALTIME, &ts);
920 oemData[KEY_TS_SLED] = ts.tv_sec;
921 flushOemData();
922
923 // Sync time with system
924 // TODO: Add code for syncing time
925
926 return IPMI_CC_OK;
927}
928
929//----------------------------------------------------------------------
930// Set PPIN Info (CMD_OEM_SET_PPIN_INFO)
931//----------------------------------------------------------------------
932// Inform BMC about PPIN data of 8 bytes for each CPU
933//
934// Request:
935// Byte 1:8 – CPU0 PPIN data
936// Optional:
937// Byte 9:16 – CPU1 PPIN data
938//
939// Response:
940// Byte 1 – Completion Code
941ipmi_ret_t ipmiOemSetPPINInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
942 ipmi_request_t request, ipmi_response_t response,
943 ipmi_data_len_t data_len, ipmi_context_t context)
944{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700945 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700946 std::string ppinStr;
947 int len;
948
949 if (*data_len > SIZE_CPU_PPIN * 2)
950 len = SIZE_CPU_PPIN * 2;
951 else
952 len = *data_len;
953 *data_len = 0;
954
955 ppinStr = bytesToStr(req, len);
956 oemData[KEY_PPIN_INFO] = ppinStr.c_str();
957 flushOemData();
958
959 return IPMI_CC_OK;
960}
961
962//----------------------------------------------------------------------
963// Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER)
964//----------------------------------------------------------------------
965ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
966 ipmi_request_t request,
967 ipmi_response_t response,
968 ipmi_data_len_t data_len,
969 ipmi_context_t context)
970{
971 /* Do nothing, return success */
972 *data_len = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800973 return IPMI_CC_OK;
974}
975
Vijay Khemkaf2246ce2020-05-27 14:26:35 -0700976// Helper function to set guid at offset in EEPROM
977static int setGUID(off_t offset, uint8_t* guid)
978{
979 int fd = -1;
980 ssize_t len;
981 int ret = 0;
982
983 errno = 0;
984
985 // Check if file is present
986 if (access(FRU_EEPROM, F_OK) == -1)
987 {
988 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl;
989 return errno;
990 }
991
992 // Open the file
993 fd = open(FRU_EEPROM, O_WRONLY);
994 if (fd == -1)
995 {
996 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl;
997 return errno;
998 }
999
1000 // seek to the offset
1001 lseek(fd, offset, SEEK_SET);
1002
1003 // Write bytes to location
1004 len = write(fd, guid, GUID_SIZE);
1005 if (len != GUID_SIZE)
1006 {
1007 phosphor::logging::log<phosphor::logging::level::ERR>(
1008 "GUID write data to EEPROM failed");
1009 ret = errno;
1010 }
1011
1012 close(fd);
1013 return ret;
1014}
1015
1016//----------------------------------------------------------------------
1017// Set System GUID (CMD_OEM_SET_SYSTEM_GUID)
1018//----------------------------------------------------------------------
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301019#if BIC_ENABLED
1020ipmi::RspType<> ipmiOemSetSystemGuid(ipmi::Context::ptr ctx, uint8_t cmdReq,
1021 std::vector<uint8_t> reqData)
1022{
1023 std::vector<uint8_t> respData;
1024
1025 if (reqData.size() != GUID_SIZE) // 16bytes
1026 {
1027
1028 return ipmi::responseReqDataLenInvalid();
1029 }
1030
1031 auto ptrReqData = reqData.insert(reqData.begin(), reqData.size());
1032
1033 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
1034
1035 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
1036 return ipmi::responseUnspecifiedError();
1037
1038 return ipmi::responseSuccess();
1039}
1040
1041#else
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001042ipmi_ret_t ipmiOemSetSystemGuid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1043 ipmi_request_t request,
1044 ipmi_response_t response,
1045 ipmi_data_len_t data_len,
1046 ipmi_context_t context)
1047{
1048 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1049
1050 if (*data_len != GUID_SIZE) // 16bytes
1051 {
1052 *data_len = 0;
1053 return IPMI_CC_REQ_DATA_LEN_INVALID;
1054 }
1055
1056 *data_len = 0;
1057
1058 if (setGUID(OFFSET_SYS_GUID, req))
1059 {
1060 return IPMI_CC_UNSPECIFIED_ERROR;
1061 }
1062 return IPMI_CC_OK;
1063}
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301064#endif
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001065
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001066//----------------------------------------------------------------------
1067// Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO)
1068//----------------------------------------------------------------------
1069ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1070 ipmi_request_t request,
1071 ipmi_response_t response,
1072 ipmi_data_len_t data_len,
1073 ipmi_context_t context)
1074{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001075 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001076 *data_len = 0;
1077 return IPMI_CC_OK;
1078}
1079
1080//----------------------------------------------------------------------
1081// Set PPR (CMD_OEM_SET_PPR)
1082//----------------------------------------------------------------------
1083ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1084 ipmi_request_t request, ipmi_response_t response,
1085 ipmi_data_len_t data_len, ipmi_context_t context)
1086{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001087 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001088 uint8_t pprCnt, pprAct, pprIndex;
1089 uint8_t selParam = req[0];
1090 uint8_t len = *data_len;
1091 std::stringstream ss;
1092 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001093
1094 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001095
1096 switch (selParam)
1097 {
1098 case PPR_ACTION:
1099 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) ==
1100 oemData[KEY_PPR].end())
1101 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1102
1103 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1104 if (pprCnt == 0)
1105 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1106
1107 pprAct = req[1];
1108 /* Check if ppr is enabled or disabled */
1109 if (!(pprAct & 0x80))
1110 pprAct = 0;
1111
1112 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct;
1113 break;
1114 case PPR_ROW_COUNT:
1115 if (req[1] > 100)
1116 return IPMI_CC_PARM_OUT_OF_RANGE;
1117
1118 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1];
1119 break;
1120 case PPR_ROW_ADDR:
1121 pprIndex = req[1];
1122 if (pprIndex > 100)
1123 return IPMI_CC_PARM_OUT_OF_RANGE;
1124
1125 if (len < PPR_ROW_ADDR_LEN + 1)
1126 {
1127 phosphor::logging::log<phosphor::logging::level::ERR>(
1128 "Invalid PPR Row Address length received");
1129 return IPMI_CC_REQ_DATA_LEN_INVALID;
1130 }
1131
1132 ss << std::hex;
1133 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1134
1135 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1136
1137 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN);
1138 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str();
1139 break;
1140 case PPR_HISTORY_DATA:
1141 pprIndex = req[1];
1142 if (pprIndex > 100)
1143 return IPMI_CC_PARM_OUT_OF_RANGE;
1144
1145 if (len < PPR_HST_DATA_LEN + 1)
1146 {
1147 phosphor::logging::log<phosphor::logging::level::ERR>(
1148 "Invalid PPR history data length received");
1149 return IPMI_CC_REQ_DATA_LEN_INVALID;
1150 }
1151
1152 ss << std::hex;
1153 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1154
1155 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1156
1157 str = bytesToStr(&req[1], PPR_HST_DATA_LEN);
1158 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str();
1159 break;
1160 default:
1161 return IPMI_CC_PARM_OUT_OF_RANGE;
1162 break;
1163 }
1164
1165 flushOemData();
1166
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001167 return IPMI_CC_OK;
1168}
1169
1170//----------------------------------------------------------------------
1171// Get PPR (CMD_OEM_GET_PPR)
1172//----------------------------------------------------------------------
1173ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1174 ipmi_request_t request, ipmi_response_t response,
1175 ipmi_data_len_t data_len, ipmi_context_t context)
1176{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001177 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1178 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001179 uint8_t pprCnt, pprIndex;
1180 uint8_t selParam = req[0];
1181 std::stringstream ss;
1182 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001183
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001184 /* Any failure will return zero length data */
1185 *data_len = 0;
1186
1187 switch (selParam)
1188 {
1189 case PPR_ACTION:
1190 res[0] = 0;
1191 *data_len = 1;
1192
1193 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1194 oemData[KEY_PPR].end())
1195 {
1196 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1197 if (pprCnt != 0)
1198 {
1199 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) !=
1200 oemData[KEY_PPR].end())
1201 {
1202 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION];
1203 }
1204 }
1205 }
1206 break;
1207 case PPR_ROW_COUNT:
1208 res[0] = 0;
1209 *data_len = 1;
1210 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1211 oemData[KEY_PPR].end())
1212 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1213 break;
1214 case PPR_ROW_ADDR:
1215 pprIndex = req[1];
1216 if (pprIndex > 100)
1217 return IPMI_CC_PARM_OUT_OF_RANGE;
1218
1219 ss << std::hex;
1220 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1221
1222 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1223 return IPMI_CC_PARM_OUT_OF_RANGE;
1224
1225 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) ==
1226 oemData[KEY_PPR][ss.str()].end())
1227 return IPMI_CC_PARM_OUT_OF_RANGE;
1228
1229 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR];
1230 *data_len = strToBytes(str, res);
1231 break;
1232 case PPR_HISTORY_DATA:
1233 pprIndex = req[1];
1234 if (pprIndex > 100)
1235 return IPMI_CC_PARM_OUT_OF_RANGE;
1236
1237 ss << std::hex;
1238 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1239
1240 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1241 return IPMI_CC_PARM_OUT_OF_RANGE;
1242
1243 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) ==
1244 oemData[KEY_PPR][ss.str()].end())
1245 return IPMI_CC_PARM_OUT_OF_RANGE;
1246
1247 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA];
1248 *data_len = strToBytes(str, res);
1249 break;
1250 default:
1251 return IPMI_CC_PARM_OUT_OF_RANGE;
1252 break;
1253 }
1254
1255 return IPMI_CC_OK;
1256}
1257
1258/* FB OEM QC Commands */
1259
1260//----------------------------------------------------------------------
1261// Set Proc Info (CMD_OEM_Q_SET_PROC_INFO)
1262//----------------------------------------------------------------------
1263//"Request:
1264// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1265// Byte 4 – Processor Index, 0 base
1266// Byte 5 – Parameter Selector
1267// Byte 6..N – Configuration parameter data (see below for Parameters
1268// of Processor Information)
1269// Response:
1270// Byte 1 – Completion code
1271//
1272// Parameter#1: (Processor Product Name)
1273//
1274// Byte 1..48 –Product name(ASCII code)
1275// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1276//
1277// Param#2: Processor Basic Information
1278// Byte 1 – Core Number
1279// Byte 2 – Thread Number (LSB)
1280// Byte 3 – Thread Number (MSB)
1281// Byte 4 – Processor frequency in MHz (LSB)
1282// Byte 5 – Processor frequency in MHz (MSB)
1283// Byte 6..7 – Revision
1284//
1285ipmi_ret_t ipmiOemQSetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1286 ipmi_request_t request, ipmi_response_t response,
1287 ipmi_data_len_t data_len, ipmi_context_t context)
1288{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001289 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1290 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001291 std::stringstream ss;
1292 std::string str;
1293 uint8_t len = *data_len;
1294
1295 *data_len = 0;
1296
1297 /* check for requested data params */
1298 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1299 {
1300 phosphor::logging::log<phosphor::logging::level::ERR>(
1301 "Invalid parameter received");
1302 return IPMI_CC_PARM_OUT_OF_RANGE;
1303 }
1304
1305 len = len - 5; // Get Actual data length
1306
1307 ss << std::hex;
1308 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1309 oemData[KEY_Q_PROC_INFO][ss.str()][KEY_PROC_INDEX] = req->procIndex;
1310
1311 str = bytesToStr(req->data, len);
1312 oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]] = str.c_str();
1313 flushOemData();
1314
1315 return IPMI_CC_OK;
1316}
1317
1318//----------------------------------------------------------------------
1319// Get Proc Info (CMD_OEM_Q_GET_PROC_INFO)
1320//----------------------------------------------------------------------
1321// Request:
1322// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1323// Byte 4 – Processor Index, 0 base
1324// Byte 5 – Parameter Selector
1325// Response:
1326// Byte 1 – Completion code
1327// Byte 2..N – Configuration Parameter Data (see below for Parameters
1328// of Processor Information)
1329//
1330// Parameter#1: (Processor Product Name)
1331//
1332// Byte 1..48 –Product name(ASCII code)
1333// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1334//
1335// Param#2: Processor Basic Information
1336// Byte 1 – Core Number
1337// Byte 2 – Thread Number (LSB)
1338// Byte 3 – Thread Number (MSB)
1339// Byte 4 – Processor frequency in MHz (LSB)
1340// Byte 5 – Processor frequency in MHz (MSB)
1341// Byte 6..7 – Revision
1342//
1343ipmi_ret_t ipmiOemQGetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1344 ipmi_request_t request, ipmi_response_t response,
1345 ipmi_data_len_t data_len, ipmi_context_t context)
1346{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001347 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1348 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
1349 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001350 std::stringstream ss;
1351 std::string str;
1352
1353 *data_len = 0;
1354
1355 /* check for requested data params */
1356 if (req->paramSel < 1 || req->paramSel >= numParam)
1357 {
1358 phosphor::logging::log<phosphor::logging::level::ERR>(
1359 "Invalid parameter received");
1360 return IPMI_CC_PARM_OUT_OF_RANGE;
1361 }
1362
1363 ss << std::hex;
1364 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1365
1366 if (oemData[KEY_Q_PROC_INFO].find(ss.str()) ==
1367 oemData[KEY_Q_PROC_INFO].end())
1368 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1369
1370 if (oemData[KEY_Q_PROC_INFO][ss.str()].find(cpuInfoKey[req->paramSel]) ==
1371 oemData[KEY_Q_PROC_INFO][ss.str()].end())
1372 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1373
1374 str = oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]];
1375 *data_len = strToBytes(str, res);
1376
1377 return IPMI_CC_OK;
1378}
1379
1380//----------------------------------------------------------------------
1381// Set Dimm Info (CMD_OEM_Q_SET_DIMM_INFO)
1382//----------------------------------------------------------------------
1383// Request:
1384// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1385// Byte 4 – DIMM Index, 0 base
1386// Byte 5 – Parameter Selector
1387// Byte 6..N – Configuration parameter data (see below for Parameters
1388// of DIMM Information)
1389// Response:
1390// Byte 1 – Completion code
1391//
1392// Param#1 (DIMM Location):
1393// Byte 1 – DIMM Present
1394// Byte 1 – DIMM Present
1395// 01h – Present
1396// FFh – Not Present
1397// Byte 2 – Node Number, 0 base
1398// Byte 3 – Channel Number , 0 base
1399// Byte 4 – DIMM Number , 0 base
1400//
1401// Param#2 (DIMM Type):
1402// Byte 1 – DIMM Type
1403// Bit [7:6]
1404// For DDR3
1405// 00 – Normal Voltage (1.5V)
1406// 01 – Ultra Low Voltage (1.25V)
1407// 10 – Low Voltage (1.35V)
1408// 11 – Reserved
1409// For DDR4
1410// 00 – Reserved
1411// 01 – Reserved
1412// 10 – Reserved
1413// 11 – Normal Voltage (1.2V)
1414// Bit [5:0]
1415// 0x00 – SDRAM
1416// 0x01 – DDR-1 RAM
1417// 0x02 – Rambus
1418// 0x03 – DDR-2 RAM
1419// 0x04 – FBDIMM
1420// 0x05 – DDR-3 RAM
1421// 0x06 – DDR-4 RAM
1422//
1423// Param#3 (DIMM Speed):
1424// Byte 1..2 – DIMM speed in MHz, LSB
1425// Byte 3..6 – DIMM size in Mbytes, LSB
1426//
1427// Param#4 (Module Part Number):
1428// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1429//
1430// Param#5 (Module Serial Number):
1431// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1432//
1433// Param#6 (Module Manufacturer ID):
1434// Byte 1 - Module Manufacturer ID, LSB
1435// Byte 2 - Module Manufacturer ID, MSB
1436//
1437ipmi_ret_t ipmiOemQSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1438 ipmi_request_t request, ipmi_response_t response,
1439 ipmi_data_len_t data_len, ipmi_context_t context)
1440{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001441 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1442 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001443 std::stringstream ss;
1444 std::string str;
1445 uint8_t len = *data_len;
1446
1447 *data_len = 0;
1448
1449 /* check for requested data params */
1450 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1451 {
1452 phosphor::logging::log<phosphor::logging::level::ERR>(
1453 "Invalid parameter received");
1454 return IPMI_CC_PARM_OUT_OF_RANGE;
1455 }
1456
1457 len = len - 5; // Get Actual data length
1458
1459 ss << std::hex;
1460 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1461 oemData[KEY_Q_DIMM_INFO][ss.str()][KEY_DIMM_INDEX] = req->dimmIndex;
1462
1463 str = bytesToStr(req->data, len);
1464 oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]] =
1465 str.c_str();
1466 flushOemData();
1467
1468 return IPMI_CC_OK;
1469}
1470
1471//----------------------------------------------------------------------
1472// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
1473//----------------------------------------------------------------------
1474// Request:
1475// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1476// Byte 4 – DIMM Index, 0 base
1477// Byte 5 – Parameter Selector
1478// Byte 6..N – Configuration parameter data (see below for Parameters
1479// of DIMM Information)
1480// Response:
1481// Byte 1 – Completion code
1482// Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters
1483// of DIMM Information)
1484//
1485// Param#1 (DIMM Location):
1486// Byte 1 – DIMM Present
1487// Byte 1 – DIMM Present
1488// 01h – Present
1489// FFh – Not Present
1490// Byte 2 – Node Number, 0 base
1491// Byte 3 – Channel Number , 0 base
1492// Byte 4 – DIMM Number , 0 base
1493//
1494// Param#2 (DIMM Type):
1495// Byte 1 – DIMM Type
1496// Bit [7:6]
1497// For DDR3
1498// 00 – Normal Voltage (1.5V)
1499// 01 – Ultra Low Voltage (1.25V)
1500// 10 – Low Voltage (1.35V)
1501// 11 – Reserved
1502// For DDR4
1503// 00 – Reserved
1504// 01 – Reserved
1505// 10 – Reserved
1506// 11 – Normal Voltage (1.2V)
1507// Bit [5:0]
1508// 0x00 – SDRAM
1509// 0x01 – DDR-1 RAM
1510// 0x02 – Rambus
1511// 0x03 – DDR-2 RAM
1512// 0x04 – FBDIMM
1513// 0x05 – DDR-3 RAM
1514// 0x06 – DDR-4 RAM
1515//
1516// Param#3 (DIMM Speed):
1517// Byte 1..2 – DIMM speed in MHz, LSB
1518// Byte 3..6 – DIMM size in Mbytes, LSB
1519//
1520// Param#4 (Module Part Number):
1521// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1522//
1523// Param#5 (Module Serial Number):
1524// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1525//
1526// Param#6 (Module Manufacturer ID):
1527// Byte 1 - Module Manufacturer ID, LSB
1528// Byte 2 - Module Manufacturer ID, MSB
1529//
1530ipmi_ret_t ipmiOemQGetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1531 ipmi_request_t request, ipmi_response_t response,
1532 ipmi_data_len_t data_len, ipmi_context_t context)
1533{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001534 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1535 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
1536 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001537 std::stringstream ss;
1538 std::string str;
1539
1540 *data_len = 0;
1541
1542 /* check for requested data params */
1543 if (req->paramSel < 1 || req->paramSel >= numParam)
1544 {
1545 phosphor::logging::log<phosphor::logging::level::ERR>(
1546 "Invalid parameter received");
1547 return IPMI_CC_PARM_OUT_OF_RANGE;
1548 }
1549
1550 ss << std::hex;
1551 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1552
1553 if (oemData[KEY_Q_DIMM_INFO].find(ss.str()) ==
1554 oemData[KEY_Q_DIMM_INFO].end())
1555 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1556
1557 if (oemData[KEY_Q_DIMM_INFO][ss.str()].find(dimmInfoKey[req->paramSel]) ==
1558 oemData[KEY_Q_DIMM_INFO][ss.str()].end())
1559 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1560
1561 str = oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]];
1562 *data_len = strToBytes(str, res);
1563
1564 return IPMI_CC_OK;
1565}
1566
1567//----------------------------------------------------------------------
1568// Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO)
1569//----------------------------------------------------------------------
1570// BIOS issue this command to provide HDD information to BMC.
1571//
1572// BIOS just can get information by standard ATA / SMART command for
1573// OB SATA controller.
1574// BIOS can get
1575// 1. Serial Number
1576// 2. Model Name
1577// 3. HDD FW Version
1578// 4. HDD Capacity
1579// 5. HDD WWN
1580//
1581// Use Get HDD info Param #5 to know the MAX HDD info index.
1582//
1583// Request:
1584// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1585// Byte 4 –
1586// [7:4] Reserved
1587// [3:0] HDD Controller Type
1588// 0x00 – BIOS
1589// 0x01 – Expander
1590// 0x02 – LSI
1591// Byte 5 – HDD Info Index, 0 base
1592// Byte 6 – Parameter Selector
1593// Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD
1594// Information)
1595//
1596// Response:
1597// Byte 1 – Completion Code
1598//
1599// Param#0 (HDD Location):
1600// Byte 1 – Controller
1601// [7:3] Device Number
1602// [2:0] Function Number
1603// For Intel C610 series (Wellsburg)
1604// D31:F2 (0xFA) – SATA control 1
1605// D31:F5 (0xFD) – SATA control 2
1606// D17:F4 (0x8C) – sSata control
1607// Byte 2 – Port Number
1608// Byte 3 – Location (0xFF: No HDD Present)
1609// BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param
1610// #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if
1611// the HDD present. BMC or other people who know the HDD location has
1612// responsibility for update Location info
1613//
1614// Param#1 (Serial Number):
1615// Bytes 1..33: HDD Serial Number
1616//
1617// Param#2 (Model Name):
1618// Byte 1..33 – HDD Model Name
1619//
1620// Param#3 (HDD FW Version):
1621// Byte 1..17 –HDD FW version
1622//
1623// Param#4 (Capacity):
1624// Byte 1..4 –HDD Block Size, LSB
1625// Byte 5..12 - HDD Block Number, LSB
1626// HDD Capacity = HDD Block size * HDD BLock number (Unit Byte)
1627//
1628// Param#5 (Max HDD Quantity):
1629// Byte 1 - Max HDD Quantity
1630// Max supported port numbers in this PCH
1631//
1632// Param#6 (HDD Type)
1633// Byte 1 – HDD Type
1634// 0h – Reserved
1635// 1h – SAS
1636// 2h – SATA
1637// 3h – PCIE SSD (NVME)
1638//
1639// Param#7 (HDD WWN)
1640// Data 1...8: HDD World Wide Name, LSB
1641//
1642ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1643 ipmi_request_t request,
1644 ipmi_response_t response,
1645 ipmi_data_len_t data_len,
1646 ipmi_context_t context)
1647{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001648 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1649 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001650 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1651 std::stringstream ss;
1652 std::string str;
1653 uint8_t len = *data_len;
1654
1655 *data_len = 0;
1656
1657 /* check for requested data params */
1658 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam ||
1659 ctrlType > 2)
1660 {
1661 phosphor::logging::log<phosphor::logging::level::ERR>(
1662 "Invalid parameter received");
1663 return IPMI_CC_PARM_OUT_OF_RANGE;
1664 }
1665
1666 len = len - 6; // Get Actual data length
1667
1668 ss << std::hex;
1669 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1670 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType;
1671 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] =
1672 req->hddIndex;
1673
1674 str = bytesToStr(req->data, len);
1675 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1676 [driveInfoKey[req->paramSel]] = str.c_str();
1677 flushOemData();
1678
1679 return IPMI_CC_OK;
1680}
1681
1682//----------------------------------------------------------------------
1683// Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO)
1684//----------------------------------------------------------------------
1685// BMC needs to check HDD presented or not first. If NOT presented, return
1686// completion code 0xD5.
1687//
1688// Request:
1689// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1690// Byte 4 –
1691//[7:4] Reserved
1692//[3:0] HDD Controller Type
1693// 0x00 – BIOS
1694// 0x01 – Expander
1695// 0x02 – LSI
1696// Byte 5 – HDD Index, 0 base
1697// Byte 6 – Parameter Selector (See Above Set HDD Information)
1698// Response:
1699// Byte 1 – Completion Code
1700// 0xD5 – Not support in current status (HDD Not Present)
1701// Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD
1702// Information)
1703//
1704ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1705 ipmi_request_t request,
1706 ipmi_response_t response,
1707 ipmi_data_len_t data_len,
1708 ipmi_context_t context)
1709{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001710 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1711 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
1712 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001713 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1714 std::stringstream ss;
1715 std::string str;
1716
1717 *data_len = 0;
1718
1719 /* check for requested data params */
1720 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2)
1721 {
1722 phosphor::logging::log<phosphor::logging::level::ERR>(
1723 "Invalid parameter received");
1724 return IPMI_CC_PARM_OUT_OF_RANGE;
1725 }
1726
1727 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) ==
1728 oemData[KEY_Q_DRIVE_INFO].end())
1729 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1730
1731 ss << std::hex;
1732 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1733
1734 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) ==
1735 oemData[KEY_Q_DRIVE_INFO].end())
1736 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1737
1738 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find(
1739 dimmInfoKey[req->paramSel]) ==
1740 oemData[KEY_Q_DRIVE_INFO][ss.str()].end())
1741 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1742
1743 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1744 [dimmInfoKey[req->paramSel]];
1745 *data_len = strToBytes(str, res);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001746
1747 return IPMI_CC_OK;
1748}
1749
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001750/* Helper function for sending DCMI commands to ME and getting response back */
1751ipmi::RspType<std::vector<uint8_t>> sendDCMICmd(uint8_t cmd,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001752 std::vector<uint8_t>& cmdData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001753{
1754 std::vector<uint8_t> respData;
1755
1756 /* Add group id as first byte to request for ME command */
1757 cmdData.insert(cmdData.begin(), groupDCMI);
1758
1759 if (sendMeCmd(ipmi::netFnGroup, cmd, cmdData, respData))
1760 return ipmi::responseUnspecifiedError();
1761
1762 /* Remove group id as first byte as it will be added by IPMID */
1763 respData.erase(respData.begin());
1764
1765 return ipmi::responseSuccess(std::move(respData));
1766}
1767
1768/* DCMI Command handellers. */
1769
1770ipmi::RspType<std::vector<uint8_t>>
1771 ipmiOemDCMIGetPowerReading(std::vector<uint8_t> reqData)
1772{
1773 return sendDCMICmd(ipmi::dcmi::cmdGetPowerReading, reqData);
1774}
1775
1776ipmi::RspType<std::vector<uint8_t>>
1777 ipmiOemDCMIGetPowerLimit(std::vector<uint8_t> reqData)
1778{
1779 return sendDCMICmd(ipmi::dcmi::cmdGetPowerLimit, reqData);
1780}
1781
1782ipmi::RspType<std::vector<uint8_t>>
1783 ipmiOemDCMISetPowerLimit(std::vector<uint8_t> reqData)
1784{
1785 return sendDCMICmd(ipmi::dcmi::cmdSetPowerLimit, reqData);
1786}
1787
1788ipmi::RspType<std::vector<uint8_t>>
1789 ipmiOemDCMIApplyPowerLimit(std::vector<uint8_t> reqData)
1790{
1791 return sendDCMICmd(ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
1792}
1793
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001794static void registerOEMFunctions(void)
1795{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001796 /* Get OEM data from json file */
1797 std::ifstream file(JSON_OEM_DATA_FILE);
1798 if (file)
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001799 {
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001800 file >> oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001801 file.close();
1802 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001803
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001804 phosphor::logging::log<phosphor::logging::level::INFO>(
1805 "Registering OEM commands");
Vijay Khemka7c0aea42020-03-05 13:31:53 -08001806
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001807 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO,
1808 NULL, ipmiOemDbgGetFrameInfo,
1809 PRIVILEGE_USER); // get debug frame info
1810 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ,
1811 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL,
1812 ipmiOemDbgGetUpdFrames,
1813 PRIVILEGE_USER); // get debug updated frames
1814 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC,
1815 NULL, ipmiOemDbgGetPostDesc,
1816 PRIVILEGE_USER); // get debug post description
1817 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC,
1818 NULL, ipmiOemDbgGetGpioDesc,
1819 PRIVILEGE_USER); // get debug gpio description
1820 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA,
1821 NULL, ipmiOemDbgGetFrameData,
1822 PRIVILEGE_USER); // get debug frame data
1823 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL,
1824 NULL, ipmiOemDbgGetCtrlPanel,
1825 PRIVILEGE_USER); // get debug control panel
1826 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL,
1827 ipmiOemSetDimmInfo,
1828 PRIVILEGE_USER); // Set Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001829 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL,
1830 ipmiOemGetBoardID,
1831 PRIVILEGE_USER); // Get Board ID
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001832 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL,
1833 ipmiOemSetMachineCfgInfo,
1834 PRIVILEGE_USER); // Set Machine Config Info
1835 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL,
1836 ipmiOemSetPostStart,
1837 PRIVILEGE_USER); // Set POST start
1838 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL,
1839 ipmiOemSetPostEnd,
1840 PRIVILEGE_USER); // Set POST End
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001841 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL,
1842 ipmiOemSetPPINInfo,
1843 PRIVILEGE_USER); // Set PPIN Info
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301844#if BIC_ENABLED
1845
1846 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1847 ipmi::cmdSetSystemGuid, ipmi::Privilege::User,
1848 ipmiOemSetSystemGuid);
1849#else
1850
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001851 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_SYSTEM_GUID, NULL,
1852 ipmiOemSetSystemGuid,
1853 PRIVILEGE_USER); // Set System GUID
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301854#endif
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001855 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL,
1856 ipmiOemSetAdrTrigger,
1857 PRIVILEGE_USER); // Set ADR Trigger
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001858 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL,
1859 ipmiOemSetBiosFlashInfo,
1860 PRIVILEGE_USER); // Set Bios Flash Info
1861 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr,
1862 PRIVILEGE_USER); // Set PPR
1863 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
1864 PRIVILEGE_USER); // Get PPR
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001865 /* FB OEM QC Commands */
1866 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_PROC_INFO, NULL,
1867 ipmiOemQSetProcInfo,
1868 PRIVILEGE_USER); // Set Proc Info
1869 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL,
1870 ipmiOemQGetProcInfo,
1871 PRIVILEGE_USER); // Get Proc Info
1872 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DIMM_INFO, NULL,
1873 ipmiOemQSetDimmInfo,
1874 PRIVILEGE_USER); // Set Dimm Info
1875 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DIMM_INFO, NULL,
1876 ipmiOemQGetDimmInfo,
1877 PRIVILEGE_USER); // Get Dimm Info
1878 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
1879 ipmiOemQSetDriveInfo,
1880 PRIVILEGE_USER); // Set Drive Info
1881 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL,
1882 ipmiOemQGetDriveInfo,
1883 PRIVILEGE_USER); // Get Drive Info
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001884
1885 /* FB OEM DCMI Commands as per DCMI spec 1.5 Section 6 */
1886 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1887 ipmi::dcmi::cmdGetPowerReading,
1888 ipmi::Privilege::User,
1889 ipmiOemDCMIGetPowerReading); // Get Power Reading
1890
1891 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1892 ipmi::dcmi::cmdGetPowerLimit,
1893 ipmi::Privilege::User,
1894 ipmiOemDCMIGetPowerLimit); // Get Power Limit
1895
1896 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1897 ipmi::dcmi::cmdSetPowerLimit,
1898 ipmi::Privilege::Operator,
1899 ipmiOemDCMISetPowerLimit); // Set Power Limit
1900
1901 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1902 ipmi::dcmi::cmdActDeactivatePwrLimit,
1903 ipmi::Privilege::Operator,
1904 ipmiOemDCMIApplyPowerLimit); // Apply Power Limit
1905
Jayashree-Df0cf6652020-11-30 11:03:30 +05301906 /* FB OEM BOOT ORDER COMMANDS */
1907 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1908 CMD_OEM_GET_BOOT_ORDER, ipmi::Privilege::User,
1909 ipmiOemGetBootOrder); // Get Boot Order
1910
1911 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1912 CMD_OEM_SET_BOOT_ORDER, ipmi::Privilege::User,
1913 ipmiOemSetBootOrder); // Set Boot Order
1914
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001915 return;
1916}
1917
1918} // namespace ipmi