blob: 60afb136b711e28adb1829ccd1ca690197ab3407 [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 Khemka63c99be2020-05-27 19:14:35 -0700185 case LanParam::IP: {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700186 auto ethIP = ethdevice + "/" + ipmi::network::IPV4_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700187 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700188 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700189 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
190
191 auto properties = ipmi::getAllDbusProperties(
192 bus, ipObjectInfo.second, ipObjectInfo.first,
193 ipmi::network::IP_INTERFACE);
194
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500195 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700196
197 std::strcpy(data, ipaddress.c_str());
198 }
199 break;
200
Vijay Khemka63c99be2020-05-27 19:14:35 -0700201 case LanParam::IPV6: {
Vijay Khemkaa7231892019-10-11 11:35:05 -0700202 auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700203 std::string ipaddress;
Vijay Khemkaa7231892019-10-11 11:35:05 -0700204 auto ipObjectInfo = ipmi::network::getIPObject(
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700205 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP);
206
207 auto properties = ipmi::getAllDbusProperties(
208 bus, ipObjectInfo.second, ipObjectInfo.first,
209 ipmi::network::IP_INTERFACE);
210
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500211 ipaddress = std::get<std::string>(properties["Address"]);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700212
213 std::strcpy(data, ipaddress.c_str());
214 }
215 break;
216
Vijay Khemka63c99be2020-05-27 19:14:35 -0700217 case LanParam::MAC: {
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700218 std::string macAddress;
219 auto macObjectInfo =
220 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
221 ipmi::network::ROOT, ethdevice);
222
223 auto variant = ipmi::getDbusProperty(
224 bus, macObjectInfo.second, macObjectInfo.first,
225 ipmi::network::MAC_INTERFACE, "MACAddress");
226
Patrick Williamsef0efbc2020-05-13 11:26:51 -0500227 macAddress = std::get<std::string>(variant);
Vijay Khemka1b6fae32019-03-25 17:43:01 -0700228
229 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
230 (data), (data + 1), (data + 2), (data + 3), (data + 4),
231 (data + 5));
232 std::strcpy(data, macAddress.c_str());
233 }
234 break;
235
236 default:
237 rc = IPMI_CC_PARM_OUT_OF_RANGE;
238 }
239 return rc;
240}
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800241
242// return code: 0 successful
Vijay Khemka63c99be2020-05-27 19:14:35 -0700243int8_t getFruData(std::string& data, std::string& name)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800244{
245 std::string objpath = "/xyz/openbmc_project/FruDevice";
246 std::string intf = "xyz.openbmc_project.FruDeviceManager";
247 std::string service = getService(dbus, intf, objpath);
248 ObjectValueTree valueTree = getManagedObjects(dbus, service, "/");
249 if (valueTree.empty())
250 {
251 phosphor::logging::log<phosphor::logging::level::ERR>(
252 "No object implements interface",
253 phosphor::logging::entry("INTF=%s", intf.c_str()));
254 return -1;
255 }
256
Vijay Khemka63c99be2020-05-27 19:14:35 -0700257 for (const auto& item : valueTree)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800258 {
259 auto interface = item.second.find("xyz.openbmc_project.FruDevice");
260 if (interface == item.second.end())
261 {
262 continue;
263 }
264
265 auto property = interface->second.find(name.c_str());
266 if (property == interface->second.end())
267 {
268 continue;
269 }
270
271 try
272 {
273 Value variant = property->second;
Vijay Khemka63c99be2020-05-27 19:14:35 -0700274 std::string& result = std::get<std::string>(variant);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800275 if (result.size() > maxFRUStringLength)
276 {
277 phosphor::logging::log<phosphor::logging::level::ERR>(
278 "FRU serial number exceed maximum length");
279 return -1;
280 }
281 data = result;
282 return 0;
283 }
Vijay Khemka63c99be2020-05-27 19:14:35 -0700284 catch (std::bad_variant_access& e)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800285 {
286 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
287 return -1;
288 }
289 }
290 return -1;
291}
292
293typedef struct
294{
295 uint8_t cur_power_state;
296 uint8_t last_power_event;
297 uint8_t misc_power_state;
298 uint8_t front_panel_button_cap_status;
299} ipmi_get_chassis_status_t;
300
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800301//----------------------------------------------------------------------
302// Get Debug Frame Info
303//----------------------------------------------------------------------
304ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
305 ipmi_request_t request,
306 ipmi_response_t response,
307 ipmi_data_len_t data_len,
308 ipmi_context_t context)
309{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700310 uint8_t* req = reinterpret_cast<uint8_t*>(request);
311 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800312 uint8_t num_frames = 3;
313
314 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
315 res[SIZE_IANA_ID] = num_frames;
316 *data_len = SIZE_IANA_ID + 1;
317
318 return IPMI_CC_OK;
319}
320
321//----------------------------------------------------------------------
322// Get Debug Updated Frames
323//----------------------------------------------------------------------
324ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
325 ipmi_request_t request,
326 ipmi_response_t response,
327 ipmi_data_len_t data_len,
328 ipmi_context_t context)
329{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700330 uint8_t* req = reinterpret_cast<uint8_t*>(request);
331 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800332 uint8_t num_updates = 3;
333 *data_len = 4;
334
335 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
336 res[SIZE_IANA_ID] = num_updates;
337 *data_len = SIZE_IANA_ID + num_updates + 1;
338 res[SIZE_IANA_ID + 1] = 1; // info page update
339 res[SIZE_IANA_ID + 2] = 2; // cri sel update
340 res[SIZE_IANA_ID + 3] = 3; // cri sensor update
341
342 return IPMI_CC_OK;
343}
344
345//----------------------------------------------------------------------
346// Get Debug POST Description
347//----------------------------------------------------------------------
348ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
349 ipmi_request_t request,
350 ipmi_response_t response,
351 ipmi_data_len_t data_len,
352 ipmi_context_t context)
353{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700354 uint8_t* req = reinterpret_cast<uint8_t*>(request);
355 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800356 uint8_t index = 0;
357 uint8_t next = 0;
358 uint8_t end = 0;
359 uint8_t phase = 0;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700360 uint8_t descLen = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800361 int ret;
362
363 index = req[3];
364 phase = req[4];
365
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700366 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800367 if (ret)
368 {
369 memcpy(res, req, SIZE_IANA_ID); // IANA ID
370 *data_len = SIZE_IANA_ID;
371 return IPMI_CC_UNSPECIFIED_ERROR;
372 }
373
374 memcpy(res, req, SIZE_IANA_ID); // IANA ID
375 res[3] = index;
376 res[4] = next;
377 res[5] = phase;
378 res[6] = end;
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700379 res[7] = descLen;
380 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800381
382 return IPMI_CC_OK;
383}
384
385//----------------------------------------------------------------------
386// Get Debug GPIO Description
387//----------------------------------------------------------------------
388ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
389 ipmi_request_t request,
390 ipmi_response_t response,
391 ipmi_data_len_t data_len,
392 ipmi_context_t context)
393{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700394 uint8_t* req = reinterpret_cast<uint8_t*>(request);
395 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800396
Vijay Khemka38183d62019-08-28 16:19:33 -0700397 uint8_t index = 0;
398 uint8_t next = 0;
399 uint8_t level = 0;
400 uint8_t pinDef = 0;
401 uint8_t descLen = 0;
402 int ret;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800403
Vijay Khemka38183d62019-08-28 16:19:33 -0700404 index = req[3];
405
406 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen,
407 &res[8]);
408 if (ret)
409 {
410 memcpy(res, req, SIZE_IANA_ID); // IANA ID
411 *data_len = SIZE_IANA_ID;
412 return IPMI_CC_UNSPECIFIED_ERROR;
413 }
414
415 memcpy(res, req, SIZE_IANA_ID); // IANA ID
416 res[3] = index;
417 res[4] = next;
418 res[5] = level;
419 res[6] = pinDef;
420 res[7] = descLen;
421 *data_len = SIZE_IANA_ID + 5 + descLen;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800422
423 return IPMI_CC_OK;
424}
425
426//----------------------------------------------------------------------
427// Get Debug Frame Data
428//----------------------------------------------------------------------
429ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
430 ipmi_request_t request,
431 ipmi_response_t response,
432 ipmi_data_len_t data_len,
433 ipmi_context_t context)
434{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700435 uint8_t* req = reinterpret_cast<uint8_t*>(request);
436 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800437 uint8_t frame;
438 uint8_t page;
439 uint8_t next;
440 uint8_t count;
441 int ret;
442
443 frame = req[3];
444 page = req[4];
445 int fr = frame;
446 int pg = page;
447
448 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]);
449 if (ret)
450 {
451 memcpy(res, req, SIZE_IANA_ID); // IANA ID
452 *data_len = SIZE_IANA_ID;
453 return IPMI_CC_UNSPECIFIED_ERROR;
454 }
455
456 memcpy(res, req, SIZE_IANA_ID); // IANA ID
457 res[3] = frame;
458 res[4] = page;
459 res[5] = next;
460 res[6] = count;
461 *data_len = SIZE_IANA_ID + 4 + count;
462
463 return IPMI_CC_OK;
464}
465
466//----------------------------------------------------------------------
467// Get Debug Control Panel
468//----------------------------------------------------------------------
469ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
470 ipmi_request_t request,
471 ipmi_response_t response,
472 ipmi_data_len_t data_len,
473 ipmi_context_t context)
474{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700475 uint8_t* req = reinterpret_cast<uint8_t*>(request);
476 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800477
478 uint8_t panel;
479 uint8_t operation;
480 uint8_t item;
481 uint8_t count;
482 ipmi_ret_t ret;
483
484 panel = req[3];
485 operation = req[4];
486 item = req[5];
487
488 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]);
489
490 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID
491 *data_len = SIZE_IANA_ID + count;
492
493 return ret;
494}
495
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800496//----------------------------------------------------------------------
497// Set Dimm Info (CMD_OEM_SET_DIMM_INFO)
498//----------------------------------------------------------------------
499ipmi_ret_t ipmiOemSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
500 ipmi_request_t request, ipmi_response_t response,
501 ipmi_data_len_t data_len, ipmi_context_t context)
502{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700503 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700504
505 uint8_t index = req[0];
506 uint8_t type = req[1];
507 uint16_t speed;
508 uint32_t size;
509
510 memcpy(&speed, &req[2], 2);
511 memcpy(&size, &req[4], 4);
512
513 std::stringstream ss;
514 ss << std::hex;
515 ss << std::setw(2) << std::setfill('0') << (int)index;
516
517 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index;
518 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type;
519 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed;
520 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size;
521
522 flushOemData();
523
524 *data_len = 0;
525
526 return IPMI_CC_OK;
527}
528
529//----------------------------------------------------------------------
530// Get Board ID (CMD_OEM_GET_BOARD_ID)
531//----------------------------------------------------------------------
532ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
533 ipmi_request_t request, ipmi_response_t response,
534 ipmi_data_len_t data_len, ipmi_context_t context)
535{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700536 uint8_t* req = reinterpret_cast<uint8_t*>(request);
537 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800538
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700539 /* TODO: Needs to implement this after GPIO implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800540 *data_len = 0;
541
542 return IPMI_CC_OK;
543}
544
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800545/* Helper functions to set boot order */
Vijay Khemka63c99be2020-05-27 19:14:35 -0700546void setBootOrder(uint8_t* data)
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800547{
548 nlohmann::json bootMode;
549 uint8_t mode = data[0];
550 int i;
551
552 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false);
553 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false);
554 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false);
555 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false);
556 oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE] = bootMode;
557
558 /* Initialize boot sequence array */
559 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ] = {};
560 for (i = 1; i < SIZE_BOOT_ORDER; i++)
561 {
562 if (data[i] >= BOOT_SEQ_ARRAY_SIZE)
563 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1] = "NA";
564 else
565 oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1] = bootSeq[data[i]];
566 }
567
568 flushOemData();
569}
570
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800571//----------------------------------------------------------------------
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700572// Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
573//----------------------------------------------------------------------
574ipmi_ret_t ipmiOemSetBootOrder(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
575 ipmi_request_t request, ipmi_response_t response,
576 ipmi_data_len_t data_len, ipmi_context_t context)
577{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700578 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700579 uint8_t len = *data_len;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700580
581 *data_len = 0;
582
583 if (len != SIZE_BOOT_ORDER)
584 {
585 phosphor::logging::log<phosphor::logging::level::ERR>(
586 "Invalid Boot order length received");
587 return IPMI_CC_REQ_DATA_LEN_INVALID;
588 }
589
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800590 setBootOrder(req);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700591
592 return IPMI_CC_OK;
593}
594
595//----------------------------------------------------------------------
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800596// Get Boot Order (CMD_OEM_GET_BOOT_ORDER)
597//----------------------------------------------------------------------
598ipmi_ret_t ipmiOemGetBootOrder(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
599 ipmi_request_t request, ipmi_response_t response,
600 ipmi_data_len_t data_len, ipmi_context_t context)
601{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700602 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700603 uint8_t mode = 0;
604 int i;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800605
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700606 *data_len = SIZE_BOOT_ORDER;
607
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800608 if (oemData.find(KEY_BOOT_ORDER) == oemData.end())
609 {
610 /* Return default boot order 0100090203ff */
611 uint8_t defaultBoot[SIZE_BOOT_ORDER] = {
612 BOOT_MODE_UEFI, bootMap["USB_DEV"], bootMap["NET_IPV6"],
613 bootMap["SATA_HDD"], bootMap["SATA_CD"], 0xff};
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700614
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800615 memcpy(res, defaultBoot, SIZE_BOOT_ORDER);
616 phosphor::logging::log<phosphor::logging::level::INFO>(
617 "Set default boot order");
618 setBootOrder(defaultBoot);
619 }
620 else
621 {
622 nlohmann::json bootMode = oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE];
623 if (bootMode["UEFI"])
624 mode |= BOOT_MODE_UEFI;
625 if (bootMode["CMOS_CLR"])
626 mode |= BOOT_MODE_CMOS_CLR;
627 if (bootMode["BOOT_FLAG"])
628 mode |= BOOT_MODE_BOOT_FLAG;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700629
Vijay Khemka877d5dd2019-12-16 14:46:21 -0800630 res[0] = mode;
631
632 for (i = 1; i < SIZE_BOOT_ORDER; i++)
633 {
634 std::string seqStr = oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1];
635 if (bootMap.find(seqStr) != bootMap.end())
636 res[i] = bootMap[seqStr];
637 else
638 res[i] = 0xff;
639 }
640 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800641
642 return IPMI_CC_OK;
643}
644
645//----------------------------------------------------------------------
646// Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO)
647//----------------------------------------------------------------------
648ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
649 ipmi_request_t request,
650 ipmi_response_t response,
651 ipmi_data_len_t data_len,
652 ipmi_context_t context)
653{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700654 machineConfigInfo_t* req = reinterpret_cast<machineConfigInfo_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700655 uint8_t len = *data_len;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800656
657 *data_len = 0;
658
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700659 if (len < sizeof(machineConfigInfo_t))
660 {
661 phosphor::logging::log<phosphor::logging::level::ERR>(
662 "Invalid machine configuration length received");
663 return IPMI_CC_REQ_DATA_LEN_INVALID;
664 }
665
Vijay Khemka63c99be2020-05-27 19:14:35 -0700666 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700667 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN";
668 else
669 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] =
670 chassisType[req->chassis_type];
671
Vijay Khemka63c99be2020-05-27 19:14:35 -0700672 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700673 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN";
674 else
675 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type];
676
677 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt;
678 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt;
679 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt;
680 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt;
681
Vijay Khemka63c99be2020-05-27 19:14:35 -0700682 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700683 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN";
684 else
685 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type];
686
687 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {};
688 int i = 0;
689 if (req->pcie_card_loc & BIT_0)
690 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1";
691 if (req->pcie_card_loc & BIT_1)
692 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2";
693 if (req->pcie_card_loc & BIT_2)
694 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3";
695 if (req->pcie_card_loc & BIT_3)
696 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4";
697
Vijay Khemka63c99be2020-05-27 19:14:35 -0700698 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700699 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN";
700 else
701 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] =
702 pcieType[req->slot1_pcie_type];
703
Vijay Khemka63c99be2020-05-27 19:14:35 -0700704 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700705 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN";
706 else
707 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] =
708 pcieType[req->slot2_pcie_type];
709
Vijay Khemka63c99be2020-05-27 19:14:35 -0700710 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700711 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN";
712 else
713 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] =
714 pcieType[req->slot3_pcie_type];
715
Vijay Khemka63c99be2020-05-27 19:14:35 -0700716 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*))
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700717 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN";
718 else
719 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] =
720 pcieType[req->slot4_pcie_type];
721
722 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt;
723
724 flushOemData();
725
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800726 return IPMI_CC_OK;
727}
728
729//----------------------------------------------------------------------
730// Set POST start (CMD_OEM_SET_POST_START)
731//----------------------------------------------------------------------
732ipmi_ret_t ipmiOemSetPostStart(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
733 ipmi_request_t request, ipmi_response_t response,
734 ipmi_data_len_t data_len, ipmi_context_t context)
735{
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800736 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event");
737
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700738 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800739 *data_len = 0;
740 return IPMI_CC_OK;
741}
742
743//----------------------------------------------------------------------
744// Set POST End (CMD_OEM_SET_POST_END)
745//----------------------------------------------------------------------
746ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
747 ipmi_request_t request, ipmi_response_t response,
748 ipmi_data_len_t data_len, ipmi_context_t context)
749{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700750 struct timespec ts;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800751
752 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event");
753
754 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700755
756 // Timestamp post end time.
757 clock_gettime(CLOCK_REALTIME, &ts);
758 oemData[KEY_TS_SLED] = ts.tv_sec;
759 flushOemData();
760
761 // Sync time with system
762 // TODO: Add code for syncing time
763
764 return IPMI_CC_OK;
765}
766
767//----------------------------------------------------------------------
768// Set PPIN Info (CMD_OEM_SET_PPIN_INFO)
769//----------------------------------------------------------------------
770// Inform BMC about PPIN data of 8 bytes for each CPU
771//
772// Request:
773// Byte 1:8 – CPU0 PPIN data
774// Optional:
775// Byte 9:16 – CPU1 PPIN data
776//
777// Response:
778// Byte 1 – Completion Code
779ipmi_ret_t ipmiOemSetPPINInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
780 ipmi_request_t request, ipmi_response_t response,
781 ipmi_data_len_t data_len, ipmi_context_t context)
782{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700783 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700784 std::string ppinStr;
785 int len;
786
787 if (*data_len > SIZE_CPU_PPIN * 2)
788 len = SIZE_CPU_PPIN * 2;
789 else
790 len = *data_len;
791 *data_len = 0;
792
793 ppinStr = bytesToStr(req, len);
794 oemData[KEY_PPIN_INFO] = ppinStr.c_str();
795 flushOemData();
796
797 return IPMI_CC_OK;
798}
799
800//----------------------------------------------------------------------
801// Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER)
802//----------------------------------------------------------------------
803ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
804 ipmi_request_t request,
805 ipmi_response_t response,
806 ipmi_data_len_t data_len,
807 ipmi_context_t context)
808{
809 /* Do nothing, return success */
810 *data_len = 0;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800811 return IPMI_CC_OK;
812}
813
Vijay Khemkaf2246ce2020-05-27 14:26:35 -0700814// Helper function to set guid at offset in EEPROM
815static int setGUID(off_t offset, uint8_t* guid)
816{
817 int fd = -1;
818 ssize_t len;
819 int ret = 0;
820
821 errno = 0;
822
823 // Check if file is present
824 if (access(FRU_EEPROM, F_OK) == -1)
825 {
826 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl;
827 return errno;
828 }
829
830 // Open the file
831 fd = open(FRU_EEPROM, O_WRONLY);
832 if (fd == -1)
833 {
834 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl;
835 return errno;
836 }
837
838 // seek to the offset
839 lseek(fd, offset, SEEK_SET);
840
841 // Write bytes to location
842 len = write(fd, guid, GUID_SIZE);
843 if (len != GUID_SIZE)
844 {
845 phosphor::logging::log<phosphor::logging::level::ERR>(
846 "GUID write data to EEPROM failed");
847 ret = errno;
848 }
849
850 close(fd);
851 return ret;
852}
853
854//----------------------------------------------------------------------
855// Set System GUID (CMD_OEM_SET_SYSTEM_GUID)
856//----------------------------------------------------------------------
857ipmi_ret_t ipmiOemSetSystemGuid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
858 ipmi_request_t request,
859 ipmi_response_t response,
860 ipmi_data_len_t data_len,
861 ipmi_context_t context)
862{
863 uint8_t* req = reinterpret_cast<uint8_t*>(request);
864
865 if (*data_len != GUID_SIZE) // 16bytes
866 {
867 *data_len = 0;
868 return IPMI_CC_REQ_DATA_LEN_INVALID;
869 }
870
871 *data_len = 0;
872
873 if (setGUID(OFFSET_SYS_GUID, req))
874 {
875 return IPMI_CC_UNSPECIFIED_ERROR;
876 }
877 return IPMI_CC_OK;
878}
879
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800880//----------------------------------------------------------------------
881// Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO)
882//----------------------------------------------------------------------
883ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
884 ipmi_request_t request,
885 ipmi_response_t response,
886 ipmi_data_len_t data_len,
887 ipmi_context_t context)
888{
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700889 /* Do nothing, return success */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800890 *data_len = 0;
891 return IPMI_CC_OK;
892}
893
894//----------------------------------------------------------------------
895// Set PPR (CMD_OEM_SET_PPR)
896//----------------------------------------------------------------------
897ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
898 ipmi_request_t request, ipmi_response_t response,
899 ipmi_data_len_t data_len, ipmi_context_t context)
900{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700901 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700902 uint8_t pprCnt, pprAct, pprIndex;
903 uint8_t selParam = req[0];
904 uint8_t len = *data_len;
905 std::stringstream ss;
906 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800907
908 *data_len = 0;
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700909
910 switch (selParam)
911 {
912 case PPR_ACTION:
913 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) ==
914 oemData[KEY_PPR].end())
915 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
916
917 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
918 if (pprCnt == 0)
919 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
920
921 pprAct = req[1];
922 /* Check if ppr is enabled or disabled */
923 if (!(pprAct & 0x80))
924 pprAct = 0;
925
926 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct;
927 break;
928 case PPR_ROW_COUNT:
929 if (req[1] > 100)
930 return IPMI_CC_PARM_OUT_OF_RANGE;
931
932 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1];
933 break;
934 case PPR_ROW_ADDR:
935 pprIndex = req[1];
936 if (pprIndex > 100)
937 return IPMI_CC_PARM_OUT_OF_RANGE;
938
939 if (len < PPR_ROW_ADDR_LEN + 1)
940 {
941 phosphor::logging::log<phosphor::logging::level::ERR>(
942 "Invalid PPR Row Address length received");
943 return IPMI_CC_REQ_DATA_LEN_INVALID;
944 }
945
946 ss << std::hex;
947 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
948
949 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
950
951 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN);
952 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str();
953 break;
954 case PPR_HISTORY_DATA:
955 pprIndex = req[1];
956 if (pprIndex > 100)
957 return IPMI_CC_PARM_OUT_OF_RANGE;
958
959 if (len < PPR_HST_DATA_LEN + 1)
960 {
961 phosphor::logging::log<phosphor::logging::level::ERR>(
962 "Invalid PPR history data length received");
963 return IPMI_CC_REQ_DATA_LEN_INVALID;
964 }
965
966 ss << std::hex;
967 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
968
969 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex;
970
971 str = bytesToStr(&req[1], PPR_HST_DATA_LEN);
972 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str();
973 break;
974 default:
975 return IPMI_CC_PARM_OUT_OF_RANGE;
976 break;
977 }
978
979 flushOemData();
980
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800981 return IPMI_CC_OK;
982}
983
984//----------------------------------------------------------------------
985// Get PPR (CMD_OEM_GET_PPR)
986//----------------------------------------------------------------------
987ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
988 ipmi_request_t request, ipmi_response_t response,
989 ipmi_data_len_t data_len, ipmi_context_t context)
990{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700991 uint8_t* req = reinterpret_cast<uint8_t*>(request);
992 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700993 uint8_t pprCnt, pprIndex;
994 uint8_t selParam = req[0];
995 std::stringstream ss;
996 std::string str;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800997
Vijay Khemka1d4a0692019-04-09 15:20:28 -0700998 /* Any failure will return zero length data */
999 *data_len = 0;
1000
1001 switch (selParam)
1002 {
1003 case PPR_ACTION:
1004 res[0] = 0;
1005 *data_len = 1;
1006
1007 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1008 oemData[KEY_PPR].end())
1009 {
1010 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1011 if (pprCnt != 0)
1012 {
1013 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) !=
1014 oemData[KEY_PPR].end())
1015 {
1016 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION];
1017 }
1018 }
1019 }
1020 break;
1021 case PPR_ROW_COUNT:
1022 res[0] = 0;
1023 *data_len = 1;
1024 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) !=
1025 oemData[KEY_PPR].end())
1026 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT];
1027 break;
1028 case PPR_ROW_ADDR:
1029 pprIndex = req[1];
1030 if (pprIndex > 100)
1031 return IPMI_CC_PARM_OUT_OF_RANGE;
1032
1033 ss << std::hex;
1034 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1035
1036 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1037 return IPMI_CC_PARM_OUT_OF_RANGE;
1038
1039 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) ==
1040 oemData[KEY_PPR][ss.str()].end())
1041 return IPMI_CC_PARM_OUT_OF_RANGE;
1042
1043 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR];
1044 *data_len = strToBytes(str, res);
1045 break;
1046 case PPR_HISTORY_DATA:
1047 pprIndex = req[1];
1048 if (pprIndex > 100)
1049 return IPMI_CC_PARM_OUT_OF_RANGE;
1050
1051 ss << std::hex;
1052 ss << std::setw(2) << std::setfill('0') << (int)pprIndex;
1053
1054 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end())
1055 return IPMI_CC_PARM_OUT_OF_RANGE;
1056
1057 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) ==
1058 oemData[KEY_PPR][ss.str()].end())
1059 return IPMI_CC_PARM_OUT_OF_RANGE;
1060
1061 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA];
1062 *data_len = strToBytes(str, res);
1063 break;
1064 default:
1065 return IPMI_CC_PARM_OUT_OF_RANGE;
1066 break;
1067 }
1068
1069 return IPMI_CC_OK;
1070}
1071
1072/* FB OEM QC Commands */
1073
1074//----------------------------------------------------------------------
1075// Set Proc Info (CMD_OEM_Q_SET_PROC_INFO)
1076//----------------------------------------------------------------------
1077//"Request:
1078// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1079// Byte 4 – Processor Index, 0 base
1080// Byte 5 – Parameter Selector
1081// Byte 6..N – Configuration parameter data (see below for Parameters
1082// of Processor Information)
1083// Response:
1084// Byte 1 – Completion code
1085//
1086// Parameter#1: (Processor Product Name)
1087//
1088// Byte 1..48 –Product name(ASCII code)
1089// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1090//
1091// Param#2: Processor Basic Information
1092// Byte 1 – Core Number
1093// Byte 2 – Thread Number (LSB)
1094// Byte 3 – Thread Number (MSB)
1095// Byte 4 – Processor frequency in MHz (LSB)
1096// Byte 5 – Processor frequency in MHz (MSB)
1097// Byte 6..7 – Revision
1098//
1099ipmi_ret_t ipmiOemQSetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1100 ipmi_request_t request, ipmi_response_t response,
1101 ipmi_data_len_t data_len, ipmi_context_t context)
1102{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001103 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1104 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001105 std::stringstream ss;
1106 std::string str;
1107 uint8_t len = *data_len;
1108
1109 *data_len = 0;
1110
1111 /* check for requested data params */
1112 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1113 {
1114 phosphor::logging::log<phosphor::logging::level::ERR>(
1115 "Invalid parameter received");
1116 return IPMI_CC_PARM_OUT_OF_RANGE;
1117 }
1118
1119 len = len - 5; // Get Actual data length
1120
1121 ss << std::hex;
1122 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1123 oemData[KEY_Q_PROC_INFO][ss.str()][KEY_PROC_INDEX] = req->procIndex;
1124
1125 str = bytesToStr(req->data, len);
1126 oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]] = str.c_str();
1127 flushOemData();
1128
1129 return IPMI_CC_OK;
1130}
1131
1132//----------------------------------------------------------------------
1133// Get Proc Info (CMD_OEM_Q_GET_PROC_INFO)
1134//----------------------------------------------------------------------
1135// Request:
1136// Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first
1137// Byte 4 – Processor Index, 0 base
1138// Byte 5 – Parameter Selector
1139// Response:
1140// Byte 1 – Completion code
1141// Byte 2..N – Configuration Parameter Data (see below for Parameters
1142// of Processor Information)
1143//
1144// Parameter#1: (Processor Product Name)
1145//
1146// Byte 1..48 –Product name(ASCII code)
1147// Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz
1148//
1149// Param#2: Processor Basic Information
1150// Byte 1 – Core Number
1151// Byte 2 – Thread Number (LSB)
1152// Byte 3 – Thread Number (MSB)
1153// Byte 4 – Processor frequency in MHz (LSB)
1154// Byte 5 – Processor frequency in MHz (MSB)
1155// Byte 6..7 – Revision
1156//
1157ipmi_ret_t ipmiOemQGetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1158 ipmi_request_t request, ipmi_response_t response,
1159 ipmi_data_len_t data_len, ipmi_context_t context)
1160{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001161 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
1162 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
1163 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001164 std::stringstream ss;
1165 std::string str;
1166
1167 *data_len = 0;
1168
1169 /* check for requested data params */
1170 if (req->paramSel < 1 || req->paramSel >= numParam)
1171 {
1172 phosphor::logging::log<phosphor::logging::level::ERR>(
1173 "Invalid parameter received");
1174 return IPMI_CC_PARM_OUT_OF_RANGE;
1175 }
1176
1177 ss << std::hex;
1178 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex;
1179
1180 if (oemData[KEY_Q_PROC_INFO].find(ss.str()) ==
1181 oemData[KEY_Q_PROC_INFO].end())
1182 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1183
1184 if (oemData[KEY_Q_PROC_INFO][ss.str()].find(cpuInfoKey[req->paramSel]) ==
1185 oemData[KEY_Q_PROC_INFO][ss.str()].end())
1186 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1187
1188 str = oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]];
1189 *data_len = strToBytes(str, res);
1190
1191 return IPMI_CC_OK;
1192}
1193
1194//----------------------------------------------------------------------
1195// Set Dimm Info (CMD_OEM_Q_SET_DIMM_INFO)
1196//----------------------------------------------------------------------
1197// Request:
1198// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1199// Byte 4 – DIMM Index, 0 base
1200// Byte 5 – Parameter Selector
1201// Byte 6..N – Configuration parameter data (see below for Parameters
1202// of DIMM Information)
1203// Response:
1204// Byte 1 – Completion code
1205//
1206// Param#1 (DIMM Location):
1207// Byte 1 – DIMM Present
1208// Byte 1 – DIMM Present
1209// 01h – Present
1210// FFh – Not Present
1211// Byte 2 – Node Number, 0 base
1212// Byte 3 – Channel Number , 0 base
1213// Byte 4 – DIMM Number , 0 base
1214//
1215// Param#2 (DIMM Type):
1216// Byte 1 – DIMM Type
1217// Bit [7:6]
1218// For DDR3
1219// 00 – Normal Voltage (1.5V)
1220// 01 – Ultra Low Voltage (1.25V)
1221// 10 – Low Voltage (1.35V)
1222// 11 – Reserved
1223// For DDR4
1224// 00 – Reserved
1225// 01 – Reserved
1226// 10 – Reserved
1227// 11 – Normal Voltage (1.2V)
1228// Bit [5:0]
1229// 0x00 – SDRAM
1230// 0x01 – DDR-1 RAM
1231// 0x02 – Rambus
1232// 0x03 – DDR-2 RAM
1233// 0x04 – FBDIMM
1234// 0x05 – DDR-3 RAM
1235// 0x06 – DDR-4 RAM
1236//
1237// Param#3 (DIMM Speed):
1238// Byte 1..2 – DIMM speed in MHz, LSB
1239// Byte 3..6 – DIMM size in Mbytes, LSB
1240//
1241// Param#4 (Module Part Number):
1242// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1243//
1244// Param#5 (Module Serial Number):
1245// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1246//
1247// Param#6 (Module Manufacturer ID):
1248// Byte 1 - Module Manufacturer ID, LSB
1249// Byte 2 - Module Manufacturer ID, MSB
1250//
1251ipmi_ret_t ipmiOemQSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1252 ipmi_request_t request, ipmi_response_t response,
1253 ipmi_data_len_t data_len, ipmi_context_t context)
1254{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001255 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1256 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001257 std::stringstream ss;
1258 std::string str;
1259 uint8_t len = *data_len;
1260
1261 *data_len = 0;
1262
1263 /* check for requested data params */
1264 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
1265 {
1266 phosphor::logging::log<phosphor::logging::level::ERR>(
1267 "Invalid parameter received");
1268 return IPMI_CC_PARM_OUT_OF_RANGE;
1269 }
1270
1271 len = len - 5; // Get Actual data length
1272
1273 ss << std::hex;
1274 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1275 oemData[KEY_Q_DIMM_INFO][ss.str()][KEY_DIMM_INDEX] = req->dimmIndex;
1276
1277 str = bytesToStr(req->data, len);
1278 oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]] =
1279 str.c_str();
1280 flushOemData();
1281
1282 return IPMI_CC_OK;
1283}
1284
1285//----------------------------------------------------------------------
1286// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
1287//----------------------------------------------------------------------
1288// Request:
1289// Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first
1290// Byte 4 – DIMM Index, 0 base
1291// Byte 5 – Parameter Selector
1292// Byte 6..N – Configuration parameter data (see below for Parameters
1293// of DIMM Information)
1294// Response:
1295// Byte 1 – Completion code
1296// Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters
1297// of DIMM Information)
1298//
1299// Param#1 (DIMM Location):
1300// Byte 1 – DIMM Present
1301// Byte 1 – DIMM Present
1302// 01h – Present
1303// FFh – Not Present
1304// Byte 2 – Node Number, 0 base
1305// Byte 3 – Channel Number , 0 base
1306// Byte 4 – DIMM Number , 0 base
1307//
1308// Param#2 (DIMM Type):
1309// Byte 1 – DIMM Type
1310// Bit [7:6]
1311// For DDR3
1312// 00 – Normal Voltage (1.5V)
1313// 01 – Ultra Low Voltage (1.25V)
1314// 10 – Low Voltage (1.35V)
1315// 11 – Reserved
1316// For DDR4
1317// 00 – Reserved
1318// 01 – Reserved
1319// 10 – Reserved
1320// 11 – Normal Voltage (1.2V)
1321// Bit [5:0]
1322// 0x00 – SDRAM
1323// 0x01 – DDR-1 RAM
1324// 0x02 – Rambus
1325// 0x03 – DDR-2 RAM
1326// 0x04 – FBDIMM
1327// 0x05 – DDR-3 RAM
1328// 0x06 – DDR-4 RAM
1329//
1330// Param#3 (DIMM Speed):
1331// Byte 1..2 – DIMM speed in MHz, LSB
1332// Byte 3..6 – DIMM size in Mbytes, LSB
1333//
1334// Param#4 (Module Part Number):
1335// Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C)
1336//
1337// Param#5 (Module Serial Number):
1338// Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C)
1339//
1340// Param#6 (Module Manufacturer ID):
1341// Byte 1 - Module Manufacturer ID, LSB
1342// Byte 2 - Module Manufacturer ID, MSB
1343//
1344ipmi_ret_t ipmiOemQGetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1345 ipmi_request_t request, ipmi_response_t response,
1346 ipmi_data_len_t data_len, ipmi_context_t context)
1347{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001348 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
1349 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
1350 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001351 std::stringstream ss;
1352 std::string str;
1353
1354 *data_len = 0;
1355
1356 /* check for requested data params */
1357 if (req->paramSel < 1 || req->paramSel >= numParam)
1358 {
1359 phosphor::logging::log<phosphor::logging::level::ERR>(
1360 "Invalid parameter received");
1361 return IPMI_CC_PARM_OUT_OF_RANGE;
1362 }
1363
1364 ss << std::hex;
1365 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
1366
1367 if (oemData[KEY_Q_DIMM_INFO].find(ss.str()) ==
1368 oemData[KEY_Q_DIMM_INFO].end())
1369 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1370
1371 if (oemData[KEY_Q_DIMM_INFO][ss.str()].find(dimmInfoKey[req->paramSel]) ==
1372 oemData[KEY_Q_DIMM_INFO][ss.str()].end())
1373 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1374
1375 str = oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]];
1376 *data_len = strToBytes(str, res);
1377
1378 return IPMI_CC_OK;
1379}
1380
1381//----------------------------------------------------------------------
1382// Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO)
1383//----------------------------------------------------------------------
1384// BIOS issue this command to provide HDD information to BMC.
1385//
1386// BIOS just can get information by standard ATA / SMART command for
1387// OB SATA controller.
1388// BIOS can get
1389// 1. Serial Number
1390// 2. Model Name
1391// 3. HDD FW Version
1392// 4. HDD Capacity
1393// 5. HDD WWN
1394//
1395// Use Get HDD info Param #5 to know the MAX HDD info index.
1396//
1397// Request:
1398// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1399// Byte 4 –
1400// [7:4] Reserved
1401// [3:0] HDD Controller Type
1402// 0x00 – BIOS
1403// 0x01 – Expander
1404// 0x02 – LSI
1405// Byte 5 – HDD Info Index, 0 base
1406// Byte 6 – Parameter Selector
1407// Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD
1408// Information)
1409//
1410// Response:
1411// Byte 1 – Completion Code
1412//
1413// Param#0 (HDD Location):
1414// Byte 1 – Controller
1415// [7:3] Device Number
1416// [2:0] Function Number
1417// For Intel C610 series (Wellsburg)
1418// D31:F2 (0xFA) – SATA control 1
1419// D31:F5 (0xFD) – SATA control 2
1420// D17:F4 (0x8C) – sSata control
1421// Byte 2 – Port Number
1422// Byte 3 – Location (0xFF: No HDD Present)
1423// BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param
1424// #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if
1425// the HDD present. BMC or other people who know the HDD location has
1426// responsibility for update Location info
1427//
1428// Param#1 (Serial Number):
1429// Bytes 1..33: HDD Serial Number
1430//
1431// Param#2 (Model Name):
1432// Byte 1..33 – HDD Model Name
1433//
1434// Param#3 (HDD FW Version):
1435// Byte 1..17 –HDD FW version
1436//
1437// Param#4 (Capacity):
1438// Byte 1..4 –HDD Block Size, LSB
1439// Byte 5..12 - HDD Block Number, LSB
1440// HDD Capacity = HDD Block size * HDD BLock number (Unit Byte)
1441//
1442// Param#5 (Max HDD Quantity):
1443// Byte 1 - Max HDD Quantity
1444// Max supported port numbers in this PCH
1445//
1446// Param#6 (HDD Type)
1447// Byte 1 – HDD Type
1448// 0h – Reserved
1449// 1h – SAS
1450// 2h – SATA
1451// 3h – PCIE SSD (NVME)
1452//
1453// Param#7 (HDD WWN)
1454// Data 1...8: HDD World Wide Name, LSB
1455//
1456ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1457 ipmi_request_t request,
1458 ipmi_response_t response,
1459 ipmi_data_len_t data_len,
1460 ipmi_context_t context)
1461{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001462 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1463 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001464 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1465 std::stringstream ss;
1466 std::string str;
1467 uint8_t len = *data_len;
1468
1469 *data_len = 0;
1470
1471 /* check for requested data params */
1472 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam ||
1473 ctrlType > 2)
1474 {
1475 phosphor::logging::log<phosphor::logging::level::ERR>(
1476 "Invalid parameter received");
1477 return IPMI_CC_PARM_OUT_OF_RANGE;
1478 }
1479
1480 len = len - 6; // Get Actual data length
1481
1482 ss << std::hex;
1483 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1484 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType;
1485 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] =
1486 req->hddIndex;
1487
1488 str = bytesToStr(req->data, len);
1489 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1490 [driveInfoKey[req->paramSel]] = str.c_str();
1491 flushOemData();
1492
1493 return IPMI_CC_OK;
1494}
1495
1496//----------------------------------------------------------------------
1497// Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO)
1498//----------------------------------------------------------------------
1499// BMC needs to check HDD presented or not first. If NOT presented, return
1500// completion code 0xD5.
1501//
1502// Request:
1503// Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first
1504// Byte 4 –
1505//[7:4] Reserved
1506//[3:0] HDD Controller Type
1507// 0x00 – BIOS
1508// 0x01 – Expander
1509// 0x02 – LSI
1510// Byte 5 – HDD Index, 0 base
1511// Byte 6 – Parameter Selector (See Above Set HDD Information)
1512// Response:
1513// Byte 1 – Completion Code
1514// 0xD5 – Not support in current status (HDD Not Present)
1515// Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD
1516// Information)
1517//
1518ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1519 ipmi_request_t request,
1520 ipmi_response_t response,
1521 ipmi_data_len_t data_len,
1522 ipmi_context_t context)
1523{
Vijay Khemka63c99be2020-05-27 19:14:35 -07001524 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request);
1525 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*);
1526 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001527 uint8_t ctrlType = req->hddCtrlType & 0x0f;
1528 std::stringstream ss;
1529 std::string str;
1530
1531 *data_len = 0;
1532
1533 /* check for requested data params */
1534 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2)
1535 {
1536 phosphor::logging::log<phosphor::logging::level::ERR>(
1537 "Invalid parameter received");
1538 return IPMI_CC_PARM_OUT_OF_RANGE;
1539 }
1540
1541 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) ==
1542 oemData[KEY_Q_DRIVE_INFO].end())
1543 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1544
1545 ss << std::hex;
1546 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex;
1547
1548 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) ==
1549 oemData[KEY_Q_DRIVE_INFO].end())
1550 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1551
1552 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find(
1553 dimmInfoKey[req->paramSel]) ==
1554 oemData[KEY_Q_DRIVE_INFO][ss.str()].end())
1555 return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
1556
1557 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()]
1558 [dimmInfoKey[req->paramSel]];
1559 *data_len = strToBytes(str, res);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001560
1561 return IPMI_CC_OK;
1562}
1563
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001564/* Helper function for sending DCMI commands to ME and getting response back */
1565ipmi::RspType<std::vector<uint8_t>> sendDCMICmd(uint8_t cmd,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001566 std::vector<uint8_t>& cmdData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001567{
1568 std::vector<uint8_t> respData;
1569
1570 /* Add group id as first byte to request for ME command */
1571 cmdData.insert(cmdData.begin(), groupDCMI);
1572
1573 if (sendMeCmd(ipmi::netFnGroup, cmd, cmdData, respData))
1574 return ipmi::responseUnspecifiedError();
1575
1576 /* Remove group id as first byte as it will be added by IPMID */
1577 respData.erase(respData.begin());
1578
1579 return ipmi::responseSuccess(std::move(respData));
1580}
1581
1582/* DCMI Command handellers. */
1583
1584ipmi::RspType<std::vector<uint8_t>>
1585 ipmiOemDCMIGetPowerReading(std::vector<uint8_t> reqData)
1586{
1587 return sendDCMICmd(ipmi::dcmi::cmdGetPowerReading, reqData);
1588}
1589
1590ipmi::RspType<std::vector<uint8_t>>
1591 ipmiOemDCMIGetPowerLimit(std::vector<uint8_t> reqData)
1592{
1593 return sendDCMICmd(ipmi::dcmi::cmdGetPowerLimit, reqData);
1594}
1595
1596ipmi::RspType<std::vector<uint8_t>>
1597 ipmiOemDCMISetPowerLimit(std::vector<uint8_t> reqData)
1598{
1599 return sendDCMICmd(ipmi::dcmi::cmdSetPowerLimit, reqData);
1600}
1601
1602ipmi::RspType<std::vector<uint8_t>>
1603 ipmiOemDCMIApplyPowerLimit(std::vector<uint8_t> reqData)
1604{
1605 return sendDCMICmd(ipmi::dcmi::cmdActDeactivatePwrLimit, reqData);
1606}
1607
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001608static void registerOEMFunctions(void)
1609{
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001610 /* Get OEM data from json file */
1611 std::ifstream file(JSON_OEM_DATA_FILE);
1612 if (file)
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001613 {
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001614 file >> oemData;
Vijay Khemkafeaa9812019-08-27 15:08:08 -07001615 file.close();
1616 }
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001617
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001618 phosphor::logging::log<phosphor::logging::level::INFO>(
1619 "Registering OEM commands");
Vijay Khemka7c0aea42020-03-05 13:31:53 -08001620
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001621 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO,
1622 NULL, ipmiOemDbgGetFrameInfo,
1623 PRIVILEGE_USER); // get debug frame info
1624 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ,
1625 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL,
1626 ipmiOemDbgGetUpdFrames,
1627 PRIVILEGE_USER); // get debug updated frames
1628 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC,
1629 NULL, ipmiOemDbgGetPostDesc,
1630 PRIVILEGE_USER); // get debug post description
1631 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC,
1632 NULL, ipmiOemDbgGetGpioDesc,
1633 PRIVILEGE_USER); // get debug gpio description
1634 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA,
1635 NULL, ipmiOemDbgGetFrameData,
1636 PRIVILEGE_USER); // get debug frame data
1637 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL,
1638 NULL, ipmiOemDbgGetCtrlPanel,
1639 PRIVILEGE_USER); // get debug control panel
1640 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL,
1641 ipmiOemSetDimmInfo,
1642 PRIVILEGE_USER); // Set Dimm Info
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001643 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL,
1644 ipmiOemGetBoardID,
1645 PRIVILEGE_USER); // Get Board ID
1646 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BOOT_ORDER, NULL,
1647 ipmiOemSetBootOrder,
1648 PRIVILEGE_USER); // Set Boot Order
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001649 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOOT_ORDER, NULL,
1650 ipmiOemGetBootOrder,
1651 PRIVILEGE_USER); // Get Boot Order
1652 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL,
1653 ipmiOemSetMachineCfgInfo,
1654 PRIVILEGE_USER); // Set Machine Config Info
1655 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL,
1656 ipmiOemSetPostStart,
1657 PRIVILEGE_USER); // Set POST start
1658 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL,
1659 ipmiOemSetPostEnd,
1660 PRIVILEGE_USER); // Set POST End
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001661 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL,
1662 ipmiOemSetPPINInfo,
1663 PRIVILEGE_USER); // Set PPIN Info
Vijay Khemkaf2246ce2020-05-27 14:26:35 -07001664 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_SYSTEM_GUID, NULL,
1665 ipmiOemSetSystemGuid,
1666 PRIVILEGE_USER); // Set System GUID
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001667 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL,
1668 ipmiOemSetAdrTrigger,
1669 PRIVILEGE_USER); // Set ADR Trigger
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001670 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL,
1671 ipmiOemSetBiosFlashInfo,
1672 PRIVILEGE_USER); // Set Bios Flash Info
1673 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr,
1674 PRIVILEGE_USER); // Set PPR
1675 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
1676 PRIVILEGE_USER); // Get PPR
Vijay Khemka1d4a0692019-04-09 15:20:28 -07001677 /* FB OEM QC Commands */
1678 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_PROC_INFO, NULL,
1679 ipmiOemQSetProcInfo,
1680 PRIVILEGE_USER); // Set Proc Info
1681 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL,
1682 ipmiOemQGetProcInfo,
1683 PRIVILEGE_USER); // Get Proc Info
1684 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DIMM_INFO, NULL,
1685 ipmiOemQSetDimmInfo,
1686 PRIVILEGE_USER); // Set Dimm Info
1687 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DIMM_INFO, NULL,
1688 ipmiOemQGetDimmInfo,
1689 PRIVILEGE_USER); // Get Dimm Info
1690 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
1691 ipmiOemQSetDriveInfo,
1692 PRIVILEGE_USER); // Set Drive Info
1693 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL,
1694 ipmiOemQGetDriveInfo,
1695 PRIVILEGE_USER); // Get Drive Info
Vijay Khemkadd14c0f2020-03-18 14:48:13 -07001696
1697 /* FB OEM DCMI Commands as per DCMI spec 1.5 Section 6 */
1698 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1699 ipmi::dcmi::cmdGetPowerReading,
1700 ipmi::Privilege::User,
1701 ipmiOemDCMIGetPowerReading); // Get Power Reading
1702
1703 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1704 ipmi::dcmi::cmdGetPowerLimit,
1705 ipmi::Privilege::User,
1706 ipmiOemDCMIGetPowerLimit); // Get Power Limit
1707
1708 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1709 ipmi::dcmi::cmdSetPowerLimit,
1710 ipmi::Privilege::Operator,
1711 ipmiOemDCMISetPowerLimit); // Set Power Limit
1712
1713 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI,
1714 ipmi::dcmi::cmdActDeactivatePwrLimit,
1715 ipmi::Privilege::Operator,
1716 ipmiOemDCMIApplyPowerLimit); // Apply Power Limit
1717
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001718 return;
1719}
1720
1721} // namespace ipmi