blob: c50e8407fab86dc11b21dc372ba1aea576900196 [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;
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070041static constexpr const char *FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom";
Vijay Khemka666a4d92019-04-03 11:27:24 -070042
43// TODO: Need to store this info after identifying proper storage
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070044static uint8_t globEna = 0x09;
Vijay Khemka666a4d92019-04-03 11:27:24 -070045static SysInfoParam sysInfoParams;
Vijay Khemka802ccb12019-08-27 15:03:44 -070046nlohmann::json appData __attribute__((init_priority(101)));
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070047
48void printGUID(uint8_t *guid, off_t offset)
49{
50 std::cout << "Read GUID from offset : " << offset << " :\n";
51 for (int i = 0; i < GUID_SIZE; i++)
52 {
53 int data = guid[i];
54 std::cout << std::hex << data << " ";
55 }
56 std::cout << std::endl;
57}
58
59int getGUID(off_t offset, uint8_t *guid)
60{
61 int fd = -1;
62 ssize_t bytes_rd;
63 int ret = 0;
64
65 errno = 0;
66
67 // Check if file is present
68 if (access(FRU_EEPROM, F_OK) == -1)
69 {
70 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl;
71 return errno;
72 }
73
74 // Open the file
75 fd = open(FRU_EEPROM, O_RDONLY);
76 if (fd == -1)
77 {
78 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl;
79 return errno;
80 }
81
82 // seek to the offset
83 lseek(fd, offset, SEEK_SET);
84
85 // Read bytes from location
86 bytes_rd = read(fd, guid, GUID_SIZE);
87 if (bytes_rd != GUID_SIZE)
88 {
89 phosphor::logging::log<phosphor::logging::level::ERR>(
90 "GUID read data from EEPROM failed");
91 ret = errno;
92 }
93 else
94 {
95 printGUID(guid, offset);
96 }
97 close(fd);
98 return ret;
99}
100
101int getSystemGUID(uint8_t *guid)
102{
103 return getGUID(OFFSET_SYS_GUID, guid);
104}
105
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700106//----------------------------------------------------------------------
Vijay Khemka666a4d92019-04-03 11:27:24 -0700107// Get Self Test Results (IPMI/Section 20.4) (CMD_APP_GET_SELFTEST_RESULTS)
108//----------------------------------------------------------------------
109ipmi_ret_t ipmiAppGetSTResults(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
110 ipmi_request_t request, ipmi_response_t response,
111 ipmi_data_len_t data_len, ipmi_context_t context)
112{
113 uint8_t *res = reinterpret_cast<uint8_t *>(response);
114
115 // TODO: Following data needs to be updated based on self-test results
116 *res++ = 0x55; // Self-Test result
117 *res++ = 0x00; // Extra error info in case of failure
118
119 *data_len = 2;
120
121 return IPMI_CC_OK;
122}
123
124//----------------------------------------------------------------------
125// Manufacturing Test On (IPMI/Section 20.5) (CMD_APP_MFR_TEST_ON)
126//----------------------------------------------------------------------
127ipmi_ret_t ipmiAppMfrTestOn(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
128 ipmi_request_t request, ipmi_response_t response,
129 ipmi_data_len_t data_len, ipmi_context_t context)
130{
131 uint8_t *req = reinterpret_cast<uint8_t *>(request);
132 std::string mfrTest = "sled-cycle";
133
134 if (!memcmp(req, mfrTest.data(), mfrTest.length()) &&
135 (*data_len == mfrTest.length()))
136 {
137 /* sled-cycle the BMC */
Vijay Khemka2515e092020-03-13 12:49:50 -0700138 system("/usr/sbin/power-util sled-cycle");
Vijay Khemka666a4d92019-04-03 11:27:24 -0700139 }
140 else
141 {
142 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
143 }
144
145 *data_len = 0;
146
147 return IPMI_CC_OK;
148}
149
150//----------------------------------------------------------------------
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700151// Set Global Enables (CMD_APP_SET_GLOBAL_ENABLES)
152//----------------------------------------------------------------------
153ipmi_ret_t ipmiAppSetGlobalEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
154 ipmi_request_t request,
155 ipmi_response_t response,
156 ipmi_data_len_t data_len,
157 ipmi_context_t context)
158{
159 uint8_t *req = reinterpret_cast<uint8_t *>(request);
160
161 globEna = *req;
162 *data_len = 0;
163
164 return IPMI_CC_OK;
165}
166
167//----------------------------------------------------------------------
168// Get Global Enables (CMD_APP_GET_GLOBAL_ENABLES)
169//----------------------------------------------------------------------
170ipmi_ret_t ipmiAppGetGlobalEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
171 ipmi_request_t request,
172 ipmi_response_t response,
173 ipmi_data_len_t data_len,
174 ipmi_context_t context)
175{
176 uint8_t *res = reinterpret_cast<uint8_t *>(response);
177
178 *data_len = 1;
179 *res++ = globEna;
180
181 return IPMI_CC_OK;
182}
183
184//----------------------------------------------------------------------
Vijay Khemka666a4d92019-04-03 11:27:24 -0700185// Clear Message flags (IPMI/Section 22.3) (CMD_APP_CLEAR_MESSAGE_FLAGS)
186//----------------------------------------------------------------------
187ipmi_ret_t ipmiAppClearMsgFlags(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
188 ipmi_request_t request,
189 ipmi_response_t response,
190 ipmi_data_len_t data_len,
191 ipmi_context_t context)
192{
193 // Do Nothing and just return success
194 *data_len = 0;
195
196 return IPMI_CC_OK;
197}
198
199//----------------------------------------------------------------------
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700200// Get System GUID (CMD_APP_GET_SYS_GUID)
201//----------------------------------------------------------------------
202ipmi_ret_t ipmiAppGetSysGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
203 ipmi_request_t request, ipmi_response_t response,
204 ipmi_data_len_t data_len, ipmi_context_t context)
205{
206 uint8_t *res = reinterpret_cast<uint8_t *>(response);
207 if (getSystemGUID(res))
208 {
209 return IPMI_CC_UNSPECIFIED_ERROR;
210 }
211 *data_len = GUID_SIZE;
212 return IPMI_CC_OK;
213}
214
Vijay Khemka666a4d92019-04-03 11:27:24 -0700215//----------------------------------------------------------------------
216// Platform specific functions for storing app data
217//----------------------------------------------------------------------
218
219void flush_app_data()
220{
Vijay Khemka802ccb12019-08-27 15:03:44 -0700221 std::ofstream file(JSON_APP_DATA_FILE);
Vijay Khemka666a4d92019-04-03 11:27:24 -0700222 file << appData;
Vijay Khemka802ccb12019-08-27 15:03:44 -0700223 file.close();
Vijay Khemka666a4d92019-04-03 11:27:24 -0700224 return;
225}
226
227static int platSetSysFWVer(uint8_t *ver)
228{
229 std::stringstream ss;
230 int i;
231
232 /* TODO: implement byte 1: Set selector
233 * byte 2: encodeing, currently only supported
234 * ASCII which is value 0, UTF and unicode are
235 * not supported yet.
236 */
237 if (ver[1] & 0x0f)
238 return -1;
239
240 for (i = 3; i < 3 + ver[2]; i++)
241 {
242 ss << (char)ver[i];
243 }
244
245 appData[KEY_SYSFW_VER] = ss.str();
246 flush_app_data();
247
248 return 0;
249}
250
251static int platGetSysFWVer(uint8_t *ver)
252{
253 std::string str = appData[KEY_SYSFW_VER].get<std::string>();
254 int len;
255
256 *ver++ = 0; // byte 1: Set selector not supported
257 *ver++ = 0; // byte 2: Only ASCII supported
258
259 len = str.length();
260 *ver++ = len;
261 memcpy(ver, str.data(), len);
262
263 return (len + 3);
264}
265
266//----------------------------------------------------------------------
267// Set Sys Info Params (IPMI/Sec 22.14a) (CMD_APP_SET_SYS_INFO_PARAMS)
268//----------------------------------------------------------------------
269ipmi_ret_t ipmiAppSetSysInfoParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
270 ipmi_request_t request,
271 ipmi_response_t response,
272 ipmi_data_len_t data_len,
273 ipmi_context_t context)
274{
275 uint8_t *req = reinterpret_cast<uint8_t *>(request);
276
277 uint8_t param = req[0];
278 uint8_t req_len = *data_len;
279
280 *data_len = 0;
281
282 switch (param)
283 {
284 case SYS_INFO_PARAM_SET_IN_PROG:
285 sysInfoParams.set_in_prog = req[1];
286 break;
287 case SYS_INFO_PARAM_SYSFW_VER:
288 memcpy(sysInfoParams.sysfw_ver, &req[1], SIZE_SYSFW_VER);
289 if (platSetSysFWVer(sysInfoParams.sysfw_ver))
290 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
291 break;
292 case SYS_INFO_PARAM_SYS_NAME:
293 memcpy(sysInfoParams.sys_name, &req[1], SIZE_SYS_NAME);
294 break;
295 case SYS_INFO_PARAM_PRI_OS_NAME:
296 memcpy(sysInfoParams.pri_os_name, &req[1], SIZE_OS_NAME);
297 break;
298 case SYS_INFO_PARAM_PRESENT_OS_NAME:
299 memcpy(sysInfoParams.present_os_name, &req[1], SIZE_OS_NAME);
300 break;
301 case SYS_INFO_PARAM_PRESENT_OS_VER:
302 memcpy(sysInfoParams.present_os_ver, &req[1], SIZE_OS_VER);
303 break;
304 case SYS_INFO_PARAM_BMC_URL:
305 memcpy(sysInfoParams.bmc_url, &req[1], SIZE_BMC_URL);
306 break;
307 case SYS_INFO_PARAM_OS_HV_URL:
308 memcpy(sysInfoParams.os_hv_url, &req[1], SIZE_OS_HV_URL);
309 break;
310 case SYS_INFO_PARAM_BIOS_CURRENT_BOOT_LIST:
311 memcpy(sysInfoParams.bios_current_boot_list, &req[1], req_len);
312 appData[KEY_BIOS_BOOT_LEN] = req_len;
313 flush_app_data();
314 break;
315 case SYS_INFO_PARAM_BIOS_FIXED_BOOT_DEVICE:
316 if (SIZE_BIOS_FIXED_BOOT_DEVICE != req_len)
317 break;
318 memcpy(sysInfoParams.bios_fixed_boot_device, &req[1],
319 SIZE_BIOS_FIXED_BOOT_DEVICE);
320 break;
321 case SYS_INFO_PARAM_BIOS_RSTR_DFLT_SETTING:
322 if (SIZE_BIOS_RSTR_DFLT_SETTING != req_len)
323 break;
324 memcpy(sysInfoParams.bios_rstr_dflt_setting, &req[1],
325 SIZE_BIOS_RSTR_DFLT_SETTING);
326 break;
327 case SYS_INFO_PARAM_LAST_BOOT_TIME:
328 if (SIZE_LAST_BOOT_TIME != req_len)
329 break;
330 memcpy(sysInfoParams.last_boot_time, &req[1], SIZE_LAST_BOOT_TIME);
331 break;
332 default:
333 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
334 break;
335 }
336
337 return IPMI_CC_OK;
338}
339
340//----------------------------------------------------------------------
341// Get Sys Info Params (IPMI/Sec 22.14b) (CMD_APP_GET_SYS_INFO_PARAMS)
342//----------------------------------------------------------------------
343ipmi_ret_t ipmiAppGetSysInfoParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
344 ipmi_request_t request,
345 ipmi_response_t response,
346 ipmi_data_len_t data_len,
347 ipmi_context_t context)
348{
349 uint8_t *req = reinterpret_cast<uint8_t *>(request);
350 uint8_t *res = reinterpret_cast<uint8_t *>(response);
351
352 uint8_t param = req[1];
353 uint8_t len;
354
355 *res++ = 1; // Parameter revision
356 *data_len = 1;
357
358 switch (param)
359 {
360 case SYS_INFO_PARAM_SET_IN_PROG:
361 *res++ = sysInfoParams.set_in_prog;
362 *data_len += 1;
363 break;
364 case SYS_INFO_PARAM_SYSFW_VER:
365 if ((len = platGetSysFWVer(res)) < 0)
366 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
367 *data_len += SIZE_SYSFW_VER;
368 break;
369 case SYS_INFO_PARAM_SYS_NAME:
370 memcpy(res, sysInfoParams.sys_name, SIZE_SYS_NAME);
371 *data_len += SIZE_SYS_NAME;
372 break;
373 case SYS_INFO_PARAM_PRI_OS_NAME:
374 memcpy(res, sysInfoParams.pri_os_name, SIZE_OS_NAME);
375 *data_len += SIZE_OS_NAME;
376 break;
377 case SYS_INFO_PARAM_PRESENT_OS_NAME:
378 memcpy(res, sysInfoParams.present_os_name, SIZE_OS_NAME);
379 *data_len += SIZE_OS_NAME;
380 break;
381 case SYS_INFO_PARAM_PRESENT_OS_VER:
382 memcpy(res, sysInfoParams.present_os_ver, SIZE_OS_VER);
383 *data_len += SIZE_OS_VER;
384 break;
385 case SYS_INFO_PARAM_BMC_URL:
386 memcpy(res, sysInfoParams.bmc_url, SIZE_BMC_URL);
387 *data_len += SIZE_BMC_URL;
388 break;
389 case SYS_INFO_PARAM_OS_HV_URL:
390 memcpy(res, sysInfoParams.os_hv_url, SIZE_OS_HV_URL);
391 *data_len += SIZE_OS_HV_URL;
392 break;
393 case SYS_INFO_PARAM_BIOS_CURRENT_BOOT_LIST:
394 len = appData[KEY_BIOS_BOOT_LEN].get<uint8_t>();
395 memcpy(res, sysInfoParams.bios_current_boot_list, len);
396 *data_len += len;
397 break;
398 case SYS_INFO_PARAM_BIOS_FIXED_BOOT_DEVICE:
399 memcpy(res, sysInfoParams.bios_fixed_boot_device,
400 SIZE_BIOS_FIXED_BOOT_DEVICE);
401 *data_len += SIZE_BIOS_FIXED_BOOT_DEVICE;
402 break;
403 case SYS_INFO_PARAM_BIOS_RSTR_DFLT_SETTING:
404 memcpy(res, sysInfoParams.bios_rstr_dflt_setting,
405 SIZE_BIOS_RSTR_DFLT_SETTING);
406 *data_len += SIZE_BIOS_RSTR_DFLT_SETTING;
407 break;
408 case SYS_INFO_PARAM_LAST_BOOT_TIME:
409 memcpy(res, sysInfoParams.last_boot_time, SIZE_LAST_BOOT_TIME);
410 *data_len += SIZE_LAST_BOOT_TIME;
411 break;
412 default:
413 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
414 break;
415 }
416 return IPMI_CC_OK;
417}
418
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700419void registerAPPFunctions()
420{
Vijay Khemka666a4d92019-04-03 11:27:24 -0700421 /* Get App data stored in json file */
Vijay Khemka802ccb12019-08-27 15:03:44 -0700422 std::ifstream file(JSON_APP_DATA_FILE);
Vijay Khemka666a4d92019-04-03 11:27:24 -0700423 if (file)
Vijay Khemka802ccb12019-08-27 15:03:44 -0700424 {
Vijay Khemka666a4d92019-04-03 11:27:24 -0700425 file >> appData;
Vijay Khemka802ccb12019-08-27 15:03:44 -0700426 file.close();
427 }
Vijay Khemka666a4d92019-04-03 11:27:24 -0700428
429 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_SELFTEST_RESULTS, NULL,
430 ipmiAppGetSTResults,
431 PRIVILEGE_USER); // Get Self Test Results
432 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_MFR_TEST_ON, NULL,
433 ipmiAppMfrTestOn,
434 PRIVILEGE_USER); // Manufacturing Test On
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700435 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_SET_GLOBAL_ENABLES, NULL,
436 ipmiAppSetGlobalEnables,
Vijay Khemka666a4d92019-04-03 11:27:24 -0700437 PRIVILEGE_USER); // Set Global Enables
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700438 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_GLOBAL_ENABLES, NULL,
439 ipmiAppGetGlobalEnables,
440 PRIVILEGE_USER); // Get Global Enables
Vijay Khemka666a4d92019-04-03 11:27:24 -0700441 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_CLEAR_MESSAGE_FLAGS, NULL,
442 ipmiAppClearMsgFlags,
443 PRIVILEGE_USER); // Clear Message flags
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700444 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_SYS_GUID, NULL,
445 ipmiAppGetSysGUID,
446 PRIVILEGE_USER); // Get System GUID
Vijay Khemka666a4d92019-04-03 11:27:24 -0700447 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_SET_SYS_INFO_PARAMS, NULL,
448 ipmiAppSetSysInfoParams,
449 PRIVILEGE_USER); // Set Sys Info Params
450 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_SYS_INFO_PARAMS, NULL,
451 ipmiAppGetSysInfoParams,
452 PRIVILEGE_USER); // Get Sys Info Params
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700453 return;
454}
455
456} // namespace ipmi