blob: 9fbcc90d039cd16eaf276be5080a326cf1472d24 [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"
19#include <ipmid/api.h>
20
Vijay Khemka1d4a0692019-04-09 15:20:28 -070021#include <nlohmann/json.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080022#include <array>
23#include <commandutils.hpp>
24#include <cstring>
25#include <iostream>
Vijay Khemka1d4a0692019-04-09 15:20:28 -070026#include <iomanip>
27#include <sstream>
28#include <fstream>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080029#include <oemcommands.hpp>
Vijay Khemka1b6fae32019-03-25 17:43:01 -070030#include <ipmid/utils.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080031#include <phosphor-logging/log.hpp>
32#include <sdbusplus/bus.hpp>
33#include <string>
34#include <vector>
35
36#define SIZE_IANA_ID 3
37
38namespace ipmi
39{
Vijay Khemkaa7231892019-10-11 11:35:05 -070040
41using namespace phosphor::logging;
42
Vijay Khemkae7d23d02019-03-08 13:13:40 -080043static void registerOEMFunctions() __attribute__((constructor));
44sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
45static constexpr size_t maxFRUStringLength = 0x3F;
46
Vijay Khemkacc0d6d92019-08-27 14:51:17 -070047int plat_udbg_get_post_desc(uint8_t, uint8_t *, uint8_t, uint8_t *, uint8_t *,
48 uint8_t *);
Vijay Khemka38183d62019-08-28 16:19:33 -070049int plat_udbg_get_gpio_desc(uint8_t, uint8_t *, uint8_t *, uint8_t *, uint8_t *,
50 uint8_t *);
Vijay Khemkae7d23d02019-03-08 13:13:40 -080051ipmi_ret_t plat_udbg_get_frame_data(uint8_t, uint8_t, uint8_t *, uint8_t *,
52 uint8_t *);
53ipmi_ret_t plat_udbg_control_panel(uint8_t, uint8_t, uint8_t, uint8_t *,
54 uint8_t *);
Vijay Khemka1b6fae32019-03-25 17:43:01 -070055namespace variant_ns = sdbusplus::message::variant_ns;
Vijay Khemkafeaa9812019-08-27 15:08:08 -070056nlohmann::json oemData __attribute__((init_priority(101)));
Vijay Khemka1b6fae32019-03-25 17:43:01 -070057
58enum class LanParam : uint8_t
59{
60 INPROGRESS = 0,
61 AUTHSUPPORT = 1,
62 AUTHENABLES = 2,
63 IP = 3,
64 IPSRC = 4,
65 MAC = 5,
66 SUBNET = 6,
67 GATEWAY = 12,
68 VLAN = 20,
69 CIPHER_SUITE_COUNT = 22,
70 CIPHER_SUITE_ENTRIES = 23,
71 IPV6 = 59,
72};
73
Vijay Khemkaa7231892019-10-11 11:35:05 -070074namespace network
75{
76
77constexpr auto ROOT = "/xyz/openbmc_project/network";
78constexpr auto SERVICE = "xyz.openbmc_project.Network";
79constexpr auto IPV4_TYPE = "ipv4";
80constexpr auto IPV6_TYPE = "ipv6";
81constexpr auto IPV4_PREFIX = "169.254";
82constexpr auto IPV6_PREFIX = "fe80";
83constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
84constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
85
86bool isLinkLocalIP(const std::string &address)
87{
88 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0;
89}
90
91DbusObjectInfo getIPObject(sdbusplus::bus::bus &bus,
92 const std::string &interface,
93 const std::string &serviceRoot,
94 const std::string &match)
95{
96 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
97
98 if (objectTree.empty())
99 {
100 log<level::ERR>("No Object has implemented the IP interface",
101 entry("INTERFACE=%s", interface.c_str()));
102 }
103
104 DbusObjectInfo objectInfo;
105
106 for (auto &object : objectTree)
107 {
108 auto variant =
109 ipmi::getDbusProperty(bus, object.second.begin()->first,
110 object.first, IP_INTERFACE, "Address");
111
112 objectInfo = std::make_pair(object.first, object.second.begin()->first);
113
114 // if LinkLocalIP found look for Non-LinkLocalIP
115 if (isLinkLocalIP(std::get<std::string>(variant)))
116 {
117 continue;
118 }
119 else
120 {
121 break;
122 }
123 }
124 return objectInfo;
125}
126
127} // namespace network
128
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700129//----------------------------------------------------------------------
130// Helper functions for storing oem data
131//----------------------------------------------------------------------
132
133void flushOemData()
134{
135 std::ofstream file(JSON_OEM_DATA_FILE);
136 file << oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -0700137 file.close();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700138 return;
139}
140
141std::string bytesToStr(uint8_t *byte, int len)
142{
143 std::stringstream ss;
144 int i;
145
146 ss << std::hex;
147 for (i = 0; i < len; i++)
148 {
149 ss << std::setw(2) << std::setfill('0') << (int)byte[i];
150 }
151
152 return ss.str();
153}
154
155int strToBytes(std::string &str, uint8_t *data)
156{
157 std::string sstr;
158 int i;
159
160 for (i = 0; i < (str.length()) / 2; i++)
161 {
162 sstr = str.substr(i * 2, 2);
163 data[i] = (uint8_t)std::strtol(sstr.c_str(), NULL, 16);
164 }
165 return i;
166}
167
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700168ipmi_ret_t getNetworkData(uint8_t lan_param, char *data)
169{
170 ipmi_ret_t rc = IPMI_CC_OK;
171 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
172
173 const std::string ethdevice = "eth0";
174
175 switch (static_cast<LanParam>(lan_param))
176 {
177 case LanParam::IP:
178 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700179 auto ethIP = ethdevice + "/" + ipmi::network::IPV4_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700180 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700181 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700182 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
183
184 auto properties = ipmi::getAllDbusProperties(
185 bus, ipObjectInfo.second, ipObjectInfo.first,
186 ipmi::network::IP_INTERFACE);
187
188 ipaddress = variant_ns::get<std::string>(properties["Address"]);
189
190 std::strcpy(data, ipaddress.c_str());
191 }
192 break;
193
194 case LanParam::IPV6:
195 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700196 auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700197 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700198 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700199 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
200
201 auto properties = ipmi::getAllDbusProperties(
202 bus, ipObjectInfo.second, ipObjectInfo.first,
203 ipmi::network::IP_INTERFACE);
204
205 ipaddress = variant_ns::get<std::string>(properties["Address"]);
206
207 std::strcpy(data, ipaddress.c_str());
208 }
209 break;
210
211 case LanParam::MAC:
212 {
213 std::string macAddress;
214 auto macObjectInfo =
215 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
216 ipmi::network::ROOT, ethdevice);
217
218 auto variant = ipmi::getDbusProperty(
219 bus, macObjectInfo.second, macObjectInfo.first,
220 ipmi::network::MAC_INTERFACE, "MACAddress");
221
222 macAddress = variant_ns::get<std::string>(variant);
223
224 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
225 (data), (data + 1), (data + 2), (data + 3), (data + 4),
226 (data + 5));
227 std::strcpy(data, macAddress.c_str());
228 }
229 break;
230
231 default:
232 rc = IPMI_CC_PARM_OUT_OF_RANGE;
233 }
234 return rc;
235}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800236
237// return code: 0 successful
238int8_t getFruData(std::string &data, std::string &name)
239{
240 std::string objpath = "/xyz/openbmc_project/FruDevice";
241 std::string intf = "xyz.openbmc_project.FruDeviceManager";
242 std::string service = getService(dbus, intf, objpath);
243 ObjectValueTree valueTree = getManagedObjects(dbus, service, "/");
244 if (valueTree.empty())
245 {
246 phosphor::logging::log<phosphor::logging::level::ERR>(
247 "No object implements interface",
248 phosphor::logging::entry("INTF=%s", intf.c_str()));
249 return -1;
250 }
251
252 for (const auto &item : valueTree)
253 {
254 auto interface = item.second.find("xyz.openbmc_project.FruDevice");
255 if (interface == item.second.end())
256 {
257 continue;
258 }
259
260 auto property = interface->second.find(name.c_str());
261 if (property == interface->second.end())
262 {
263 continue;
264 }
265
266 try
267 {
268 Value variant = property->second;
269 std::string &result =
270 sdbusplus::message::variant_ns::get<std::string>(variant);
271 if (result.size() > maxFRUStringLength)
272 {
273 phosphor::logging::log<phosphor::logging::level::ERR>(
274 "FRU serial number exceed maximum length");
275 return -1;
276 }
277 data = result;
278 return 0;
279 }
280 catch (sdbusplus::message::variant_ns::bad_variant_access &e)
281 {
282 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
283 return -1;
284 }
285 }
286 return -1;
287}
288
289typedef struct
290{
291 uint8_t cur_power_state;
292 uint8_t last_power_event;
293 uint8_t misc_power_state;
294 uint8_t front_panel_button_cap_status;
295} ipmi_get_chassis_status_t;
296
297// Todo: Needs to update this as per power policy when integrated
298//----------------------------------------------------------------------
299// Get Chassis Status commands
300//----------------------------------------------------------------------
301ipmi_ret_t ipmiGetChassisStatus(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
302 ipmi_request_t request,
303 ipmi_response_t response,
304 ipmi_data_len_t data_len,
305 ipmi_context_t context)
306{
307 ipmi_get_chassis_status_t chassis_status;
308 uint8_t s = 2;
309
310 *data_len = 4;
311
312 // Current Power State
313 // [7] reserved
314 // [6..5] power restore policy
315 // 00b = chassis stays powered off after AC/mains returns
316 // 01b = after AC returns, power is restored to the state that was
317 // in effect when AC/mains was lost.
318 // 10b = chassis always powers up after AC/mains returns
319 // 11b = unknow
320 // Set to 00b, by observing the hardware behavior.
321 // Do we need to define a dbus property to identify the restore
322 // policy?
323
324 // [4] power control fault
325 // 1b = controller attempted to turn system power on or off, but
326 // system did not enter desired state.
327 // Set to 0b, since We don't support it..
328
329 // [3] power fault
330 // 1b = fault detected in main power subsystem.
331 // set to 0b. for we don't support it.
332
333 // [2] 1b = interlock (chassis is presently shut down because a chassis
334 // panel interlock switch is active). (IPMI 1.5)
335 // set to 0b, for we don't support it.
336
337 // [1] power overload
338 // 1b = system shutdown because of power overload condition.
339 // set to 0b, for we don't support it.
340
341 // [0] power is on
342 // 1b = system power is on
343 // 0b = system power is off(soft-off S4/S5, or mechanical off)
344
345 chassis_status.cur_power_state = ((s & 0x3) << 5) | (1 & 0x1);
346
347 // Last Power Event
348 // [7..5] – reserved
349 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
350 // [3] – 1b = last power down caused by power fault
351 // [2] – 1b = last power down caused by a power interlock being activated
352 // [1] – 1b = last power down caused by a Power overload
353 // [0] – 1b = AC failed
354 // set to 0x0, for we don't support these fields.
355
356 chassis_status.last_power_event = 0;
357
358 // Misc. Chassis State
359 // [7] – reserved
360 // [6] – 1b = Chassis Identify command and state info supported (Optional)
361 // 0b = Chassis Identify command support unspecified via this command.
362 // (The Get Command Support command , if implemented, would still
363 // indicate support for the Chassis Identify command)
364 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved
365 // (return
366 // as 00b) otherwise. Returns the present chassis identify state.
367 // Refer to the Chassis Identify command for more info.
368 // 00b = chassis identify state = Off
369 // 01b = chassis identify state = Temporary(timed) On
370 // 10b = chassis identify state = Indefinite On
371 // 11b = reserved
372 // [3] – 1b = Cooling/fan fault detected
373 // [2] – 1b = Drive Fault
374 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
375 // push-buttons disabled.)
376 // [0] – 1b = Chassis Intrusion active
377 // set to 0, for we don't support them.
378 chassis_status.misc_power_state = 0x40;
379
380 // Front Panel Button Capabilities and disable/enable status(Optional)
381 // set to 0, for we don't support them.
382 chassis_status.front_panel_button_cap_status = 0;
383
384 // Pack the actual response
385 std::memcpy(response, &chassis_status, *data_len);
386
387 return IPMI_CC_OK;
388}
389
390//----------------------------------------------------------------------
391// Get Debug Frame Info
392//----------------------------------------------------------------------
393ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
394 ipmi_request_t request,
395 ipmi_response_t response,
396 ipmi_data_len_t data_len,
397 ipmi_context_t context)
398{
399 uint8_t *req = reinterpret_cast<uint8_t *>(request);
400 uint8_t *res = reinterpret_cast<uint8_t *>(response);
401 uint8_t num_frames = 3;
402
403 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
404 res[SIZE_IANA_ID] = num_frames;
405 *data_len = SIZE_IANA_ID + 1;
406
407 return IPMI_CC_OK;
408}
409
410//----------------------------------------------------------------------
411// Get Debug Updated Frames
412//----------------------------------------------------------------------
413ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
414 ipmi_request_t request,
415 ipmi_response_t response,
416 ipmi_data_len_t data_len,
417 ipmi_context_t context)
418{
419 uint8_t *req = reinterpret_cast<uint8_t *>(request);
420 uint8_t *res = reinterpret_cast<uint8_t *>(response);
421 uint8_t num_updates = 3;
422 *data_len = 4;
423
424 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
425 res[SIZE_IANA_ID] = num_updates;
426 *data_len = SIZE_IANA_ID + num_updates + 1;
427 res[SIZE_IANA_ID + 1] = 1; // info page update
428 res[SIZE_IANA_ID + 2] = 2; // cri sel update
429 res[SIZE_IANA_ID + 3] = 3; // cri sensor update
430
431 return IPMI_CC_OK;
432}
433
434//----------------------------------------------------------------------
435// Get Debug POST Description
436//----------------------------------------------------------------------
437ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
438 ipmi_request_t request,
439 ipmi_response_t response,
440 ipmi_data_len_t data_len,
441 ipmi_context_t context)
442{
443 uint8_t *req = reinterpret_cast<uint8_t *>(request);
444 uint8_t *res = reinterpret_cast<uint8_t *>(response);
445 uint8_t index = 0;
446 uint8_t next = 0;
447 uint8_t end = 0;
448 uint8_t phase = 0;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700449 uint8_t descLen = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800450 int ret;
451
452 index = req[3];
453 phase = req[4];
454
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700455 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800456 if (ret)
457 {
458 memcpy(res, req, SIZE_IANA_ID); // IANA ID
459 *data_len = SIZE_IANA_ID;
460 return IPMI_CC_UNSPECIFIED_ERROR;
461 }
462
463 memcpy(res, req, SIZE_IANA_ID); // IANA ID
464 res[3] = index;
465 res[4] = next;
466 res[5] = phase;
467 res[6] = end;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700468 res[7] = descLen;
469 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800470
471 return IPMI_CC_OK;
472}
473
474//----------------------------------------------------------------------
475// Get Debug GPIO Description
476//----------------------------------------------------------------------
477ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
478 ipmi_request_t request,
479 ipmi_response_t response,
480 ipmi_data_len_t data_len,
481 ipmi_context_t context)
482{
483 uint8_t *req = reinterpret_cast<uint8_t *>(request);
484 uint8_t *res = reinterpret_cast<uint8_t *>(response);
485
Vijay Khemka38183d62019-08-28 16:19:33 -0700486 uint8_t index = 0;
487 uint8_t next = 0;
488 uint8_t level = 0;
489 uint8_t pinDef = 0;
490 uint8_t descLen = 0;
491 int ret;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800492
Vijay Khemka38183d62019-08-28 16:19:33 -0700493 index = req[3];
494
495 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen,
496 &res[8]);
497 if (ret)
498 {
499 memcpy(res, req, SIZE_IANA_ID); // IANA ID
500 *data_len = SIZE_IANA_ID;
501 return IPMI_CC_UNSPECIFIED_ERROR;
502 }
503
504 memcpy(res, req, SIZE_IANA_ID); // IANA ID
505 res[3] = index;
506 res[4] = next;
507 res[5] = level;
508 res[6] = pinDef;
509 res[7] = descLen;
510 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800511
512 return IPMI_CC_OK;
513}
514
515//----------------------------------------------------------------------
516// Get Debug Frame Data
517//----------------------------------------------------------------------
518ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
519 ipmi_request_t request,
520 ipmi_response_t response,
521 ipmi_data_len_t data_len,
522 ipmi_context_t context)
523{
524 uint8_t *req = reinterpret_cast<uint8_t *>(request);
525 uint8_t *res = reinterpret_cast<uint8_t *>(response);
526 uint8_t frame;
527 uint8_t page;
528 uint8_t next;
529 uint8_t count;
530 int ret;
531
532 frame = req[3];
533 page = req[4];
534 int fr = frame;
535 int pg = page;
536
537 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]);
538 if (ret)
539 {
540 memcpy(res, req, SIZE_IANA_ID); // IANA ID
541 *data_len = SIZE_IANA_ID;
542 return IPMI_CC_UNSPECIFIED_ERROR;
543 }
544
545 memcpy(res, req, SIZE_IANA_ID); // IANA ID
546 res[3] = frame;
547 res[4] = page;
548 res[5] = next;
549 res[6] = count;
550 *data_len = SIZE_IANA_ID + 4 + count;
551
552 return IPMI_CC_OK;
553}
554
555//----------------------------------------------------------------------
556// Get Debug Control Panel
557//----------------------------------------------------------------------
558ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
559 ipmi_request_t request,
560 ipmi_response_t response,
561 ipmi_data_len_t data_len,
562 ipmi_context_t context)
563{
564 uint8_t *req = reinterpret_cast<uint8_t *>(request);
565 uint8_t *res = reinterpret_cast<uint8_t *>(response);
566
567 uint8_t panel;
568 uint8_t operation;
569 uint8_t item;
570 uint8_t count;
571 ipmi_ret_t ret;
572
573 panel = req[3];
574 operation = req[4];
575 item = req[5];
576
577 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]);
578
579 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
580 *data_len = SIZE_IANA_ID + count;
581
582 return ret;
583}
584
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800585//----------------------------------------------------------------------
586// Set Dimm Info (CMD_OEM_SET_DIMM_INFO)
587//----------------------------------------------------------------------
588ipmi_ret_t ipmiOemSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
589 ipmi_request_t request, ipmi_response_t response,
590 ipmi_data_len_t data_len, ipmi_context_t context)
591{
592 uint8_t *req = reinterpret_cast<uint8_t *>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700593
594 uint8_t index = req[0];
595 uint8_t type = req[1];
596 uint16_t speed;
597 uint32_t size;
598
599 memcpy(&speed, &req[2], 2);
600 memcpy(&size, &req[4], 4);
601
602 std::stringstream ss;
603 ss << std::hex;
604 ss << std::setw(2) << std::setfill('0') << (int)index;
605
606 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index;
607 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type;
608 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed;
609 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size;
610
611 flushOemData();
612
613 *data_len = 0;
614
615 return IPMI_CC_OK;
616}
617
618//----------------------------------------------------------------------
619// Get Board ID (CMD_OEM_GET_BOARD_ID)
620//----------------------------------------------------------------------
621ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
622 ipmi_request_t request, ipmi_response_t response,
623 ipmi_data_len_t data_len, ipmi_context_t context)
624{
625 uint8_t *req = reinterpret_cast<uint8_t *>(request);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800626 uint8_t *res = reinterpret_cast<uint8_t *>(response);
627
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700628 /* TODO: Needs to implement this after GPIO implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800629 *data_len = 0;
630
631 return IPMI_CC_OK;
632}
633
634//----------------------------------------------------------------------
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700635// Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
636//----------------------------------------------------------------------
637ipmi_ret_t ipmiOemSetBootOrder(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
638 ipmi_request_t request, ipmi_response_t response,
639 ipmi_data_len_t data_len, ipmi_context_t context)
640{
641 uint8_t *req = reinterpret_cast<uint8_t *>(request);
642 uint8_t len = *data_len;
643 uint8_t mode = req[0];
644 nlohmann::json bootMode;
645 int i;
646
647 *data_len = 0;
648
649 if (len != SIZE_BOOT_ORDER)
650 {
651 phosphor::logging::log<phosphor::logging::level::ERR>(
652 "Invalid Boot order length received");
653 return IPMI_CC_REQ_DATA_LEN_INVALID;
654 }
655
656 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false);
657 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false);
658 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false);
659 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false);
660
661 oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE] = bootMode;
662
663 /* Initialize boot sequence array */
664 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ] = {};
665 for (i = 1; i < SIZE_BOOT_ORDER; i++)
666 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1] = bootSeq[req[i]];
667
668 flushOemData();
669
670 return IPMI_CC_OK;
671}
672
673//----------------------------------------------------------------------
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800674// Get Boot Order (CMD_OEM_GET_BOOT_ORDER)
675//----------------------------------------------------------------------
676ipmi_ret_t ipmiOemGetBootOrder(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
677 ipmi_request_t request, ipmi_response_t response,
678 ipmi_data_len_t data_len, ipmi_context_t context)
679{
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800680 uint8_t *res = reinterpret_cast<uint8_t *>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700681 nlohmann::json bootMode = oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE];
682 uint8_t mode = 0;
683 int i;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800684
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700685 *data_len = SIZE_BOOT_ORDER;
686
687 if (bootMode["UEFI"])
688 mode |= BOOT_MODE_UEFI;
689 if (bootMode["CMOS_CLR"])
690 mode |= BOOT_MODE_CMOS_CLR;
691 if (bootMode["BOOT_FLAG"])
692 mode |= BOOT_MODE_BOOT_FLAG;
693
694 res[0] = mode;
695
696 for (i = 1; i < SIZE_BOOT_ORDER; i++)
697 res[i] = bootMap[oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1]];
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800698
699 return IPMI_CC_OK;
700}
701
702//----------------------------------------------------------------------
703// Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO)
704//----------------------------------------------------------------------
705ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
706 ipmi_request_t request,
707 ipmi_response_t response,
708 ipmi_data_len_t data_len,
709 ipmi_context_t context)
710{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700711 machineConfigInfo_t *req = reinterpret_cast<machineConfigInfo_t *>(request);
712 uint8_t len = *data_len;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800713
714 *data_len = 0;
715
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700716 if (len < sizeof(machineConfigInfo_t))
717 {
718 phosphor::logging::log<phosphor::logging::level::ERR>(
719 "Invalid machine configuration length received");
720 return IPMI_CC_REQ_DATA_LEN_INVALID;
721 }
722
723 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t *))
724 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN";
725 else
726 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] =
727 chassisType[req->chassis_type];
728
729 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t *))
730 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN";
731 else
732 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type];
733
734 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt;
735 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt;
736 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt;
737 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt;
738
739 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t *))
740 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN";
741 else
742 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type];
743
744 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {};
745 int i = 0;
746 if (req->pcie_card_loc & BIT_0)
747 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1";
748 if (req->pcie_card_loc & BIT_1)
749 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2";
750 if (req->pcie_card_loc & BIT_2)
751 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3";
752 if (req->pcie_card_loc & BIT_3)
753 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4";
754
755 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t *))
756 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN";
757 else
758 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] =
759 pcieType[req->slot1_pcie_type];
760
761 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t *))
762 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN";
763 else
764 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] =
765 pcieType[req->slot2_pcie_type];
766
767 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t *))
768 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN";
769 else
770 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] =
771 pcieType[req->slot3_pcie_type];
772
773 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t *))
774 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN";
775 else
776 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] =
777 pcieType[req->slot4_pcie_type];
778
779 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt;
780
781 flushOemData();
782
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800783 return IPMI_CC_OK;
784}
785
786//----------------------------------------------------------------------
787// Set POST start (CMD_OEM_SET_POST_START)
788//----------------------------------------------------------------------
789ipmi_ret_t ipmiOemSetPostStart(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 Khemkae7d23d02019-03-08 13:13:40 -0800793 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event");
794
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700795 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800796 *data_len = 0;
797 return IPMI_CC_OK;
798}
799
800//----------------------------------------------------------------------
801// Set POST End (CMD_OEM_SET_POST_END)
802//----------------------------------------------------------------------
803ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
804 ipmi_request_t request, ipmi_response_t response,
805 ipmi_data_len_t data_len, ipmi_context_t context)
806{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700807 struct timespec ts;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800808
809 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event");
810
811 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700812
813 // Timestamp post end time.
814 clock_gettime(CLOCK_REALTIME, &ts);
815 oemData[KEY_TS_SLED] = ts.tv_sec;
816 flushOemData();
817
818 // Sync time with system
819 // TODO: Add code for syncing time
820
821 return IPMI_CC_OK;
822}
823
824//----------------------------------------------------------------------
825// Set PPIN Info (CMD_OEM_SET_PPIN_INFO)
826//----------------------------------------------------------------------
827// Inform BMC about PPIN data of 8 bytes for each CPU
828//
829// Request:
830// Byte 1:8 – CPU0 PPIN data
831// Optional:
832// Byte 9:16 – CPU1 PPIN data
833//
834// Response:
835// Byte 1 – Completion Code
836ipmi_ret_t ipmiOemSetPPINInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
837 ipmi_request_t request, ipmi_response_t response,
838 ipmi_data_len_t data_len, ipmi_context_t context)
839{
840 uint8_t *req = reinterpret_cast<uint8_t *>(request);
841 std::string ppinStr;
842 int len;
843
844 if (*data_len > SIZE_CPU_PPIN * 2)
845 len = SIZE_CPU_PPIN * 2;
846 else
847 len = *data_len;
848 *data_len = 0;
849
850 ppinStr = bytesToStr(req, len);
851 oemData[KEY_PPIN_INFO] = ppinStr.c_str();
852 flushOemData();
853
854 return IPMI_CC_OK;
855}
856
857//----------------------------------------------------------------------
858// Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER)
859//----------------------------------------------------------------------
860ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
861 ipmi_request_t request,
862 ipmi_response_t response,
863 ipmi_data_len_t data_len,
864 ipmi_context_t context)
865{
866 /* Do nothing, return success */
867 *data_len = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800868 return IPMI_CC_OK;
869}
870
871//----------------------------------------------------------------------
872// Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO)
873//----------------------------------------------------------------------
874ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
875 ipmi_request_t request,
876 ipmi_response_t response,
877 ipmi_data_len_t data_len,
878 ipmi_context_t context)
879{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700880 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800881 *data_len = 0;
882 return IPMI_CC_OK;
883}
884
885//----------------------------------------------------------------------
886// Set PPR (CMD_OEM_SET_PPR)
887//----------------------------------------------------------------------
888ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
889 ipmi_request_t request, ipmi_response_t response,
890 ipmi_data_len_t data_len, ipmi_context_t context)
891{
892 uint8_t *req = reinterpret_cast<uint8_t *>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700893 uint8_t pprCnt, pprAct, pprIndex;
894 uint8_t selParam = req[0];
895 uint8_t len = *data_len;
896 std::stringstream ss;
897 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800898
899 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700900
901 switch (selParam)
902 {
903 case PPR_ACTION:
904 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) ==
905 oemData[KEY_PPR].end())
906 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
907
908 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
909 if (pprCnt == 0)
910 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
911
912 pprAct = req[1];
913 /* Check if ppr is enabled or disabled */
914 if (!(pprAct & 0x80))
915 pprAct = 0;
916
917 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct;
918 break;
919 case PPR_ROW_COUNT:
920 if (req[1] > 100)
921 return IPMI_CC_PARM_OUT_OF_RANGE;
922
923 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1];
924 break;
925 case PPR_ROW_ADDR:
926 pprIndex = req[1];
927 if (pprIndex > 100)
928 return IPMI_CC_PARM_OUT_OF_RANGE;
929
930 if (len < PPR_ROW_ADDR_LEN + 1)
931 {
932 phosphor::logging::log<phosphor::logging::level::ERR>(
933 "Invalid PPR Row Address length received");
934 return IPMI_CC_REQ_DATA_LEN_INVALID;
935 }
936
937 ss << std::hex;
938 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
939
940 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
941
942 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN);
943 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str();
944 break;
945 case PPR_HISTORY_DATA:
946 pprIndex = req[1];
947 if (pprIndex > 100)
948 return IPMI_CC_PARM_OUT_OF_RANGE;
949
950 if (len < PPR_HST_DATA_LEN + 1)
951 {
952 phosphor::logging::log<phosphor::logging::level::ERR>(
953 "Invalid PPR history data length received");
954 return IPMI_CC_REQ_DATA_LEN_INVALID;
955 }
956
957 ss << std::hex;
958 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
959
960 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
961
962 str = bytesToStr(&req[1], PPR_HST_DATA_LEN);
963 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str();
964 break;
965 default:
966 return IPMI_CC_PARM_OUT_OF_RANGE;
967 break;
968 }
969
970 flushOemData();
971
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800972 return IPMI_CC_OK;
973}
974
975//----------------------------------------------------------------------
976// Get PPR (CMD_OEM_GET_PPR)
977//----------------------------------------------------------------------
978ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
979 ipmi_request_t request, ipmi_response_t response,
980 ipmi_data_len_t data_len, ipmi_context_t context)
981{
982 uint8_t *req = reinterpret_cast<uint8_t *>(request);
983 uint8_t *res = reinterpret_cast<uint8_t *>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700984 uint8_t pprCnt, pprIndex;
985 uint8_t selParam = req[0];
986 std::stringstream ss;
987 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800988
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700989 /* Any failure will return zero length data */
990 *data_len = 0;
991
992 switch (selParam)
993 {
994 case PPR_ACTION:
995 res[0] = 0;
996 *data_len = 1;
997
998 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
999 oemData[KEY_PPR].end())
1000 {
1001 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1002 if (pprCnt != 0)
1003 {
1004 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) !=
1005 oemData[KEY_PPR].end())
1006 {
1007 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION];
1008 }
1009 }
1010 }
1011 break;
1012 case PPR_ROW_COUNT:
1013 res[0] = 0;
1014 *data_len = 1;
1015 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1016 oemData[KEY_PPR].end())
1017 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1018 break;
1019 case PPR_ROW_ADDR:
1020 pprIndex = req[1];
1021 if (pprIndex > 100)
1022 return IPMI_CC_PARM_OUT_OF_RANGE;
1023
1024 ss << std::hex;
1025 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1026
1027 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1028 return IPMI_CC_PARM_OUT_OF_RANGE;
1029
1030 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) ==
1031 oemData[KEY_PPR][ss.str()].end())
1032 return IPMI_CC_PARM_OUT_OF_RANGE;
1033
1034 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR];
1035 *data_len = strToBytes(str, res);
1036 break;
1037 case PPR_HISTORY_DATA:
1038 pprIndex = req[1];
1039 if (pprIndex > 100)
1040 return IPMI_CC_PARM_OUT_OF_RANGE;
1041
1042 ss << std::hex;
1043 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1044
1045 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1046 return IPMI_CC_PARM_OUT_OF_RANGE;
1047
1048 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) ==
1049 oemData[KEY_PPR][ss.str()].end())
1050 return IPMI_CC_PARM_OUT_OF_RANGE;
1051
1052 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA];
1053 *data_len = strToBytes(str, res);
1054 break;
1055 default:
1056 return IPMI_CC_PARM_OUT_OF_RANGE;
1057 break;
1058 }
1059
1060 return IPMI_CC_OK;
1061}
1062
1063/* FB OEM QC Commands */
1064
1065//----------------------------------------------------------------------
1066// Set Proc Info (CMD_OEM_Q_SET_PROC_INFO)
1067//----------------------------------------------------------------------
1068//"Request:
1069// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1070// Byte 4 – Processor Index, 0 base
1071// Byte 5 – Parameter Selector
1072// Byte 6..N – Configuration parameter data (see below for Parameters
1073// of Processor Information)
1074// Response:
1075// Byte 1 – Completion code
1076//
1077// Parameter#1: (Processor Product Name)
1078//
1079// Byte 1..48 –Product name(ASCII code)
1080// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1081//
1082// Param#2: Processor Basic Information
1083// Byte 1 – Core Number
1084// Byte 2 – Thread Number (LSB)
1085// Byte 3 – Thread Number (MSB)
1086// Byte 4 – Processor frequency in MHz (LSB)
1087// Byte 5 – Processor frequency in MHz (MSB)
1088// Byte 6..7 – Revision
1089//
1090ipmi_ret_t ipmiOemQSetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1091 ipmi_request_t request, ipmi_response_t response,
1092 ipmi_data_len_t data_len, ipmi_context_t context)
1093{
1094 qProcInfo_t *req = reinterpret_cast<qProcInfo_t *>(request);
1095 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t *);
1096 std::stringstream ss;
1097 std::string str;
1098 uint8_t len = *data_len;
1099
1100 *data_len = 0;
1101
1102 /* check for requested data params */
1103 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1104 {
1105 phosphor::logging::log<phosphor::logging::level::ERR>(
1106 "Invalid parameter received");
1107 return IPMI_CC_PARM_OUT_OF_RANGE;
1108 }
1109
1110 len = len - 5; // Get Actual data length
1111
1112 ss << std::hex;
1113 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1114 oemData[KEY_Q_PROC_INFO][ss.str()][KEY_PROC_INDEX] = req->procIndex;
1115
1116 str = bytesToStr(req->data, len);
1117 oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]] = str.c_str();
1118 flushOemData();
1119
1120 return IPMI_CC_OK;
1121}
1122
1123//----------------------------------------------------------------------
1124// Get Proc Info (CMD_OEM_Q_GET_PROC_INFO)
1125//----------------------------------------------------------------------
1126// Request:
1127// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1128// Byte 4 – Processor Index, 0 base
1129// Byte 5 – Parameter Selector
1130// Response:
1131// Byte 1 – Completion code
1132// Byte 2..N – Configuration Parameter Data (see below for Parameters
1133// of Processor Information)
1134//
1135// Parameter#1: (Processor Product Name)
1136//
1137// Byte 1..48 –Product name(ASCII code)
1138// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1139//
1140// Param#2: Processor Basic Information
1141// Byte 1 – Core Number
1142// Byte 2 – Thread Number (LSB)
1143// Byte 3 – Thread Number (MSB)
1144// Byte 4 – Processor frequency in MHz (LSB)
1145// Byte 5 – Processor frequency in MHz (MSB)
1146// Byte 6..7 – Revision
1147//
1148ipmi_ret_t ipmiOemQGetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1149 ipmi_request_t request, ipmi_response_t response,
1150 ipmi_data_len_t data_len, ipmi_context_t context)
1151{
1152 qProcInfo_t *req = reinterpret_cast<qProcInfo_t *>(request);
1153 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t *);
1154 uint8_t *res = reinterpret_cast<uint8_t *>(response);
1155 std::stringstream ss;
1156 std::string str;
1157
1158 *data_len = 0;
1159
1160 /* check for requested data params */
1161 if (req->paramSel < 1 || req->paramSel >= numParam)
1162 {
1163 phosphor::logging::log<phosphor::logging::level::ERR>(
1164 "Invalid parameter received");
1165 return IPMI_CC_PARM_OUT_OF_RANGE;
1166 }
1167
1168 ss << std::hex;
1169 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1170
1171 if (oemData[KEY_Q_PROC_INFO].find(ss.str()) ==
1172 oemData[KEY_Q_PROC_INFO].end())
1173 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1174
1175 if (oemData[KEY_Q_PROC_INFO][ss.str()].find(cpuInfoKey[req->paramSel]) ==
1176 oemData[KEY_Q_PROC_INFO][ss.str()].end())
1177 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1178
1179 str = oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]];
1180 *data_len = strToBytes(str, res);
1181
1182 return IPMI_CC_OK;
1183}
1184
1185//----------------------------------------------------------------------
1186// Set Dimm Info (CMD_OEM_Q_SET_DIMM_INFO)
1187//----------------------------------------------------------------------
1188// Request:
1189// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1190// Byte 4 – DIMM Index, 0 base
1191// Byte 5 – Parameter Selector
1192// Byte 6..N – Configuration parameter data (see below for Parameters
1193// of DIMM Information)
1194// Response:
1195// Byte 1 – Completion code
1196//
1197// Param#1 (DIMM Location):
1198// Byte 1 – DIMM Present
1199// Byte 1 – DIMM Present
1200// 01h – Present
1201// FFh – Not Present
1202// Byte 2 – Node Number, 0 base
1203// Byte 3 – Channel Number , 0 base
1204// Byte 4 – DIMM Number , 0 base
1205//
1206// Param#2 (DIMM Type):
1207// Byte 1 – DIMM Type
1208// Bit [7:6]
1209// For DDR3
1210// 00 – Normal Voltage (1.5V)
1211// 01 – Ultra Low Voltage (1.25V)
1212// 10 – Low Voltage (1.35V)
1213// 11 – Reserved
1214// For DDR4
1215// 00 – Reserved
1216// 01 – Reserved
1217// 10 – Reserved
1218// 11 – Normal Voltage (1.2V)
1219// Bit [5:0]
1220// 0x00 – SDRAM
1221// 0x01 – DDR-1 RAM
1222// 0x02 – Rambus
1223// 0x03 – DDR-2 RAM
1224// 0x04 – FBDIMM
1225// 0x05 – DDR-3 RAM
1226// 0x06 – DDR-4 RAM
1227//
1228// Param#3 (DIMM Speed):
1229// Byte 1..2 – DIMM speed in MHz, LSB
1230// Byte 3..6 – DIMM size in Mbytes, LSB
1231//
1232// Param#4 (Module Part Number):
1233// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1234//
1235// Param#5 (Module Serial Number):
1236// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1237//
1238// Param#6 (Module Manufacturer ID):
1239// Byte 1 - Module Manufacturer ID, LSB
1240// Byte 2 - Module Manufacturer ID, MSB
1241//
1242ipmi_ret_t ipmiOemQSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1243 ipmi_request_t request, ipmi_response_t response,
1244 ipmi_data_len_t data_len, ipmi_context_t context)
1245{
1246 qDimmInfo_t *req = reinterpret_cast<qDimmInfo_t *>(request);
1247 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t *);
1248 std::stringstream ss;
1249 std::string str;
1250 uint8_t len = *data_len;
1251
1252 *data_len = 0;
1253
1254 /* check for requested data params */
1255 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1256 {
1257 phosphor::logging::log<phosphor::logging::level::ERR>(
1258 "Invalid parameter received");
1259 return IPMI_CC_PARM_OUT_OF_RANGE;
1260 }
1261
1262 len = len - 5; // Get Actual data length
1263
1264 ss << std::hex;
1265 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1266 oemData[KEY_Q_DIMM_INFO][ss.str()][KEY_DIMM_INDEX] = req->dimmIndex;
1267
1268 str = bytesToStr(req->data, len);
1269 oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]] =
1270 str.c_str();
1271 flushOemData();
1272
1273 return IPMI_CC_OK;
1274}
1275
1276//----------------------------------------------------------------------
1277// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
1278//----------------------------------------------------------------------
1279// Request:
1280// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1281// Byte 4 – DIMM Index, 0 base
1282// Byte 5 – Parameter Selector
1283// Byte 6..N – Configuration parameter data (see below for Parameters
1284// of DIMM Information)
1285// Response:
1286// Byte 1 – Completion code
1287// Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters
1288// of DIMM Information)
1289//
1290// Param#1 (DIMM Location):
1291// Byte 1 – DIMM Present
1292// Byte 1 – DIMM Present
1293// 01h – Present
1294// FFh – Not Present
1295// Byte 2 – Node Number, 0 base
1296// Byte 3 – Channel Number , 0 base
1297// Byte 4 – DIMM Number , 0 base
1298//
1299// Param#2 (DIMM Type):
1300// Byte 1 – DIMM Type
1301// Bit [7:6]
1302// For DDR3
1303// 00 – Normal Voltage (1.5V)
1304// 01 – Ultra Low Voltage (1.25V)
1305// 10 – Low Voltage (1.35V)
1306// 11 – Reserved
1307// For DDR4
1308// 00 – Reserved
1309// 01 – Reserved
1310// 10 – Reserved
1311// 11 – Normal Voltage (1.2V)
1312// Bit [5:0]
1313// 0x00 – SDRAM
1314// 0x01 – DDR-1 RAM
1315// 0x02 – Rambus
1316// 0x03 – DDR-2 RAM
1317// 0x04 – FBDIMM
1318// 0x05 – DDR-3 RAM
1319// 0x06 – DDR-4 RAM
1320//
1321// Param#3 (DIMM Speed):
1322// Byte 1..2 – DIMM speed in MHz, LSB
1323// Byte 3..6 – DIMM size in Mbytes, LSB
1324//
1325// Param#4 (Module Part Number):
1326// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1327//
1328// Param#5 (Module Serial Number):
1329// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1330//
1331// Param#6 (Module Manufacturer ID):
1332// Byte 1 - Module Manufacturer ID, LSB
1333// Byte 2 - Module Manufacturer ID, MSB
1334//
1335ipmi_ret_t ipmiOemQGetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1336 ipmi_request_t request, ipmi_response_t response,
1337 ipmi_data_len_t data_len, ipmi_context_t context)
1338{
1339 qDimmInfo_t *req = reinterpret_cast<qDimmInfo_t *>(request);
1340 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t *);
1341 uint8_t *res = reinterpret_cast<uint8_t *>(response);
1342 std::stringstream ss;
1343 std::string str;
1344
1345 *data_len = 0;
1346
1347 /* check for requested data params */
1348 if (req->paramSel < 1 || req->paramSel >= numParam)
1349 {
1350 phosphor::logging::log<phosphor::logging::level::ERR>(
1351 "Invalid parameter received");
1352 return IPMI_CC_PARM_OUT_OF_RANGE;
1353 }
1354
1355 ss << std::hex;
1356 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1357
1358 if (oemData[KEY_Q_DIMM_INFO].find(ss.str()) ==
1359 oemData[KEY_Q_DIMM_INFO].end())
1360 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1361
1362 if (oemData[KEY_Q_DIMM_INFO][ss.str()].find(dimmInfoKey[req->paramSel]) ==
1363 oemData[KEY_Q_DIMM_INFO][ss.str()].end())
1364 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1365
1366 str = oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]];
1367 *data_len = strToBytes(str, res);
1368
1369 return IPMI_CC_OK;
1370}
1371
1372//----------------------------------------------------------------------
1373// Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO)
1374//----------------------------------------------------------------------
1375// BIOS issue this command to provide HDD information to BMC.
1376//
1377// BIOS just can get information by standard ATA / SMART command for
1378// OB SATA controller.
1379// BIOS can get
1380// 1. Serial Number
1381// 2. Model Name
1382// 3. HDD FW Version
1383// 4. HDD Capacity
1384// 5. HDD WWN
1385//
1386// Use Get HDD info Param #5 to know the MAX HDD info index.
1387//
1388// Request:
1389// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1390// Byte 4 –
1391// [7:4] Reserved
1392// [3:0] HDD Controller Type
1393// 0x00 – BIOS
1394// 0x01 – Expander
1395// 0x02 – LSI
1396// Byte 5 – HDD Info Index, 0 base
1397// Byte 6 – Parameter Selector
1398// Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD
1399// Information)
1400//
1401// Response:
1402// Byte 1 – Completion Code
1403//
1404// Param#0 (HDD Location):
1405// Byte 1 – Controller
1406// [7:3] Device Number
1407// [2:0] Function Number
1408// For Intel C610 series (Wellsburg)
1409// D31:F2 (0xFA) – SATA control 1
1410// D31:F5 (0xFD) – SATA control 2
1411// D17:F4 (0x8C) – sSata control
1412// Byte 2 – Port Number
1413// Byte 3 – Location (0xFF: No HDD Present)
1414// BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param
1415// #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if
1416// the HDD present. BMC or other people who know the HDD location has
1417// responsibility for update Location info
1418//
1419// Param#1 (Serial Number):
1420// Bytes 1..33: HDD Serial Number
1421//
1422// Param#2 (Model Name):
1423// Byte 1..33 – HDD Model Name
1424//
1425// Param#3 (HDD FW Version):
1426// Byte 1..17 –HDD FW version
1427//
1428// Param#4 (Capacity):
1429// Byte 1..4 –HDD Block Size, LSB
1430// Byte 5..12 - HDD Block Number, LSB
1431// HDD Capacity = HDD Block size * HDD BLock number (Unit Byte)
1432//
1433// Param#5 (Max HDD Quantity):
1434// Byte 1 - Max HDD Quantity
1435// Max supported port numbers in this PCH
1436//
1437// Param#6 (HDD Type)
1438// Byte 1 – HDD Type
1439// 0h – Reserved
1440// 1h – SAS
1441// 2h – SATA
1442// 3h – PCIE SSD (NVME)
1443//
1444// Param#7 (HDD WWN)
1445// Data 1...8: HDD World Wide Name, LSB
1446//
1447ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1448 ipmi_request_t request,
1449 ipmi_response_t response,
1450 ipmi_data_len_t data_len,
1451 ipmi_context_t context)
1452{
1453 qDriveInfo_t *req = reinterpret_cast<qDriveInfo_t *>(request);
1454 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t *);
1455 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1456 std::stringstream ss;
1457 std::string str;
1458 uint8_t len = *data_len;
1459
1460 *data_len = 0;
1461
1462 /* check for requested data params */
1463 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam ||
1464 ctrlType > 2)
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 - 6; // Get Actual data length
1472
1473 ss << std::hex;
1474 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1475 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType;
1476 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] =
1477 req->hddIndex;
1478
1479 str = bytesToStr(req->data, len);
1480 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1481 [driveInfoKey[req->paramSel]] = str.c_str();
1482 flushOemData();
1483
1484 return IPMI_CC_OK;
1485}
1486
1487//----------------------------------------------------------------------
1488// Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO)
1489//----------------------------------------------------------------------
1490// BMC needs to check HDD presented or not first. If NOT presented, return
1491// completion code 0xD5.
1492//
1493// Request:
1494// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1495// Byte 4 –
1496//[7:4] Reserved
1497//[3:0] HDD Controller Type
1498// 0x00 – BIOS
1499// 0x01 – Expander
1500// 0x02 – LSI
1501// Byte 5 – HDD Index, 0 base
1502// Byte 6 – Parameter Selector (See Above Set HDD Information)
1503// Response:
1504// Byte 1 – Completion Code
1505// 0xD5 – Not support in current status (HDD Not Present)
1506// Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD
1507// Information)
1508//
1509ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1510 ipmi_request_t request,
1511 ipmi_response_t response,
1512 ipmi_data_len_t data_len,
1513 ipmi_context_t context)
1514{
1515 qDriveInfo_t *req = reinterpret_cast<qDriveInfo_t *>(request);
1516 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t *);
1517 uint8_t *res = reinterpret_cast<uint8_t *>(response);
1518 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1519 std::stringstream ss;
1520 std::string str;
1521
1522 *data_len = 0;
1523
1524 /* check for requested data params */
1525 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2)
1526 {
1527 phosphor::logging::log<phosphor::logging::level::ERR>(
1528 "Invalid parameter received");
1529 return IPMI_CC_PARM_OUT_OF_RANGE;
1530 }
1531
1532 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) ==
1533 oemData[KEY_Q_DRIVE_INFO].end())
1534 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1535
1536 ss << std::hex;
1537 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1538
1539 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) ==
1540 oemData[KEY_Q_DRIVE_INFO].end())
1541 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1542
1543 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find(
1544 dimmInfoKey[req->paramSel]) ==
1545 oemData[KEY_Q_DRIVE_INFO][ss.str()].end())
1546 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1547
1548 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1549 [dimmInfoKey[req->paramSel]];
1550 *data_len = strToBytes(str, res);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001551
1552 return IPMI_CC_OK;
1553}
1554
1555static void registerOEMFunctions(void)
1556{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001557 /* Get OEM data from json file */
1558 std::ifstream file(JSON_OEM_DATA_FILE);
1559 if (file)
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001560 {
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001561 file >> oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001562 file.close();
1563 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001564
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001565 phosphor::logging::log<phosphor::logging::level::INFO>(
1566 "Registering OEM commands");
1567 ipmiPrintAndRegister(NETFUN_CHASSIS, 1, NULL, ipmiGetChassisStatus,
1568 PRIVILEGE_USER); // get chassis status
1569 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO,
1570 NULL, ipmiOemDbgGetFrameInfo,
1571 PRIVILEGE_USER); // get debug frame info
1572 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ,
1573 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL,
1574 ipmiOemDbgGetUpdFrames,
1575 PRIVILEGE_USER); // get debug updated frames
1576 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC,
1577 NULL, ipmiOemDbgGetPostDesc,
1578 PRIVILEGE_USER); // get debug post description
1579 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC,
1580 NULL, ipmiOemDbgGetGpioDesc,
1581 PRIVILEGE_USER); // get debug gpio description
1582 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA,
1583 NULL, ipmiOemDbgGetFrameData,
1584 PRIVILEGE_USER); // get debug frame data
1585 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL,
1586 NULL, ipmiOemDbgGetCtrlPanel,
1587 PRIVILEGE_USER); // get debug control panel
1588 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL,
1589 ipmiOemSetDimmInfo,
1590 PRIVILEGE_USER); // Set Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001591 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL,
1592 ipmiOemGetBoardID,
1593 PRIVILEGE_USER); // Get Board ID
1594 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BOOT_ORDER, NULL,
1595 ipmiOemSetBootOrder,
1596 PRIVILEGE_USER); // Set Boot Order
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001597 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOOT_ORDER, NULL,
1598 ipmiOemGetBootOrder,
1599 PRIVILEGE_USER); // Get Boot Order
1600 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL,
1601 ipmiOemSetMachineCfgInfo,
1602 PRIVILEGE_USER); // Set Machine Config Info
1603 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL,
1604 ipmiOemSetPostStart,
1605 PRIVILEGE_USER); // Set POST start
1606 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL,
1607 ipmiOemSetPostEnd,
1608 PRIVILEGE_USER); // Set POST End
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001609 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL,
1610 ipmiOemSetPPINInfo,
1611 PRIVILEGE_USER); // Set PPIN Info
1612 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL,
1613 ipmiOemSetAdrTrigger,
1614 PRIVILEGE_USER); // Set ADR Trigger
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001615 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL,
1616 ipmiOemSetBiosFlashInfo,
1617 PRIVILEGE_USER); // Set Bios Flash Info
1618 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr,
1619 PRIVILEGE_USER); // Set PPR
1620 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
1621 PRIVILEGE_USER); // Get PPR
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001622 /* FB OEM QC Commands */
1623 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_PROC_INFO, NULL,
1624 ipmiOemQSetProcInfo,
1625 PRIVILEGE_USER); // Set Proc Info
1626 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL,
1627 ipmiOemQGetProcInfo,
1628 PRIVILEGE_USER); // Get Proc Info
1629 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DIMM_INFO, NULL,
1630 ipmiOemQSetDimmInfo,
1631 PRIVILEGE_USER); // Set Dimm Info
1632 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DIMM_INFO, NULL,
1633 ipmiOemQGetDimmInfo,
1634 PRIVILEGE_USER); // Get Dimm Info
1635 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
1636 ipmiOemQSetDriveInfo,
1637 PRIVILEGE_USER); // Set Drive Info
1638 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL,
1639 ipmiOemQGetDriveInfo,
1640 PRIVILEGE_USER); // Get Drive Info
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001641 return;
1642}
1643
1644} // namespace ipmi