blob: 5aecea7b126df7f67f3b9bfed6a526f46ca8dec1 [file] [log] [blame]
Vijay Khemkaa2d52f12019-03-27 14:54:00 -07001/*
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 <ipmid/api.h>
19
20#include <sys/stat.h>
21#include <fcntl.h>
22#include <unistd.h>
Vijay Khemka666a4d92019-04-03 11:27:24 -070023#include <nlohmann/json.hpp>
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070024#include <commandutils.hpp>
25#include <iostream>
Vijay Khemka666a4d92019-04-03 11:27:24 -070026#include <iomanip>
27#include <sstream>
28#include <fstream>
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070029#include <phosphor-logging/log.hpp>
30#include <sdbusplus/message/types.hpp>
31#include <appcommands.hpp>
32
33namespace ipmi
34{
35
36static void registerAPPFunctions() __attribute__((constructor));
37static constexpr size_t GUID_SIZE = 16;
38// TODO Make offset and location runtime configurable to ensure we
39// can make each define their own locations.
40static constexpr off_t OFFSET_SYS_GUID = 0x17F0;
41static constexpr off_t OFFSET_DEV_GUID = 0x1800;
42static constexpr const char *FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom";
Vijay Khemka666a4d92019-04-03 11:27:24 -070043
44// TODO: Need to store this info after identifying proper storage
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070045static uint8_t globEna = 0x09;
Vijay Khemka666a4d92019-04-03 11:27:24 -070046static SysInfoParam sysInfoParams;
47nlohmann::json appData;
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070048
49void printGUID(uint8_t *guid, off_t offset)
50{
51 std::cout << "Read GUID from offset : " << offset << " :\n";
52 for (int i = 0; i < GUID_SIZE; i++)
53 {
54 int data = guid[i];
55 std::cout << std::hex << data << " ";
56 }
57 std::cout << std::endl;
58}
59
60int getGUID(off_t offset, uint8_t *guid)
61{
62 int fd = -1;
63 ssize_t bytes_rd;
64 int ret = 0;
65
66 errno = 0;
67
68 // Check if file is present
69 if (access(FRU_EEPROM, F_OK) == -1)
70 {
71 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl;
72 return errno;
73 }
74
75 // Open the file
76 fd = open(FRU_EEPROM, O_RDONLY);
77 if (fd == -1)
78 {
79 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl;
80 return errno;
81 }
82
83 // seek to the offset
84 lseek(fd, offset, SEEK_SET);
85
86 // Read bytes from location
87 bytes_rd = read(fd, guid, GUID_SIZE);
88 if (bytes_rd != GUID_SIZE)
89 {
90 phosphor::logging::log<phosphor::logging::level::ERR>(
91 "GUID read data from EEPROM failed");
92 ret = errno;
93 }
94 else
95 {
96 printGUID(guid, offset);
97 }
98 close(fd);
99 return ret;
100}
101
102int getSystemGUID(uint8_t *guid)
103{
104 return getGUID(OFFSET_SYS_GUID, guid);
105}
106
107int getDeviceGUID(uint8_t *guid)
108{
109 return getGUID(OFFSET_DEV_GUID, guid);
110}
111
112//----------------------------------------------------------------------
Vijay Khemka666a4d92019-04-03 11:27:24 -0700113// Get Self Test Results (IPMI/Section 20.4) (CMD_APP_GET_SELFTEST_RESULTS)
114//----------------------------------------------------------------------
115ipmi_ret_t ipmiAppGetSTResults(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
116 ipmi_request_t request, ipmi_response_t response,
117 ipmi_data_len_t data_len, ipmi_context_t context)
118{
119 uint8_t *res = reinterpret_cast<uint8_t *>(response);
120
121 // TODO: Following data needs to be updated based on self-test results
122 *res++ = 0x55; // Self-Test result
123 *res++ = 0x00; // Extra error info in case of failure
124
125 *data_len = 2;
126
127 return IPMI_CC_OK;
128}
129
130//----------------------------------------------------------------------
131// Manufacturing Test On (IPMI/Section 20.5) (CMD_APP_MFR_TEST_ON)
132//----------------------------------------------------------------------
133ipmi_ret_t ipmiAppMfrTestOn(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
134 ipmi_request_t request, ipmi_response_t response,
135 ipmi_data_len_t data_len, ipmi_context_t context)
136{
137 uint8_t *req = reinterpret_cast<uint8_t *>(request);
138 std::string mfrTest = "sled-cycle";
139
140 if (!memcmp(req, mfrTest.data(), mfrTest.length()) &&
141 (*data_len == mfrTest.length()))
142 {
143 /* sled-cycle the BMC */
144 system("/usr/sbin/power-util mb sled-cycle");
145 }
146 else
147 {
148 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
149 }
150
151 *data_len = 0;
152
153 return IPMI_CC_OK;
154}
155
156//----------------------------------------------------------------------
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700157// Get Device GUID (CMD_APP_GET_DEV_GUID)
158//----------------------------------------------------------------------
159ipmi_ret_t ipmiAppGetDevGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
160 ipmi_request_t request, ipmi_response_t response,
161 ipmi_data_len_t data_len, ipmi_context_t context)
162{
163 uint8_t *res = reinterpret_cast<uint8_t *>(response);
164
165 if (getDeviceGUID(res))
166 {
167 return IPMI_CC_UNSPECIFIED_ERROR;
168 }
169 *data_len = GUID_SIZE;
170
171 return IPMI_CC_OK;
172}
173
174//----------------------------------------------------------------------
175// Set Global Enables (CMD_APP_SET_GLOBAL_ENABLES)
176//----------------------------------------------------------------------
177ipmi_ret_t ipmiAppSetGlobalEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
178 ipmi_request_t request,
179 ipmi_response_t response,
180 ipmi_data_len_t data_len,
181 ipmi_context_t context)
182{
183 uint8_t *req = reinterpret_cast<uint8_t *>(request);
184
185 globEna = *req;
186 *data_len = 0;
187
188 return IPMI_CC_OK;
189}
190
191//----------------------------------------------------------------------
192// Get Global Enables (CMD_APP_GET_GLOBAL_ENABLES)
193//----------------------------------------------------------------------
194ipmi_ret_t ipmiAppGetGlobalEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
195 ipmi_request_t request,
196 ipmi_response_t response,
197 ipmi_data_len_t data_len,
198 ipmi_context_t context)
199{
200 uint8_t *res = reinterpret_cast<uint8_t *>(response);
201
202 *data_len = 1;
203 *res++ = globEna;
204
205 return IPMI_CC_OK;
206}
207
208//----------------------------------------------------------------------
Vijay Khemka666a4d92019-04-03 11:27:24 -0700209// Clear Message flags (IPMI/Section 22.3) (CMD_APP_CLEAR_MESSAGE_FLAGS)
210//----------------------------------------------------------------------
211ipmi_ret_t ipmiAppClearMsgFlags(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
212 ipmi_request_t request,
213 ipmi_response_t response,
214 ipmi_data_len_t data_len,
215 ipmi_context_t context)
216{
217 // Do Nothing and just return success
218 *data_len = 0;
219
220 return IPMI_CC_OK;
221}
222
223//----------------------------------------------------------------------
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700224// Get System GUID (CMD_APP_GET_SYS_GUID)
225//----------------------------------------------------------------------
226ipmi_ret_t ipmiAppGetSysGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
227 ipmi_request_t request, ipmi_response_t response,
228 ipmi_data_len_t data_len, ipmi_context_t context)
229{
230 uint8_t *res = reinterpret_cast<uint8_t *>(response);
231 if (getSystemGUID(res))
232 {
233 return IPMI_CC_UNSPECIFIED_ERROR;
234 }
235 *data_len = GUID_SIZE;
236 return IPMI_CC_OK;
237}
238
Vijay Khemka666a4d92019-04-03 11:27:24 -0700239//----------------------------------------------------------------------
240// Platform specific functions for storing app data
241//----------------------------------------------------------------------
242
243void flush_app_data()
244{
245 std::ofstream file(JSON_DATA_FILE);
246 file << appData;
247 return;
248}
249
250static int platSetSysFWVer(uint8_t *ver)
251{
252 std::stringstream ss;
253 int i;
254
255 /* TODO: implement byte 1: Set selector
256 * byte 2: encodeing, currently only supported
257 * ASCII which is value 0, UTF and unicode are
258 * not supported yet.
259 */
260 if (ver[1] & 0x0f)
261 return -1;
262
263 for (i = 3; i < 3 + ver[2]; i++)
264 {
265 ss << (char)ver[i];
266 }
267
268 appData[KEY_SYSFW_VER] = ss.str();
269 flush_app_data();
270
271 return 0;
272}
273
274static int platGetSysFWVer(uint8_t *ver)
275{
276 std::string str = appData[KEY_SYSFW_VER].get<std::string>();
277 int len;
278
279 *ver++ = 0; // byte 1: Set selector not supported
280 *ver++ = 0; // byte 2: Only ASCII supported
281
282 len = str.length();
283 *ver++ = len;
284 memcpy(ver, str.data(), len);
285
286 return (len + 3);
287}
288
289//----------------------------------------------------------------------
290// Set Sys Info Params (IPMI/Sec 22.14a) (CMD_APP_SET_SYS_INFO_PARAMS)
291//----------------------------------------------------------------------
292ipmi_ret_t ipmiAppSetSysInfoParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
293 ipmi_request_t request,
294 ipmi_response_t response,
295 ipmi_data_len_t data_len,
296 ipmi_context_t context)
297{
298 uint8_t *req = reinterpret_cast<uint8_t *>(request);
299
300 uint8_t param = req[0];
301 uint8_t req_len = *data_len;
302
303 *data_len = 0;
304
305 switch (param)
306 {
307 case SYS_INFO_PARAM_SET_IN_PROG:
308 sysInfoParams.set_in_prog = req[1];
309 break;
310 case SYS_INFO_PARAM_SYSFW_VER:
311 memcpy(sysInfoParams.sysfw_ver, &req[1], SIZE_SYSFW_VER);
312 if (platSetSysFWVer(sysInfoParams.sysfw_ver))
313 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
314 break;
315 case SYS_INFO_PARAM_SYS_NAME:
316 memcpy(sysInfoParams.sys_name, &req[1], SIZE_SYS_NAME);
317 break;
318 case SYS_INFO_PARAM_PRI_OS_NAME:
319 memcpy(sysInfoParams.pri_os_name, &req[1], SIZE_OS_NAME);
320 break;
321 case SYS_INFO_PARAM_PRESENT_OS_NAME:
322 memcpy(sysInfoParams.present_os_name, &req[1], SIZE_OS_NAME);
323 break;
324 case SYS_INFO_PARAM_PRESENT_OS_VER:
325 memcpy(sysInfoParams.present_os_ver, &req[1], SIZE_OS_VER);
326 break;
327 case SYS_INFO_PARAM_BMC_URL:
328 memcpy(sysInfoParams.bmc_url, &req[1], SIZE_BMC_URL);
329 break;
330 case SYS_INFO_PARAM_OS_HV_URL:
331 memcpy(sysInfoParams.os_hv_url, &req[1], SIZE_OS_HV_URL);
332 break;
333 case SYS_INFO_PARAM_BIOS_CURRENT_BOOT_LIST:
334 memcpy(sysInfoParams.bios_current_boot_list, &req[1], req_len);
335 appData[KEY_BIOS_BOOT_LEN] = req_len;
336 flush_app_data();
337 break;
338 case SYS_INFO_PARAM_BIOS_FIXED_BOOT_DEVICE:
339 if (SIZE_BIOS_FIXED_BOOT_DEVICE != req_len)
340 break;
341 memcpy(sysInfoParams.bios_fixed_boot_device, &req[1],
342 SIZE_BIOS_FIXED_BOOT_DEVICE);
343 break;
344 case SYS_INFO_PARAM_BIOS_RSTR_DFLT_SETTING:
345 if (SIZE_BIOS_RSTR_DFLT_SETTING != req_len)
346 break;
347 memcpy(sysInfoParams.bios_rstr_dflt_setting, &req[1],
348 SIZE_BIOS_RSTR_DFLT_SETTING);
349 break;
350 case SYS_INFO_PARAM_LAST_BOOT_TIME:
351 if (SIZE_LAST_BOOT_TIME != req_len)
352 break;
353 memcpy(sysInfoParams.last_boot_time, &req[1], SIZE_LAST_BOOT_TIME);
354 break;
355 default:
356 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
357 break;
358 }
359
360 return IPMI_CC_OK;
361}
362
363//----------------------------------------------------------------------
364// Get Sys Info Params (IPMI/Sec 22.14b) (CMD_APP_GET_SYS_INFO_PARAMS)
365//----------------------------------------------------------------------
366ipmi_ret_t ipmiAppGetSysInfoParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
367 ipmi_request_t request,
368 ipmi_response_t response,
369 ipmi_data_len_t data_len,
370 ipmi_context_t context)
371{
372 uint8_t *req = reinterpret_cast<uint8_t *>(request);
373 uint8_t *res = reinterpret_cast<uint8_t *>(response);
374
375 uint8_t param = req[1];
376 uint8_t len;
377
378 *res++ = 1; // Parameter revision
379 *data_len = 1;
380
381 switch (param)
382 {
383 case SYS_INFO_PARAM_SET_IN_PROG:
384 *res++ = sysInfoParams.set_in_prog;
385 *data_len += 1;
386 break;
387 case SYS_INFO_PARAM_SYSFW_VER:
388 if ((len = platGetSysFWVer(res)) < 0)
389 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
390 *data_len += SIZE_SYSFW_VER;
391 break;
392 case SYS_INFO_PARAM_SYS_NAME:
393 memcpy(res, sysInfoParams.sys_name, SIZE_SYS_NAME);
394 *data_len += SIZE_SYS_NAME;
395 break;
396 case SYS_INFO_PARAM_PRI_OS_NAME:
397 memcpy(res, sysInfoParams.pri_os_name, SIZE_OS_NAME);
398 *data_len += SIZE_OS_NAME;
399 break;
400 case SYS_INFO_PARAM_PRESENT_OS_NAME:
401 memcpy(res, sysInfoParams.present_os_name, SIZE_OS_NAME);
402 *data_len += SIZE_OS_NAME;
403 break;
404 case SYS_INFO_PARAM_PRESENT_OS_VER:
405 memcpy(res, sysInfoParams.present_os_ver, SIZE_OS_VER);
406 *data_len += SIZE_OS_VER;
407 break;
408 case SYS_INFO_PARAM_BMC_URL:
409 memcpy(res, sysInfoParams.bmc_url, SIZE_BMC_URL);
410 *data_len += SIZE_BMC_URL;
411 break;
412 case SYS_INFO_PARAM_OS_HV_URL:
413 memcpy(res, sysInfoParams.os_hv_url, SIZE_OS_HV_URL);
414 *data_len += SIZE_OS_HV_URL;
415 break;
416 case SYS_INFO_PARAM_BIOS_CURRENT_BOOT_LIST:
417 len = appData[KEY_BIOS_BOOT_LEN].get<uint8_t>();
418 memcpy(res, sysInfoParams.bios_current_boot_list, len);
419 *data_len += len;
420 break;
421 case SYS_INFO_PARAM_BIOS_FIXED_BOOT_DEVICE:
422 memcpy(res, sysInfoParams.bios_fixed_boot_device,
423 SIZE_BIOS_FIXED_BOOT_DEVICE);
424 *data_len += SIZE_BIOS_FIXED_BOOT_DEVICE;
425 break;
426 case SYS_INFO_PARAM_BIOS_RSTR_DFLT_SETTING:
427 memcpy(res, sysInfoParams.bios_rstr_dflt_setting,
428 SIZE_BIOS_RSTR_DFLT_SETTING);
429 *data_len += SIZE_BIOS_RSTR_DFLT_SETTING;
430 break;
431 case SYS_INFO_PARAM_LAST_BOOT_TIME:
432 memcpy(res, sysInfoParams.last_boot_time, SIZE_LAST_BOOT_TIME);
433 *data_len += SIZE_LAST_BOOT_TIME;
434 break;
435 default:
436 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
437 break;
438 }
439 return IPMI_CC_OK;
440}
441
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700442void registerAPPFunctions()
443{
Vijay Khemka666a4d92019-04-03 11:27:24 -0700444 /* Get App data stored in json file */
445 std::ifstream file(JSON_DATA_FILE);
446 if (file)
447 file >> appData;
448
449 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_SELFTEST_RESULTS, NULL,
450 ipmiAppGetSTResults,
451 PRIVILEGE_USER); // Get Self Test Results
452 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_MFR_TEST_ON, NULL,
453 ipmiAppMfrTestOn,
454 PRIVILEGE_USER); // Manufacturing Test On
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700455 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_DEV_GUID, NULL,
456 ipmiAppGetDevGUID,
457 PRIVILEGE_USER); // Get Device GUID
458 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_SET_GLOBAL_ENABLES, NULL,
459 ipmiAppSetGlobalEnables,
Vijay Khemka666a4d92019-04-03 11:27:24 -0700460 PRIVILEGE_USER); // Set Global Enables
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700461 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_GLOBAL_ENABLES, NULL,
462 ipmiAppGetGlobalEnables,
463 PRIVILEGE_USER); // Get Global Enables
Vijay Khemka666a4d92019-04-03 11:27:24 -0700464 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_CLEAR_MESSAGE_FLAGS, NULL,
465 ipmiAppClearMsgFlags,
466 PRIVILEGE_USER); // Clear Message flags
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700467 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_SYS_GUID, NULL,
468 ipmiAppGetSysGUID,
469 PRIVILEGE_USER); // Get System GUID
Vijay Khemka666a4d92019-04-03 11:27:24 -0700470 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_SET_SYS_INFO_PARAMS, NULL,
471 ipmiAppSetSysInfoParams,
472 PRIVILEGE_USER); // Set Sys Info Params
473 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_SYS_INFO_PARAMS, NULL,
474 ipmiAppGetSysInfoParams,
475 PRIVILEGE_USER); // Get Sys Info Params
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700476 return;
477}
478
479} // namespace ipmi