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