blob: 0b40d470502a27ddc360b5318959408fec547ce4 [file] [log] [blame]
Chris Austen41a4b312015-10-25 03:45:42 -05001#include <stdint.h>
2#include <cstdlib>
3#include <cstring>
4#include <fstream>
5#include <iostream>
6#include <algorithm>
7#include <vector>
8#include <memory>
9#include <systemd/sd-bus.h>
Sergey Solomineb9b8142016-08-23 09:07:28 -050010#include <mapper.h>
Adriana Kobylak2efb3e72017-02-06 21:43:59 -060011#include <elog.hpp>
12#include <elog-errors-HostEvent.hpp>
Tomd700e762016-09-20 18:24:13 +053013#include "host-ipmid/ipmid-api.h"
Chris Austen41a4b312015-10-25 03:45:42 -050014#include "sensorhandler.h"
Tomd700e762016-09-20 18:24:13 +053015#include "storagehandler.h"
16
Chris Austen41a4b312015-10-25 03:45:42 -050017
18using namespace std;
Adriana Kobylak2efb3e72017-02-06 21:43:59 -060019using namespace phosphor::logging;
Chris Austen41a4b312015-10-25 03:45:42 -050020
Chris Austen41a4b312015-10-25 03:45:42 -050021//////////////////////////
22struct esel_section_headers_t {
23 uint8_t sectionid[2];
24 uint8_t sectionlength[2];
25 uint8_t version;
26 uint8_t subsectiontype;
27 uint8_t compid;
28};
29
30struct severity_values_t {
31 uint8_t type;
32 const char *description;
33};
34
35
36const std::vector<severity_values_t> g_sev_desc = {
37 {0x10, "recoverable error"},
38 {0x20, "predictive error"},
39 {0x40, "unrecoverable error"},
40 {0x50, "critical error"},
41 {0x60, "error from a diagnostic test"},
42 {0x70, "recovered symptom "},
43 {0xFF, "Unknown"},
44};
45
46const char* sev_lookup(uint8_t n) {
47 auto i = std::find_if(std::begin(g_sev_desc), std::end(g_sev_desc),
48 [n](auto p){ return p.type == n || p.type == 0xFF; });
49 return i->description;
50}
51
52
53
54
55int find_sensor_type_string(uint8_t sensor_number, char **s) {
56
57 dbus_interface_t a;
58 const char *p;
Matthew Barth56181052017-01-23 09:36:29 -060059 int r;
Chris Austen41a4b312015-10-25 03:45:42 -050060
61 r = find_openbmc_path("SENSOR", sensor_number, &a);
62
63 if ((r < 0) || (a.bus[0] == 0)) {
64 // Just make a generic message for errors that
65 // occur on sensors that dont exist
Matthew Barth56181052017-01-23 09:36:29 -060066 r = asprintf(s, "Unknown Sensor (0x%02x)", sensor_number);
Chris Austen41a4b312015-10-25 03:45:42 -050067 } else {
68
69 if ((p = strrchr (a.path, '/')) == NULL) {
70 p = "/Unknown Sensor";
71 }
72
Matthew Barth56181052017-01-23 09:36:29 -060073 *s = strdup(p+1);
Chris Austen41a4b312015-10-25 03:45:42 -050074 }
75
76 return 0;
77}
78
79
80size_t getfilestream(const char *fn, uint8_t **buffer) {
81
82 FILE *fp;
Matthew Barth8b470052016-09-21 10:02:57 -050083 ssize_t size = 0;
Nan Lidfe6e422016-05-13 21:46:26 +080084 int r;
Chris Austen41a4b312015-10-25 03:45:42 -050085
86 if ((fp = fopen(fn, "rb")) != NULL) {
87
Nan Lidfe6e422016-05-13 21:46:26 +080088 r = fseek(fp, 0, SEEK_END);
89 if (r) {
90 fprintf(stderr,"Fseek failed\n");
91 goto fclose_fp;
92 }
93
Chris Austen41a4b312015-10-25 03:45:42 -050094 size = ftell(fp);
Nan Lidfe6e422016-05-13 21:46:26 +080095 if (size == -1L) {
96 fprintf(stderr,"Ftell failed for %s\n", strerror(errno));
97 size = 0;
98 goto fclose_fp;
99 }
100
101 r = fseek(fp, 0, SEEK_SET);
102 if (r) {
103 fprintf(stderr,"Fseek failed\n");
104 size = 0;
105 goto fclose_fp;
106 }
Chris Austen41a4b312015-10-25 03:45:42 -0500107
Chris Austen41a4b312015-10-25 03:45:42 -0500108 *buffer = new uint8_t [size];
109
Nan Lidfe6e422016-05-13 21:46:26 +0800110 r = fread(*buffer, 1, size, fp);
111 if ( r != size) {
112 size = 0;
113 fprintf(stderr,"Fread failed\n");
114 }
115
116fclose_fp:
Chris Austen41a4b312015-10-25 03:45:42 -0500117 fclose(fp);
118 }
119
Matthew Barth8b470052016-09-21 10:02:57 -0500120 return static_cast<size_t>(size);
Chris Austen41a4b312015-10-25 03:45:42 -0500121}
122
123
124const char *create_esel_severity(const uint8_t *buffer) {
125
126 uint8_t severity;
127 // Dive in to the IBM log to find the severity
128 severity = (0xF0 & buffer[0x4A]);
129
130 return sev_lookup(severity);
131}
132
133int create_esel_association(const uint8_t *buffer, char **m) {
134
135 ipmi_add_sel_request_t *p;
136 dbus_interface_t dbusint;
137 uint8_t sensor;
138
139 p = ( ipmi_add_sel_request_t *) buffer;
140
141 sensor = p->sensornumber;
142
143 find_openbmc_path("SENSOR", sensor, &dbusint);
144
Chris Austen6dc2e912016-02-20 01:00:06 -0600145 // Simply no associations if the sensor can not be found
Chris Austen41a4b312015-10-25 03:45:42 -0500146 if (strlen(dbusint.path) < 1) {
Chris Austen6dc2e912016-02-20 01:00:06 -0600147 printf("Sensor 0x%x not found\n", sensor);
148 memset(dbusint.path,0,sizeof(dbusint.path));
Chris Austen41a4b312015-10-25 03:45:42 -0500149 }
150
Matthew Barth56181052017-01-23 09:36:29 -0600151 *m = strdup(dbusint.path);
Chris Austen41a4b312015-10-25 03:45:42 -0500152
153 return 0;
154}
155
156
157
158int create_esel_description(const uint8_t *buffer, const char *sev, char **message) {
159
160
161 ipmi_add_sel_request_t *p;
Chris Austen41a4b312015-10-25 03:45:42 -0500162 char *m;
Matthew Barth56181052017-01-23 09:36:29 -0600163 int r;
Chris Austen41a4b312015-10-25 03:45:42 -0500164
165 p = ( ipmi_add_sel_request_t *) buffer;
166
167 find_sensor_type_string(p->sensornumber,&m);
168
Matthew Barth56181052017-01-23 09:36:29 -0600169 r = asprintf(message, "A %s has experienced a %s", m, sev );
170 if (r == -1) {
171 fprintf(stderr,
172 "Failed to allocate memory for ESEL description\n");
173 }
Chris Austen41a4b312015-10-25 03:45:42 -0500174
175 free(m);
176
177 return 0;
178}
179
180
181int send_esel_to_dbus(const char *desc, const char *sev, const char *details, uint8_t *debug, size_t debuglen) {
182
183 sd_bus *mbus = NULL;
184 sd_bus_error error = SD_BUS_ERROR_NULL;
185 sd_bus_message *reply = NULL, *m=NULL;
Chris Austen169395e2015-12-02 20:56:15 -0600186 uint16_t x;
Chris Austen41a4b312015-10-25 03:45:42 -0500187 int r;
Sergey Solomineb9b8142016-08-23 09:07:28 -0500188 const char *object_name = "/org/openbmc/records/events";
189 char *bus_name = NULL;
Chris Austen41a4b312015-10-25 03:45:42 -0500190
Adriana Kobylak2efb3e72017-02-06 21:43:59 -0600191 // Allocate enough space to represent the data in hex separated by spaces,
192 // to mimic how IPMI would display the data.
193 unique_ptr<char[]> selData(new char[debuglen*3]());
194 uint32_t i = 0;
195 for(i = 0; i < debuglen; i++)
196 {
197 sprintf(&selData[i*3], "%02x ", 0xFF & ((char*)debug)[i]);
198 }
199 log<level::INFO>("Received Host Event", entry("ESEL=%s", selData.get()));
200
201 try
202 {
203 elog<org::open_power::Error::Host::Event>(
204 prev_entry<org::open_power::Error::Host::Event::ESEL>());
205 }
206 catch (elogException<org::open_power::Error::Host::Event>& e)
207 {
208 commit(e.name());
209 }
210
Chris Austen30195fa2015-11-13 14:39:19 -0600211 mbus = ipmid_get_sd_bus_connection();
Sergey Solomineb9b8142016-08-23 09:07:28 -0500212 r = mapper_get_service(mbus, object_name, &bus_name);
213 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400214 fprintf(stderr, "Failed to get %s connection: %s\n",
215 object_name, strerror(-r));
Sergey Solomineb9b8142016-08-23 09:07:28 -0500216 goto finish;
217 }
Chris Austen41a4b312015-10-25 03:45:42 -0500218 r = sd_bus_message_new_method_call(mbus,&m,
Sergey Solomineb9b8142016-08-23 09:07:28 -0500219 bus_name,
220 object_name,
Chris Austen41a4b312015-10-25 03:45:42 -0500221 "org.openbmc.recordlog",
222 "acceptHostMessage");
223 if (r < 0) {
224 fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600225 goto finish;
Chris Austen41a4b312015-10-25 03:45:42 -0500226 }
227
228 r = sd_bus_message_append(m, "sss", desc, sev, details);
229 if (r < 0) {
230 fprintf(stderr, "Failed add the message strings : %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600231 goto finish;
Chris Austen41a4b312015-10-25 03:45:42 -0500232 }
233
234 r = sd_bus_message_append_array(m, 'y', debug, debuglen);
235 if (r < 0) {
236 fprintf(stderr, "Failed to add the raw array of bytes: %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600237 goto finish;
Chris Austen41a4b312015-10-25 03:45:42 -0500238 }
Chris Austen41a4b312015-10-25 03:45:42 -0500239 // Call the IPMI responder on the bus so the message can be sent to the CEC
240 r = sd_bus_call(mbus, m, 0, &error, &reply);
241 if (r < 0) {
Chris Austen169395e2015-12-02 20:56:15 -0600242 fprintf(stderr, "Failed to call the method: %s %s\n", __FUNCTION__, strerror(-r));
243 goto finish;
Chris Austen41a4b312015-10-25 03:45:42 -0500244 }
Chris Austen169395e2015-12-02 20:56:15 -0600245 r = sd_bus_message_read(reply, "q", &x);
Chris Austen41a4b312015-10-25 03:45:42 -0500246 if (r < 0) {
Chris Austen7cc33322015-11-11 00:20:22 -0600247 fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
Chris Austen41a4b312015-10-25 03:45:42 -0500248 }
249
Chris Austen169395e2015-12-02 20:56:15 -0600250finish:
Chris Austen41a4b312015-10-25 03:45:42 -0500251 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600252 m = sd_bus_message_unref(m);
253 reply = sd_bus_message_unref(reply);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500254 free (bus_name);
Chris Austen41a4b312015-10-25 03:45:42 -0500255 return r;
Chris Austen41a4b312015-10-25 03:45:42 -0500256}
257
258
259void send_esel(uint16_t recordid) {
Joel Stanleyf19539e2015-11-25 17:24:05 +1030260 char *desc, *assoc;
Chris Austen41a4b312015-10-25 03:45:42 -0500261 const char *sev;
262 uint8_t *buffer = NULL;
Chris Austen6dc2e912016-02-20 01:00:06 -0600263 const char *path = "/tmp/esel";
Matthew Barth8b470052016-09-21 10:02:57 -0500264 ssize_t sz;
Nan Lidfe6e422016-05-13 21:46:26 +0800265 int r;
Chris Austen41a4b312015-10-25 03:45:42 -0500266
Chris Austen41a4b312015-10-25 03:45:42 -0500267 sz = getfilestream(path, &buffer);
Chris Austen41a4b312015-10-25 03:45:42 -0500268 if (sz == 0) {
269 printf("Error file does not exist %d\n",__LINE__);
Chris Austen41a4b312015-10-25 03:45:42 -0500270 return;
271 }
272
Chris Austen41a4b312015-10-25 03:45:42 -0500273 sev = create_esel_severity(buffer);
Chris Austen41a4b312015-10-25 03:45:42 -0500274 create_esel_association(buffer, &assoc);
Chris Austen41a4b312015-10-25 03:45:42 -0500275 create_esel_description(buffer, sev, &desc);
276
Nan Lidfe6e422016-05-13 21:46:26 +0800277 r = send_esel_to_dbus(desc, sev, assoc, buffer, sz);
278 if (r < 0) {
279 fprintf(stderr, "Failed to send esel to dbus\n");
280 }
Chris Austen41a4b312015-10-25 03:45:42 -0500281
Chris Austen41a4b312015-10-25 03:45:42 -0500282 free(assoc);
283 free(desc);
Chris Austen41a4b312015-10-25 03:45:42 -0500284 delete[] buffer;
285
Chris Austen41a4b312015-10-25 03:45:42 -0500286 return;
287}