blob: 52eceb3f366a17e94973f0b57929604f61568758 [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
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070018#include <fcntl.h>
Vijay Khemka63c99be2020-05-27 19:14:35 -070019#include <ipmid/api.h>
20#include <sys/stat.h>
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070021#include <unistd.h>
Vijay Khemka63c99be2020-05-27 19:14:35 -070022
23#include <appcommands.hpp>
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070024#include <commandutils.hpp>
Vijay Khemka63c99be2020-05-27 19:14:35 -070025#include <nlohmann/json.hpp>
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070026#include <phosphor-logging/log.hpp>
27#include <sdbusplus/message/types.hpp>
Vijay Khemka63c99be2020-05-27 19:14:35 -070028
29#include <fstream>
30#include <iomanip>
31#include <iostream>
32#include <sstream>
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070033
34namespace ipmi
35{
36
37static void registerAPPFunctions() __attribute__((constructor));
38static constexpr size_t GUID_SIZE = 16;
39// TODO Make offset and location runtime configurable to ensure we
40// can make each define their own locations.
41static constexpr off_t OFFSET_SYS_GUID = 0x17F0;
Vijay Khemka63c99be2020-05-27 19:14:35 -070042static 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;
Vijay Khemka802ccb12019-08-27 15:03:44 -070047nlohmann::json appData __attribute__((init_priority(101)));
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070048
Vijay Khemka63c99be2020-05-27 19:14:35 -070049void printGUID(uint8_t* guid, off_t offset)
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070050{
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
Vijay Khemka63c99be2020-05-27 19:14:35 -070060int getGUID(off_t offset, uint8_t* guid)
Vijay Khemkaa2d52f12019-03-27 14:54:00 -070061{
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
Vijay Khemka63c99be2020-05-27 19:14:35 -0700102int getSystemGUID(uint8_t* guid)
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700103{
104 return getGUID(OFFSET_SYS_GUID, guid);
105}
106
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700107//----------------------------------------------------------------------
Vijay Khemka666a4d92019-04-03 11:27:24 -0700108// Get Self Test Results (IPMI/Section 20.4) (CMD_APP_GET_SELFTEST_RESULTS)
109//----------------------------------------------------------------------
110ipmi_ret_t ipmiAppGetSTResults(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
111 ipmi_request_t request, ipmi_response_t response,
112 ipmi_data_len_t data_len, ipmi_context_t context)
113{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700114 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka666a4d92019-04-03 11:27:24 -0700115
116 // TODO: Following data needs to be updated based on self-test results
117 *res++ = 0x55; // Self-Test result
118 *res++ = 0x00; // Extra error info in case of failure
119
120 *data_len = 2;
121
122 return IPMI_CC_OK;
123}
124
125//----------------------------------------------------------------------
126// Manufacturing Test On (IPMI/Section 20.5) (CMD_APP_MFR_TEST_ON)
127//----------------------------------------------------------------------
128ipmi_ret_t ipmiAppMfrTestOn(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
129 ipmi_request_t request, ipmi_response_t response,
130 ipmi_data_len_t data_len, ipmi_context_t context)
131{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700132 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka666a4d92019-04-03 11:27:24 -0700133 std::string mfrTest = "sled-cycle";
134
135 if (!memcmp(req, mfrTest.data(), mfrTest.length()) &&
136 (*data_len == mfrTest.length()))
137 {
138 /* sled-cycle the BMC */
Vijay Khemka2515e092020-03-13 12:49:50 -0700139 system("/usr/sbin/power-util sled-cycle");
Vijay Khemka666a4d92019-04-03 11:27:24 -0700140 }
141 else
142 {
143 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
144 }
145
146 *data_len = 0;
147
148 return IPMI_CC_OK;
149}
150
151//----------------------------------------------------------------------
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700152// Set Global Enables (CMD_APP_SET_GLOBAL_ENABLES)
153//----------------------------------------------------------------------
154ipmi_ret_t ipmiAppSetGlobalEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
155 ipmi_request_t request,
156 ipmi_response_t response,
157 ipmi_data_len_t data_len,
158 ipmi_context_t context)
159{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700160 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700161
162 globEna = *req;
163 *data_len = 0;
164
165 return IPMI_CC_OK;
166}
167
168//----------------------------------------------------------------------
169// Get Global Enables (CMD_APP_GET_GLOBAL_ENABLES)
170//----------------------------------------------------------------------
171ipmi_ret_t ipmiAppGetGlobalEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
172 ipmi_request_t request,
173 ipmi_response_t response,
174 ipmi_data_len_t data_len,
175 ipmi_context_t context)
176{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700177 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700178
179 *data_len = 1;
180 *res++ = globEna;
181
182 return IPMI_CC_OK;
183}
184
185//----------------------------------------------------------------------
Vijay Khemka666a4d92019-04-03 11:27:24 -0700186// Clear Message flags (IPMI/Section 22.3) (CMD_APP_CLEAR_MESSAGE_FLAGS)
187//----------------------------------------------------------------------
188ipmi_ret_t ipmiAppClearMsgFlags(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
189 ipmi_request_t request,
190 ipmi_response_t response,
191 ipmi_data_len_t data_len,
192 ipmi_context_t context)
193{
194 // Do Nothing and just return success
195 *data_len = 0;
196
197 return IPMI_CC_OK;
198}
199
200//----------------------------------------------------------------------
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700201// Get System GUID (CMD_APP_GET_SYS_GUID)
202//----------------------------------------------------------------------
203ipmi_ret_t ipmiAppGetSysGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
204 ipmi_request_t request, ipmi_response_t response,
205 ipmi_data_len_t data_len, ipmi_context_t context)
206{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700207 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700208 if (getSystemGUID(res))
209 {
210 return IPMI_CC_UNSPECIFIED_ERROR;
211 }
212 *data_len = GUID_SIZE;
213 return IPMI_CC_OK;
214}
215
Vijay Khemka666a4d92019-04-03 11:27:24 -0700216//----------------------------------------------------------------------
217// Platform specific functions for storing app data
218//----------------------------------------------------------------------
219
220void flush_app_data()
221{
Vijay Khemka802ccb12019-08-27 15:03:44 -0700222 std::ofstream file(JSON_APP_DATA_FILE);
Vijay Khemka666a4d92019-04-03 11:27:24 -0700223 file << appData;
Vijay Khemka802ccb12019-08-27 15:03:44 -0700224 file.close();
Vijay Khemka666a4d92019-04-03 11:27:24 -0700225 return;
226}
227
Vijay Khemka63c99be2020-05-27 19:14:35 -0700228static int platSetSysFWVer(uint8_t* ver)
Vijay Khemka666a4d92019-04-03 11:27:24 -0700229{
230 std::stringstream ss;
231 int i;
232
233 /* TODO: implement byte 1: Set selector
234 * byte 2: encodeing, currently only supported
235 * ASCII which is value 0, UTF and unicode are
236 * not supported yet.
237 */
238 if (ver[1] & 0x0f)
239 return -1;
240
241 for (i = 3; i < 3 + ver[2]; i++)
242 {
243 ss << (char)ver[i];
244 }
245
246 appData[KEY_SYSFW_VER] = ss.str();
247 flush_app_data();
248
249 return 0;
250}
251
Vijay Khemka63c99be2020-05-27 19:14:35 -0700252static int platGetSysFWVer(uint8_t* ver)
Vijay Khemka666a4d92019-04-03 11:27:24 -0700253{
254 std::string str = appData[KEY_SYSFW_VER].get<std::string>();
255 int len;
256
257 *ver++ = 0; // byte 1: Set selector not supported
258 *ver++ = 0; // byte 2: Only ASCII supported
259
260 len = str.length();
261 *ver++ = len;
262 memcpy(ver, str.data(), len);
263
264 return (len + 3);
265}
266
267//----------------------------------------------------------------------
268// Set Sys Info Params (IPMI/Sec 22.14a) (CMD_APP_SET_SYS_INFO_PARAMS)
269//----------------------------------------------------------------------
270ipmi_ret_t ipmiAppSetSysInfoParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
271 ipmi_request_t request,
272 ipmi_response_t response,
273 ipmi_data_len_t data_len,
274 ipmi_context_t context)
275{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700276 uint8_t* req = reinterpret_cast<uint8_t*>(request);
Vijay Khemka666a4d92019-04-03 11:27:24 -0700277
278 uint8_t param = req[0];
279 uint8_t req_len = *data_len;
280
281 *data_len = 0;
282
283 switch (param)
284 {
285 case SYS_INFO_PARAM_SET_IN_PROG:
286 sysInfoParams.set_in_prog = req[1];
287 break;
288 case SYS_INFO_PARAM_SYSFW_VER:
289 memcpy(sysInfoParams.sysfw_ver, &req[1], SIZE_SYSFW_VER);
290 if (platSetSysFWVer(sysInfoParams.sysfw_ver))
291 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
292 break;
293 case SYS_INFO_PARAM_SYS_NAME:
294 memcpy(sysInfoParams.sys_name, &req[1], SIZE_SYS_NAME);
295 break;
296 case SYS_INFO_PARAM_PRI_OS_NAME:
297 memcpy(sysInfoParams.pri_os_name, &req[1], SIZE_OS_NAME);
298 break;
299 case SYS_INFO_PARAM_PRESENT_OS_NAME:
300 memcpy(sysInfoParams.present_os_name, &req[1], SIZE_OS_NAME);
301 break;
302 case SYS_INFO_PARAM_PRESENT_OS_VER:
303 memcpy(sysInfoParams.present_os_ver, &req[1], SIZE_OS_VER);
304 break;
305 case SYS_INFO_PARAM_BMC_URL:
306 memcpy(sysInfoParams.bmc_url, &req[1], SIZE_BMC_URL);
307 break;
308 case SYS_INFO_PARAM_OS_HV_URL:
309 memcpy(sysInfoParams.os_hv_url, &req[1], SIZE_OS_HV_URL);
310 break;
311 case SYS_INFO_PARAM_BIOS_CURRENT_BOOT_LIST:
312 memcpy(sysInfoParams.bios_current_boot_list, &req[1], req_len);
313 appData[KEY_BIOS_BOOT_LEN] = req_len;
314 flush_app_data();
315 break;
316 case SYS_INFO_PARAM_BIOS_FIXED_BOOT_DEVICE:
317 if (SIZE_BIOS_FIXED_BOOT_DEVICE != req_len)
318 break;
319 memcpy(sysInfoParams.bios_fixed_boot_device, &req[1],
320 SIZE_BIOS_FIXED_BOOT_DEVICE);
321 break;
322 case SYS_INFO_PARAM_BIOS_RSTR_DFLT_SETTING:
323 if (SIZE_BIOS_RSTR_DFLT_SETTING != req_len)
324 break;
325 memcpy(sysInfoParams.bios_rstr_dflt_setting, &req[1],
326 SIZE_BIOS_RSTR_DFLT_SETTING);
327 break;
328 case SYS_INFO_PARAM_LAST_BOOT_TIME:
329 if (SIZE_LAST_BOOT_TIME != req_len)
330 break;
331 memcpy(sysInfoParams.last_boot_time, &req[1], SIZE_LAST_BOOT_TIME);
332 break;
333 default:
334 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
335 break;
336 }
337
338 return IPMI_CC_OK;
339}
340
341//----------------------------------------------------------------------
342// Get Sys Info Params (IPMI/Sec 22.14b) (CMD_APP_GET_SYS_INFO_PARAMS)
343//----------------------------------------------------------------------
344ipmi_ret_t ipmiAppGetSysInfoParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
345 ipmi_request_t request,
346 ipmi_response_t response,
347 ipmi_data_len_t data_len,
348 ipmi_context_t context)
349{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700350 uint8_t* req = reinterpret_cast<uint8_t*>(request);
351 uint8_t* res = reinterpret_cast<uint8_t*>(response);
Vijay Khemka666a4d92019-04-03 11:27:24 -0700352
353 uint8_t param = req[1];
354 uint8_t len;
355
356 *res++ = 1; // Parameter revision
357 *data_len = 1;
358
359 switch (param)
360 {
361 case SYS_INFO_PARAM_SET_IN_PROG:
362 *res++ = sysInfoParams.set_in_prog;
363 *data_len += 1;
364 break;
365 case SYS_INFO_PARAM_SYSFW_VER:
366 if ((len = platGetSysFWVer(res)) < 0)
367 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
368 *data_len += SIZE_SYSFW_VER;
369 break;
370 case SYS_INFO_PARAM_SYS_NAME:
371 memcpy(res, sysInfoParams.sys_name, SIZE_SYS_NAME);
372 *data_len += SIZE_SYS_NAME;
373 break;
374 case SYS_INFO_PARAM_PRI_OS_NAME:
375 memcpy(res, sysInfoParams.pri_os_name, SIZE_OS_NAME);
376 *data_len += SIZE_OS_NAME;
377 break;
378 case SYS_INFO_PARAM_PRESENT_OS_NAME:
379 memcpy(res, sysInfoParams.present_os_name, SIZE_OS_NAME);
380 *data_len += SIZE_OS_NAME;
381 break;
382 case SYS_INFO_PARAM_PRESENT_OS_VER:
383 memcpy(res, sysInfoParams.present_os_ver, SIZE_OS_VER);
384 *data_len += SIZE_OS_VER;
385 break;
386 case SYS_INFO_PARAM_BMC_URL:
387 memcpy(res, sysInfoParams.bmc_url, SIZE_BMC_URL);
388 *data_len += SIZE_BMC_URL;
389 break;
390 case SYS_INFO_PARAM_OS_HV_URL:
391 memcpy(res, sysInfoParams.os_hv_url, SIZE_OS_HV_URL);
392 *data_len += SIZE_OS_HV_URL;
393 break;
394 case SYS_INFO_PARAM_BIOS_CURRENT_BOOT_LIST:
395 len = appData[KEY_BIOS_BOOT_LEN].get<uint8_t>();
396 memcpy(res, sysInfoParams.bios_current_boot_list, len);
397 *data_len += len;
398 break;
399 case SYS_INFO_PARAM_BIOS_FIXED_BOOT_DEVICE:
400 memcpy(res, sysInfoParams.bios_fixed_boot_device,
401 SIZE_BIOS_FIXED_BOOT_DEVICE);
402 *data_len += SIZE_BIOS_FIXED_BOOT_DEVICE;
403 break;
404 case SYS_INFO_PARAM_BIOS_RSTR_DFLT_SETTING:
405 memcpy(res, sysInfoParams.bios_rstr_dflt_setting,
406 SIZE_BIOS_RSTR_DFLT_SETTING);
407 *data_len += SIZE_BIOS_RSTR_DFLT_SETTING;
408 break;
409 case SYS_INFO_PARAM_LAST_BOOT_TIME:
410 memcpy(res, sysInfoParams.last_boot_time, SIZE_LAST_BOOT_TIME);
411 *data_len += SIZE_LAST_BOOT_TIME;
412 break;
413 default:
414 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
415 break;
416 }
417 return IPMI_CC_OK;
418}
419
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700420void registerAPPFunctions()
421{
Vijay Khemka666a4d92019-04-03 11:27:24 -0700422 /* Get App data stored in json file */
Vijay Khemka802ccb12019-08-27 15:03:44 -0700423 std::ifstream file(JSON_APP_DATA_FILE);
Vijay Khemka666a4d92019-04-03 11:27:24 -0700424 if (file)
Vijay Khemka802ccb12019-08-27 15:03:44 -0700425 {
Vijay Khemka666a4d92019-04-03 11:27:24 -0700426 file >> appData;
Vijay Khemka802ccb12019-08-27 15:03:44 -0700427 file.close();
428 }
Vijay Khemka666a4d92019-04-03 11:27:24 -0700429
430 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_SELFTEST_RESULTS, NULL,
431 ipmiAppGetSTResults,
432 PRIVILEGE_USER); // Get Self Test Results
433 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_MFR_TEST_ON, NULL,
434 ipmiAppMfrTestOn,
435 PRIVILEGE_USER); // Manufacturing Test On
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700436 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_SET_GLOBAL_ENABLES, NULL,
437 ipmiAppSetGlobalEnables,
Vijay Khemka666a4d92019-04-03 11:27:24 -0700438 PRIVILEGE_USER); // Set Global Enables
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700439 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_GLOBAL_ENABLES, NULL,
440 ipmiAppGetGlobalEnables,
441 PRIVILEGE_USER); // Get Global Enables
Vijay Khemka666a4d92019-04-03 11:27:24 -0700442 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_CLEAR_MESSAGE_FLAGS, NULL,
443 ipmiAppClearMsgFlags,
444 PRIVILEGE_USER); // Clear Message flags
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700445 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_SYS_GUID, NULL,
446 ipmiAppGetSysGUID,
447 PRIVILEGE_USER); // Get System GUID
Vijay Khemka666a4d92019-04-03 11:27:24 -0700448 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_SET_SYS_INFO_PARAMS, NULL,
449 ipmiAppSetSysInfoParams,
450 PRIVILEGE_USER); // Set Sys Info Params
451 ipmiPrintAndRegister(NETFUN_APP, CMD_APP_GET_SYS_INFO_PARAMS, NULL,
452 ipmiAppGetSysInfoParams,
453 PRIVILEGE_USER); // Get Sys Info Params
Vijay Khemkaa2d52f12019-03-27 14:54:00 -0700454 return;
455}
456
457} // namespace ipmi