blob: e700d116517e3a75c7b64c9833c2c95a25caecd9 [file] [log] [blame]
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001/*
2 * Copyright (c) 2018 Intel Corporation.
3 * Copyright (c) 2018-present Facebook.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "xyz/openbmc_project/Common/error.hpp"
Vijay Khemkae7d23d02019-03-08 13:13:40 -080019
Vijay Khemka63c99be2020-05-27 19:14:35 -070020#include <ipmid/api.hpp>
Vijay Khemka1b6fae32019-03-25 17:43:01 -070021#include <ipmid/utils.hpp>
Vijay Khemka63c99be2020-05-27 19:14:35 -070022#include <commandutils.hpp>
23#include <nlohmann/json.hpp>
24#include <oemcommands.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080025#include <phosphor-logging/log.hpp>
26#include <sdbusplus/bus.hpp>
Vijay Khemka63c99be2020-05-27 19:14:35 -070027
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053028#include <ipmid/api.hpp>
29#include <ipmid/api-types.hpp>
30
Vijay Khemka63c99be2020-05-27 19:14:35 -070031#include <array>
32#include <cstring>
33#include <fstream>
34#include <iomanip>
35#include <iostream>
36#include <sstream>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080037#include <string>
38#include <vector>
39
40#define SIZE_IANA_ID 3
41
42namespace ipmi
43{
Vijay Khemkaa7231892019-10-11 11:35:05 -070044
45using namespace phosphor::logging;
46
Vijay Khemkae7d23d02019-03-08 13:13:40 -080047static void registerOEMFunctions() __attribute__((constructor));
48sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
49static constexpr size_t maxFRUStringLength = 0x3F;
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053050constexpr uint8_t cmdSetSystemGuid = 0xEF;
Vijay Khemkae7d23d02019-03-08 13:13:40 -080051
Vijay Khemka63c99be2020-05-27 19:14:35 -070052int plat_udbg_get_post_desc(uint8_t, uint8_t*, uint8_t, uint8_t*, uint8_t*,
53 uint8_t*);
54int plat_udbg_get_gpio_desc(uint8_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*,
55 uint8_t*);
56ipmi_ret_t plat_udbg_get_frame_data(uint8_t, uint8_t, uint8_t*, uint8_t*,
57 uint8_t*);
58ipmi_ret_t plat_udbg_control_panel(uint8_t, uint8_t, uint8_t, uint8_t*,
59 uint8_t*);
60int sendMeCmd(uint8_t, uint8_t, std::vector<uint8_t>&, std::vector<uint8_t>&);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -070061
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +053062int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
63 std::vector<uint8_t>&);
64
Vijay Khemkafeaa9812019-08-27 15:08:08 -070065nlohmann::json oemData __attribute__((init_priority(101)));
Vijay Khemka1b6fae32019-03-25 17:43:01 -070066
Vijay Khemkaf2246ce2020-05-27 14:26:35 -070067static constexpr size_t GUID_SIZE = 16;
68// TODO Make offset and location runtime configurable to ensure we
69// can make each define their own locations.
70static constexpr off_t OFFSET_SYS_GUID = 0x17F0;
71static constexpr const char* FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom";
72
Vijay Khemka1b6fae32019-03-25 17:43:01 -070073enum class LanParam : uint8_t
74{
75 INPROGRESS = 0,
76 AUTHSUPPORT = 1,
77 AUTHENABLES = 2,
78 IP = 3,
79 IPSRC = 4,
80 MAC = 5,
81 SUBNET = 6,
82 GATEWAY = 12,
83 VLAN = 20,
84 CIPHER_SUITE_COUNT = 22,
85 CIPHER_SUITE_ENTRIES = 23,
86 IPV6 = 59,
87};
88
Vijay Khemkaa7231892019-10-11 11:35:05 -070089namespace network
90{
91
92constexpr auto ROOT = "/xyz/openbmc_project/network";
93constexpr auto SERVICE = "xyz.openbmc_project.Network";
94constexpr auto IPV4_TYPE = "ipv4";
95constexpr auto IPV6_TYPE = "ipv6";
96constexpr auto IPV4_PREFIX = "169.254";
97constexpr auto IPV6_PREFIX = "fe80";
98constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
99constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
100
Vijay Khemka63c99be2020-05-27 19:14:35 -0700101bool isLinkLocalIP(const std::string& address)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700102{
103 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0;
104}
105
Vijay Khemka63c99be2020-05-27 19:14:35 -0700106DbusObjectInfo getIPObject(sdbusplus::bus::bus& bus,
107 const std::string& interface,
108 const std::string& serviceRoot,
109 const std::string& match)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700110{
111 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
112
113 if (objectTree.empty())
114 {
115 log<level::ERR>("No Object has implemented the IP interface",
116 entry("INTERFACE=%s", interface.c_str()));
117 }
118
119 DbusObjectInfo objectInfo;
120
Vijay Khemka63c99be2020-05-27 19:14:35 -0700121 for (auto& object : objectTree)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700122 {
123 auto variant =
124 ipmi::getDbusProperty(bus, object.second.begin()->first,
125 object.first, IP_INTERFACE, "Address");
126
127 objectInfo = std::make_pair(object.first, object.second.begin()->first);
128
129 // if LinkLocalIP found look for Non-LinkLocalIP
130 if (isLinkLocalIP(std::get<std::string>(variant)))
131 {
132 continue;
133 }
134 else
135 {
136 break;
137 }
138 }
139 return objectInfo;
140}
141
142} // namespace network
143
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700144//----------------------------------------------------------------------
145// Helper functions for storing oem data
146//----------------------------------------------------------------------
147
148void flushOemData()
149{
150 std::ofstream file(JSON_OEM_DATA_FILE);
151 file << oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -0700152 file.close();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700153 return;
154}
155
Vijay Khemka63c99be2020-05-27 19:14:35 -0700156std::string bytesToStr(uint8_t* byte, int len)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700157{
158 std::stringstream ss;
159 int i;
160
161 ss << std::hex;
162 for (i = 0; i < len; i++)
163 {
164 ss << std::setw(2) << std::setfill('0') << (int)byte[i];
165 }
166
167 return ss.str();
168}
169
Vijay Khemka63c99be2020-05-27 19:14:35 -0700170int strToBytes(std::string& str, uint8_t* data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700171{
172 std::string sstr;
173 int i;
174
175 for (i = 0; i < (str.length()) / 2; i++)
176 {
177 sstr = str.substr(i * 2, 2);
178 data[i] = (uint8_t)std::strtol(sstr.c_str(), NULL, 16);
179 }
180 return i;
181}
182
Vijay Khemka63c99be2020-05-27 19:14:35 -0700183ipmi_ret_t getNetworkData(uint8_t lan_param, char* data)
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700184{
185 ipmi_ret_t rc = IPMI_CC_OK;
186 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
187
188 const std::string ethdevice = "eth0";
189
190 switch (static_cast<LanParam>(lan_param))
191 {
Vijay Khemkad1194022020-05-27 18:58:33 -0700192 case LanParam::IP:
193 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700194 auto ethIP = ethdevice + "/" + ipmi::network::IPV4_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700195 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700196 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700197 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
198
199 auto properties = ipmi::getAllDbusProperties(
200 bus, ipObjectInfo.second, ipObjectInfo.first,
201 ipmi::network::IP_INTERFACE);
202
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500203 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700204
205 std::strcpy(data, ipaddress.c_str());
206 }
207 break;
208
Vijay Khemkad1194022020-05-27 18:58:33 -0700209 case LanParam::IPV6:
210 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700211 auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700212 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700213 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700214 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
215
216 auto properties = ipmi::getAllDbusProperties(
217 bus, ipObjectInfo.second, ipObjectInfo.first,
218 ipmi::network::IP_INTERFACE);
219
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500220 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700221
222 std::strcpy(data, ipaddress.c_str());
223 }
224 break;
225
Vijay Khemkad1194022020-05-27 18:58:33 -0700226 case LanParam::MAC:
227 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700228 std::string macAddress;
229 auto macObjectInfo =
230 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
231 ipmi::network::ROOT, ethdevice);
232
233 auto variant = ipmi::getDbusProperty(
234 bus, macObjectInfo.second, macObjectInfo.first,
235 ipmi::network::MAC_INTERFACE, "MACAddress");
236
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500237 macAddress = std::get<std::string>(variant);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700238
239 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
240 (data), (data + 1), (data + 2), (data + 3), (data + 4),
241 (data + 5));
242 std::strcpy(data, macAddress.c_str());
243 }
244 break;
245
246 default:
247 rc = IPMI_CC_PARM_OUT_OF_RANGE;
248 }
249 return rc;
250}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800251
252// return code: 0 successful
Vijay Khemka63c99be2020-05-27 19:14:35 -0700253int8_t getFruData(std::string& data, std::string& name)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800254{
255 std::string objpath = "/xyz/openbmc_project/FruDevice";
256 std::string intf = "xyz.openbmc_project.FruDeviceManager";
257 std::string service = getService(dbus, intf, objpath);
258 ObjectValueTree valueTree = getManagedObjects(dbus, service, "/");
259 if (valueTree.empty())
260 {
261 phosphor::logging::log<phosphor::logging::level::ERR>(
262 "No object implements interface",
263 phosphor::logging::entry("INTF=%s", intf.c_str()));
264 return -1;
265 }
266
Vijay Khemka63c99be2020-05-27 19:14:35 -0700267 for (const auto& item : valueTree)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800268 {
269 auto interface = item.second.find("xyz.openbmc_project.FruDevice");
270 if (interface == item.second.end())
271 {
272 continue;
273 }
274
275 auto property = interface->second.find(name.c_str());
276 if (property == interface->second.end())
277 {
278 continue;
279 }
280
281 try
282 {
283 Value variant = property->second;
Vijay Khemka63c99be2020-05-27 19:14:35 -0700284 std::string& result = std::get<std::string>(variant);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800285 if (result.size() > maxFRUStringLength)
286 {
287 phosphor::logging::log<phosphor::logging::level::ERR>(
288 "FRU serial number exceed maximum length");
289 return -1;
290 }
291 data = result;
292 return 0;
293 }
Vijay Khemka63c99be2020-05-27 19:14:35 -0700294 catch (std::bad_variant_access& e)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800295 {
296 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
297 return -1;
298 }
299 }
300 return -1;
301}
302
303typedef struct
304{
305 uint8_t cur_power_state;
306 uint8_t last_power_event;
307 uint8_t misc_power_state;
308 uint8_t front_panel_button_cap_status;
309} ipmi_get_chassis_status_t;
310
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800311//----------------------------------------------------------------------
312// Get Debug Frame Info
313//----------------------------------------------------------------------
314ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
315 ipmi_request_t request,
316 ipmi_response_t response,
317 ipmi_data_len_t data_len,
318 ipmi_context_t context)
319{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700320 uint8_t* req = reinterpret_cast<uint8_t*>(request);
321 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800322 uint8_t num_frames = 3;
323
324 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
325 res[SIZE_IANA_ID] = num_frames;
326 *data_len = SIZE_IANA_ID + 1;
327
328 return IPMI_CC_OK;
329}
330
331//----------------------------------------------------------------------
332// Get Debug Updated Frames
333//----------------------------------------------------------------------
334ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
335 ipmi_request_t request,
336 ipmi_response_t response,
337 ipmi_data_len_t data_len,
338 ipmi_context_t context)
339{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700340 uint8_t* req = reinterpret_cast<uint8_t*>(request);
341 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800342 uint8_t num_updates = 3;
343 *data_len = 4;
344
345 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
346 res[SIZE_IANA_ID] = num_updates;
347 *data_len = SIZE_IANA_ID + num_updates + 1;
348 res[SIZE_IANA_ID + 1] = 1; // info page update
349 res[SIZE_IANA_ID + 2] = 2; // cri sel update
350 res[SIZE_IANA_ID + 3] = 3; // cri sensor update
351
352 return IPMI_CC_OK;
353}
354
355//----------------------------------------------------------------------
356// Get Debug POST Description
357//----------------------------------------------------------------------
358ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
359 ipmi_request_t request,
360 ipmi_response_t response,
361 ipmi_data_len_t data_len,
362 ipmi_context_t context)
363{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700364 uint8_t* req = reinterpret_cast<uint8_t*>(request);
365 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800366 uint8_t index = 0;
367 uint8_t next = 0;
368 uint8_t end = 0;
369 uint8_t phase = 0;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700370 uint8_t descLen = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800371 int ret;
372
373 index = req[3];
374 phase = req[4];
375
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700376 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800377 if (ret)
378 {
379 memcpy(res, req, SIZE_IANA_ID); // IANA ID
380 *data_len = SIZE_IANA_ID;
381 return IPMI_CC_UNSPECIFIED_ERROR;
382 }
383
384 memcpy(res, req, SIZE_IANA_ID); // IANA ID
385 res[3] = index;
386 res[4] = next;
387 res[5] = phase;
388 res[6] = end;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700389 res[7] = descLen;
390 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800391
392 return IPMI_CC_OK;
393}
394
395//----------------------------------------------------------------------
396// Get Debug GPIO Description
397//----------------------------------------------------------------------
398ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
399 ipmi_request_t request,
400 ipmi_response_t response,
401 ipmi_data_len_t data_len,
402 ipmi_context_t context)
403{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700404 uint8_t* req = reinterpret_cast<uint8_t*>(request);
405 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800406
Vijay Khemka38183d62019-08-28 16:19:33 -0700407 uint8_t index = 0;
408 uint8_t next = 0;
409 uint8_t level = 0;
410 uint8_t pinDef = 0;
411 uint8_t descLen = 0;
412 int ret;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800413
Vijay Khemka38183d62019-08-28 16:19:33 -0700414 index = req[3];
415
416 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen,
417 &res[8]);
418 if (ret)
419 {
420 memcpy(res, req, SIZE_IANA_ID); // IANA ID
421 *data_len = SIZE_IANA_ID;
422 return IPMI_CC_UNSPECIFIED_ERROR;
423 }
424
425 memcpy(res, req, SIZE_IANA_ID); // IANA ID
426 res[3] = index;
427 res[4] = next;
428 res[5] = level;
429 res[6] = pinDef;
430 res[7] = descLen;
431 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800432
433 return IPMI_CC_OK;
434}
435
436//----------------------------------------------------------------------
437// Get Debug Frame Data
438//----------------------------------------------------------------------
439ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
440 ipmi_request_t request,
441 ipmi_response_t response,
442 ipmi_data_len_t data_len,
443 ipmi_context_t context)
444{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700445 uint8_t* req = reinterpret_cast<uint8_t*>(request);
446 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800447 uint8_t frame;
448 uint8_t page;
449 uint8_t next;
450 uint8_t count;
451 int ret;
452
453 frame = req[3];
454 page = req[4];
455 int fr = frame;
456 int pg = page;
457
458 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]);
459 if (ret)
460 {
461 memcpy(res, req, SIZE_IANA_ID); // IANA ID
462 *data_len = SIZE_IANA_ID;
463 return IPMI_CC_UNSPECIFIED_ERROR;
464 }
465
466 memcpy(res, req, SIZE_IANA_ID); // IANA ID
467 res[3] = frame;
468 res[4] = page;
469 res[5] = next;
470 res[6] = count;
471 *data_len = SIZE_IANA_ID + 4 + count;
472
473 return IPMI_CC_OK;
474}
475
476//----------------------------------------------------------------------
477// Get Debug Control Panel
478//----------------------------------------------------------------------
479ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
480 ipmi_request_t request,
481 ipmi_response_t response,
482 ipmi_data_len_t data_len,
483 ipmi_context_t context)
484{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700485 uint8_t* req = reinterpret_cast<uint8_t*>(request);
486 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800487
488 uint8_t panel;
489 uint8_t operation;
490 uint8_t item;
491 uint8_t count;
492 ipmi_ret_t ret;
493
494 panel = req[3];
495 operation = req[4];
496 item = req[5];
497
498 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]);
499
500 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
501 *data_len = SIZE_IANA_ID + count;
502
503 return ret;
504}
505
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800506//----------------------------------------------------------------------
507// Set Dimm Info (CMD_OEM_SET_DIMM_INFO)
508//----------------------------------------------------------------------
509ipmi_ret_t ipmiOemSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
510 ipmi_request_t request, ipmi_response_t response,
511 ipmi_data_len_t data_len, ipmi_context_t context)
512{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700513 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700514
515 uint8_t index = req[0];
516 uint8_t type = req[1];
517 uint16_t speed;
518 uint32_t size;
519
520 memcpy(&speed, &req[2], 2);
521 memcpy(&size, &req[4], 4);
522
523 std::stringstream ss;
524 ss << std::hex;
525 ss << std::setw(2) << std::setfill('0') << (int)index;
526
527 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index;
528 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type;
529 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed;
530 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size;
531
532 flushOemData();
533
534 *data_len = 0;
535
536 return IPMI_CC_OK;
537}
538
539//----------------------------------------------------------------------
540// Get Board ID (CMD_OEM_GET_BOARD_ID)
541//----------------------------------------------------------------------
542ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
543 ipmi_request_t request, ipmi_response_t response,
544 ipmi_data_len_t data_len, ipmi_context_t context)
545{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700546 uint8_t* req = reinterpret_cast<uint8_t*>(request);
547 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800548
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700549 /* TODO: Needs to implement this after GPIO implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800550 *data_len = 0;
551
552 return IPMI_CC_OK;
553}
554
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800555/* Helper functions to set boot order */
Vijay Khemka63c99be2020-05-27 19:14:35 -0700556void setBootOrder(uint8_t* data)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800557{
558 nlohmann::json bootMode;
559 uint8_t mode = data[0];
560 int i;
561
562 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false);
563 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false);
564 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false);
565 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false);
566 oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE] = bootMode;
567
568 /* Initialize boot sequence array */
569 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ] = {};
570 for (i = 1; i < SIZE_BOOT_ORDER; i++)
571 {
572 if (data[i] >= BOOT_SEQ_ARRAY_SIZE)
573 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1] = "NA";
574 else
575 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1] = bootSeq[data[i]];
576 }
577
578 flushOemData();
579}
580
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800581//----------------------------------------------------------------------
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700582// Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
583//----------------------------------------------------------------------
584ipmi_ret_t ipmiOemSetBootOrder(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
585 ipmi_request_t request, ipmi_response_t response,
586 ipmi_data_len_t data_len, ipmi_context_t context)
587{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700588 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700589 uint8_t len = *data_len;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700590
591 *data_len = 0;
592
593 if (len != SIZE_BOOT_ORDER)
594 {
595 phosphor::logging::log<phosphor::logging::level::ERR>(
596 "Invalid Boot order length received");
597 return IPMI_CC_REQ_DATA_LEN_INVALID;
598 }
599
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800600 setBootOrder(req);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700601
602 return IPMI_CC_OK;
603}
604
605//----------------------------------------------------------------------
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800606// Get Boot Order (CMD_OEM_GET_BOOT_ORDER)
607//----------------------------------------------------------------------
608ipmi_ret_t ipmiOemGetBootOrder(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
609 ipmi_request_t request, ipmi_response_t response,
610 ipmi_data_len_t data_len, ipmi_context_t context)
611{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700612 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700613 uint8_t mode = 0;
614 int i;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800615
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700616 *data_len = SIZE_BOOT_ORDER;
617
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800618 if (oemData.find(KEY_BOOT_ORDER) == oemData.end())
619 {
620 /* Return default boot order 0100090203ff */
621 uint8_t defaultBoot[SIZE_BOOT_ORDER] = {
622 BOOT_MODE_UEFI, bootMap["USB_DEV"], bootMap["NET_IPV6"],
623 bootMap["SATA_HDD"], bootMap["SATA_CD"], 0xff};
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700624
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800625 memcpy(res, defaultBoot, SIZE_BOOT_ORDER);
626 phosphor::logging::log<phosphor::logging::level::INFO>(
627 "Set default boot order");
628 setBootOrder(defaultBoot);
629 }
630 else
631 {
632 nlohmann::json bootMode = oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE];
633 if (bootMode["UEFI"])
634 mode |= BOOT_MODE_UEFI;
635 if (bootMode["CMOS_CLR"])
636 mode |= BOOT_MODE_CMOS_CLR;
637 if (bootMode["BOOT_FLAG"])
638 mode |= BOOT_MODE_BOOT_FLAG;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700639
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800640 res[0] = mode;
641
642 for (i = 1; i < SIZE_BOOT_ORDER; i++)
643 {
644 std::string seqStr = oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1];
645 if (bootMap.find(seqStr) != bootMap.end())
646 res[i] = bootMap[seqStr];
647 else
648 res[i] = 0xff;
649 }
650 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800651
652 return IPMI_CC_OK;
653}
654
655//----------------------------------------------------------------------
656// Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO)
657//----------------------------------------------------------------------
658ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
659 ipmi_request_t request,
660 ipmi_response_t response,
661 ipmi_data_len_t data_len,
662 ipmi_context_t context)
663{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700664 machineConfigInfo_t* req = reinterpret_cast<machineConfigInfo_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700665 uint8_t len = *data_len;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800666
667 *data_len = 0;
668
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700669 if (len < sizeof(machineConfigInfo_t))
670 {
671 phosphor::logging::log<phosphor::logging::level::ERR>(
672 "Invalid machine configuration length received");
673 return IPMI_CC_REQ_DATA_LEN_INVALID;
674 }
675
Vijay Khemka63c99be2020-05-27 19:14:35 -0700676 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700677 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN";
678 else
679 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] =
680 chassisType[req->chassis_type];
681
Vijay Khemka63c99be2020-05-27 19:14:35 -0700682 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700683 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN";
684 else
685 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type];
686
687 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt;
688 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt;
689 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt;
690 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt;
691
Vijay Khemka63c99be2020-05-27 19:14:35 -0700692 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700693 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN";
694 else
695 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type];
696
697 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {};
698 int i = 0;
699 if (req->pcie_card_loc & BIT_0)
700 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1";
701 if (req->pcie_card_loc & BIT_1)
702 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2";
703 if (req->pcie_card_loc & BIT_2)
704 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3";
705 if (req->pcie_card_loc & BIT_3)
706 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4";
707
Vijay Khemka63c99be2020-05-27 19:14:35 -0700708 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700709 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN";
710 else
711 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] =
712 pcieType[req->slot1_pcie_type];
713
Vijay Khemka63c99be2020-05-27 19:14:35 -0700714 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700715 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN";
716 else
717 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] =
718 pcieType[req->slot2_pcie_type];
719
Vijay Khemka63c99be2020-05-27 19:14:35 -0700720 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700721 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN";
722 else
723 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] =
724 pcieType[req->slot3_pcie_type];
725
Vijay Khemka63c99be2020-05-27 19:14:35 -0700726 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700727 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN";
728 else
729 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] =
730 pcieType[req->slot4_pcie_type];
731
732 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt;
733
734 flushOemData();
735
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800736 return IPMI_CC_OK;
737}
738
739//----------------------------------------------------------------------
740// Set POST start (CMD_OEM_SET_POST_START)
741//----------------------------------------------------------------------
742ipmi_ret_t ipmiOemSetPostStart(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
743 ipmi_request_t request, ipmi_response_t response,
744 ipmi_data_len_t data_len, ipmi_context_t context)
745{
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800746 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event");
747
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700748 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800749 *data_len = 0;
750 return IPMI_CC_OK;
751}
752
753//----------------------------------------------------------------------
754// Set POST End (CMD_OEM_SET_POST_END)
755//----------------------------------------------------------------------
756ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
757 ipmi_request_t request, ipmi_response_t response,
758 ipmi_data_len_t data_len, ipmi_context_t context)
759{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700760 struct timespec ts;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800761
762 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event");
763
764 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700765
766 // Timestamp post end time.
767 clock_gettime(CLOCK_REALTIME, &ts);
768 oemData[KEY_TS_SLED] = ts.tv_sec;
769 flushOemData();
770
771 // Sync time with system
772 // TODO: Add code for syncing time
773
774 return IPMI_CC_OK;
775}
776
777//----------------------------------------------------------------------
778// Set PPIN Info (CMD_OEM_SET_PPIN_INFO)
779//----------------------------------------------------------------------
780// Inform BMC about PPIN data of 8 bytes for each CPU
781//
782// Request:
783// Byte 1:8 – CPU0 PPIN data
784// Optional:
785// Byte 9:16 – CPU1 PPIN data
786//
787// Response:
788// Byte 1 – Completion Code
789ipmi_ret_t ipmiOemSetPPINInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
790 ipmi_request_t request, ipmi_response_t response,
791 ipmi_data_len_t data_len, ipmi_context_t context)
792{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700793 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700794 std::string ppinStr;
795 int len;
796
797 if (*data_len > SIZE_CPU_PPIN * 2)
798 len = SIZE_CPU_PPIN * 2;
799 else
800 len = *data_len;
801 *data_len = 0;
802
803 ppinStr = bytesToStr(req, len);
804 oemData[KEY_PPIN_INFO] = ppinStr.c_str();
805 flushOemData();
806
807 return IPMI_CC_OK;
808}
809
810//----------------------------------------------------------------------
811// Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER)
812//----------------------------------------------------------------------
813ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
814 ipmi_request_t request,
815 ipmi_response_t response,
816 ipmi_data_len_t data_len,
817 ipmi_context_t context)
818{
819 /* Do nothing, return success */
820 *data_len = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800821 return IPMI_CC_OK;
822}
823
Vijay Khemkaf2246ce2020-05-27 14:26:35 -0700824// Helper function to set guid at offset in EEPROM
825static int setGUID(off_t offset, uint8_t* guid)
826{
827 int fd = -1;
828 ssize_t len;
829 int ret = 0;
830
831 errno = 0;
832
833 // Check if file is present
834 if (access(FRU_EEPROM, F_OK) == -1)
835 {
836 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl;
837 return errno;
838 }
839
840 // Open the file
841 fd = open(FRU_EEPROM, O_WRONLY);
842 if (fd == -1)
843 {
844 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl;
845 return errno;
846 }
847
848 // seek to the offset
849 lseek(fd, offset, SEEK_SET);
850
851 // Write bytes to location
852 len = write(fd, guid, GUID_SIZE);
853 if (len != GUID_SIZE)
854 {
855 phosphor::logging::log<phosphor::logging::level::ERR>(
856 "GUID write data to EEPROM failed");
857 ret = errno;
858 }
859
860 close(fd);
861 return ret;
862}
863
864//----------------------------------------------------------------------
865// Set System GUID (CMD_OEM_SET_SYSTEM_GUID)
866//----------------------------------------------------------------------
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +0530867#if BIC_ENABLED
868ipmi::RspType<> ipmiOemSetSystemGuid(ipmi::Context::ptr ctx, uint8_t cmdReq,
869 std::vector<uint8_t> reqData)
870{
871 std::vector<uint8_t> respData;
872
873 if (reqData.size() != GUID_SIZE) // 16bytes
874 {
875
876 return ipmi::responseReqDataLenInvalid();
877 }
878
879 auto ptrReqData = reqData.insert(reqData.begin(), reqData.size());
880
881 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
882
883 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
884 return ipmi::responseUnspecifiedError();
885
886 return ipmi::responseSuccess();
887}
888
889#else
Vijay Khemkaf2246ce2020-05-27 14:26:35 -0700890ipmi_ret_t ipmiOemSetSystemGuid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
891 ipmi_request_t request,
892 ipmi_response_t response,
893 ipmi_data_len_t data_len,
894 ipmi_context_t context)
895{
896 uint8_t* req = reinterpret_cast<uint8_t*>(request);
897
898 if (*data_len != GUID_SIZE) // 16bytes
899 {
900 *data_len = 0;
901 return IPMI_CC_REQ_DATA_LEN_INVALID;
902 }
903
904 *data_len = 0;
905
906 if (setGUID(OFFSET_SYS_GUID, req))
907 {
908 return IPMI_CC_UNSPECIFIED_ERROR;
909 }
910 return IPMI_CC_OK;
911}
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +0530912#endif
Vijay Khemkaf2246ce2020-05-27 14:26:35 -0700913
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800914//----------------------------------------------------------------------
915// Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO)
916//----------------------------------------------------------------------
917ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
918 ipmi_request_t request,
919 ipmi_response_t response,
920 ipmi_data_len_t data_len,
921 ipmi_context_t context)
922{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700923 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800924 *data_len = 0;
925 return IPMI_CC_OK;
926}
927
928//----------------------------------------------------------------------
929// Set PPR (CMD_OEM_SET_PPR)
930//----------------------------------------------------------------------
931ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
932 ipmi_request_t request, ipmi_response_t response,
933 ipmi_data_len_t data_len, ipmi_context_t context)
934{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700935 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700936 uint8_t pprCnt, pprAct, pprIndex;
937 uint8_t selParam = req[0];
938 uint8_t len = *data_len;
939 std::stringstream ss;
940 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800941
942 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700943
944 switch (selParam)
945 {
946 case PPR_ACTION:
947 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) ==
948 oemData[KEY_PPR].end())
949 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
950
951 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
952 if (pprCnt == 0)
953 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
954
955 pprAct = req[1];
956 /* Check if ppr is enabled or disabled */
957 if (!(pprAct & 0x80))
958 pprAct = 0;
959
960 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct;
961 break;
962 case PPR_ROW_COUNT:
963 if (req[1] > 100)
964 return IPMI_CC_PARM_OUT_OF_RANGE;
965
966 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1];
967 break;
968 case PPR_ROW_ADDR:
969 pprIndex = req[1];
970 if (pprIndex > 100)
971 return IPMI_CC_PARM_OUT_OF_RANGE;
972
973 if (len < PPR_ROW_ADDR_LEN + 1)
974 {
975 phosphor::logging::log<phosphor::logging::level::ERR>(
976 "Invalid PPR Row Address length received");
977 return IPMI_CC_REQ_DATA_LEN_INVALID;
978 }
979
980 ss << std::hex;
981 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
982
983 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
984
985 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN);
986 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str();
987 break;
988 case PPR_HISTORY_DATA:
989 pprIndex = req[1];
990 if (pprIndex > 100)
991 return IPMI_CC_PARM_OUT_OF_RANGE;
992
993 if (len < PPR_HST_DATA_LEN + 1)
994 {
995 phosphor::logging::log<phosphor::logging::level::ERR>(
996 "Invalid PPR history data length received");
997 return IPMI_CC_REQ_DATA_LEN_INVALID;
998 }
999
1000 ss << std::hex;
1001 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1002
1003 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
1004
1005 str = bytesToStr(&req[1], PPR_HST_DATA_LEN);
1006 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str();
1007 break;
1008 default:
1009 return IPMI_CC_PARM_OUT_OF_RANGE;
1010 break;
1011 }
1012
1013 flushOemData();
1014
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001015 return IPMI_CC_OK;
1016}
1017
1018//----------------------------------------------------------------------
1019// Get PPR (CMD_OEM_GET_PPR)
1020//----------------------------------------------------------------------
1021ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1022 ipmi_request_t request, ipmi_response_t response,
1023 ipmi_data_len_t data_len, ipmi_context_t context)
1024{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001025 uint8_t* req = reinterpret_cast<uint8_t*>(request);
1026 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001027 uint8_t pprCnt, pprIndex;
1028 uint8_t selParam = req[0];
1029 std::stringstream ss;
1030 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001031
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001032 /* Any failure will return zero length data */
1033 *data_len = 0;
1034
1035 switch (selParam)
1036 {
1037 case PPR_ACTION:
1038 res[0] = 0;
1039 *data_len = 1;
1040
1041 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1042 oemData[KEY_PPR].end())
1043 {
1044 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1045 if (pprCnt != 0)
1046 {
1047 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) !=
1048 oemData[KEY_PPR].end())
1049 {
1050 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION];
1051 }
1052 }
1053 }
1054 break;
1055 case PPR_ROW_COUNT:
1056 res[0] = 0;
1057 *data_len = 1;
1058 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1059 oemData[KEY_PPR].end())
1060 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1061 break;
1062 case PPR_ROW_ADDR:
1063 pprIndex = req[1];
1064 if (pprIndex > 100)
1065 return IPMI_CC_PARM_OUT_OF_RANGE;
1066
1067 ss << std::hex;
1068 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1069
1070 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1071 return IPMI_CC_PARM_OUT_OF_RANGE;
1072
1073 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) ==
1074 oemData[KEY_PPR][ss.str()].end())
1075 return IPMI_CC_PARM_OUT_OF_RANGE;
1076
1077 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR];
1078 *data_len = strToBytes(str, res);
1079 break;
1080 case PPR_HISTORY_DATA:
1081 pprIndex = req[1];
1082 if (pprIndex > 100)
1083 return IPMI_CC_PARM_OUT_OF_RANGE;
1084
1085 ss << std::hex;
1086 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1087
1088 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1089 return IPMI_CC_PARM_OUT_OF_RANGE;
1090
1091 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) ==
1092 oemData[KEY_PPR][ss.str()].end())
1093 return IPMI_CC_PARM_OUT_OF_RANGE;
1094
1095 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA];
1096 *data_len = strToBytes(str, res);
1097 break;
1098 default:
1099 return IPMI_CC_PARM_OUT_OF_RANGE;
1100 break;
1101 }
1102
1103 return IPMI_CC_OK;
1104}
1105
1106/* FB OEM QC Commands */
1107
1108//----------------------------------------------------------------------
1109// Set Proc Info (CMD_OEM_Q_SET_PROC_INFO)
1110//----------------------------------------------------------------------
1111//"Request:
1112// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1113// Byte 4 – Processor Index, 0 base
1114// Byte 5 – Parameter Selector
1115// Byte 6..N – Configuration parameter data (see below for Parameters
1116// of Processor Information)
1117// Response:
1118// Byte 1 – Completion code
1119//
1120// Parameter#1: (Processor Product Name)
1121//
1122// Byte 1..48 –Product name(ASCII code)
1123// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1124//
1125// Param#2: Processor Basic Information
1126// Byte 1 – Core Number
1127// Byte 2 – Thread Number (LSB)
1128// Byte 3 – Thread Number (MSB)
1129// Byte 4 – Processor frequency in MHz (LSB)
1130// Byte 5 – Processor frequency in MHz (MSB)
1131// Byte 6..7 – Revision
1132//
1133ipmi_ret_t ipmiOemQSetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1134 ipmi_request_t request, ipmi_response_t response,
1135 ipmi_data_len_t data_len, ipmi_context_t context)
1136{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001137 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1138 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001139 std::stringstream ss;
1140 std::string str;
1141 uint8_t len = *data_len;
1142
1143 *data_len = 0;
1144
1145 /* check for requested data params */
1146 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1147 {
1148 phosphor::logging::log<phosphor::logging::level::ERR>(
1149 "Invalid parameter received");
1150 return IPMI_CC_PARM_OUT_OF_RANGE;
1151 }
1152
1153 len = len - 5; // Get Actual data length
1154
1155 ss << std::hex;
1156 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1157 oemData[KEY_Q_PROC_INFO][ss.str()][KEY_PROC_INDEX] = req->procIndex;
1158
1159 str = bytesToStr(req->data, len);
1160 oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]] = str.c_str();
1161 flushOemData();
1162
1163 return IPMI_CC_OK;
1164}
1165
1166//----------------------------------------------------------------------
1167// Get Proc Info (CMD_OEM_Q_GET_PROC_INFO)
1168//----------------------------------------------------------------------
1169// Request:
1170// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1171// Byte 4 – Processor Index, 0 base
1172// Byte 5 – Parameter Selector
1173// Response:
1174// Byte 1 – Completion code
1175// Byte 2..N – Configuration Parameter Data (see below for Parameters
1176// of Processor Information)
1177//
1178// Parameter#1: (Processor Product Name)
1179//
1180// Byte 1..48 –Product name(ASCII code)
1181// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1182//
1183// Param#2: Processor Basic Information
1184// Byte 1 – Core Number
1185// Byte 2 – Thread Number (LSB)
1186// Byte 3 – Thread Number (MSB)
1187// Byte 4 – Processor frequency in MHz (LSB)
1188// Byte 5 – Processor frequency in MHz (MSB)
1189// Byte 6..7 – Revision
1190//
1191ipmi_ret_t ipmiOemQGetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1192 ipmi_request_t request, ipmi_response_t response,
1193 ipmi_data_len_t data_len, ipmi_context_t context)
1194{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001195 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1196 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
1197 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001198 std::stringstream ss;
1199 std::string str;
1200
1201 *data_len = 0;
1202
1203 /* check for requested data params */
1204 if (req->paramSel < 1 || req->paramSel >= numParam)
1205 {
1206 phosphor::logging::log<phosphor::logging::level::ERR>(
1207 "Invalid parameter received");
1208 return IPMI_CC_PARM_OUT_OF_RANGE;
1209 }
1210
1211 ss << std::hex;
1212 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1213
1214 if (oemData[KEY_Q_PROC_INFO].find(ss.str()) ==
1215 oemData[KEY_Q_PROC_INFO].end())
1216 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1217
1218 if (oemData[KEY_Q_PROC_INFO][ss.str()].find(cpuInfoKey[req->paramSel]) ==
1219 oemData[KEY_Q_PROC_INFO][ss.str()].end())
1220 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1221
1222 str = oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]];
1223 *data_len = strToBytes(str, res);
1224
1225 return IPMI_CC_OK;
1226}
1227
1228//----------------------------------------------------------------------
1229// Set Dimm Info (CMD_OEM_Q_SET_DIMM_INFO)
1230//----------------------------------------------------------------------
1231// Request:
1232// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1233// Byte 4 – DIMM Index, 0 base
1234// Byte 5 – Parameter Selector
1235// Byte 6..N – Configuration parameter data (see below for Parameters
1236// of DIMM Information)
1237// Response:
1238// Byte 1 – Completion code
1239//
1240// Param#1 (DIMM Location):
1241// Byte 1 – DIMM Present
1242// Byte 1 – DIMM Present
1243// 01h – Present
1244// FFh – Not Present
1245// Byte 2 – Node Number, 0 base
1246// Byte 3 – Channel Number , 0 base
1247// Byte 4 – DIMM Number , 0 base
1248//
1249// Param#2 (DIMM Type):
1250// Byte 1 – DIMM Type
1251// Bit [7:6]
1252// For DDR3
1253// 00 – Normal Voltage (1.5V)
1254// 01 – Ultra Low Voltage (1.25V)
1255// 10 – Low Voltage (1.35V)
1256// 11 – Reserved
1257// For DDR4
1258// 00 – Reserved
1259// 01 – Reserved
1260// 10 – Reserved
1261// 11 – Normal Voltage (1.2V)
1262// Bit [5:0]
1263// 0x00 – SDRAM
1264// 0x01 – DDR-1 RAM
1265// 0x02 – Rambus
1266// 0x03 – DDR-2 RAM
1267// 0x04 – FBDIMM
1268// 0x05 – DDR-3 RAM
1269// 0x06 – DDR-4 RAM
1270//
1271// Param#3 (DIMM Speed):
1272// Byte 1..2 – DIMM speed in MHz, LSB
1273// Byte 3..6 – DIMM size in Mbytes, LSB
1274//
1275// Param#4 (Module Part Number):
1276// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1277//
1278// Param#5 (Module Serial Number):
1279// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1280//
1281// Param#6 (Module Manufacturer ID):
1282// Byte 1 - Module Manufacturer ID, LSB
1283// Byte 2 - Module Manufacturer ID, MSB
1284//
1285ipmi_ret_t ipmiOemQSetDimmInfo(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 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1290 uint8_t numParam = sizeof(dimmInfoKey) / 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->dimmIndex;
1309 oemData[KEY_Q_DIMM_INFO][ss.str()][KEY_DIMM_INDEX] = req->dimmIndex;
1310
1311 str = bytesToStr(req->data, len);
1312 oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]] =
1313 str.c_str();
1314 flushOemData();
1315
1316 return IPMI_CC_OK;
1317}
1318
1319//----------------------------------------------------------------------
1320// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
1321//----------------------------------------------------------------------
1322// Request:
1323// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1324// Byte 4 – DIMM Index, 0 base
1325// Byte 5 – Parameter Selector
1326// Byte 6..N – Configuration parameter data (see below for Parameters
1327// of DIMM Information)
1328// Response:
1329// Byte 1 – Completion code
1330// Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters
1331// of DIMM Information)
1332//
1333// Param#1 (DIMM Location):
1334// Byte 1 – DIMM Present
1335// Byte 1 – DIMM Present
1336// 01h – Present
1337// FFh – Not Present
1338// Byte 2 – Node Number, 0 base
1339// Byte 3 – Channel Number , 0 base
1340// Byte 4 – DIMM Number , 0 base
1341//
1342// Param#2 (DIMM Type):
1343// Byte 1 – DIMM Type
1344// Bit [7:6]
1345// For DDR3
1346// 00 – Normal Voltage (1.5V)
1347// 01 – Ultra Low Voltage (1.25V)
1348// 10 – Low Voltage (1.35V)
1349// 11 – Reserved
1350// For DDR4
1351// 00 – Reserved
1352// 01 – Reserved
1353// 10 – Reserved
1354// 11 – Normal Voltage (1.2V)
1355// Bit [5:0]
1356// 0x00 – SDRAM
1357// 0x01 – DDR-1 RAM
1358// 0x02 – Rambus
1359// 0x03 – DDR-2 RAM
1360// 0x04 – FBDIMM
1361// 0x05 – DDR-3 RAM
1362// 0x06 – DDR-4 RAM
1363//
1364// Param#3 (DIMM Speed):
1365// Byte 1..2 – DIMM speed in MHz, LSB
1366// Byte 3..6 – DIMM size in Mbytes, LSB
1367//
1368// Param#4 (Module Part Number):
1369// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1370//
1371// Param#5 (Module Serial Number):
1372// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1373//
1374// Param#6 (Module Manufacturer ID):
1375// Byte 1 - Module Manufacturer ID, LSB
1376// Byte 2 - Module Manufacturer ID, MSB
1377//
1378ipmi_ret_t ipmiOemQGetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1379 ipmi_request_t request, ipmi_response_t response,
1380 ipmi_data_len_t data_len, ipmi_context_t context)
1381{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001382 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1383 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
1384 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001385 std::stringstream ss;
1386 std::string str;
1387
1388 *data_len = 0;
1389
1390 /* check for requested data params */
1391 if (req->paramSel < 1 || req->paramSel >= numParam)
1392 {
1393 phosphor::logging::log<phosphor::logging::level::ERR>(
1394 "Invalid parameter received");
1395 return IPMI_CC_PARM_OUT_OF_RANGE;
1396 }
1397
1398 ss << std::hex;
1399 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1400
1401 if (oemData[KEY_Q_DIMM_INFO].find(ss.str()) ==
1402 oemData[KEY_Q_DIMM_INFO].end())
1403 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1404
1405 if (oemData[KEY_Q_DIMM_INFO][ss.str()].find(dimmInfoKey[req->paramSel]) ==
1406 oemData[KEY_Q_DIMM_INFO][ss.str()].end())
1407 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1408
1409 str = oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]];
1410 *data_len = strToBytes(str, res);
1411
1412 return IPMI_CC_OK;
1413}
1414
1415//----------------------------------------------------------------------
1416// Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO)
1417//----------------------------------------------------------------------
1418// BIOS issue this command to provide HDD information to BMC.
1419//
1420// BIOS just can get information by standard ATA / SMART command for
1421// OB SATA controller.
1422// BIOS can get
1423// 1. Serial Number
1424// 2. Model Name
1425// 3. HDD FW Version
1426// 4. HDD Capacity
1427// 5. HDD WWN
1428//
1429// Use Get HDD info Param #5 to know the MAX HDD info index.
1430//
1431// Request:
1432// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1433// Byte 4 –
1434// [7:4] Reserved
1435// [3:0] HDD Controller Type
1436// 0x00 – BIOS
1437// 0x01 – Expander
1438// 0x02 – LSI
1439// Byte 5 – HDD Info Index, 0 base
1440// Byte 6 – Parameter Selector
1441// Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD
1442// Information)
1443//
1444// Response:
1445// Byte 1 – Completion Code
1446//
1447// Param#0 (HDD Location):
1448// Byte 1 – Controller
1449// [7:3] Device Number
1450// [2:0] Function Number
1451// For Intel C610 series (Wellsburg)
1452// D31:F2 (0xFA) – SATA control 1
1453// D31:F5 (0xFD) – SATA control 2
1454// D17:F4 (0x8C) – sSata control
1455// Byte 2 – Port Number
1456// Byte 3 – Location (0xFF: No HDD Present)
1457// BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param
1458// #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if
1459// the HDD present. BMC or other people who know the HDD location has
1460// responsibility for update Location info
1461//
1462// Param#1 (Serial Number):
1463// Bytes 1..33: HDD Serial Number
1464//
1465// Param#2 (Model Name):
1466// Byte 1..33 – HDD Model Name
1467//
1468// Param#3 (HDD FW Version):
1469// Byte 1..17 –HDD FW version
1470//
1471// Param#4 (Capacity):
1472// Byte 1..4 –HDD Block Size, LSB
1473// Byte 5..12 - HDD Block Number, LSB
1474// HDD Capacity = HDD Block size * HDD BLock number (Unit Byte)
1475//
1476// Param#5 (Max HDD Quantity):
1477// Byte 1 - Max HDD Quantity
1478// Max supported port numbers in this PCH
1479//
1480// Param#6 (HDD Type)
1481// Byte 1 – HDD Type
1482// 0h – Reserved
1483// 1h – SAS
1484// 2h – SATA
1485// 3h – PCIE SSD (NVME)
1486//
1487// Param#7 (HDD WWN)
1488// Data 1...8: HDD World Wide Name, LSB
1489//
1490ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1491 ipmi_request_t request,
1492 ipmi_response_t response,
1493 ipmi_data_len_t data_len,
1494 ipmi_context_t context)
1495{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001496 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1497 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001498 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1499 std::stringstream ss;
1500 std::string str;
1501 uint8_t len = *data_len;
1502
1503 *data_len = 0;
1504
1505 /* check for requested data params */
1506 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam ||
1507 ctrlType > 2)
1508 {
1509 phosphor::logging::log<phosphor::logging::level::ERR>(
1510 "Invalid parameter received");
1511 return IPMI_CC_PARM_OUT_OF_RANGE;
1512 }
1513
1514 len = len - 6; // Get Actual data length
1515
1516 ss << std::hex;
1517 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1518 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType;
1519 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] =
1520 req->hddIndex;
1521
1522 str = bytesToStr(req->data, len);
1523 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1524 [driveInfoKey[req->paramSel]] = str.c_str();
1525 flushOemData();
1526
1527 return IPMI_CC_OK;
1528}
1529
1530//----------------------------------------------------------------------
1531// Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO)
1532//----------------------------------------------------------------------
1533// BMC needs to check HDD presented or not first. If NOT presented, return
1534// completion code 0xD5.
1535//
1536// Request:
1537// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1538// Byte 4 –
1539//[7:4] Reserved
1540//[3:0] HDD Controller Type
1541// 0x00 – BIOS
1542// 0x01 – Expander
1543// 0x02 – LSI
1544// Byte 5 – HDD Index, 0 base
1545// Byte 6 – Parameter Selector (See Above Set HDD Information)
1546// Response:
1547// Byte 1 – Completion Code
1548// 0xD5 – Not support in current status (HDD Not Present)
1549// Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD
1550// Information)
1551//
1552ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1553 ipmi_request_t request,
1554 ipmi_response_t response,
1555 ipmi_data_len_t data_len,
1556 ipmi_context_t context)
1557{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001558 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1559 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
1560 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001561 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1562 std::stringstream ss;
1563 std::string str;
1564
1565 *data_len = 0;
1566
1567 /* check for requested data params */
1568 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2)
1569 {
1570 phosphor::logging::log<phosphor::logging::level::ERR>(
1571 "Invalid parameter received");
1572 return IPMI_CC_PARM_OUT_OF_RANGE;
1573 }
1574
1575 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) ==
1576 oemData[KEY_Q_DRIVE_INFO].end())
1577 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1578
1579 ss << std::hex;
1580 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1581
1582 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) ==
1583 oemData[KEY_Q_DRIVE_INFO].end())
1584 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1585
1586 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find(
1587 dimmInfoKey[req->paramSel]) ==
1588 oemData[KEY_Q_DRIVE_INFO][ss.str()].end())
1589 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1590
1591 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1592 [dimmInfoKey[req->paramSel]];
1593 *data_len = strToBytes(str, res);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001594
1595 return IPMI_CC_OK;
1596}
1597
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001598/* Helper function for sending DCMI commands to ME and getting response back */
1599ipmi::RspType<std::vector<uint8_t>> sendDCMICmd(uint8_t cmd,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001600 std::vector<uint8_t>& cmdData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001601{
1602 std::vector<uint8_t> respData;
1603
1604 /* Add group id as first byte to request for ME command */
1605 cmdData.insert(cmdData.begin(), groupDCMI);
1606
1607 if (sendMeCmd(ipmi::netFnGroup, cmd, cmdData, respData))
1608 return ipmi::responseUnspecifiedError();
1609
1610 /* Remove group id as first byte as it will be added by IPMID */
1611 respData.erase(respData.begin());
1612
1613 return ipmi::responseSuccess(std::move(respData));
1614}
1615
1616/* DCMI Command handellers. */
1617
1618ipmi::RspType<std::vector<uint8_t>>
1619 ipmiOemDCMIGetPowerReading(std::vector<uint8_t> reqData)
1620{
1621 return sendDCMICmd(ipmi::dcmi::cmdGetPowerReading, reqData);
1622}
1623
1624ipmi::RspType<std::vector<uint8_t>>
1625 ipmiOemDCMIGetPowerLimit(std::vector<uint8_t> reqData)
1626{
1627 return sendDCMICmd(ipmi::dcmi::cmdGetPowerLimit, reqData);
1628}
1629
1630ipmi::RspType<std::vector<uint8_t>>
1631 ipmiOemDCMISetPowerLimit(std::vector<uint8_t> reqData)
1632{
1633 return sendDCMICmd(ipmi::dcmi::cmdSetPowerLimit, reqData);
1634}
1635
1636ipmi::RspType<std::vector<uint8_t>>
1637 ipmiOemDCMIApplyPowerLimit(std::vector<uint8_t> reqData)
1638{
1639 return sendDCMICmd(ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
1640}
1641
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001642static void registerOEMFunctions(void)
1643{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001644 /* Get OEM data from json file */
1645 std::ifstream file(JSON_OEM_DATA_FILE);
1646 if (file)
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001647 {
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001648 file >> oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001649 file.close();
1650 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001651
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001652 phosphor::logging::log<phosphor::logging::level::INFO>(
1653 "Registering OEM commands");
Vijay Khemka7c0aea42020-03-05 13:31:53 -08001654
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001655 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO,
1656 NULL, ipmiOemDbgGetFrameInfo,
1657 PRIVILEGE_USER); // get debug frame info
1658 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ,
1659 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL,
1660 ipmiOemDbgGetUpdFrames,
1661 PRIVILEGE_USER); // get debug updated frames
1662 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC,
1663 NULL, ipmiOemDbgGetPostDesc,
1664 PRIVILEGE_USER); // get debug post description
1665 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC,
1666 NULL, ipmiOemDbgGetGpioDesc,
1667 PRIVILEGE_USER); // get debug gpio description
1668 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA,
1669 NULL, ipmiOemDbgGetFrameData,
1670 PRIVILEGE_USER); // get debug frame data
1671 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL,
1672 NULL, ipmiOemDbgGetCtrlPanel,
1673 PRIVILEGE_USER); // get debug control panel
1674 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL,
1675 ipmiOemSetDimmInfo,
1676 PRIVILEGE_USER); // Set Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001677 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL,
1678 ipmiOemGetBoardID,
1679 PRIVILEGE_USER); // Get Board ID
1680 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BOOT_ORDER, NULL,
1681 ipmiOemSetBootOrder,
1682 PRIVILEGE_USER); // Set Boot Order
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001683 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOOT_ORDER, NULL,
1684 ipmiOemGetBootOrder,
1685 PRIVILEGE_USER); // Get Boot Order
1686 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL,
1687 ipmiOemSetMachineCfgInfo,
1688 PRIVILEGE_USER); // Set Machine Config Info
1689 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL,
1690 ipmiOemSetPostStart,
1691 PRIVILEGE_USER); // Set POST start
1692 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL,
1693 ipmiOemSetPostEnd,
1694 PRIVILEGE_USER); // Set POST End
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001695 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL,
1696 ipmiOemSetPPINInfo,
1697 PRIVILEGE_USER); // Set PPIN Info
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301698#if BIC_ENABLED
1699
1700 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne,
1701 ipmi::cmdSetSystemGuid, ipmi::Privilege::User,
1702 ipmiOemSetSystemGuid);
1703#else
1704
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001705 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_SYSTEM_GUID, NULL,
1706 ipmiOemSetSystemGuid,
1707 PRIVILEGE_USER); // Set System GUID
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +05301708#endif
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001709 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL,
1710 ipmiOemSetAdrTrigger,
1711 PRIVILEGE_USER); // Set ADR Trigger
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001712 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL,
1713 ipmiOemSetBiosFlashInfo,
1714 PRIVILEGE_USER); // Set Bios Flash Info
1715 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr,
1716 PRIVILEGE_USER); // Set PPR
1717 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
1718 PRIVILEGE_USER); // Get PPR
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001719 /* FB OEM QC Commands */
1720 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_PROC_INFO, NULL,
1721 ipmiOemQSetProcInfo,
1722 PRIVILEGE_USER); // Set Proc Info
1723 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL,
1724 ipmiOemQGetProcInfo,
1725 PRIVILEGE_USER); // Get Proc Info
1726 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DIMM_INFO, NULL,
1727 ipmiOemQSetDimmInfo,
1728 PRIVILEGE_USER); // Set Dimm Info
1729 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DIMM_INFO, NULL,
1730 ipmiOemQGetDimmInfo,
1731 PRIVILEGE_USER); // Get Dimm Info
1732 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
1733 ipmiOemQSetDriveInfo,
1734 PRIVILEGE_USER); // Set Drive Info
1735 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL,
1736 ipmiOemQGetDriveInfo,
1737 PRIVILEGE_USER); // Get Drive Info
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001738
1739 /* FB OEM DCMI Commands as per DCMI spec 1.5 Section 6 */
1740 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1741 ipmi::dcmi::cmdGetPowerReading,
1742 ipmi::Privilege::User,
1743 ipmiOemDCMIGetPowerReading); // Get Power Reading
1744
1745 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1746 ipmi::dcmi::cmdGetPowerLimit,
1747 ipmi::Privilege::User,
1748 ipmiOemDCMIGetPowerLimit); // Get Power Limit
1749
1750 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1751 ipmi::dcmi::cmdSetPowerLimit,
1752 ipmi::Privilege::Operator,
1753 ipmiOemDCMISetPowerLimit); // Set Power Limit
1754
1755 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1756 ipmi::dcmi::cmdActDeactivatePwrLimit,
1757 ipmi::Privilege::Operator,
1758 ipmiOemDCMIApplyPowerLimit); // Apply Power Limit
1759
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001760 return;
1761}
1762
1763} // namespace ipmi