blob: ea5da827f2a9835a9707449cd1a0def0e076535f [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
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530340bool isMultiHostPlatform()
341{
342 bool platform;
343 if (INSTANCES == "0")
344 {
345 platform = false;
346 }
347 else
348 {
349 platform = true;
350 }
351 return platform;
352}
353
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800354// return code: 0 successful
Vijay Khemka63c99be2020-05-27 19:14:35 -0700355int8_t getFruData(std::string& data, std::string& name)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800356{
357 std::string objpath = "/xyz/openbmc_project/FruDevice";
358 std::string intf = "xyz.openbmc_project.FruDeviceManager";
359 std::string service = getService(dbus, intf, objpath);
360 ObjectValueTree valueTree = getManagedObjects(dbus, service, "/");
361 if (valueTree.empty())
362 {
363 phosphor::logging::log<phosphor::logging::level::ERR>(
364 "No object implements interface",
365 phosphor::logging::entry("INTF=%s", intf.c_str()));
366 return -1;
367 }
368
Vijay Khemka63c99be2020-05-27 19:14:35 -0700369 for (const auto& item : valueTree)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800370 {
371 auto interface = item.second.find("xyz.openbmc_project.FruDevice");
372 if (interface == item.second.end())
373 {
374 continue;
375 }
376
377 auto property = interface->second.find(name.c_str());
378 if (property == interface->second.end())
379 {
380 continue;
381 }
382
383 try
384 {
385 Value variant = property->second;
Vijay Khemka63c99be2020-05-27 19:14:35 -0700386 std::string& result = std::get<std::string>(variant);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800387 if (result.size() > maxFRUStringLength)
388 {
389 phosphor::logging::log<phosphor::logging::level::ERR>(
390 "FRU serial number exceed maximum length");
391 return -1;
392 }
393 data = result;
394 return 0;
395 }
Patrick Williams35d12542021-10-06 11:21:13 -0500396 catch (const std::bad_variant_access& e)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800397 {
398 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
399 return -1;
400 }
401 }
402 return -1;
403}
404
405typedef struct
406{
407 uint8_t cur_power_state;
408 uint8_t last_power_event;
409 uint8_t misc_power_state;
410 uint8_t front_panel_button_cap_status;
411} ipmi_get_chassis_status_t;
412
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800413//----------------------------------------------------------------------
414// Get Debug Frame Info
415//----------------------------------------------------------------------
416ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
417 ipmi_request_t request,
418 ipmi_response_t response,
419 ipmi_data_len_t data_len,
420 ipmi_context_t context)
421{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700422 uint8_t* req = reinterpret_cast<uint8_t*>(request);
423 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800424 uint8_t num_frames = 3;
425
426 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
427 res[SIZE_IANA_ID] = num_frames;
428 *data_len = SIZE_IANA_ID + 1;
429
430 return IPMI_CC_OK;
431}
432
433//----------------------------------------------------------------------
434// Get Debug Updated Frames
435//----------------------------------------------------------------------
436ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
437 ipmi_request_t request,
438 ipmi_response_t response,
439 ipmi_data_len_t data_len,
440 ipmi_context_t context)
441{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700442 uint8_t* req = reinterpret_cast<uint8_t*>(request);
443 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800444 uint8_t num_updates = 3;
445 *data_len = 4;
446
447 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
448 res[SIZE_IANA_ID] = num_updates;
449 *data_len = SIZE_IANA_ID + num_updates + 1;
450 res[SIZE_IANA_ID + 1] = 1; // info page update
451 res[SIZE_IANA_ID + 2] = 2; // cri sel update
452 res[SIZE_IANA_ID + 3] = 3; // cri sensor update
453
454 return IPMI_CC_OK;
455}
456
457//----------------------------------------------------------------------
458// Get Debug POST Description
459//----------------------------------------------------------------------
460ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
461 ipmi_request_t request,
462 ipmi_response_t response,
463 ipmi_data_len_t data_len,
464 ipmi_context_t context)
465{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700466 uint8_t* req = reinterpret_cast<uint8_t*>(request);
467 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800468 uint8_t index = 0;
469 uint8_t next = 0;
470 uint8_t end = 0;
471 uint8_t phase = 0;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700472 uint8_t descLen = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800473 int ret;
474
475 index = req[3];
476 phase = req[4];
477
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700478 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800479 if (ret)
480 {
481 memcpy(res, req, SIZE_IANA_ID); // IANA ID
482 *data_len = SIZE_IANA_ID;
483 return IPMI_CC_UNSPECIFIED_ERROR;
484 }
485
486 memcpy(res, req, SIZE_IANA_ID); // IANA ID
487 res[3] = index;
488 res[4] = next;
489 res[5] = phase;
490 res[6] = end;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700491 res[7] = descLen;
492 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800493
494 return IPMI_CC_OK;
495}
496
497//----------------------------------------------------------------------
498// Get Debug GPIO Description
499//----------------------------------------------------------------------
500ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
501 ipmi_request_t request,
502 ipmi_response_t response,
503 ipmi_data_len_t data_len,
504 ipmi_context_t context)
505{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700506 uint8_t* req = reinterpret_cast<uint8_t*>(request);
507 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800508
Vijay Khemka38183d62019-08-28 16:19:33 -0700509 uint8_t index = 0;
510 uint8_t next = 0;
511 uint8_t level = 0;
512 uint8_t pinDef = 0;
513 uint8_t descLen = 0;
514 int ret;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800515
Vijay Khemka38183d62019-08-28 16:19:33 -0700516 index = req[3];
517
518 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen,
519 &res[8]);
520 if (ret)
521 {
522 memcpy(res, req, SIZE_IANA_ID); // IANA ID
523 *data_len = SIZE_IANA_ID;
524 return IPMI_CC_UNSPECIFIED_ERROR;
525 }
526
527 memcpy(res, req, SIZE_IANA_ID); // IANA ID
528 res[3] = index;
529 res[4] = next;
530 res[5] = level;
531 res[6] = pinDef;
532 res[7] = descLen;
533 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800534
535 return IPMI_CC_OK;
536}
537
538//----------------------------------------------------------------------
539// Get Debug Frame Data
540//----------------------------------------------------------------------
541ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
542 ipmi_request_t request,
543 ipmi_response_t response,
544 ipmi_data_len_t data_len,
545 ipmi_context_t context)
546{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700547 uint8_t* req = reinterpret_cast<uint8_t*>(request);
548 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800549 uint8_t frame;
550 uint8_t page;
551 uint8_t next;
552 uint8_t count;
553 int ret;
554
555 frame = req[3];
556 page = req[4];
557 int fr = frame;
558 int pg = page;
559
560 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]);
561 if (ret)
562 {
563 memcpy(res, req, SIZE_IANA_ID); // IANA ID
564 *data_len = SIZE_IANA_ID;
565 return IPMI_CC_UNSPECIFIED_ERROR;
566 }
567
568 memcpy(res, req, SIZE_IANA_ID); // IANA ID
569 res[3] = frame;
570 res[4] = page;
571 res[5] = next;
572 res[6] = count;
573 *data_len = SIZE_IANA_ID + 4 + count;
574
575 return IPMI_CC_OK;
576}
577
578//----------------------------------------------------------------------
579// Get Debug Control Panel
580//----------------------------------------------------------------------
581ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
582 ipmi_request_t request,
583 ipmi_response_t response,
584 ipmi_data_len_t data_len,
585 ipmi_context_t context)
586{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700587 uint8_t* req = reinterpret_cast<uint8_t*>(request);
588 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800589
590 uint8_t panel;
591 uint8_t operation;
592 uint8_t item;
593 uint8_t count;
594 ipmi_ret_t ret;
595
596 panel = req[3];
597 operation = req[4];
598 item = req[5];
599
600 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]);
601
602 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
603 *data_len = SIZE_IANA_ID + count;
604
605 return ret;
606}
607
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800608//----------------------------------------------------------------------
609// Set Dimm Info (CMD_OEM_SET_DIMM_INFO)
610//----------------------------------------------------------------------
611ipmi_ret_t ipmiOemSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
612 ipmi_request_t request, ipmi_response_t response,
613 ipmi_data_len_t data_len, ipmi_context_t context)
614{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700615 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700616
617 uint8_t index = req[0];
618 uint8_t type = req[1];
619 uint16_t speed;
620 uint32_t size;
621
622 memcpy(&speed, &req[2], 2);
623 memcpy(&size, &req[4], 4);
624
625 std::stringstream ss;
626 ss << std::hex;
627 ss << std::setw(2) << std::setfill('0') << (int)index;
628
629 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index;
630 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type;
631 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed;
632 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size;
633
634 flushOemData();
635
636 *data_len = 0;
637
638 return IPMI_CC_OK;
639}
640
641//----------------------------------------------------------------------
642// Get Board ID (CMD_OEM_GET_BOARD_ID)
643//----------------------------------------------------------------------
644ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
645 ipmi_request_t request, ipmi_response_t response,
646 ipmi_data_len_t data_len, ipmi_context_t context)
647{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700648 uint8_t* req = reinterpret_cast<uint8_t*>(request);
649 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800650
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700651 /* TODO: Needs to implement this after GPIO implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800652 *data_len = 0;
653
654 return IPMI_CC_OK;
655}
656
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800657/* Helper functions to set boot order */
Jayashree-Df0cf6652020-11-30 11:03:30 +0530658void setBootOrder(std::string bootObjPath, uint8_t* data,
659 std::string bootOrderKey)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800660{
Jayashree-Df0cf6652020-11-30 11:03:30 +0530661
662 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
663
664 // SETTING BOOT MODE PROPERTY
665 auto bootValue = ipmi::boot::modeIpmiToDbus.find((data[0]));
666 std::string bootOption =
667 ipmi::boot::Mode::convertModesToString((bootValue->second));
668
669 std::string service =
670 getService(*dbus, ipmi::boot::bootModeIntf, bootObjPath);
671 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf,
672 ipmi::boot::bootModeProp, bootOption);
673
674 // SETTING BOOT SOURCE PROPERTY
675 auto bootOrder = ipmi::boot::sourceIpmiToDbus.find((data[1]));
676 std::string bootSource =
677 ipmi::boot::Source::convertSourcesToString((bootOrder->second));
678
679 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath);
680 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf,
681 ipmi::boot::bootSourceProp, bootSource);
682
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800683 nlohmann::json bootMode;
684 uint8_t mode = data[0];
685 int i;
686
687 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false);
688 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false);
689 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false);
690 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false);
Jayashree-Df0cf6652020-11-30 11:03:30 +0530691 oemData[bootOrderKey][KEY_BOOT_MODE] = bootMode;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800692
693 /* Initialize boot sequence array */
Jayashree-Df0cf6652020-11-30 11:03:30 +0530694 oemData[bootOrderKey][KEY_BOOT_SEQ] = {};
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800695 for (i = 1; i < SIZE_BOOT_ORDER; i++)
696 {
697 if (data[i] >= BOOT_SEQ_ARRAY_SIZE)
Jayashree-Df0cf6652020-11-30 11:03:30 +0530698 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = "NA";
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800699 else
Jayashree-Df0cf6652020-11-30 11:03:30 +0530700 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = bootSeq[data[i]];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800701 }
702
703 flushOemData();
704}
705
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800706//----------------------------------------------------------------------
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700707// Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
708//----------------------------------------------------------------------
Jayashree-Df0cf6652020-11-30 11:03:30 +0530709ipmi::RspType<std::vector<uint8_t>>
710 ipmiOemSetBootOrder(ipmi::Context::ptr ctx, std::vector<uint8_t> data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700711{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700712
Jayashree-Df0cf6652020-11-30 11:03:30 +0530713 uint8_t bootSeq[SIZE_BOOT_ORDER];
714 size_t len = data.size();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700715
716 if (len != SIZE_BOOT_ORDER)
717 {
718 phosphor::logging::log<phosphor::logging::level::ERR>(
719 "Invalid Boot order length received");
Jayashree-Df0cf6652020-11-30 11:03:30 +0530720 return ipmi::responseReqDataLenInvalid();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700721 }
722
Jayashree-Df0cf6652020-11-30 11:03:30 +0530723 std::copy(std::begin(data), std::end(data), bootSeq);
724 std::optional<size_t> hostId = ipmi::boot::findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700725
Jayashree-Df0cf6652020-11-30 11:03:30 +0530726 if (!hostId)
727 {
728 phosphor::logging::log<phosphor::logging::level::ERR>(
729 "Invalid Host Id received");
730 return ipmi::responseInvalidCommand();
731 }
732 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
733
734 setBootOrder(bootObjPath, bootSeq, hostName);
735
736 return ipmi::responseSuccess(data);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700737}
738
739//----------------------------------------------------------------------
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800740// Get Boot Order (CMD_OEM_GET_BOOT_ORDER)
741//----------------------------------------------------------------------
Jayashree-Df0cf6652020-11-30 11:03:30 +0530742ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>
743 ipmiOemGetBootOrder(ipmi::Context::ptr ctx)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800744{
Jayashree-Df0cf6652020-11-30 11:03:30 +0530745 uint8_t bootOption, bootOrder;
746 uint8_t bootSeq[SIZE_BOOT_ORDER];
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700747 uint8_t mode = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800748
Jayashree-Df0cf6652020-11-30 11:03:30 +0530749 std::optional<size_t> hostId = ipmi::boot::findHost(ctx->hostIdx);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700750
Jayashree-Df0cf6652020-11-30 11:03:30 +0530751 if (!hostId)
752 {
753 phosphor::logging::log<phosphor::logging::level::ERR>(
754 "Invalid Host Id received");
755 return ipmi::responseInvalidCommand();
756 }
757 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId);
758
759 // GETTING PROPERTY OF MODE INTERFACE
760
761 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
762
763 std::string service =
764 getService(*dbus, ipmi::boot::bootModeIntf, bootObjPath);
765 Value variant =
766 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf,
767 ipmi::boot::bootModeProp);
768
769 auto bootMode = ipmi::boot::Mode::convertModesFromString(
770 std::get<std::string>(variant));
771
772 bootOption = ipmi::boot::modeDbusToIpmi.at(bootMode);
773
774 // GETTING PROPERTY OF SOURCE INTERFACE
775
776 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath);
777 variant =
778 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf,
779 ipmi::boot::bootSourceProp);
780 auto bootSource = ipmi::boot::Source::convertSourcesFromString(
781 std::get<std::string>(variant));
782
783 bootOrder = ipmi::boot::sourceDbusToIpmi.at(bootSource);
784
785 if (oemData.find(hostName) == oemData.end())
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800786 {
787 /* Return default boot order 0100090203ff */
788 uint8_t defaultBoot[SIZE_BOOT_ORDER] = {
789 BOOT_MODE_UEFI, bootMap["USB_DEV"], bootMap["NET_IPV6"],
790 bootMap["SATA_HDD"], bootMap["SATA_CD"], 0xff};
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700791
Jayashree-Df0cf6652020-11-30 11:03:30 +0530792 memcpy(bootSeq, defaultBoot, SIZE_BOOT_ORDER);
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800793 phosphor::logging::log<phosphor::logging::level::INFO>(
794 "Set default boot order");
Jayashree-Df0cf6652020-11-30 11:03:30 +0530795 setBootOrder(bootObjPath, defaultBoot, hostName);
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800796 }
797 else
798 {
Jayashree-Df0cf6652020-11-30 11:03:30 +0530799 nlohmann::json bootMode = oemData[hostName][KEY_BOOT_MODE];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800800 if (bootMode["UEFI"])
801 mode |= BOOT_MODE_UEFI;
802 if (bootMode["CMOS_CLR"])
803 mode |= BOOT_MODE_CMOS_CLR;
804 if (bootMode["BOOT_FLAG"])
805 mode |= BOOT_MODE_BOOT_FLAG;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700806
Jayashree-Df0cf6652020-11-30 11:03:30 +0530807 bootSeq[0] = mode;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800808
Jayashree-Df0cf6652020-11-30 11:03:30 +0530809 for (int i = 1; i < SIZE_BOOT_ORDER; i++)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800810 {
Jayashree-Df0cf6652020-11-30 11:03:30 +0530811 std::string seqStr = oemData[hostName][KEY_BOOT_SEQ][i - 1];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800812 if (bootMap.find(seqStr) != bootMap.end())
Jayashree-Df0cf6652020-11-30 11:03:30 +0530813 bootSeq[i] = bootMap[seqStr];
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800814 else
Jayashree-Df0cf6652020-11-30 11:03:30 +0530815 bootSeq[i] = 0xff;
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800816 }
817 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800818
Jayashree-Df0cf6652020-11-30 11:03:30 +0530819 return ipmi::responseSuccess(bootOption, bootOrder, bootSeq[2], bootSeq[3],
820 bootSeq[4], bootSeq[5]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800821}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800822// Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO)
823//----------------------------------------------------------------------
824ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
825 ipmi_request_t request,
826 ipmi_response_t response,
827 ipmi_data_len_t data_len,
828 ipmi_context_t context)
829{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700830 machineConfigInfo_t* req = reinterpret_cast<machineConfigInfo_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700831 uint8_t len = *data_len;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800832
833 *data_len = 0;
834
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700835 if (len < sizeof(machineConfigInfo_t))
836 {
837 phosphor::logging::log<phosphor::logging::level::ERR>(
838 "Invalid machine configuration length received");
839 return IPMI_CC_REQ_DATA_LEN_INVALID;
840 }
841
Vijay Khemka63c99be2020-05-27 19:14:35 -0700842 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700843 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN";
844 else
845 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] =
846 chassisType[req->chassis_type];
847
Vijay Khemka63c99be2020-05-27 19:14:35 -0700848 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700849 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN";
850 else
851 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type];
852
853 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt;
854 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt;
855 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt;
856 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt;
857
Vijay Khemka63c99be2020-05-27 19:14:35 -0700858 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700859 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN";
860 else
861 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type];
862
863 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {};
864 int i = 0;
865 if (req->pcie_card_loc & BIT_0)
866 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1";
867 if (req->pcie_card_loc & BIT_1)
868 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2";
869 if (req->pcie_card_loc & BIT_2)
870 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3";
871 if (req->pcie_card_loc & BIT_3)
872 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4";
873
Vijay Khemka63c99be2020-05-27 19:14:35 -0700874 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700875 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN";
876 else
877 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] =
878 pcieType[req->slot1_pcie_type];
879
Vijay Khemka63c99be2020-05-27 19:14:35 -0700880 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700881 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN";
882 else
883 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] =
884 pcieType[req->slot2_pcie_type];
885
Vijay Khemka63c99be2020-05-27 19:14:35 -0700886 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700887 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN";
888 else
889 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] =
890 pcieType[req->slot3_pcie_type];
891
Vijay Khemka63c99be2020-05-27 19:14:35 -0700892 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700893 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN";
894 else
895 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] =
896 pcieType[req->slot4_pcie_type];
897
898 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt;
899
900 flushOemData();
901
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800902 return IPMI_CC_OK;
903}
904
905//----------------------------------------------------------------------
906// Set POST start (CMD_OEM_SET_POST_START)
907//----------------------------------------------------------------------
908ipmi_ret_t ipmiOemSetPostStart(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 Khemkae7d23d02019-03-08 13:13:40 -0800912 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event");
913
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700914 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800915 *data_len = 0;
916 return IPMI_CC_OK;
917}
918
919//----------------------------------------------------------------------
920// Set POST End (CMD_OEM_SET_POST_END)
921//----------------------------------------------------------------------
922ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
923 ipmi_request_t request, ipmi_response_t response,
924 ipmi_data_len_t data_len, ipmi_context_t context)
925{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700926 struct timespec ts;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800927
928 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event");
929
930 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700931
932 // Timestamp post end time.
933 clock_gettime(CLOCK_REALTIME, &ts);
934 oemData[KEY_TS_SLED] = ts.tv_sec;
935 flushOemData();
936
937 // Sync time with system
938 // TODO: Add code for syncing time
939
940 return IPMI_CC_OK;
941}
942
943//----------------------------------------------------------------------
944// Set PPIN Info (CMD_OEM_SET_PPIN_INFO)
945//----------------------------------------------------------------------
946// Inform BMC about PPIN data of 8 bytes for each CPU
947//
948// Request:
949// Byte 1:8 – CPU0 PPIN data
950// Optional:
951// Byte 9:16 – CPU1 PPIN data
952//
953// Response:
954// Byte 1 – Completion Code
955ipmi_ret_t ipmiOemSetPPINInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
956 ipmi_request_t request, ipmi_response_t response,
957 ipmi_data_len_t data_len, ipmi_context_t context)
958{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700959 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700960 std::string ppinStr;
961 int len;
962
963 if (*data_len > SIZE_CPU_PPIN * 2)
964 len = SIZE_CPU_PPIN * 2;
965 else
966 len = *data_len;
967 *data_len = 0;
968
969 ppinStr = bytesToStr(req, len);
970 oemData[KEY_PPIN_INFO] = ppinStr.c_str();
971 flushOemData();
972
973 return IPMI_CC_OK;
974}
975
976//----------------------------------------------------------------------
977// Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER)
978//----------------------------------------------------------------------
979ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
980 ipmi_request_t request,
981 ipmi_response_t response,
982 ipmi_data_len_t data_len,
983 ipmi_context_t context)
984{
985 /* Do nothing, return success */
986 *data_len = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800987 return IPMI_CC_OK;
988}
989
Vijay Khemkaf2246ce2020-05-27 14:26:35 -0700990// Helper function to set guid at offset in EEPROM
991static int setGUID(off_t offset, uint8_t* guid)
992{
993 int fd = -1;
994 ssize_t len;
995 int ret = 0;
996
997 errno = 0;
998
999 // Check if file is present
1000 if (access(FRU_EEPROM, F_OK) == -1)
1001 {
1002 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl;
1003 return errno;
1004 }
1005
1006 // Open the file
1007 fd = open(FRU_EEPROM, O_WRONLY);
1008 if (fd == -1)
1009 {
1010 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl;
1011 return errno;
1012 }
1013
1014 // seek to the offset
1015 lseek(fd, offset, SEEK_SET);
1016
1017 // Write bytes to location
1018 len = write(fd, guid, GUID_SIZE);
1019 if (len != GUID_SIZE)
1020 {
1021 phosphor::logging::log<phosphor::logging::level::ERR>(
1022 "GUID write data to EEPROM failed");
1023 ret = errno;
1024 }
1025
1026 close(fd);
1027 return ret;
1028}
1029
1030//----------------------------------------------------------------------
1031// Set System GUID (CMD_OEM_SET_SYSTEM_GUID)
1032//----------------------------------------------------------------------
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301033#if BIC_ENABLED
1034ipmi::RspType<> ipmiOemSetSystemGuid(ipmi::Context::ptr ctx, uint8_t cmdReq,
1035 std::vector<uint8_t> reqData)
1036{
1037 std::vector<uint8_t> respData;
1038
1039 if (reqData.size() != GUID_SIZE) // 16bytes
1040 {
1041
1042 return ipmi::responseReqDataLenInvalid();
1043 }
1044
1045 auto ptrReqData = reqData.insert(reqData.begin(), reqData.size());
1046
1047 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
1048
1049 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
1050 return ipmi::responseUnspecifiedError();
1051
1052 return ipmi::responseSuccess();
1053}
1054
1055#else
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001056ipmi_ret_t ipmiOemSetSystemGuid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1057 ipmi_request_t request,
1058 ipmi_response_t response,
1059 ipmi_data_len_t data_len,
1060 ipmi_context_t context)
1061{
1062 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1063
1064 if (*data_len != GUID_SIZE) // 16bytes
1065 {
1066 *data_len = 0;
1067 return IPMI_CC_REQ_DATA_LEN_INVALID;
1068 }
1069
1070 *data_len = 0;
1071
1072 if (setGUID(OFFSET_SYS_GUID, req))
1073 {
1074 return IPMI_CC_UNSPECIFIED_ERROR;
1075 }
1076 return IPMI_CC_OK;
1077}
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301078#endif
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001079
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001080//----------------------------------------------------------------------
1081// Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO)
1082//----------------------------------------------------------------------
1083ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1084 ipmi_request_t request,
1085 ipmi_response_t response,
1086 ipmi_data_len_t data_len,
1087 ipmi_context_t context)
1088{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001089 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001090 *data_len = 0;
1091 return IPMI_CC_OK;
1092}
1093
1094//----------------------------------------------------------------------
1095// Set PPR (CMD_OEM_SET_PPR)
1096//----------------------------------------------------------------------
1097ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1098 ipmi_request_t request, ipmi_response_t response,
1099 ipmi_data_len_t data_len, ipmi_context_t context)
1100{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001101 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001102 uint8_t pprCnt, pprAct, pprIndex;
1103 uint8_t selParam = req[0];
1104 uint8_t len = *data_len;
1105 std::stringstream ss;
1106 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001107
1108 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001109
1110 switch (selParam)
1111 {
1112 case PPR_ACTION:
1113 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) ==
1114 oemData[KEY_PPR].end())
1115 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1116
1117 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1118 if (pprCnt == 0)
1119 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1120
1121 pprAct = req[1];
1122 /* Check if ppr is enabled or disabled */
1123 if (!(pprAct & 0x80))
1124 pprAct = 0;
1125
1126 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct;
1127 break;
1128 case PPR_ROW_COUNT:
1129 if (req[1] > 100)
1130 return IPMI_CC_PARM_OUT_OF_RANGE;
1131
1132 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1];
1133 break;
1134 case PPR_ROW_ADDR:
1135 pprIndex = req[1];
1136 if (pprIndex > 100)
1137 return IPMI_CC_PARM_OUT_OF_RANGE;
1138
1139 if (len < PPR_ROW_ADDR_LEN + 1)
1140 {
1141 phosphor::logging::log<phosphor::logging::level::ERR>(
1142 "Invalid PPR Row Address length received");
1143 return IPMI_CC_REQ_DATA_LEN_INVALID;
1144 }
1145
1146 ss << std::hex;
1147 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1148
1149 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1150
1151 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN);
1152 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str();
1153 break;
1154 case PPR_HISTORY_DATA:
1155 pprIndex = req[1];
1156 if (pprIndex > 100)
1157 return IPMI_CC_PARM_OUT_OF_RANGE;
1158
1159 if (len < PPR_HST_DATA_LEN + 1)
1160 {
1161 phosphor::logging::log<phosphor::logging::level::ERR>(
1162 "Invalid PPR history data length received");
1163 return IPMI_CC_REQ_DATA_LEN_INVALID;
1164 }
1165
1166 ss << std::hex;
1167 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1168
1169 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1170
1171 str = bytesToStr(&req[1], PPR_HST_DATA_LEN);
1172 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str();
1173 break;
1174 default:
1175 return IPMI_CC_PARM_OUT_OF_RANGE;
1176 break;
1177 }
1178
1179 flushOemData();
1180
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001181 return IPMI_CC_OK;
1182}
1183
1184//----------------------------------------------------------------------
1185// Get PPR (CMD_OEM_GET_PPR)
1186//----------------------------------------------------------------------
1187ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1188 ipmi_request_t request, ipmi_response_t response,
1189 ipmi_data_len_t data_len, ipmi_context_t context)
1190{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001191 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1192 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001193 uint8_t pprCnt, pprIndex;
1194 uint8_t selParam = req[0];
1195 std::stringstream ss;
1196 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001197
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001198 /* Any failure will return zero length data */
1199 *data_len = 0;
1200
1201 switch (selParam)
1202 {
1203 case PPR_ACTION:
1204 res[0] = 0;
1205 *data_len = 1;
1206
1207 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1208 oemData[KEY_PPR].end())
1209 {
1210 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1211 if (pprCnt != 0)
1212 {
1213 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) !=
1214 oemData[KEY_PPR].end())
1215 {
1216 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION];
1217 }
1218 }
1219 }
1220 break;
1221 case PPR_ROW_COUNT:
1222 res[0] = 0;
1223 *data_len = 1;
1224 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1225 oemData[KEY_PPR].end())
1226 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1227 break;
1228 case PPR_ROW_ADDR:
1229 pprIndex = req[1];
1230 if (pprIndex > 100)
1231 return IPMI_CC_PARM_OUT_OF_RANGE;
1232
1233 ss << std::hex;
1234 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1235
1236 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1237 return IPMI_CC_PARM_OUT_OF_RANGE;
1238
1239 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) ==
1240 oemData[KEY_PPR][ss.str()].end())
1241 return IPMI_CC_PARM_OUT_OF_RANGE;
1242
1243 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR];
1244 *data_len = strToBytes(str, res);
1245 break;
1246 case PPR_HISTORY_DATA:
1247 pprIndex = req[1];
1248 if (pprIndex > 100)
1249 return IPMI_CC_PARM_OUT_OF_RANGE;
1250
1251 ss << std::hex;
1252 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1253
1254 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1255 return IPMI_CC_PARM_OUT_OF_RANGE;
1256
1257 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) ==
1258 oemData[KEY_PPR][ss.str()].end())
1259 return IPMI_CC_PARM_OUT_OF_RANGE;
1260
1261 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA];
1262 *data_len = strToBytes(str, res);
1263 break;
1264 default:
1265 return IPMI_CC_PARM_OUT_OF_RANGE;
1266 break;
1267 }
1268
1269 return IPMI_CC_OK;
1270}
1271
1272/* FB OEM QC Commands */
1273
1274//----------------------------------------------------------------------
1275// Set Proc Info (CMD_OEM_Q_SET_PROC_INFO)
1276//----------------------------------------------------------------------
1277//"Request:
1278// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1279// Byte 4 – Processor Index, 0 base
1280// Byte 5 – Parameter Selector
1281// Byte 6..N – Configuration parameter data (see below for Parameters
1282// of Processor Information)
1283// Response:
1284// Byte 1 – Completion code
1285//
1286// Parameter#1: (Processor Product Name)
1287//
1288// Byte 1..48 –Product name(ASCII code)
1289// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1290//
1291// Param#2: Processor Basic Information
1292// Byte 1 – Core Number
1293// Byte 2 – Thread Number (LSB)
1294// Byte 3 – Thread Number (MSB)
1295// Byte 4 – Processor frequency in MHz (LSB)
1296// Byte 5 – Processor frequency in MHz (MSB)
1297// Byte 6..7 – Revision
1298//
1299ipmi_ret_t ipmiOemQSetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1300 ipmi_request_t request, ipmi_response_t response,
1301 ipmi_data_len_t data_len, ipmi_context_t context)
1302{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001303 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1304 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001305 std::stringstream ss;
1306 std::string str;
1307 uint8_t len = *data_len;
1308
1309 *data_len = 0;
1310
1311 /* check for requested data params */
1312 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1313 {
1314 phosphor::logging::log<phosphor::logging::level::ERR>(
1315 "Invalid parameter received");
1316 return IPMI_CC_PARM_OUT_OF_RANGE;
1317 }
1318
1319 len = len - 5; // Get Actual data length
1320
1321 ss << std::hex;
1322 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1323 oemData[KEY_Q_PROC_INFO][ss.str()][KEY_PROC_INDEX] = req->procIndex;
1324
1325 str = bytesToStr(req->data, len);
1326 oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]] = str.c_str();
1327 flushOemData();
1328
1329 return IPMI_CC_OK;
1330}
1331
1332//----------------------------------------------------------------------
1333// Get Proc Info (CMD_OEM_Q_GET_PROC_INFO)
1334//----------------------------------------------------------------------
1335// Request:
1336// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1337// Byte 4 – Processor Index, 0 base
1338// Byte 5 – Parameter Selector
1339// Response:
1340// Byte 1 – Completion code
1341// Byte 2..N – Configuration Parameter Data (see below for Parameters
1342// of Processor Information)
1343//
1344// Parameter#1: (Processor Product Name)
1345//
1346// Byte 1..48 –Product name(ASCII code)
1347// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1348//
1349// Param#2: Processor Basic Information
1350// Byte 1 – Core Number
1351// Byte 2 – Thread Number (LSB)
1352// Byte 3 – Thread Number (MSB)
1353// Byte 4 – Processor frequency in MHz (LSB)
1354// Byte 5 – Processor frequency in MHz (MSB)
1355// Byte 6..7 – Revision
1356//
1357ipmi_ret_t ipmiOemQGetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1358 ipmi_request_t request, ipmi_response_t response,
1359 ipmi_data_len_t data_len, ipmi_context_t context)
1360{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001361 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1362 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
1363 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001364 std::stringstream ss;
1365 std::string str;
1366
1367 *data_len = 0;
1368
1369 /* check for requested data params */
1370 if (req->paramSel < 1 || req->paramSel >= numParam)
1371 {
1372 phosphor::logging::log<phosphor::logging::level::ERR>(
1373 "Invalid parameter received");
1374 return IPMI_CC_PARM_OUT_OF_RANGE;
1375 }
1376
1377 ss << std::hex;
1378 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1379
1380 if (oemData[KEY_Q_PROC_INFO].find(ss.str()) ==
1381 oemData[KEY_Q_PROC_INFO].end())
1382 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1383
1384 if (oemData[KEY_Q_PROC_INFO][ss.str()].find(cpuInfoKey[req->paramSel]) ==
1385 oemData[KEY_Q_PROC_INFO][ss.str()].end())
1386 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1387
1388 str = oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]];
1389 *data_len = strToBytes(str, res);
1390
1391 return IPMI_CC_OK;
1392}
1393
1394//----------------------------------------------------------------------
1395// Set Dimm Info (CMD_OEM_Q_SET_DIMM_INFO)
1396//----------------------------------------------------------------------
1397// Request:
1398// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1399// Byte 4 – DIMM Index, 0 base
1400// Byte 5 – Parameter Selector
1401// Byte 6..N – Configuration parameter data (see below for Parameters
1402// of DIMM Information)
1403// Response:
1404// Byte 1 – Completion code
1405//
1406// Param#1 (DIMM Location):
1407// Byte 1 – DIMM Present
1408// Byte 1 – DIMM Present
1409// 01h – Present
1410// FFh – Not Present
1411// Byte 2 – Node Number, 0 base
1412// Byte 3 – Channel Number , 0 base
1413// Byte 4 – DIMM Number , 0 base
1414//
1415// Param#2 (DIMM Type):
1416// Byte 1 – DIMM Type
1417// Bit [7:6]
1418// For DDR3
1419// 00 – Normal Voltage (1.5V)
1420// 01 – Ultra Low Voltage (1.25V)
1421// 10 – Low Voltage (1.35V)
1422// 11 – Reserved
1423// For DDR4
1424// 00 – Reserved
1425// 01 – Reserved
1426// 10 – Reserved
1427// 11 – Normal Voltage (1.2V)
1428// Bit [5:0]
1429// 0x00 – SDRAM
1430// 0x01 – DDR-1 RAM
1431// 0x02 – Rambus
1432// 0x03 – DDR-2 RAM
1433// 0x04 – FBDIMM
1434// 0x05 – DDR-3 RAM
1435// 0x06 – DDR-4 RAM
1436//
1437// Param#3 (DIMM Speed):
1438// Byte 1..2 – DIMM speed in MHz, LSB
1439// Byte 3..6 – DIMM size in Mbytes, LSB
1440//
1441// Param#4 (Module Part Number):
1442// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1443//
1444// Param#5 (Module Serial Number):
1445// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1446//
1447// Param#6 (Module Manufacturer ID):
1448// Byte 1 - Module Manufacturer ID, LSB
1449// Byte 2 - Module Manufacturer ID, MSB
1450//
1451ipmi_ret_t ipmiOemQSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1452 ipmi_request_t request, ipmi_response_t response,
1453 ipmi_data_len_t data_len, ipmi_context_t context)
1454{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001455 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1456 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001457 std::stringstream ss;
1458 std::string str;
1459 uint8_t len = *data_len;
1460
1461 *data_len = 0;
1462
1463 /* check for requested data params */
1464 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1465 {
1466 phosphor::logging::log<phosphor::logging::level::ERR>(
1467 "Invalid parameter received");
1468 return IPMI_CC_PARM_OUT_OF_RANGE;
1469 }
1470
1471 len = len - 5; // Get Actual data length
1472
1473 ss << std::hex;
1474 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1475 oemData[KEY_Q_DIMM_INFO][ss.str()][KEY_DIMM_INDEX] = req->dimmIndex;
1476
1477 str = bytesToStr(req->data, len);
1478 oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]] =
1479 str.c_str();
1480 flushOemData();
1481
1482 return IPMI_CC_OK;
1483}
1484
1485//----------------------------------------------------------------------
1486// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
1487//----------------------------------------------------------------------
1488// Request:
1489// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1490// Byte 4 – DIMM Index, 0 base
1491// Byte 5 – Parameter Selector
1492// Byte 6..N – Configuration parameter data (see below for Parameters
1493// of DIMM Information)
1494// Response:
1495// Byte 1 – Completion code
1496// Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters
1497// of DIMM Information)
1498//
1499// Param#1 (DIMM Location):
1500// Byte 1 – DIMM Present
1501// Byte 1 – DIMM Present
1502// 01h – Present
1503// FFh – Not Present
1504// Byte 2 – Node Number, 0 base
1505// Byte 3 – Channel Number , 0 base
1506// Byte 4 – DIMM Number , 0 base
1507//
1508// Param#2 (DIMM Type):
1509// Byte 1 – DIMM Type
1510// Bit [7:6]
1511// For DDR3
1512// 00 – Normal Voltage (1.5V)
1513// 01 – Ultra Low Voltage (1.25V)
1514// 10 – Low Voltage (1.35V)
1515// 11 – Reserved
1516// For DDR4
1517// 00 – Reserved
1518// 01 – Reserved
1519// 10 – Reserved
1520// 11 – Normal Voltage (1.2V)
1521// Bit [5:0]
1522// 0x00 – SDRAM
1523// 0x01 – DDR-1 RAM
1524// 0x02 – Rambus
1525// 0x03 – DDR-2 RAM
1526// 0x04 – FBDIMM
1527// 0x05 – DDR-3 RAM
1528// 0x06 – DDR-4 RAM
1529//
1530// Param#3 (DIMM Speed):
1531// Byte 1..2 – DIMM speed in MHz, LSB
1532// Byte 3..6 – DIMM size in Mbytes, LSB
1533//
1534// Param#4 (Module Part Number):
1535// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1536//
1537// Param#5 (Module Serial Number):
1538// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1539//
1540// Param#6 (Module Manufacturer ID):
1541// Byte 1 - Module Manufacturer ID, LSB
1542// Byte 2 - Module Manufacturer ID, MSB
1543//
1544ipmi_ret_t ipmiOemQGetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1545 ipmi_request_t request, ipmi_response_t response,
1546 ipmi_data_len_t data_len, ipmi_context_t context)
1547{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001548 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1549 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
1550 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001551 std::stringstream ss;
1552 std::string str;
1553
1554 *data_len = 0;
1555
1556 /* check for requested data params */
1557 if (req->paramSel < 1 || req->paramSel >= numParam)
1558 {
1559 phosphor::logging::log<phosphor::logging::level::ERR>(
1560 "Invalid parameter received");
1561 return IPMI_CC_PARM_OUT_OF_RANGE;
1562 }
1563
1564 ss << std::hex;
1565 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1566
1567 if (oemData[KEY_Q_DIMM_INFO].find(ss.str()) ==
1568 oemData[KEY_Q_DIMM_INFO].end())
1569 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1570
1571 if (oemData[KEY_Q_DIMM_INFO][ss.str()].find(dimmInfoKey[req->paramSel]) ==
1572 oemData[KEY_Q_DIMM_INFO][ss.str()].end())
1573 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1574
1575 str = oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]];
1576 *data_len = strToBytes(str, res);
1577
1578 return IPMI_CC_OK;
1579}
1580
1581//----------------------------------------------------------------------
1582// Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO)
1583//----------------------------------------------------------------------
1584// BIOS issue this command to provide HDD information to BMC.
1585//
1586// BIOS just can get information by standard ATA / SMART command for
1587// OB SATA controller.
1588// BIOS can get
1589// 1. Serial Number
1590// 2. Model Name
1591// 3. HDD FW Version
1592// 4. HDD Capacity
1593// 5. HDD WWN
1594//
1595// Use Get HDD info Param #5 to know the MAX HDD info index.
1596//
1597// Request:
1598// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1599// Byte 4 –
1600// [7:4] Reserved
1601// [3:0] HDD Controller Type
1602// 0x00 – BIOS
1603// 0x01 – Expander
1604// 0x02 – LSI
1605// Byte 5 – HDD Info Index, 0 base
1606// Byte 6 – Parameter Selector
1607// Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD
1608// Information)
1609//
1610// Response:
1611// Byte 1 – Completion Code
1612//
1613// Param#0 (HDD Location):
1614// Byte 1 – Controller
1615// [7:3] Device Number
1616// [2:0] Function Number
1617// For Intel C610 series (Wellsburg)
1618// D31:F2 (0xFA) – SATA control 1
1619// D31:F5 (0xFD) – SATA control 2
1620// D17:F4 (0x8C) – sSata control
1621// Byte 2 – Port Number
1622// Byte 3 – Location (0xFF: No HDD Present)
1623// BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param
1624// #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if
1625// the HDD present. BMC or other people who know the HDD location has
1626// responsibility for update Location info
1627//
1628// Param#1 (Serial Number):
1629// Bytes 1..33: HDD Serial Number
1630//
1631// Param#2 (Model Name):
1632// Byte 1..33 – HDD Model Name
1633//
1634// Param#3 (HDD FW Version):
1635// Byte 1..17 –HDD FW version
1636//
1637// Param#4 (Capacity):
1638// Byte 1..4 –HDD Block Size, LSB
1639// Byte 5..12 - HDD Block Number, LSB
1640// HDD Capacity = HDD Block size * HDD BLock number (Unit Byte)
1641//
1642// Param#5 (Max HDD Quantity):
1643// Byte 1 - Max HDD Quantity
1644// Max supported port numbers in this PCH
1645//
1646// Param#6 (HDD Type)
1647// Byte 1 – HDD Type
1648// 0h – Reserved
1649// 1h – SAS
1650// 2h – SATA
1651// 3h – PCIE SSD (NVME)
1652//
1653// Param#7 (HDD WWN)
1654// Data 1...8: HDD World Wide Name, LSB
1655//
1656ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1657 ipmi_request_t request,
1658 ipmi_response_t response,
1659 ipmi_data_len_t data_len,
1660 ipmi_context_t context)
1661{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001662 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1663 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001664 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1665 std::stringstream ss;
1666 std::string str;
1667 uint8_t len = *data_len;
1668
1669 *data_len = 0;
1670
1671 /* check for requested data params */
1672 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam ||
1673 ctrlType > 2)
1674 {
1675 phosphor::logging::log<phosphor::logging::level::ERR>(
1676 "Invalid parameter received");
1677 return IPMI_CC_PARM_OUT_OF_RANGE;
1678 }
1679
1680 len = len - 6; // Get Actual data length
1681
1682 ss << std::hex;
1683 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1684 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType;
1685 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] =
1686 req->hddIndex;
1687
1688 str = bytesToStr(req->data, len);
1689 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1690 [driveInfoKey[req->paramSel]] = str.c_str();
1691 flushOemData();
1692
1693 return IPMI_CC_OK;
1694}
1695
1696//----------------------------------------------------------------------
1697// Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO)
1698//----------------------------------------------------------------------
1699// BMC needs to check HDD presented or not first. If NOT presented, return
1700// completion code 0xD5.
1701//
1702// Request:
1703// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1704// Byte 4 –
1705//[7:4] Reserved
1706//[3:0] HDD Controller Type
1707// 0x00 – BIOS
1708// 0x01 – Expander
1709// 0x02 – LSI
1710// Byte 5 – HDD Index, 0 base
1711// Byte 6 – Parameter Selector (See Above Set HDD Information)
1712// Response:
1713// Byte 1 – Completion Code
1714// 0xD5 – Not support in current status (HDD Not Present)
1715// Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD
1716// Information)
1717//
1718ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1719 ipmi_request_t request,
1720 ipmi_response_t response,
1721 ipmi_data_len_t data_len,
1722 ipmi_context_t context)
1723{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001724 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1725 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
1726 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001727 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1728 std::stringstream ss;
1729 std::string str;
1730
1731 *data_len = 0;
1732
1733 /* check for requested data params */
1734 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2)
1735 {
1736 phosphor::logging::log<phosphor::logging::level::ERR>(
1737 "Invalid parameter received");
1738 return IPMI_CC_PARM_OUT_OF_RANGE;
1739 }
1740
1741 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) ==
1742 oemData[KEY_Q_DRIVE_INFO].end())
1743 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1744
1745 ss << std::hex;
1746 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1747
1748 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) ==
1749 oemData[KEY_Q_DRIVE_INFO].end())
1750 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1751
1752 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find(
1753 dimmInfoKey[req->paramSel]) ==
1754 oemData[KEY_Q_DRIVE_INFO][ss.str()].end())
1755 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1756
1757 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1758 [dimmInfoKey[req->paramSel]];
1759 *data_len = strToBytes(str, res);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001760
1761 return IPMI_CC_OK;
1762}
1763
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001764/* Helper function for sending DCMI commands to ME and getting response back */
1765ipmi::RspType<std::vector<uint8_t>> sendDCMICmd(uint8_t cmd,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001766 std::vector<uint8_t>& cmdData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001767{
1768 std::vector<uint8_t> respData;
1769
1770 /* Add group id as first byte to request for ME command */
1771 cmdData.insert(cmdData.begin(), groupDCMI);
1772
1773 if (sendMeCmd(ipmi::netFnGroup, cmd, cmdData, respData))
1774 return ipmi::responseUnspecifiedError();
1775
1776 /* Remove group id as first byte as it will be added by IPMID */
1777 respData.erase(respData.begin());
1778
1779 return ipmi::responseSuccess(std::move(respData));
1780}
1781
1782/* DCMI Command handellers. */
1783
1784ipmi::RspType<std::vector<uint8_t>>
1785 ipmiOemDCMIGetPowerReading(std::vector<uint8_t> reqData)
1786{
1787 return sendDCMICmd(ipmi::dcmi::cmdGetPowerReading, reqData);
1788}
1789
1790ipmi::RspType<std::vector<uint8_t>>
1791 ipmiOemDCMIGetPowerLimit(std::vector<uint8_t> reqData)
1792{
1793 return sendDCMICmd(ipmi::dcmi::cmdGetPowerLimit, reqData);
1794}
1795
1796ipmi::RspType<std::vector<uint8_t>>
1797 ipmiOemDCMISetPowerLimit(std::vector<uint8_t> reqData)
1798{
1799 return sendDCMICmd(ipmi::dcmi::cmdSetPowerLimit, reqData);
1800}
1801
1802ipmi::RspType<std::vector<uint8_t>>
1803 ipmiOemDCMIApplyPowerLimit(std::vector<uint8_t> reqData)
1804{
1805 return sendDCMICmd(ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
1806}
1807
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001808static void registerOEMFunctions(void)
1809{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001810 /* Get OEM data from json file */
1811 std::ifstream file(JSON_OEM_DATA_FILE);
1812 if (file)
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001813 {
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001814 file >> oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001815 file.close();
1816 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001817
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001818 phosphor::logging::log<phosphor::logging::level::INFO>(
1819 "Registering OEM commands");
Vijay Khemka7c0aea42020-03-05 13:31:53 -08001820
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001821 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO,
1822 NULL, ipmiOemDbgGetFrameInfo,
1823 PRIVILEGE_USER); // get debug frame info
1824 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ,
1825 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL,
1826 ipmiOemDbgGetUpdFrames,
1827 PRIVILEGE_USER); // get debug updated frames
1828 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC,
1829 NULL, ipmiOemDbgGetPostDesc,
1830 PRIVILEGE_USER); // get debug post description
1831 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC,
1832 NULL, ipmiOemDbgGetGpioDesc,
1833 PRIVILEGE_USER); // get debug gpio description
1834 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA,
1835 NULL, ipmiOemDbgGetFrameData,
1836 PRIVILEGE_USER); // get debug frame data
1837 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL,
1838 NULL, ipmiOemDbgGetCtrlPanel,
1839 PRIVILEGE_USER); // get debug control panel
1840 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL,
1841 ipmiOemSetDimmInfo,
1842 PRIVILEGE_USER); // Set Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001843 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL,
1844 ipmiOemGetBoardID,
1845 PRIVILEGE_USER); // Get Board ID
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001846 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL,
1847 ipmiOemSetMachineCfgInfo,
1848 PRIVILEGE_USER); // Set Machine Config Info
1849 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL,
1850 ipmiOemSetPostStart,
1851 PRIVILEGE_USER); // Set POST start
1852 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL,
1853 ipmiOemSetPostEnd,
1854 PRIVILEGE_USER); // Set POST End
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001855 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL,
1856 ipmiOemSetPPINInfo,
1857 PRIVILEGE_USER); // Set PPIN Info
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301858#if BIC_ENABLED
1859
1860 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1861 ipmi::cmdSetSystemGuid, ipmi::Privilege::User,
1862 ipmiOemSetSystemGuid);
1863#else
1864
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001865 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_SYSTEM_GUID, NULL,
1866 ipmiOemSetSystemGuid,
1867 PRIVILEGE_USER); // Set System GUID
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301868#endif
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001869 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL,
1870 ipmiOemSetAdrTrigger,
1871 PRIVILEGE_USER); // Set ADR Trigger
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001872 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL,
1873 ipmiOemSetBiosFlashInfo,
1874 PRIVILEGE_USER); // Set Bios Flash Info
1875 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr,
1876 PRIVILEGE_USER); // Set PPR
1877 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
1878 PRIVILEGE_USER); // Get PPR
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001879 /* FB OEM QC Commands */
1880 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_PROC_INFO, NULL,
1881 ipmiOemQSetProcInfo,
1882 PRIVILEGE_USER); // Set Proc Info
1883 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL,
1884 ipmiOemQGetProcInfo,
1885 PRIVILEGE_USER); // Get Proc Info
1886 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DIMM_INFO, NULL,
1887 ipmiOemQSetDimmInfo,
1888 PRIVILEGE_USER); // Set Dimm Info
1889 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DIMM_INFO, NULL,
1890 ipmiOemQGetDimmInfo,
1891 PRIVILEGE_USER); // Get Dimm Info
1892 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
1893 ipmiOemQSetDriveInfo,
1894 PRIVILEGE_USER); // Set Drive Info
1895 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL,
1896 ipmiOemQGetDriveInfo,
1897 PRIVILEGE_USER); // Get Drive Info
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001898
1899 /* FB OEM DCMI Commands as per DCMI spec 1.5 Section 6 */
1900 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1901 ipmi::dcmi::cmdGetPowerReading,
1902 ipmi::Privilege::User,
1903 ipmiOemDCMIGetPowerReading); // Get Power Reading
1904
1905 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1906 ipmi::dcmi::cmdGetPowerLimit,
1907 ipmi::Privilege::User,
1908 ipmiOemDCMIGetPowerLimit); // Get Power Limit
1909
1910 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1911 ipmi::dcmi::cmdSetPowerLimit,
1912 ipmi::Privilege::Operator,
1913 ipmiOemDCMISetPowerLimit); // Set Power Limit
1914
1915 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1916 ipmi::dcmi::cmdActDeactivatePwrLimit,
1917 ipmi::Privilege::Operator,
1918 ipmiOemDCMIApplyPowerLimit); // Apply Power Limit
1919
Jayashree-Df0cf6652020-11-30 11:03:30 +05301920 /* FB OEM BOOT ORDER COMMANDS */
1921 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1922 CMD_OEM_GET_BOOT_ORDER, ipmi::Privilege::User,
1923 ipmiOemGetBootOrder); // Get Boot Order
1924
1925 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1926 CMD_OEM_SET_BOOT_ORDER, ipmi::Privilege::User,
1927 ipmiOemSetBootOrder); // Set Boot Order
1928
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001929 return;
1930}
1931
1932} // namespace ipmi