blob: 84e309243b9557c78257a5423f53a8d9c5ec76ae [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>
Tomd700e762016-09-20 18:24:13 +053011#include "host-ipmid/ipmid-api.h"
Chris Austen41a4b312015-10-25 03:45:42 -050012#include "sensorhandler.h"
Tomd700e762016-09-20 18:24:13 +053013#include "storagehandler.h"
14
Chris Austen41a4b312015-10-25 03:45:42 -050015
16using namespace std;
17
Chris Austen41a4b312015-10-25 03:45:42 -050018//////////////////////////
19struct esel_section_headers_t {
20 uint8_t sectionid[2];
21 uint8_t sectionlength[2];
22 uint8_t version;
23 uint8_t subsectiontype;
24 uint8_t compid;
25};
26
27struct severity_values_t {
28 uint8_t type;
29 const char *description;
30};
31
32
33const std::vector<severity_values_t> g_sev_desc = {
34 {0x10, "recoverable error"},
35 {0x20, "predictive error"},
36 {0x40, "unrecoverable error"},
37 {0x50, "critical error"},
38 {0x60, "error from a diagnostic test"},
39 {0x70, "recovered symptom "},
40 {0xFF, "Unknown"},
41};
42
43const char* sev_lookup(uint8_t n) {
44 auto i = std::find_if(std::begin(g_sev_desc), std::end(g_sev_desc),
45 [n](auto p){ return p.type == n || p.type == 0xFF; });
46 return i->description;
47}
48
49
50
51
52int find_sensor_type_string(uint8_t sensor_number, char **s) {
53
54 dbus_interface_t a;
55 const char *p;
Matthew Barth56181052017-01-23 09:36:29 -060056 int r;
Chris Austen41a4b312015-10-25 03:45:42 -050057
58 r = find_openbmc_path("SENSOR", sensor_number, &a);
59
60 if ((r < 0) || (a.bus[0] == 0)) {
61 // Just make a generic message for errors that
62 // occur on sensors that dont exist
Matthew Barth56181052017-01-23 09:36:29 -060063 r = asprintf(s, "Unknown Sensor (0x%02x)", sensor_number);
Chris Austen41a4b312015-10-25 03:45:42 -050064 } else {
65
66 if ((p = strrchr (a.path, '/')) == NULL) {
67 p = "/Unknown Sensor";
68 }
69
Matthew Barth56181052017-01-23 09:36:29 -060070 *s = strdup(p+1);
Chris Austen41a4b312015-10-25 03:45:42 -050071 }
72
73 return 0;
74}
75
76
77size_t getfilestream(const char *fn, uint8_t **buffer) {
78
79 FILE *fp;
Matthew Barth8b470052016-09-21 10:02:57 -050080 ssize_t size = 0;
Nan Lidfe6e422016-05-13 21:46:26 +080081 int r;
Chris Austen41a4b312015-10-25 03:45:42 -050082
83 if ((fp = fopen(fn, "rb")) != NULL) {
84
Nan Lidfe6e422016-05-13 21:46:26 +080085 r = fseek(fp, 0, SEEK_END);
86 if (r) {
87 fprintf(stderr,"Fseek failed\n");
88 goto fclose_fp;
89 }
90
Chris Austen41a4b312015-10-25 03:45:42 -050091 size = ftell(fp);
Nan Lidfe6e422016-05-13 21:46:26 +080092 if (size == -1L) {
93 fprintf(stderr,"Ftell failed for %s\n", strerror(errno));
94 size = 0;
95 goto fclose_fp;
96 }
97
98 r = fseek(fp, 0, SEEK_SET);
99 if (r) {
100 fprintf(stderr,"Fseek failed\n");
101 size = 0;
102 goto fclose_fp;
103 }
Chris Austen41a4b312015-10-25 03:45:42 -0500104
Chris Austen41a4b312015-10-25 03:45:42 -0500105 *buffer = new uint8_t [size];
106
Nan Lidfe6e422016-05-13 21:46:26 +0800107 r = fread(*buffer, 1, size, fp);
108 if ( r != size) {
109 size = 0;
110 fprintf(stderr,"Fread failed\n");
111 }
112
113fclose_fp:
Chris Austen41a4b312015-10-25 03:45:42 -0500114 fclose(fp);
115 }
116
Matthew Barth8b470052016-09-21 10:02:57 -0500117 return static_cast<size_t>(size);
Chris Austen41a4b312015-10-25 03:45:42 -0500118}
119
120
121const char *create_esel_severity(const uint8_t *buffer) {
122
123 uint8_t severity;
124 // Dive in to the IBM log to find the severity
125 severity = (0xF0 & buffer[0x4A]);
126
127 return sev_lookup(severity);
128}
129
130int create_esel_association(const uint8_t *buffer, char **m) {
131
132 ipmi_add_sel_request_t *p;
133 dbus_interface_t dbusint;
134 uint8_t sensor;
135
136 p = ( ipmi_add_sel_request_t *) buffer;
137
138 sensor = p->sensornumber;
139
140 find_openbmc_path("SENSOR", sensor, &dbusint);
141
Chris Austen6dc2e912016-02-20 01:00:06 -0600142 // Simply no associations if the sensor can not be found
Chris Austen41a4b312015-10-25 03:45:42 -0500143 if (strlen(dbusint.path) < 1) {
Chris Austen6dc2e912016-02-20 01:00:06 -0600144 printf("Sensor 0x%x not found\n", sensor);
145 memset(dbusint.path,0,sizeof(dbusint.path));
Chris Austen41a4b312015-10-25 03:45:42 -0500146 }
147
Matthew Barth56181052017-01-23 09:36:29 -0600148 *m = strdup(dbusint.path);
Chris Austen41a4b312015-10-25 03:45:42 -0500149
150 return 0;
151}
152
153
154
155int create_esel_description(const uint8_t *buffer, const char *sev, char **message) {
156
157
158 ipmi_add_sel_request_t *p;
Chris Austen41a4b312015-10-25 03:45:42 -0500159 char *m;
Matthew Barth56181052017-01-23 09:36:29 -0600160 int r;
Chris Austen41a4b312015-10-25 03:45:42 -0500161
162 p = ( ipmi_add_sel_request_t *) buffer;
163
164 find_sensor_type_string(p->sensornumber,&m);
165
Matthew Barth56181052017-01-23 09:36:29 -0600166 r = asprintf(message, "A %s has experienced a %s", m, sev );
167 if (r == -1) {
168 fprintf(stderr,
169 "Failed to allocate memory for ESEL description\n");
170 }
Chris Austen41a4b312015-10-25 03:45:42 -0500171
172 free(m);
173
174 return 0;
175}
176
177
178int send_esel_to_dbus(const char *desc, const char *sev, const char *details, uint8_t *debug, size_t debuglen) {
179
180 sd_bus *mbus = NULL;
181 sd_bus_error error = SD_BUS_ERROR_NULL;
182 sd_bus_message *reply = NULL, *m=NULL;
Chris Austen169395e2015-12-02 20:56:15 -0600183 uint16_t x;
Chris Austen41a4b312015-10-25 03:45:42 -0500184 int r;
Sergey Solomineb9b8142016-08-23 09:07:28 -0500185 const char *object_name = "/org/openbmc/records/events";
186 char *bus_name = NULL;
Chris Austen41a4b312015-10-25 03:45:42 -0500187
Chris Austen30195fa2015-11-13 14:39:19 -0600188 mbus = ipmid_get_sd_bus_connection();
Sergey Solomineb9b8142016-08-23 09:07:28 -0500189 r = mapper_get_service(mbus, object_name, &bus_name);
190 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400191 fprintf(stderr, "Failed to get %s connection: %s\n",
192 object_name, strerror(-r));
Sergey Solomineb9b8142016-08-23 09:07:28 -0500193 goto finish;
194 }
Chris Austen41a4b312015-10-25 03:45:42 -0500195 r = sd_bus_message_new_method_call(mbus,&m,
Sergey Solomineb9b8142016-08-23 09:07:28 -0500196 bus_name,
197 object_name,
Chris Austen41a4b312015-10-25 03:45:42 -0500198 "org.openbmc.recordlog",
199 "acceptHostMessage");
200 if (r < 0) {
201 fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600202 goto finish;
Chris Austen41a4b312015-10-25 03:45:42 -0500203 }
204
205 r = sd_bus_message_append(m, "sss", desc, sev, details);
206 if (r < 0) {
207 fprintf(stderr, "Failed add the message strings : %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600208 goto finish;
Chris Austen41a4b312015-10-25 03:45:42 -0500209 }
210
211 r = sd_bus_message_append_array(m, 'y', debug, debuglen);
212 if (r < 0) {
213 fprintf(stderr, "Failed to add the raw array of bytes: %s\n", strerror(-r));
Chris Austen169395e2015-12-02 20:56:15 -0600214 goto finish;
Chris Austen41a4b312015-10-25 03:45:42 -0500215 }
Chris Austen41a4b312015-10-25 03:45:42 -0500216 // Call the IPMI responder on the bus so the message can be sent to the CEC
217 r = sd_bus_call(mbus, m, 0, &error, &reply);
218 if (r < 0) {
Chris Austen169395e2015-12-02 20:56:15 -0600219 fprintf(stderr, "Failed to call the method: %s %s\n", __FUNCTION__, strerror(-r));
220 goto finish;
Chris Austen41a4b312015-10-25 03:45:42 -0500221 }
Chris Austen169395e2015-12-02 20:56:15 -0600222 r = sd_bus_message_read(reply, "q", &x);
Chris Austen41a4b312015-10-25 03:45:42 -0500223 if (r < 0) {
Chris Austen7cc33322015-11-11 00:20:22 -0600224 fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
Chris Austen41a4b312015-10-25 03:45:42 -0500225 }
226
Chris Austen169395e2015-12-02 20:56:15 -0600227finish:
Chris Austen41a4b312015-10-25 03:45:42 -0500228 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600229 m = sd_bus_message_unref(m);
230 reply = sd_bus_message_unref(reply);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500231 free (bus_name);
Chris Austen41a4b312015-10-25 03:45:42 -0500232 return r;
Chris Austen41a4b312015-10-25 03:45:42 -0500233}
234
235
236void send_esel(uint16_t recordid) {
Joel Stanleyf19539e2015-11-25 17:24:05 +1030237 char *desc, *assoc;
Chris Austen41a4b312015-10-25 03:45:42 -0500238 const char *sev;
239 uint8_t *buffer = NULL;
Chris Austen6dc2e912016-02-20 01:00:06 -0600240 const char *path = "/tmp/esel";
Matthew Barth8b470052016-09-21 10:02:57 -0500241 ssize_t sz;
Nan Lidfe6e422016-05-13 21:46:26 +0800242 int r;
Chris Austen41a4b312015-10-25 03:45:42 -0500243
Chris Austen41a4b312015-10-25 03:45:42 -0500244 sz = getfilestream(path, &buffer);
Chris Austen41a4b312015-10-25 03:45:42 -0500245 if (sz == 0) {
246 printf("Error file does not exist %d\n",__LINE__);
Chris Austen41a4b312015-10-25 03:45:42 -0500247 return;
248 }
249
Chris Austen41a4b312015-10-25 03:45:42 -0500250 sev = create_esel_severity(buffer);
Chris Austen41a4b312015-10-25 03:45:42 -0500251 create_esel_association(buffer, &assoc);
Chris Austen41a4b312015-10-25 03:45:42 -0500252 create_esel_description(buffer, sev, &desc);
253
Nan Lidfe6e422016-05-13 21:46:26 +0800254 r = send_esel_to_dbus(desc, sev, assoc, buffer, sz);
255 if (r < 0) {
256 fprintf(stderr, "Failed to send esel to dbus\n");
257 }
Chris Austen41a4b312015-10-25 03:45:42 -0500258
Chris Austen41a4b312015-10-25 03:45:42 -0500259 free(assoc);
260 free(desc);
Chris Austen41a4b312015-10-25 03:45:42 -0500261 delete[] buffer;
262
Chris Austen41a4b312015-10-25 03:45:42 -0500263 return;
264}