1 #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>
10 #include <mapper.h>
11 #include "ipmid.H"
12 #include "storagehandler.h"
13 #include "sensorhandler.h"
14 
15 using namespace std;
16 
17 extern int find_openbmc_path(const char *, const uint8_t , dbus_interface_t *);
18 
19 
20 //////////////////////////
21 struct esel_section_headers_t {
22 	uint8_t sectionid[2];
23 	uint8_t sectionlength[2];
24 	uint8_t version;
25 	uint8_t subsectiontype;
26 	uint8_t compid;
27 };
28 
29 struct severity_values_t {
30 	uint8_t type;
31 	const char *description;
32 };
33 
34 
35 const std::vector<severity_values_t> g_sev_desc = {
36 	{0x10, "recoverable error"},
37 	{0x20, "predictive error"},
38 	{0x40, "unrecoverable error"},
39 	{0x50, "critical error"},
40 	{0x60, "error from a diagnostic test"},
41 	{0x70, "recovered symptom "},
42 	{0xFF, "Unknown"},
43 };
44 
45 const char* sev_lookup(uint8_t n) {
46 	auto i = std::find_if(std::begin(g_sev_desc), std::end(g_sev_desc),
47 	                      [n](auto p){ return p.type == n || p.type == 0xFF; });
48 	return i->description;
49 }
50 
51 
52 
53 
54 int find_sensor_type_string(uint8_t sensor_number, char **s) {
55 
56 	dbus_interface_t a;
57 	const char *p;
58 	char r;
59 
60 	r = find_openbmc_path("SENSOR", sensor_number, &a);
61 
62 	if ((r < 0) || (a.bus[0] == 0)) {
63 		// Just make a generic message for errors that
64 		// occur on sensors that dont exist
65 		asprintf(s, "Unknown Sensor (0x%02x)", sensor_number);
66 	} else {
67 
68 		if ((p = strrchr (a.path, '/')) == NULL) {
69 			p = "/Unknown Sensor";
70 		}
71 
72 		asprintf(s, "%s", p+1);
73 	}
74 
75 	return 0;
76 }
77 
78 
79 size_t getfilestream(const char *fn, uint8_t **buffer) {
80 
81 	FILE *fp;
82 	size_t size = 0;
83 	int r;
84 
85 	if ((fp = fopen(fn, "rb")) != NULL) {
86 
87 		r = fseek(fp, 0, SEEK_END);
88 		if (r) {
89 			fprintf(stderr,"Fseek failed\n");
90 			goto fclose_fp;
91 		}
92 
93 		size = ftell(fp);
94 		if (size == -1L) {
95 			fprintf(stderr,"Ftell failed for %s\n", strerror(errno));
96 			size = 0;
97 			goto fclose_fp;
98 		}
99 
100 		r = fseek(fp, 0, SEEK_SET);
101 		if (r) {
102 			fprintf(stderr,"Fseek failed\n");
103 			size = 0;
104 			goto fclose_fp;
105 		}
106 
107 		*buffer = new uint8_t [size];
108 
109 		r = fread(*buffer, 1, size, fp);
110 		if ( r != size) {
111 			size = 0;
112 			fprintf(stderr,"Fread failed\n");
113 		}
114 
115 fclose_fp:
116 		fclose(fp);
117 	}
118 
119 	return size;
120 }
121 
122 
123 const char *create_esel_severity(const uint8_t *buffer) {
124 
125 	uint8_t severity;
126 	// Dive in to the IBM log to find the severity
127 	severity = (0xF0  & buffer[0x4A]);
128 
129 	return sev_lookup(severity);
130 }
131 
132 int create_esel_association(const uint8_t *buffer, char **m) {
133 
134 	ipmi_add_sel_request_t *p;
135 	dbus_interface_t dbusint;
136 	uint8_t sensor;
137 
138 	p = ( ipmi_add_sel_request_t *) buffer;
139 
140 	sensor = p->sensornumber;
141 
142 	find_openbmc_path("SENSOR", sensor, &dbusint);
143 
144 	// Simply no associations if the sensor can not be found
145 	if (strlen(dbusint.path) < 1) {
146 		printf("Sensor 0x%x not found\n", sensor);
147 		memset(dbusint.path,0,sizeof(dbusint.path));
148 	}
149 
150 	asprintf(m, "%s", dbusint.path);
151 
152 	return 0;
153 }
154 
155 
156 
157 int create_esel_description(const uint8_t *buffer, const char *sev, char **message) {
158 
159 
160 	ipmi_add_sel_request_t *p;
161 	char *m;
162 
163 	p =  ( ipmi_add_sel_request_t *) buffer;
164 
165 	find_sensor_type_string(p->sensornumber,&m);
166 
167 	asprintf(message, "A %s has experienced a %s", m, sev );
168 
169 	free(m);
170 
171 	return 0;
172 }
173 
174 
175 int send_esel_to_dbus(const char *desc, const char *sev, const char *details, uint8_t *debug, size_t debuglen) {
176 
177 	sd_bus *mbus = NULL;
178     sd_bus_error error = SD_BUS_ERROR_NULL;
179     sd_bus_message *reply = NULL, *m=NULL;
180     uint16_t x;
181     int r;
182     const char *object_name  =  "/org/openbmc/records/events";
183     char *bus_name = NULL;
184 
185     mbus = ipmid_get_sd_bus_connection();
186     r = mapper_get_service(mbus, object_name, &bus_name);
187     if (r < 0) {
188         fprintf(stderr, "Failed to get connection, return value: %s.\n", strerror(-r));
189         goto finish;
190     }
191     r = sd_bus_message_new_method_call(mbus,&m,
192     									bus_name,
193     									object_name,
194     									"org.openbmc.recordlog",
195     									"acceptHostMessage");
196     if (r < 0) {
197         fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
198         goto finish;
199     }
200 
201     r = sd_bus_message_append(m, "sss", desc, sev, details);
202     if (r < 0) {
203         fprintf(stderr, "Failed add the message strings : %s\n", strerror(-r));
204         goto finish;
205     }
206 
207     r = sd_bus_message_append_array(m, 'y', debug, debuglen);
208     if (r < 0) {
209         fprintf(stderr, "Failed to add the raw array of bytes: %s\n", strerror(-r));
210         goto finish;
211     }
212     // Call the IPMI responder on the bus so the message can be sent to the CEC
213     r = sd_bus_call(mbus, m, 0, &error, &reply);
214     if (r < 0) {
215         fprintf(stderr, "Failed to call the method: %s %s\n", __FUNCTION__, strerror(-r));
216         goto finish;
217     }
218     r = sd_bus_message_read(reply, "q", &x);
219     if (r < 0) {
220         fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
221     }
222 
223 finish:
224     sd_bus_error_free(&error);
225     m = sd_bus_message_unref(m);
226     reply = sd_bus_message_unref(reply);
227     free (bus_name);
228     return r;
229 }
230 
231 
232 void send_esel(uint16_t recordid) {
233 	char *desc, *assoc;
234 	const char *sev;
235 	uint8_t *buffer = NULL;
236 	const char *path = "/tmp/esel";
237 	size_t sz;
238 	int r;
239 
240 	sz = getfilestream(path, &buffer);
241 	if (sz == 0) {
242 		printf("Error file does not exist %d\n",__LINE__);
243 		return;
244 	}
245 
246 	sev = create_esel_severity(buffer);
247 	create_esel_association(buffer, &assoc);
248 	create_esel_description(buffer, sev, &desc);
249 
250 	r = send_esel_to_dbus(desc, sev, assoc, buffer, sz);
251 	if (r < 0) {
252 		fprintf(stderr, "Failed to send esel to dbus\n");
253 	}
254 
255 	free(assoc);
256 	free(desc);
257 	delete[] buffer;
258 
259 	return;
260 }
261