blob: bbcb441990fdaa78525201a2ca4152eed071a4ef [file] [log] [blame]
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +05301#include <cstdio>
2#include <string>
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -05003#include <arpa/inet.h>
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +05304#include <systemd/sd-bus.h>
5#include <mapper.h>
6#include <chrono>
Tom Joseph6f7deaa2017-06-30 19:03:54 +05307#include "selutility.hpp"
Chris Austen41a4b312015-10-25 03:45:42 -05008#include "storagehandler.h"
9#include "storageaddsel.h"
Patrick Williams37af7332016-09-02 21:21:42 -050010#include "host-ipmid/ipmid-api.h"
Tom Joseph6f7deaa2017-06-30 19:03:54 +053011#include <phosphor-logging/log.hpp>
12#include <sdbusplus/server.hpp>
13#include "xyz/openbmc_project/Common/error.hpp"
Chris Austen41a4b312015-10-25 03:45:42 -050014
Chris Austenb4f5b922015-10-13 12:44:43 -050015void register_netfn_storage_functions() __attribute__((constructor));
16
17
18unsigned int g_sel_time = 0xFFFFFFFF;
Nan Li36c0cb62016-03-31 11:16:08 +080019extern unsigned short g_sel_reserve;
Chris Austenb4f5b922015-10-13 12:44:43 -050020
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +053021constexpr auto time_manager_intf = "org.openbmc.TimeManager";
22constexpr auto time_manager_obj = "/org/openbmc/TimeManager";
23
Tom Joseph6f7deaa2017-06-30 19:03:54 +053024namespace cache
25{
26 /*
27 * This cache contains the object paths of the logging entries sorted in the
28 * order of the filename(numeric order). The cache is initialized by
29 * invoking readLoggingObjectPaths with the cache as the parameter. The
30 * cache is invoked in the execution of the Get SEL info and Delete SEL
31 * entry command. The Get SEL Info command is typically invoked before the
32 * Get SEL entry command, so the cache is utilized for responding to Get SEL
33 * entry command. The cache is invalidated by clearing after Delete SEL
34 * entry and Clear SEL command.
35 */
36 ipmi::sel::ObjectPaths paths;
37
38} // namespace objectPathsCache
39
40using InternalFailure =
41 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
42using namespace phosphor::logging;
43
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -050044ipmi_ret_t ipmi_storage_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
45 ipmi_request_t request, ipmi_response_t response,
Chris Austenb4f5b922015-10-13 12:44:43 -050046 ipmi_data_len_t data_len, ipmi_context_t context)
47{
48 printf("Handling STORAGE WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
49 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +080050 ipmi_ret_t rc = IPMI_CC_INVALID;
Chris Austenb4f5b922015-10-13 12:44:43 -050051 *data_len = 0;
52 return rc;
53}
54
Tom Joseph6f7deaa2017-06-30 19:03:54 +053055ipmi_ret_t getSELInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
56 ipmi_request_t request, ipmi_response_t response,
57 ipmi_data_len_t data_len, ipmi_context_t context)
58{
59 std::vector<uint8_t> outPayload(sizeof(ipmi::sel::GetSELInfoResponse));
60 auto responseData = reinterpret_cast<ipmi::sel::GetSELInfoResponse*>
61 (outPayload.data());
62
63 responseData->selVersion = ipmi::sel::selVersion;
64 // Last erase timestamp is not available from log manager.
65 responseData->eraseTimeStamp = ipmi::sel::invalidTimeStamp;
66 responseData->operationSupport = ipmi::sel::operationSupport;
67
68 ipmi::sel::readLoggingObjectPaths(cache::paths);
69 responseData->entries = 0;
70 responseData->addTimeStamp = ipmi::sel::invalidTimeStamp;
71
72 if (!cache::paths.empty())
73 {
74 responseData->entries = static_cast<uint16_t>(cache::paths.size());
75
76 try
77 {
78 responseData->addTimeStamp = static_cast<uint32_t>(
79 (ipmi::sel::getEntryTimeStamp(cache::paths.back())
80 .count()));
81 }
82 catch (InternalFailure& e)
83 {
84 }
85 catch (const std::runtime_error& e)
86 {
87 log<level::ERR>(e.what());
88 }
89 }
90
91 memcpy(response, outPayload.data(), outPayload.size());
92 *data_len = outPayload.size();
93
94 return IPMI_CC_OK;
95}
96
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -050097ipmi_ret_t ipmi_storage_get_sel_time(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
98 ipmi_request_t request, ipmi_response_t response,
99 ipmi_data_len_t data_len, ipmi_context_t context)
100{
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530101 using namespace std::chrono;
102
103 char *time_provider = nullptr;
104 const char* time_in_str = nullptr;
105 uint64_t host_time_usec = 0;
106 uint32_t resp = 0;
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500107 ipmi_ret_t rc = IPMI_CC_OK;
Chris Austenb4f5b922015-10-13 12:44:43 -0500108
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530109 sd_bus_message *reply = nullptr;
110 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500111
112 printf("IPMI Handling GET-SEL-TIME\n");
113
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530114 auto bus = ipmid_get_sd_bus_connection();
115
116 auto rct = mapper_get_service(bus, time_manager_obj, &time_provider);
117 if (rct < 0) {
118 printf("Error [%s] getting bus name for time provider\n",
119 strerror(-rct));
120 rc = IPMI_CC_UNSPECIFIED_ERROR;
121 goto finish;
122 }
123
124 rct = sd_bus_call_method(bus,
125 time_provider,
126 time_manager_obj,
127 time_manager_intf,
128 "GetTime",
129 &bus_error,
130 &reply,
131 "s",
132 "host");
133 if (rct < 0) {
134 printf("Error [%s] getting time\n", strerror(-rct));
135 rc = IPMI_CC_UNSPECIFIED_ERROR;
136 goto finish;
137 }
138
139 rct = sd_bus_message_read(reply, "sx", &time_in_str, &host_time_usec);
140 if (rct < 0) {
141 fprintf(stderr, "Error [%s] parsing get-time response\n",
142 strerror(-rct));
143 rc = IPMI_CC_UNSPECIFIED_ERROR;
144 goto finish;
145 }
146
147 // Time is really long int but IPMI wants just uint32. This works okay until
148 // the number of seconds since 1970 overflows uint32 size.. Still a whole
149 // lot of time here to even think about that.
150 resp = duration_cast<seconds>(microseconds(host_time_usec)).count();
151 resp = htole32(resp);
152 printf("Host Time read:[%s] :: [%d]\n", time_in_str, resp);
153
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500154 // From the IPMI Spec 2.0, response should be a 32-bit value
155 *data_len = sizeof(resp);
156
157 // Pack the actual response
158 memcpy(response, &resp, *data_len);
159
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530160finish:
161 sd_bus_error_free(&bus_error);
162 reply = sd_bus_message_unref(reply);
163 free(time_provider);
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500164 return rc;
165}
166
167ipmi_ret_t ipmi_storage_set_sel_time(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
168 ipmi_request_t request, ipmi_response_t response,
Chris Austenb4f5b922015-10-13 12:44:43 -0500169 ipmi_data_len_t data_len, ipmi_context_t context)
170{
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530171 char *time_provider = nullptr;
172 int time_rc = 0;
173 ipmi_ret_t rc = IPMI_CC_OK;
174
175 sd_bus_message *reply = nullptr;
176 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
177
Norman James82330442015-11-19 16:53:26 -0600178 uint32_t* secs = (uint32_t*)request;
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530179 *data_len = 0;
Chris Austenb4f5b922015-10-13 12:44:43 -0500180
181 printf("Handling Set-SEL-Time:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
Norman James82330442015-11-19 16:53:26 -0600182 printf("Data: 0x%X]\n",*secs);
Chris Austenb4f5b922015-10-13 12:44:43 -0500183
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530184 auto bus = ipmid_get_sd_bus_connection();
Norman James82330442015-11-19 16:53:26 -0600185
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530186 auto rct = mapper_get_service(bus, time_manager_obj, &time_provider);
187 if (rct < 0) {
188 printf("Error [%s] getting bus name for time provider\n",
189 strerror(-rct));
190 rc = IPMI_CC_UNSPECIFIED_ERROR;
191 goto finish;
Norman James82330442015-11-19 16:53:26 -0600192 }
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530193
194 rct = sd_bus_call_method(bus,
195 time_provider,
196 time_manager_obj,
197 time_manager_intf,
198 "SetTime",
199 &bus_error,
200 &reply,
201 "ss",
202 "host",
203 std::to_string(le32toh(*secs)).c_str());
204
205 if (rct < 0) {
206 printf("Error [%s] setting time\n", strerror(-rct));
207 rc = IPMI_CC_UNSPECIFIED_ERROR;
208 goto finish;
209 }
210
211 rct = sd_bus_message_read(reply, "i", &time_rc);
212 if (rct < 0) {
213 fprintf(stderr, "Error [%s] parsing set-time response\n",
214 strerror(-rct));
215 rc = IPMI_CC_UNSPECIFIED_ERROR;
216 goto finish;
217 }
218
219 if (time_rc < 0) {
220 printf("Error setting time.");
Norman James82330442015-11-19 16:53:26 -0600221 rc = IPMI_CC_UNSPECIFIED_ERROR;
222 }
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530223
224finish:
225 sd_bus_error_free(&bus_error);
226 reply = sd_bus_message_unref(reply);
227 free(time_provider);
Chris Austenb4f5b922015-10-13 12:44:43 -0500228 return rc;
229}
230
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500231ipmi_ret_t ipmi_storage_reserve_sel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
232 ipmi_request_t request, ipmi_response_t response,
Chris Austenb4f5b922015-10-13 12:44:43 -0500233 ipmi_data_len_t data_len, ipmi_context_t context)
234{
Chris Austenb4f5b922015-10-13 12:44:43 -0500235 ipmi_ret_t rc = IPMI_CC_OK;
236
Nan Li36c0cb62016-03-31 11:16:08 +0800237 // IPMI spec, Reservation ID, the value simply increases against each execution of reserve_sel command.
238 if( ++g_sel_reserve == 0)
239 g_sel_reserve = 1;
Chris Austenb4f5b922015-10-13 12:44:43 -0500240
Nan Li36c0cb62016-03-31 11:16:08 +0800241 printf("IPMI Handling RESERVE-SEL 0x%04x\n", g_sel_reserve);
Chris Austen41a4b312015-10-25 03:45:42 -0500242
Chris Austenb4f5b922015-10-13 12:44:43 -0500243 *data_len = sizeof(g_sel_reserve);
244
245 // Pack the actual response
246 memcpy(response, &g_sel_reserve, *data_len);
247
248 return rc;
249}
250
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500251ipmi_ret_t ipmi_storage_add_sel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
252 ipmi_request_t request, ipmi_response_t response,
Chris Austenb4f5b922015-10-13 12:44:43 -0500253 ipmi_data_len_t data_len, ipmi_context_t context)
254{
255
256 ipmi_ret_t rc = IPMI_CC_OK;
Chris Austen41a4b312015-10-25 03:45:42 -0500257 ipmi_add_sel_request_t *p = (ipmi_add_sel_request_t*) request;
258 uint16_t recordid;
Chris Austenb4f5b922015-10-13 12:44:43 -0500259
Chris Austen313d95b2015-10-31 12:55:30 -0500260 recordid = ((uint16_t)p->eventdata[1] << 8) | p->eventdata[2];
Chris Austen41a4b312015-10-25 03:45:42 -0500261
262 printf("IPMI Handling ADD-SEL for record 0x%04x\n", recordid);
Chris Austenb4f5b922015-10-13 12:44:43 -0500263
264 *data_len = sizeof(g_sel_reserve);
265
266 // Pack the actual response
Chris Austen7cc33322015-11-11 00:20:22 -0600267 memcpy(response, &p->eventdata[1], 2);
Chris Austenb4f5b922015-10-13 12:44:43 -0500268
Chris Austen41a4b312015-10-25 03:45:42 -0500269 send_esel(recordid);
Chris Austenb4f5b922015-10-13 12:44:43 -0500270
271 return rc;
272}
273
274
275
276void register_netfn_storage_functions()
277{
Tom05732372016-09-06 17:21:23 +0530278 // <Wildcard Command>
Chris Austenb4f5b922015-10-13 12:44:43 -0500279 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_WILDCARD);
Tom05732372016-09-06 17:21:23 +0530280 ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_WILDCARD, NULL, ipmi_storage_wildcard,
281 PRIVILEGE_USER);
Chris Austenb4f5b922015-10-13 12:44:43 -0500282
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530283 // <Get SEL Info>
284 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_GET_SEL_INFO);
285 ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_INFO, NULL, getSELInfo,
286 PRIVILEGE_USER);
287
Tom05732372016-09-06 17:21:23 +0530288 // <Get SEL Time>
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500289 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_GET_SEL_TIME);
Tom05732372016-09-06 17:21:23 +0530290 ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_TIME, NULL, ipmi_storage_get_sel_time,
291 PRIVILEGE_USER);
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500292
Tom05732372016-09-06 17:21:23 +0530293 // <Set SEL Time>
Chris Austenb4f5b922015-10-13 12:44:43 -0500294 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_SET_SEL_TIME);
Tom05732372016-09-06 17:21:23 +0530295 ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_SET_SEL_TIME, NULL, ipmi_storage_set_sel_time,
296 PRIVILEGE_OPERATOR);
Chris Austenb4f5b922015-10-13 12:44:43 -0500297
Tom05732372016-09-06 17:21:23 +0530298 // <Reserve SEL>
Chris Austenb4f5b922015-10-13 12:44:43 -0500299 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_RESERVE_SEL);
Tom05732372016-09-06 17:21:23 +0530300 ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_RESERVE_SEL, NULL, ipmi_storage_reserve_sel,
301 PRIVILEGE_USER);
Chris Austenb4f5b922015-10-13 12:44:43 -0500302
Tom05732372016-09-06 17:21:23 +0530303 // <Add SEL Entry>
Chris Austenb4f5b922015-10-13 12:44:43 -0500304 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_ADD_SEL);
Tom05732372016-09-06 17:21:23 +0530305 ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_ADD_SEL, NULL, ipmi_storage_add_sel,
306 PRIVILEGE_OPERATOR);
Chris Austenb4f5b922015-10-13 12:44:43 -0500307 return;
308}
309