blob: be03ca39b006ca4e6d7ffb31d2ed67f2d98852ad [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
28#include <array>
29#include <cstring>
30#include <fstream>
31#include <iomanip>
32#include <iostream>
33#include <sstream>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080034#include <string>
35#include <vector>
36
37#define SIZE_IANA_ID 3
38
39namespace ipmi
40{
Vijay Khemkaa7231892019-10-11 11:35:05 -070041
42using namespace phosphor::logging;
43
Vijay Khemkae7d23d02019-03-08 13:13:40 -080044static void registerOEMFunctions() __attribute__((constructor));
45sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
46static constexpr size_t maxFRUStringLength = 0x3F;
47
Vijay Khemka63c99be2020-05-27 19:14:35 -070048int plat_udbg_get_post_desc(uint8_t, uint8_t*, uint8_t, uint8_t*, uint8_t*,
49 uint8_t*);
50int plat_udbg_get_gpio_desc(uint8_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*,
51 uint8_t*);
52ipmi_ret_t plat_udbg_get_frame_data(uint8_t, uint8_t, uint8_t*, uint8_t*,
53 uint8_t*);
54ipmi_ret_t plat_udbg_control_panel(uint8_t, uint8_t, uint8_t, uint8_t*,
55 uint8_t*);
56int sendMeCmd(uint8_t, uint8_t, std::vector<uint8_t>&, std::vector<uint8_t>&);
Vijay Khemkadd14c0f2020-03-18 14:48:13 -070057
Vijay Khemkafeaa9812019-08-27 15:08:08 -070058nlohmann::json oemData __attribute__((init_priority(101)));
Vijay Khemka1b6fae32019-03-25 17:43:01 -070059
Vijay Khemkaf2246ce2020-05-27 14:26:35 -070060static constexpr size_t GUID_SIZE = 16;
61// TODO Make offset and location runtime configurable to ensure we
62// can make each define their own locations.
63static constexpr off_t OFFSET_SYS_GUID = 0x17F0;
64static constexpr const char* FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom";
65
Vijay Khemka1b6fae32019-03-25 17:43:01 -070066enum class LanParam : uint8_t
67{
68 INPROGRESS = 0,
69 AUTHSUPPORT = 1,
70 AUTHENABLES = 2,
71 IP = 3,
72 IPSRC = 4,
73 MAC = 5,
74 SUBNET = 6,
75 GATEWAY = 12,
76 VLAN = 20,
77 CIPHER_SUITE_COUNT = 22,
78 CIPHER_SUITE_ENTRIES = 23,
79 IPV6 = 59,
80};
81
Vijay Khemkaa7231892019-10-11 11:35:05 -070082namespace network
83{
84
85constexpr auto ROOT = "/xyz/openbmc_project/network";
86constexpr auto SERVICE = "xyz.openbmc_project.Network";
87constexpr auto IPV4_TYPE = "ipv4";
88constexpr auto IPV6_TYPE = "ipv6";
89constexpr auto IPV4_PREFIX = "169.254";
90constexpr auto IPV6_PREFIX = "fe80";
91constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
92constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
93
Vijay Khemka63c99be2020-05-27 19:14:35 -070094bool isLinkLocalIP(const std::string& address)
Vijay Khemkaa7231892019-10-11 11:35:05 -070095{
96 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0;
97}
98
Vijay Khemka63c99be2020-05-27 19:14:35 -070099DbusObjectInfo getIPObject(sdbusplus::bus::bus& bus,
100 const std::string& interface,
101 const std::string& serviceRoot,
102 const std::string& match)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700103{
104 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
105
106 if (objectTree.empty())
107 {
108 log<level::ERR>("No Object has implemented the IP interface",
109 entry("INTERFACE=%s", interface.c_str()));
110 }
111
112 DbusObjectInfo objectInfo;
113
Vijay Khemka63c99be2020-05-27 19:14:35 -0700114 for (auto& object : objectTree)
Vijay Khemkaa7231892019-10-11 11:35:05 -0700115 {
116 auto variant =
117 ipmi::getDbusProperty(bus, object.second.begin()->first,
118 object.first, IP_INTERFACE, "Address");
119
120 objectInfo = std::make_pair(object.first, object.second.begin()->first);
121
122 // if LinkLocalIP found look for Non-LinkLocalIP
123 if (isLinkLocalIP(std::get<std::string>(variant)))
124 {
125 continue;
126 }
127 else
128 {
129 break;
130 }
131 }
132 return objectInfo;
133}
134
135} // namespace network
136
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700137//----------------------------------------------------------------------
138// Helper functions for storing oem data
139//----------------------------------------------------------------------
140
141void flushOemData()
142{
143 std::ofstream file(JSON_OEM_DATA_FILE);
144 file << oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -0700145 file.close();
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700146 return;
147}
148
Vijay Khemka63c99be2020-05-27 19:14:35 -0700149std::string bytesToStr(uint8_t* byte, int len)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700150{
151 std::stringstream ss;
152 int i;
153
154 ss << std::hex;
155 for (i = 0; i < len; i++)
156 {
157 ss << std::setw(2) << std::setfill('0') << (int)byte[i];
158 }
159
160 return ss.str();
161}
162
Vijay Khemka63c99be2020-05-27 19:14:35 -0700163int strToBytes(std::string& str, uint8_t* data)
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700164{
165 std::string sstr;
166 int i;
167
168 for (i = 0; i < (str.length()) / 2; i++)
169 {
170 sstr = str.substr(i * 2, 2);
171 data[i] = (uint8_t)std::strtol(sstr.c_str(), NULL, 16);
172 }
173 return i;
174}
175
Vijay Khemka63c99be2020-05-27 19:14:35 -0700176ipmi_ret_t getNetworkData(uint8_t lan_param, char* data)
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700177{
178 ipmi_ret_t rc = IPMI_CC_OK;
179 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
180
181 const std::string ethdevice = "eth0";
182
183 switch (static_cast<LanParam>(lan_param))
184 {
Vijay Khemkad1194022020-05-27 18:58:33 -0700185 case LanParam::IP:
186 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700187 auto ethIP = ethdevice + "/" + ipmi::network::IPV4_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700188 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700189 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700190 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
191
192 auto properties = ipmi::getAllDbusProperties(
193 bus, ipObjectInfo.second, ipObjectInfo.first,
194 ipmi::network::IP_INTERFACE);
195
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500196 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700197
198 std::strcpy(data, ipaddress.c_str());
199 }
200 break;
201
Vijay Khemkad1194022020-05-27 18:58:33 -0700202 case LanParam::IPV6:
203 {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700204 auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700205 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700206 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700207 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
208
209 auto properties = ipmi::getAllDbusProperties(
210 bus, ipObjectInfo.second, ipObjectInfo.first,
211 ipmi::network::IP_INTERFACE);
212
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500213 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700214
215 std::strcpy(data, ipaddress.c_str());
216 }
217 break;
218
Vijay Khemkad1194022020-05-27 18:58:33 -0700219 case LanParam::MAC:
220 {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700221 std::string macAddress;
222 auto macObjectInfo =
223 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
224 ipmi::network::ROOT, ethdevice);
225
226 auto variant = ipmi::getDbusProperty(
227 bus, macObjectInfo.second, macObjectInfo.first,
228 ipmi::network::MAC_INTERFACE, "MACAddress");
229
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500230 macAddress = std::get<std::string>(variant);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700231
232 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
233 (data), (data + 1), (data + 2), (data + 3), (data + 4),
234 (data + 5));
235 std::strcpy(data, macAddress.c_str());
236 }
237 break;
238
239 default:
240 rc = IPMI_CC_PARM_OUT_OF_RANGE;
241 }
242 return rc;
243}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800244
245// return code: 0 successful
Vijay Khemka63c99be2020-05-27 19:14:35 -0700246int8_t getFruData(std::string& data, std::string& name)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800247{
248 std::string objpath = "/xyz/openbmc_project/FruDevice";
249 std::string intf = "xyz.openbmc_project.FruDeviceManager";
250 std::string service = getService(dbus, intf, objpath);
251 ObjectValueTree valueTree = getManagedObjects(dbus, service, "/");
252 if (valueTree.empty())
253 {
254 phosphor::logging::log<phosphor::logging::level::ERR>(
255 "No object implements interface",
256 phosphor::logging::entry("INTF=%s", intf.c_str()));
257 return -1;
258 }
259
Vijay Khemka63c99be2020-05-27 19:14:35 -0700260 for (const auto& item : valueTree)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800261 {
262 auto interface = item.second.find("xyz.openbmc_project.FruDevice");
263 if (interface == item.second.end())
264 {
265 continue;
266 }
267
268 auto property = interface->second.find(name.c_str());
269 if (property == interface->second.end())
270 {
271 continue;
272 }
273
274 try
275 {
276 Value variant = property->second;
Vijay Khemka63c99be2020-05-27 19:14:35 -0700277 std::string& result = std::get<std::string>(variant);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800278 if (result.size() > maxFRUStringLength)
279 {
280 phosphor::logging::log<phosphor::logging::level::ERR>(
281 "FRU serial number exceed maximum length");
282 return -1;
283 }
284 data = result;
285 return 0;
286 }
Vijay Khemka63c99be2020-05-27 19:14:35 -0700287 catch (std::bad_variant_access& e)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800288 {
289 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
290 return -1;
291 }
292 }
293 return -1;
294}
295
296typedef struct
297{
298 uint8_t cur_power_state;
299 uint8_t last_power_event;
300 uint8_t misc_power_state;
301 uint8_t front_panel_button_cap_status;
302} ipmi_get_chassis_status_t;
303
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800304//----------------------------------------------------------------------
305// Get Debug Frame Info
306//----------------------------------------------------------------------
307ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
308 ipmi_request_t request,
309 ipmi_response_t response,
310 ipmi_data_len_t data_len,
311 ipmi_context_t context)
312{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700313 uint8_t* req = reinterpret_cast<uint8_t*>(request);
314 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800315 uint8_t num_frames = 3;
316
317 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
318 res[SIZE_IANA_ID] = num_frames;
319 *data_len = SIZE_IANA_ID + 1;
320
321 return IPMI_CC_OK;
322}
323
324//----------------------------------------------------------------------
325// Get Debug Updated Frames
326//----------------------------------------------------------------------
327ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
328 ipmi_request_t request,
329 ipmi_response_t response,
330 ipmi_data_len_t data_len,
331 ipmi_context_t context)
332{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700333 uint8_t* req = reinterpret_cast<uint8_t*>(request);
334 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800335 uint8_t num_updates = 3;
336 *data_len = 4;
337
338 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
339 res[SIZE_IANA_ID] = num_updates;
340 *data_len = SIZE_IANA_ID + num_updates + 1;
341 res[SIZE_IANA_ID + 1] = 1; // info page update
342 res[SIZE_IANA_ID + 2] = 2; // cri sel update
343 res[SIZE_IANA_ID + 3] = 3; // cri sensor update
344
345 return IPMI_CC_OK;
346}
347
348//----------------------------------------------------------------------
349// Get Debug POST Description
350//----------------------------------------------------------------------
351ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
352 ipmi_request_t request,
353 ipmi_response_t response,
354 ipmi_data_len_t data_len,
355 ipmi_context_t context)
356{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700357 uint8_t* req = reinterpret_cast<uint8_t*>(request);
358 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800359 uint8_t index = 0;
360 uint8_t next = 0;
361 uint8_t end = 0;
362 uint8_t phase = 0;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700363 uint8_t descLen = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800364 int ret;
365
366 index = req[3];
367 phase = req[4];
368
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700369 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800370 if (ret)
371 {
372 memcpy(res, req, SIZE_IANA_ID); // IANA ID
373 *data_len = SIZE_IANA_ID;
374 return IPMI_CC_UNSPECIFIED_ERROR;
375 }
376
377 memcpy(res, req, SIZE_IANA_ID); // IANA ID
378 res[3] = index;
379 res[4] = next;
380 res[5] = phase;
381 res[6] = end;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700382 res[7] = descLen;
383 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800384
385 return IPMI_CC_OK;
386}
387
388//----------------------------------------------------------------------
389// Get Debug GPIO Description
390//----------------------------------------------------------------------
391ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
392 ipmi_request_t request,
393 ipmi_response_t response,
394 ipmi_data_len_t data_len,
395 ipmi_context_t context)
396{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700397 uint8_t* req = reinterpret_cast<uint8_t*>(request);
398 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800399
Vijay Khemka38183d62019-08-28 16:19:33 -0700400 uint8_t index = 0;
401 uint8_t next = 0;
402 uint8_t level = 0;
403 uint8_t pinDef = 0;
404 uint8_t descLen = 0;
405 int ret;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800406
Vijay Khemka38183d62019-08-28 16:19:33 -0700407 index = req[3];
408
409 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen,
410 &res[8]);
411 if (ret)
412 {
413 memcpy(res, req, SIZE_IANA_ID); // IANA ID
414 *data_len = SIZE_IANA_ID;
415 return IPMI_CC_UNSPECIFIED_ERROR;
416 }
417
418 memcpy(res, req, SIZE_IANA_ID); // IANA ID
419 res[3] = index;
420 res[4] = next;
421 res[5] = level;
422 res[6] = pinDef;
423 res[7] = descLen;
424 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800425
426 return IPMI_CC_OK;
427}
428
429//----------------------------------------------------------------------
430// Get Debug Frame Data
431//----------------------------------------------------------------------
432ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
433 ipmi_request_t request,
434 ipmi_response_t response,
435 ipmi_data_len_t data_len,
436 ipmi_context_t context)
437{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700438 uint8_t* req = reinterpret_cast<uint8_t*>(request);
439 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800440 uint8_t frame;
441 uint8_t page;
442 uint8_t next;
443 uint8_t count;
444 int ret;
445
446 frame = req[3];
447 page = req[4];
448 int fr = frame;
449 int pg = page;
450
451 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]);
452 if (ret)
453 {
454 memcpy(res, req, SIZE_IANA_ID); // IANA ID
455 *data_len = SIZE_IANA_ID;
456 return IPMI_CC_UNSPECIFIED_ERROR;
457 }
458
459 memcpy(res, req, SIZE_IANA_ID); // IANA ID
460 res[3] = frame;
461 res[4] = page;
462 res[5] = next;
463 res[6] = count;
464 *data_len = SIZE_IANA_ID + 4 + count;
465
466 return IPMI_CC_OK;
467}
468
469//----------------------------------------------------------------------
470// Get Debug Control Panel
471//----------------------------------------------------------------------
472ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
473 ipmi_request_t request,
474 ipmi_response_t response,
475 ipmi_data_len_t data_len,
476 ipmi_context_t context)
477{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700478 uint8_t* req = reinterpret_cast<uint8_t*>(request);
479 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800480
481 uint8_t panel;
482 uint8_t operation;
483 uint8_t item;
484 uint8_t count;
485 ipmi_ret_t ret;
486
487 panel = req[3];
488 operation = req[4];
489 item = req[5];
490
491 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]);
492
493 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
494 *data_len = SIZE_IANA_ID + count;
495
496 return ret;
497}
498
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800499//----------------------------------------------------------------------
500// Set Dimm Info (CMD_OEM_SET_DIMM_INFO)
501//----------------------------------------------------------------------
502ipmi_ret_t ipmiOemSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
503 ipmi_request_t request, ipmi_response_t response,
504 ipmi_data_len_t data_len, ipmi_context_t context)
505{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700506 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700507
508 uint8_t index = req[0];
509 uint8_t type = req[1];
510 uint16_t speed;
511 uint32_t size;
512
513 memcpy(&speed, &req[2], 2);
514 memcpy(&size, &req[4], 4);
515
516 std::stringstream ss;
517 ss << std::hex;
518 ss << std::setw(2) << std::setfill('0') << (int)index;
519
520 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index;
521 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type;
522 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed;
523 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size;
524
525 flushOemData();
526
527 *data_len = 0;
528
529 return IPMI_CC_OK;
530}
531
532//----------------------------------------------------------------------
533// Get Board ID (CMD_OEM_GET_BOARD_ID)
534//----------------------------------------------------------------------
535ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
536 ipmi_request_t request, ipmi_response_t response,
537 ipmi_data_len_t data_len, ipmi_context_t context)
538{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700539 uint8_t* req = reinterpret_cast<uint8_t*>(request);
540 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800541
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700542 /* TODO: Needs to implement this after GPIO implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800543 *data_len = 0;
544
545 return IPMI_CC_OK;
546}
547
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800548/* Helper functions to set boot order */
Vijay Khemka63c99be2020-05-27 19:14:35 -0700549void setBootOrder(uint8_t* data)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800550{
551 nlohmann::json bootMode;
552 uint8_t mode = data[0];
553 int i;
554
555 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false);
556 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false);
557 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false);
558 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false);
559 oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE] = bootMode;
560
561 /* Initialize boot sequence array */
562 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ] = {};
563 for (i = 1; i < SIZE_BOOT_ORDER; i++)
564 {
565 if (data[i] >= BOOT_SEQ_ARRAY_SIZE)
566 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1] = "NA";
567 else
568 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1] = bootSeq[data[i]];
569 }
570
571 flushOemData();
572}
573
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800574//----------------------------------------------------------------------
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700575// Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
576//----------------------------------------------------------------------
577ipmi_ret_t ipmiOemSetBootOrder(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
578 ipmi_request_t request, ipmi_response_t response,
579 ipmi_data_len_t data_len, ipmi_context_t context)
580{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700581 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700582 uint8_t len = *data_len;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700583
584 *data_len = 0;
585
586 if (len != SIZE_BOOT_ORDER)
587 {
588 phosphor::logging::log<phosphor::logging::level::ERR>(
589 "Invalid Boot order length received");
590 return IPMI_CC_REQ_DATA_LEN_INVALID;
591 }
592
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800593 setBootOrder(req);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700594
595 return IPMI_CC_OK;
596}
597
598//----------------------------------------------------------------------
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800599// Get Boot Order (CMD_OEM_GET_BOOT_ORDER)
600//----------------------------------------------------------------------
601ipmi_ret_t ipmiOemGetBootOrder(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
602 ipmi_request_t request, ipmi_response_t response,
603 ipmi_data_len_t data_len, ipmi_context_t context)
604{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700605 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700606 uint8_t mode = 0;
607 int i;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800608
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700609 *data_len = SIZE_BOOT_ORDER;
610
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800611 if (oemData.find(KEY_BOOT_ORDER) == oemData.end())
612 {
613 /* Return default boot order 0100090203ff */
614 uint8_t defaultBoot[SIZE_BOOT_ORDER] = {
615 BOOT_MODE_UEFI, bootMap["USB_DEV"], bootMap["NET_IPV6"],
616 bootMap["SATA_HDD"], bootMap["SATA_CD"], 0xff};
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700617
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800618 memcpy(res, defaultBoot, SIZE_BOOT_ORDER);
619 phosphor::logging::log<phosphor::logging::level::INFO>(
620 "Set default boot order");
621 setBootOrder(defaultBoot);
622 }
623 else
624 {
625 nlohmann::json bootMode = oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE];
626 if (bootMode["UEFI"])
627 mode |= BOOT_MODE_UEFI;
628 if (bootMode["CMOS_CLR"])
629 mode |= BOOT_MODE_CMOS_CLR;
630 if (bootMode["BOOT_FLAG"])
631 mode |= BOOT_MODE_BOOT_FLAG;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700632
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800633 res[0] = mode;
634
635 for (i = 1; i < SIZE_BOOT_ORDER; i++)
636 {
637 std::string seqStr = oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1];
638 if (bootMap.find(seqStr) != bootMap.end())
639 res[i] = bootMap[seqStr];
640 else
641 res[i] = 0xff;
642 }
643 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800644
645 return IPMI_CC_OK;
646}
647
648//----------------------------------------------------------------------
649// Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO)
650//----------------------------------------------------------------------
651ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
652 ipmi_request_t request,
653 ipmi_response_t response,
654 ipmi_data_len_t data_len,
655 ipmi_context_t context)
656{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700657 machineConfigInfo_t* req = reinterpret_cast<machineConfigInfo_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700658 uint8_t len = *data_len;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800659
660 *data_len = 0;
661
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700662 if (len < sizeof(machineConfigInfo_t))
663 {
664 phosphor::logging::log<phosphor::logging::level::ERR>(
665 "Invalid machine configuration length received");
666 return IPMI_CC_REQ_DATA_LEN_INVALID;
667 }
668
Vijay Khemka63c99be2020-05-27 19:14:35 -0700669 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700670 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN";
671 else
672 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] =
673 chassisType[req->chassis_type];
674
Vijay Khemka63c99be2020-05-27 19:14:35 -0700675 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700676 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN";
677 else
678 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type];
679
680 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt;
681 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt;
682 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt;
683 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt;
684
Vijay Khemka63c99be2020-05-27 19:14:35 -0700685 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700686 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN";
687 else
688 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type];
689
690 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {};
691 int i = 0;
692 if (req->pcie_card_loc & BIT_0)
693 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1";
694 if (req->pcie_card_loc & BIT_1)
695 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2";
696 if (req->pcie_card_loc & BIT_2)
697 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3";
698 if (req->pcie_card_loc & BIT_3)
699 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4";
700
Vijay Khemka63c99be2020-05-27 19:14:35 -0700701 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700702 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN";
703 else
704 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] =
705 pcieType[req->slot1_pcie_type];
706
Vijay Khemka63c99be2020-05-27 19:14:35 -0700707 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700708 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN";
709 else
710 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] =
711 pcieType[req->slot2_pcie_type];
712
Vijay Khemka63c99be2020-05-27 19:14:35 -0700713 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700714 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN";
715 else
716 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] =
717 pcieType[req->slot3_pcie_type];
718
Vijay Khemka63c99be2020-05-27 19:14:35 -0700719 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700720 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN";
721 else
722 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] =
723 pcieType[req->slot4_pcie_type];
724
725 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt;
726
727 flushOemData();
728
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800729 return IPMI_CC_OK;
730}
731
732//----------------------------------------------------------------------
733// Set POST start (CMD_OEM_SET_POST_START)
734//----------------------------------------------------------------------
735ipmi_ret_t ipmiOemSetPostStart(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
736 ipmi_request_t request, ipmi_response_t response,
737 ipmi_data_len_t data_len, ipmi_context_t context)
738{
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800739 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event");
740
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700741 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800742 *data_len = 0;
743 return IPMI_CC_OK;
744}
745
746//----------------------------------------------------------------------
747// Set POST End (CMD_OEM_SET_POST_END)
748//----------------------------------------------------------------------
749ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
750 ipmi_request_t request, ipmi_response_t response,
751 ipmi_data_len_t data_len, ipmi_context_t context)
752{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700753 struct timespec ts;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800754
755 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event");
756
757 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700758
759 // Timestamp post end time.
760 clock_gettime(CLOCK_REALTIME, &ts);
761 oemData[KEY_TS_SLED] = ts.tv_sec;
762 flushOemData();
763
764 // Sync time with system
765 // TODO: Add code for syncing time
766
767 return IPMI_CC_OK;
768}
769
770//----------------------------------------------------------------------
771// Set PPIN Info (CMD_OEM_SET_PPIN_INFO)
772//----------------------------------------------------------------------
773// Inform BMC about PPIN data of 8 bytes for each CPU
774//
775// Request:
776// Byte 1:8 – CPU0 PPIN data
777// Optional:
778// Byte 9:16 – CPU1 PPIN data
779//
780// Response:
781// Byte 1 – Completion Code
782ipmi_ret_t ipmiOemSetPPINInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
783 ipmi_request_t request, ipmi_response_t response,
784 ipmi_data_len_t data_len, ipmi_context_t context)
785{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700786 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700787 std::string ppinStr;
788 int len;
789
790 if (*data_len > SIZE_CPU_PPIN * 2)
791 len = SIZE_CPU_PPIN * 2;
792 else
793 len = *data_len;
794 *data_len = 0;
795
796 ppinStr = bytesToStr(req, len);
797 oemData[KEY_PPIN_INFO] = ppinStr.c_str();
798 flushOemData();
799
800 return IPMI_CC_OK;
801}
802
803//----------------------------------------------------------------------
804// Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER)
805//----------------------------------------------------------------------
806ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
807 ipmi_request_t request,
808 ipmi_response_t response,
809 ipmi_data_len_t data_len,
810 ipmi_context_t context)
811{
812 /* Do nothing, return success */
813 *data_len = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800814 return IPMI_CC_OK;
815}
816
Vijay Khemkaf2246ce2020-05-27 14:26:35 -0700817// Helper function to set guid at offset in EEPROM
818static int setGUID(off_t offset, uint8_t* guid)
819{
820 int fd = -1;
821 ssize_t len;
822 int ret = 0;
823
824 errno = 0;
825
826 // Check if file is present
827 if (access(FRU_EEPROM, F_OK) == -1)
828 {
829 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl;
830 return errno;
831 }
832
833 // Open the file
834 fd = open(FRU_EEPROM, O_WRONLY);
835 if (fd == -1)
836 {
837 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl;
838 return errno;
839 }
840
841 // seek to the offset
842 lseek(fd, offset, SEEK_SET);
843
844 // Write bytes to location
845 len = write(fd, guid, GUID_SIZE);
846 if (len != GUID_SIZE)
847 {
848 phosphor::logging::log<phosphor::logging::level::ERR>(
849 "GUID write data to EEPROM failed");
850 ret = errno;
851 }
852
853 close(fd);
854 return ret;
855}
856
857//----------------------------------------------------------------------
858// Set System GUID (CMD_OEM_SET_SYSTEM_GUID)
859//----------------------------------------------------------------------
860ipmi_ret_t ipmiOemSetSystemGuid(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 uint8_t* req = reinterpret_cast<uint8_t*>(request);
867
868 if (*data_len != GUID_SIZE) // 16bytes
869 {
870 *data_len = 0;
871 return IPMI_CC_REQ_DATA_LEN_INVALID;
872 }
873
874 *data_len = 0;
875
876 if (setGUID(OFFSET_SYS_GUID, req))
877 {
878 return IPMI_CC_UNSPECIFIED_ERROR;
879 }
880 return IPMI_CC_OK;
881}
882
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800883//----------------------------------------------------------------------
884// Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO)
885//----------------------------------------------------------------------
886ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
887 ipmi_request_t request,
888 ipmi_response_t response,
889 ipmi_data_len_t data_len,
890 ipmi_context_t context)
891{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700892 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800893 *data_len = 0;
894 return IPMI_CC_OK;
895}
896
897//----------------------------------------------------------------------
898// Set PPR (CMD_OEM_SET_PPR)
899//----------------------------------------------------------------------
900ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
901 ipmi_request_t request, ipmi_response_t response,
902 ipmi_data_len_t data_len, ipmi_context_t context)
903{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700904 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700905 uint8_t pprCnt, pprAct, pprIndex;
906 uint8_t selParam = req[0];
907 uint8_t len = *data_len;
908 std::stringstream ss;
909 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800910
911 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700912
913 switch (selParam)
914 {
915 case PPR_ACTION:
916 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) ==
917 oemData[KEY_PPR].end())
918 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
919
920 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
921 if (pprCnt == 0)
922 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
923
924 pprAct = req[1];
925 /* Check if ppr is enabled or disabled */
926 if (!(pprAct & 0x80))
927 pprAct = 0;
928
929 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct;
930 break;
931 case PPR_ROW_COUNT:
932 if (req[1] > 100)
933 return IPMI_CC_PARM_OUT_OF_RANGE;
934
935 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1];
936 break;
937 case PPR_ROW_ADDR:
938 pprIndex = req[1];
939 if (pprIndex > 100)
940 return IPMI_CC_PARM_OUT_OF_RANGE;
941
942 if (len < PPR_ROW_ADDR_LEN + 1)
943 {
944 phosphor::logging::log<phosphor::logging::level::ERR>(
945 "Invalid PPR Row Address length received");
946 return IPMI_CC_REQ_DATA_LEN_INVALID;
947 }
948
949 ss << std::hex;
950 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
951
952 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
953
954 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN);
955 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str();
956 break;
957 case PPR_HISTORY_DATA:
958 pprIndex = req[1];
959 if (pprIndex > 100)
960 return IPMI_CC_PARM_OUT_OF_RANGE;
961
962 if (len < PPR_HST_DATA_LEN + 1)
963 {
964 phosphor::logging::log<phosphor::logging::level::ERR>(
965 "Invalid PPR history data length received");
966 return IPMI_CC_REQ_DATA_LEN_INVALID;
967 }
968
969 ss << std::hex;
970 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
971
972 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
973
974 str = bytesToStr(&req[1], PPR_HST_DATA_LEN);
975 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str();
976 break;
977 default:
978 return IPMI_CC_PARM_OUT_OF_RANGE;
979 break;
980 }
981
982 flushOemData();
983
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800984 return IPMI_CC_OK;
985}
986
987//----------------------------------------------------------------------
988// Get PPR (CMD_OEM_GET_PPR)
989//----------------------------------------------------------------------
990ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
991 ipmi_request_t request, ipmi_response_t response,
992 ipmi_data_len_t data_len, ipmi_context_t context)
993{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700994 uint8_t* req = reinterpret_cast<uint8_t*>(request);
995 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700996 uint8_t pprCnt, pprIndex;
997 uint8_t selParam = req[0];
998 std::stringstream ss;
999 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001000
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001001 /* Any failure will return zero length data */
1002 *data_len = 0;
1003
1004 switch (selParam)
1005 {
1006 case PPR_ACTION:
1007 res[0] = 0;
1008 *data_len = 1;
1009
1010 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1011 oemData[KEY_PPR].end())
1012 {
1013 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1014 if (pprCnt != 0)
1015 {
1016 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) !=
1017 oemData[KEY_PPR].end())
1018 {
1019 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION];
1020 }
1021 }
1022 }
1023 break;
1024 case PPR_ROW_COUNT:
1025 res[0] = 0;
1026 *data_len = 1;
1027 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1028 oemData[KEY_PPR].end())
1029 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1030 break;
1031 case PPR_ROW_ADDR:
1032 pprIndex = req[1];
1033 if (pprIndex > 100)
1034 return IPMI_CC_PARM_OUT_OF_RANGE;
1035
1036 ss << std::hex;
1037 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1038
1039 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1040 return IPMI_CC_PARM_OUT_OF_RANGE;
1041
1042 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) ==
1043 oemData[KEY_PPR][ss.str()].end())
1044 return IPMI_CC_PARM_OUT_OF_RANGE;
1045
1046 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR];
1047 *data_len = strToBytes(str, res);
1048 break;
1049 case PPR_HISTORY_DATA:
1050 pprIndex = req[1];
1051 if (pprIndex > 100)
1052 return IPMI_CC_PARM_OUT_OF_RANGE;
1053
1054 ss << std::hex;
1055 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1056
1057 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1058 return IPMI_CC_PARM_OUT_OF_RANGE;
1059
1060 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) ==
1061 oemData[KEY_PPR][ss.str()].end())
1062 return IPMI_CC_PARM_OUT_OF_RANGE;
1063
1064 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA];
1065 *data_len = strToBytes(str, res);
1066 break;
1067 default:
1068 return IPMI_CC_PARM_OUT_OF_RANGE;
1069 break;
1070 }
1071
1072 return IPMI_CC_OK;
1073}
1074
1075/* FB OEM QC Commands */
1076
1077//----------------------------------------------------------------------
1078// Set Proc Info (CMD_OEM_Q_SET_PROC_INFO)
1079//----------------------------------------------------------------------
1080//"Request:
1081// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1082// Byte 4 – Processor Index, 0 base
1083// Byte 5 – Parameter Selector
1084// Byte 6..N – Configuration parameter data (see below for Parameters
1085// of Processor Information)
1086// Response:
1087// Byte 1 – Completion code
1088//
1089// Parameter#1: (Processor Product Name)
1090//
1091// Byte 1..48 –Product name(ASCII code)
1092// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1093//
1094// Param#2: Processor Basic Information
1095// Byte 1 – Core Number
1096// Byte 2 – Thread Number (LSB)
1097// Byte 3 – Thread Number (MSB)
1098// Byte 4 – Processor frequency in MHz (LSB)
1099// Byte 5 – Processor frequency in MHz (MSB)
1100// Byte 6..7 – Revision
1101//
1102ipmi_ret_t ipmiOemQSetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1103 ipmi_request_t request, ipmi_response_t response,
1104 ipmi_data_len_t data_len, ipmi_context_t context)
1105{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001106 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1107 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001108 std::stringstream ss;
1109 std::string str;
1110 uint8_t len = *data_len;
1111
1112 *data_len = 0;
1113
1114 /* check for requested data params */
1115 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1116 {
1117 phosphor::logging::log<phosphor::logging::level::ERR>(
1118 "Invalid parameter received");
1119 return IPMI_CC_PARM_OUT_OF_RANGE;
1120 }
1121
1122 len = len - 5; // Get Actual data length
1123
1124 ss << std::hex;
1125 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1126 oemData[KEY_Q_PROC_INFO][ss.str()][KEY_PROC_INDEX] = req->procIndex;
1127
1128 str = bytesToStr(req->data, len);
1129 oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]] = str.c_str();
1130 flushOemData();
1131
1132 return IPMI_CC_OK;
1133}
1134
1135//----------------------------------------------------------------------
1136// Get Proc Info (CMD_OEM_Q_GET_PROC_INFO)
1137//----------------------------------------------------------------------
1138// Request:
1139// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1140// Byte 4 – Processor Index, 0 base
1141// Byte 5 – Parameter Selector
1142// Response:
1143// Byte 1 – Completion code
1144// Byte 2..N – Configuration Parameter Data (see below for Parameters
1145// of Processor Information)
1146//
1147// Parameter#1: (Processor Product Name)
1148//
1149// Byte 1..48 –Product name(ASCII code)
1150// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1151//
1152// Param#2: Processor Basic Information
1153// Byte 1 – Core Number
1154// Byte 2 – Thread Number (LSB)
1155// Byte 3 – Thread Number (MSB)
1156// Byte 4 – Processor frequency in MHz (LSB)
1157// Byte 5 – Processor frequency in MHz (MSB)
1158// Byte 6..7 – Revision
1159//
1160ipmi_ret_t ipmiOemQGetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1161 ipmi_request_t request, ipmi_response_t response,
1162 ipmi_data_len_t data_len, ipmi_context_t context)
1163{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001164 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1165 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
1166 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001167 std::stringstream ss;
1168 std::string str;
1169
1170 *data_len = 0;
1171
1172 /* check for requested data params */
1173 if (req->paramSel < 1 || req->paramSel >= numParam)
1174 {
1175 phosphor::logging::log<phosphor::logging::level::ERR>(
1176 "Invalid parameter received");
1177 return IPMI_CC_PARM_OUT_OF_RANGE;
1178 }
1179
1180 ss << std::hex;
1181 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1182
1183 if (oemData[KEY_Q_PROC_INFO].find(ss.str()) ==
1184 oemData[KEY_Q_PROC_INFO].end())
1185 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1186
1187 if (oemData[KEY_Q_PROC_INFO][ss.str()].find(cpuInfoKey[req->paramSel]) ==
1188 oemData[KEY_Q_PROC_INFO][ss.str()].end())
1189 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1190
1191 str = oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]];
1192 *data_len = strToBytes(str, res);
1193
1194 return IPMI_CC_OK;
1195}
1196
1197//----------------------------------------------------------------------
1198// Set Dimm Info (CMD_OEM_Q_SET_DIMM_INFO)
1199//----------------------------------------------------------------------
1200// Request:
1201// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1202// Byte 4 – DIMM Index, 0 base
1203// Byte 5 – Parameter Selector
1204// Byte 6..N – Configuration parameter data (see below for Parameters
1205// of DIMM Information)
1206// Response:
1207// Byte 1 – Completion code
1208//
1209// Param#1 (DIMM Location):
1210// Byte 1 – DIMM Present
1211// Byte 1 – DIMM Present
1212// 01h – Present
1213// FFh – Not Present
1214// Byte 2 – Node Number, 0 base
1215// Byte 3 – Channel Number , 0 base
1216// Byte 4 – DIMM Number , 0 base
1217//
1218// Param#2 (DIMM Type):
1219// Byte 1 – DIMM Type
1220// Bit [7:6]
1221// For DDR3
1222// 00 – Normal Voltage (1.5V)
1223// 01 – Ultra Low Voltage (1.25V)
1224// 10 – Low Voltage (1.35V)
1225// 11 – Reserved
1226// For DDR4
1227// 00 – Reserved
1228// 01 – Reserved
1229// 10 – Reserved
1230// 11 – Normal Voltage (1.2V)
1231// Bit [5:0]
1232// 0x00 – SDRAM
1233// 0x01 – DDR-1 RAM
1234// 0x02 – Rambus
1235// 0x03 – DDR-2 RAM
1236// 0x04 – FBDIMM
1237// 0x05 – DDR-3 RAM
1238// 0x06 – DDR-4 RAM
1239//
1240// Param#3 (DIMM Speed):
1241// Byte 1..2 – DIMM speed in MHz, LSB
1242// Byte 3..6 – DIMM size in Mbytes, LSB
1243//
1244// Param#4 (Module Part Number):
1245// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1246//
1247// Param#5 (Module Serial Number):
1248// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1249//
1250// Param#6 (Module Manufacturer ID):
1251// Byte 1 - Module Manufacturer ID, LSB
1252// Byte 2 - Module Manufacturer ID, MSB
1253//
1254ipmi_ret_t ipmiOemQSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1255 ipmi_request_t request, ipmi_response_t response,
1256 ipmi_data_len_t data_len, ipmi_context_t context)
1257{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001258 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1259 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001260 std::stringstream ss;
1261 std::string str;
1262 uint8_t len = *data_len;
1263
1264 *data_len = 0;
1265
1266 /* check for requested data params */
1267 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1268 {
1269 phosphor::logging::log<phosphor::logging::level::ERR>(
1270 "Invalid parameter received");
1271 return IPMI_CC_PARM_OUT_OF_RANGE;
1272 }
1273
1274 len = len - 5; // Get Actual data length
1275
1276 ss << std::hex;
1277 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1278 oemData[KEY_Q_DIMM_INFO][ss.str()][KEY_DIMM_INDEX] = req->dimmIndex;
1279
1280 str = bytesToStr(req->data, len);
1281 oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]] =
1282 str.c_str();
1283 flushOemData();
1284
1285 return IPMI_CC_OK;
1286}
1287
1288//----------------------------------------------------------------------
1289// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
1290//----------------------------------------------------------------------
1291// Request:
1292// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1293// Byte 4 – DIMM Index, 0 base
1294// Byte 5 – Parameter Selector
1295// Byte 6..N – Configuration parameter data (see below for Parameters
1296// of DIMM Information)
1297// Response:
1298// Byte 1 – Completion code
1299// Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters
1300// of DIMM Information)
1301//
1302// Param#1 (DIMM Location):
1303// Byte 1 – DIMM Present
1304// Byte 1 – DIMM Present
1305// 01h – Present
1306// FFh – Not Present
1307// Byte 2 – Node Number, 0 base
1308// Byte 3 – Channel Number , 0 base
1309// Byte 4 – DIMM Number , 0 base
1310//
1311// Param#2 (DIMM Type):
1312// Byte 1 – DIMM Type
1313// Bit [7:6]
1314// For DDR3
1315// 00 – Normal Voltage (1.5V)
1316// 01 – Ultra Low Voltage (1.25V)
1317// 10 – Low Voltage (1.35V)
1318// 11 – Reserved
1319// For DDR4
1320// 00 – Reserved
1321// 01 – Reserved
1322// 10 – Reserved
1323// 11 – Normal Voltage (1.2V)
1324// Bit [5:0]
1325// 0x00 – SDRAM
1326// 0x01 – DDR-1 RAM
1327// 0x02 – Rambus
1328// 0x03 – DDR-2 RAM
1329// 0x04 – FBDIMM
1330// 0x05 – DDR-3 RAM
1331// 0x06 – DDR-4 RAM
1332//
1333// Param#3 (DIMM Speed):
1334// Byte 1..2 – DIMM speed in MHz, LSB
1335// Byte 3..6 – DIMM size in Mbytes, LSB
1336//
1337// Param#4 (Module Part Number):
1338// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1339//
1340// Param#5 (Module Serial Number):
1341// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1342//
1343// Param#6 (Module Manufacturer ID):
1344// Byte 1 - Module Manufacturer ID, LSB
1345// Byte 2 - Module Manufacturer ID, MSB
1346//
1347ipmi_ret_t ipmiOemQGetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1348 ipmi_request_t request, ipmi_response_t response,
1349 ipmi_data_len_t data_len, ipmi_context_t context)
1350{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001351 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1352 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
1353 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001354 std::stringstream ss;
1355 std::string str;
1356
1357 *data_len = 0;
1358
1359 /* check for requested data params */
1360 if (req->paramSel < 1 || req->paramSel >= numParam)
1361 {
1362 phosphor::logging::log<phosphor::logging::level::ERR>(
1363 "Invalid parameter received");
1364 return IPMI_CC_PARM_OUT_OF_RANGE;
1365 }
1366
1367 ss << std::hex;
1368 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1369
1370 if (oemData[KEY_Q_DIMM_INFO].find(ss.str()) ==
1371 oemData[KEY_Q_DIMM_INFO].end())
1372 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1373
1374 if (oemData[KEY_Q_DIMM_INFO][ss.str()].find(dimmInfoKey[req->paramSel]) ==
1375 oemData[KEY_Q_DIMM_INFO][ss.str()].end())
1376 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1377
1378 str = oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]];
1379 *data_len = strToBytes(str, res);
1380
1381 return IPMI_CC_OK;
1382}
1383
1384//----------------------------------------------------------------------
1385// Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO)
1386//----------------------------------------------------------------------
1387// BIOS issue this command to provide HDD information to BMC.
1388//
1389// BIOS just can get information by standard ATA / SMART command for
1390// OB SATA controller.
1391// BIOS can get
1392// 1. Serial Number
1393// 2. Model Name
1394// 3. HDD FW Version
1395// 4. HDD Capacity
1396// 5. HDD WWN
1397//
1398// Use Get HDD info Param #5 to know the MAX HDD info index.
1399//
1400// Request:
1401// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1402// Byte 4 –
1403// [7:4] Reserved
1404// [3:0] HDD Controller Type
1405// 0x00 – BIOS
1406// 0x01 – Expander
1407// 0x02 – LSI
1408// Byte 5 – HDD Info Index, 0 base
1409// Byte 6 – Parameter Selector
1410// Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD
1411// Information)
1412//
1413// Response:
1414// Byte 1 – Completion Code
1415//
1416// Param#0 (HDD Location):
1417// Byte 1 – Controller
1418// [7:3] Device Number
1419// [2:0] Function Number
1420// For Intel C610 series (Wellsburg)
1421// D31:F2 (0xFA) – SATA control 1
1422// D31:F5 (0xFD) – SATA control 2
1423// D17:F4 (0x8C) – sSata control
1424// Byte 2 – Port Number
1425// Byte 3 – Location (0xFF: No HDD Present)
1426// BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param
1427// #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if
1428// the HDD present. BMC or other people who know the HDD location has
1429// responsibility for update Location info
1430//
1431// Param#1 (Serial Number):
1432// Bytes 1..33: HDD Serial Number
1433//
1434// Param#2 (Model Name):
1435// Byte 1..33 – HDD Model Name
1436//
1437// Param#3 (HDD FW Version):
1438// Byte 1..17 –HDD FW version
1439//
1440// Param#4 (Capacity):
1441// Byte 1..4 –HDD Block Size, LSB
1442// Byte 5..12 - HDD Block Number, LSB
1443// HDD Capacity = HDD Block size * HDD BLock number (Unit Byte)
1444//
1445// Param#5 (Max HDD Quantity):
1446// Byte 1 - Max HDD Quantity
1447// Max supported port numbers in this PCH
1448//
1449// Param#6 (HDD Type)
1450// Byte 1 – HDD Type
1451// 0h – Reserved
1452// 1h – SAS
1453// 2h – SATA
1454// 3h – PCIE SSD (NVME)
1455//
1456// Param#7 (HDD WWN)
1457// Data 1...8: HDD World Wide Name, LSB
1458//
1459ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1460 ipmi_request_t request,
1461 ipmi_response_t response,
1462 ipmi_data_len_t data_len,
1463 ipmi_context_t context)
1464{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001465 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1466 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001467 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1468 std::stringstream ss;
1469 std::string str;
1470 uint8_t len = *data_len;
1471
1472 *data_len = 0;
1473
1474 /* check for requested data params */
1475 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam ||
1476 ctrlType > 2)
1477 {
1478 phosphor::logging::log<phosphor::logging::level::ERR>(
1479 "Invalid parameter received");
1480 return IPMI_CC_PARM_OUT_OF_RANGE;
1481 }
1482
1483 len = len - 6; // Get Actual data length
1484
1485 ss << std::hex;
1486 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1487 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType;
1488 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] =
1489 req->hddIndex;
1490
1491 str = bytesToStr(req->data, len);
1492 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1493 [driveInfoKey[req->paramSel]] = str.c_str();
1494 flushOemData();
1495
1496 return IPMI_CC_OK;
1497}
1498
1499//----------------------------------------------------------------------
1500// Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO)
1501//----------------------------------------------------------------------
1502// BMC needs to check HDD presented or not first. If NOT presented, return
1503// completion code 0xD5.
1504//
1505// Request:
1506// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1507// Byte 4 –
1508//[7:4] Reserved
1509//[3:0] HDD Controller Type
1510// 0x00 – BIOS
1511// 0x01 – Expander
1512// 0x02 – LSI
1513// Byte 5 – HDD Index, 0 base
1514// Byte 6 – Parameter Selector (See Above Set HDD Information)
1515// Response:
1516// Byte 1 – Completion Code
1517// 0xD5 – Not support in current status (HDD Not Present)
1518// Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD
1519// Information)
1520//
1521ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1522 ipmi_request_t request,
1523 ipmi_response_t response,
1524 ipmi_data_len_t data_len,
1525 ipmi_context_t context)
1526{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001527 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1528 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
1529 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001530 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1531 std::stringstream ss;
1532 std::string str;
1533
1534 *data_len = 0;
1535
1536 /* check for requested data params */
1537 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2)
1538 {
1539 phosphor::logging::log<phosphor::logging::level::ERR>(
1540 "Invalid parameter received");
1541 return IPMI_CC_PARM_OUT_OF_RANGE;
1542 }
1543
1544 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) ==
1545 oemData[KEY_Q_DRIVE_INFO].end())
1546 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1547
1548 ss << std::hex;
1549 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1550
1551 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) ==
1552 oemData[KEY_Q_DRIVE_INFO].end())
1553 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1554
1555 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find(
1556 dimmInfoKey[req->paramSel]) ==
1557 oemData[KEY_Q_DRIVE_INFO][ss.str()].end())
1558 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1559
1560 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1561 [dimmInfoKey[req->paramSel]];
1562 *data_len = strToBytes(str, res);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001563
1564 return IPMI_CC_OK;
1565}
1566
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001567/* Helper function for sending DCMI commands to ME and getting response back */
1568ipmi::RspType<std::vector<uint8_t>> sendDCMICmd(uint8_t cmd,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001569 std::vector<uint8_t>& cmdData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001570{
1571 std::vector<uint8_t> respData;
1572
1573 /* Add group id as first byte to request for ME command */
1574 cmdData.insert(cmdData.begin(), groupDCMI);
1575
1576 if (sendMeCmd(ipmi::netFnGroup, cmd, cmdData, respData))
1577 return ipmi::responseUnspecifiedError();
1578
1579 /* Remove group id as first byte as it will be added by IPMID */
1580 respData.erase(respData.begin());
1581
1582 return ipmi::responseSuccess(std::move(respData));
1583}
1584
1585/* DCMI Command handellers. */
1586
1587ipmi::RspType<std::vector<uint8_t>>
1588 ipmiOemDCMIGetPowerReading(std::vector<uint8_t> reqData)
1589{
1590 return sendDCMICmd(ipmi::dcmi::cmdGetPowerReading, reqData);
1591}
1592
1593ipmi::RspType<std::vector<uint8_t>>
1594 ipmiOemDCMIGetPowerLimit(std::vector<uint8_t> reqData)
1595{
1596 return sendDCMICmd(ipmi::dcmi::cmdGetPowerLimit, reqData);
1597}
1598
1599ipmi::RspType<std::vector<uint8_t>>
1600 ipmiOemDCMISetPowerLimit(std::vector<uint8_t> reqData)
1601{
1602 return sendDCMICmd(ipmi::dcmi::cmdSetPowerLimit, reqData);
1603}
1604
1605ipmi::RspType<std::vector<uint8_t>>
1606 ipmiOemDCMIApplyPowerLimit(std::vector<uint8_t> reqData)
1607{
1608 return sendDCMICmd(ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
1609}
1610
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001611static void registerOEMFunctions(void)
1612{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001613 /* Get OEM data from json file */
1614 std::ifstream file(JSON_OEM_DATA_FILE);
1615 if (file)
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001616 {
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001617 file >> oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001618 file.close();
1619 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001620
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001621 phosphor::logging::log<phosphor::logging::level::INFO>(
1622 "Registering OEM commands");
Vijay Khemka7c0aea42020-03-05 13:31:53 -08001623
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001624 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO,
1625 NULL, ipmiOemDbgGetFrameInfo,
1626 PRIVILEGE_USER); // get debug frame info
1627 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ,
1628 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL,
1629 ipmiOemDbgGetUpdFrames,
1630 PRIVILEGE_USER); // get debug updated frames
1631 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC,
1632 NULL, ipmiOemDbgGetPostDesc,
1633 PRIVILEGE_USER); // get debug post description
1634 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC,
1635 NULL, ipmiOemDbgGetGpioDesc,
1636 PRIVILEGE_USER); // get debug gpio description
1637 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA,
1638 NULL, ipmiOemDbgGetFrameData,
1639 PRIVILEGE_USER); // get debug frame data
1640 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL,
1641 NULL, ipmiOemDbgGetCtrlPanel,
1642 PRIVILEGE_USER); // get debug control panel
1643 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL,
1644 ipmiOemSetDimmInfo,
1645 PRIVILEGE_USER); // Set Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001646 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL,
1647 ipmiOemGetBoardID,
1648 PRIVILEGE_USER); // Get Board ID
1649 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BOOT_ORDER, NULL,
1650 ipmiOemSetBootOrder,
1651 PRIVILEGE_USER); // Set Boot Order
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001652 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOOT_ORDER, NULL,
1653 ipmiOemGetBootOrder,
1654 PRIVILEGE_USER); // Get Boot Order
1655 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL,
1656 ipmiOemSetMachineCfgInfo,
1657 PRIVILEGE_USER); // Set Machine Config Info
1658 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL,
1659 ipmiOemSetPostStart,
1660 PRIVILEGE_USER); // Set POST start
1661 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL,
1662 ipmiOemSetPostEnd,
1663 PRIVILEGE_USER); // Set POST End
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001664 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL,
1665 ipmiOemSetPPINInfo,
1666 PRIVILEGE_USER); // Set PPIN Info
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001667 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_SYSTEM_GUID, NULL,
1668 ipmiOemSetSystemGuid,
1669 PRIVILEGE_USER); // Set System GUID
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001670 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL,
1671 ipmiOemSetAdrTrigger,
1672 PRIVILEGE_USER); // Set ADR Trigger
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001673 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL,
1674 ipmiOemSetBiosFlashInfo,
1675 PRIVILEGE_USER); // Set Bios Flash Info
1676 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr,
1677 PRIVILEGE_USER); // Set PPR
1678 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
1679 PRIVILEGE_USER); // Get PPR
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001680 /* FB OEM QC Commands */
1681 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_PROC_INFO, NULL,
1682 ipmiOemQSetProcInfo,
1683 PRIVILEGE_USER); // Set Proc Info
1684 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL,
1685 ipmiOemQGetProcInfo,
1686 PRIVILEGE_USER); // Get Proc Info
1687 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DIMM_INFO, NULL,
1688 ipmiOemQSetDimmInfo,
1689 PRIVILEGE_USER); // Set Dimm Info
1690 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DIMM_INFO, NULL,
1691 ipmiOemQGetDimmInfo,
1692 PRIVILEGE_USER); // Get Dimm Info
1693 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
1694 ipmiOemQSetDriveInfo,
1695 PRIVILEGE_USER); // Set Drive Info
1696 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL,
1697 ipmiOemQGetDriveInfo,
1698 PRIVILEGE_USER); // Get Drive Info
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001699
1700 /* FB OEM DCMI Commands as per DCMI spec 1.5 Section 6 */
1701 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1702 ipmi::dcmi::cmdGetPowerReading,
1703 ipmi::Privilege::User,
1704 ipmiOemDCMIGetPowerReading); // Get Power Reading
1705
1706 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1707 ipmi::dcmi::cmdGetPowerLimit,
1708 ipmi::Privilege::User,
1709 ipmiOemDCMIGetPowerLimit); // Get Power Limit
1710
1711 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1712 ipmi::dcmi::cmdSetPowerLimit,
1713 ipmi::Privilege::Operator,
1714 ipmiOemDCMISetPowerLimit); // Set Power Limit
1715
1716 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1717 ipmi::dcmi::cmdActDeactivatePwrLimit,
1718 ipmi::Privilege::Operator,
1719 ipmiOemDCMIApplyPowerLimit); // Apply Power Limit
1720
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001721 return;
1722}
1723
1724} // namespace ipmi