| Chris Austen | 41a4b31 | 2015-10-25 03:45:42 -0500 | [diff] [blame] | 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 |  | 
|  | 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 |  | 
|  | 84 | if ((fp = fopen(fn, "rb")) != NULL) { | 
|  | 85 |  | 
|  | 86 | fseek(fp, 0, SEEK_END); | 
|  | 87 | size = ftell(fp); | 
|  | 88 | fseek(fp, 0, SEEK_SET); | 
|  | 89 |  | 
|  | 90 | size = 0x100; | 
|  | 91 |  | 
|  | 92 | *buffer = new uint8_t [size]; | 
|  | 93 |  | 
|  | 94 | fread(*buffer, 1, size, fp); | 
|  | 95 | fclose(fp); | 
|  | 96 | } | 
|  | 97 |  | 
|  | 98 | return size; | 
|  | 99 | } | 
|  | 100 |  | 
|  | 101 |  | 
|  | 102 | const char *create_esel_severity(const uint8_t *buffer) { | 
|  | 103 |  | 
|  | 104 | uint8_t severity; | 
|  | 105 | // Dive in to the IBM log to find the severity | 
|  | 106 | severity = (0xF0  & buffer[0x4A]); | 
|  | 107 |  | 
|  | 108 | return sev_lookup(severity); | 
|  | 109 | } | 
|  | 110 |  | 
|  | 111 | int create_esel_association(const uint8_t *buffer, char **m) { | 
|  | 112 |  | 
|  | 113 | ipmi_add_sel_request_t *p; | 
|  | 114 | dbus_interface_t dbusint; | 
|  | 115 | uint8_t sensor; | 
|  | 116 |  | 
|  | 117 | p = ( ipmi_add_sel_request_t *) buffer; | 
|  | 118 |  | 
|  | 119 | sensor = p->sensornumber; | 
|  | 120 |  | 
|  | 121 | find_openbmc_path("SENSOR", sensor, &dbusint); | 
|  | 122 |  | 
|  | 123 | if (strlen(dbusint.path) < 1) { | 
|  | 124 | printf("Sensor not found\n"); | 
|  | 125 | snprintf(dbusint.path, sizeof(dbusint.path), "0x%x", sensor); | 
|  | 126 | } | 
|  | 127 |  | 
|  | 128 | asprintf(m, "%s", dbusint.path); | 
|  | 129 |  | 
|  | 130 | return 0; | 
|  | 131 | } | 
|  | 132 |  | 
|  | 133 |  | 
|  | 134 |  | 
|  | 135 | int create_esel_description(const uint8_t *buffer, const char *sev, char **message) { | 
|  | 136 |  | 
|  | 137 |  | 
|  | 138 | ipmi_add_sel_request_t *p; | 
|  | 139 | int r; | 
|  | 140 | char *m; | 
|  | 141 |  | 
|  | 142 | p =  ( ipmi_add_sel_request_t *) buffer; | 
|  | 143 |  | 
|  | 144 | find_sensor_type_string(p->sensornumber,&m); | 
|  | 145 |  | 
|  | 146 | asprintf(message, "A %s has experienced a %s", m, sev ); | 
|  | 147 |  | 
|  | 148 | free(m); | 
|  | 149 |  | 
|  | 150 | return 0; | 
|  | 151 | } | 
|  | 152 |  | 
|  | 153 |  | 
|  | 154 | int send_esel_to_dbus(const char *desc, const char *sev, const char *details, uint8_t *debug, size_t debuglen) { | 
|  | 155 |  | 
|  | 156 | sd_bus *mbus = NULL; | 
|  | 157 | sd_bus_error error = SD_BUS_ERROR_NULL; | 
|  | 158 | sd_bus_message *reply = NULL, *m=NULL; | 
|  | 159 | uint16_t *pty; | 
|  | 160 | int r; | 
|  | 161 |  | 
|  | 162 |  | 
|  | 163 |  | 
|  | 164 | /* Connect to system bus */ | 
|  | 165 | r = sd_bus_open_system(&mbus); | 
|  | 166 | if (r < 0) { | 
|  | 167 | fprintf(stderr, "Failed to connect to system bus: %s\n", | 
|  | 168 | strerror(-r)); | 
|  | 169 | goto finish; | 
|  | 170 | } | 
|  | 171 | r = sd_bus_message_new_method_call(mbus,&m, | 
|  | 172 | "org.openbmc.records.events", | 
|  | 173 | "/org/openbmc/records/events", | 
|  | 174 | "org.openbmc.recordlog", | 
|  | 175 | "acceptHostMessage"); | 
|  | 176 | if (r < 0) { | 
|  | 177 | fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r)); | 
|  | 178 | return -1; | 
|  | 179 | } | 
|  | 180 |  | 
|  | 181 | r = sd_bus_message_append(m, "sss", desc, sev, details); | 
|  | 182 | if (r < 0) { | 
|  | 183 | fprintf(stderr, "Failed add the message strings : %s\n", strerror(-r)); | 
|  | 184 | return -1; | 
|  | 185 | } | 
|  | 186 |  | 
|  | 187 | r = sd_bus_message_append_array(m, 'y', debug, debuglen); | 
|  | 188 | if (r < 0) { | 
|  | 189 | fprintf(stderr, "Failed to add the raw array of bytes: %s\n", strerror(-r)); | 
|  | 190 | return -1; | 
|  | 191 | } | 
|  | 192 |  | 
|  | 193 | // Call the IPMI responder on the bus so the message can be sent to the CEC | 
|  | 194 | r = sd_bus_call(mbus, m, 0, &error, &reply); | 
|  | 195 | if (r < 0) { | 
|  | 196 | fprintf(stderr, "Failed to call the method: %s", strerror(-r)); | 
|  | 197 | return -1; | 
|  | 198 | } | 
|  | 199 |  | 
|  | 200 | r = sd_bus_message_read(reply, "q", &pty); | 
|  | 201 | if (r < 0) { | 
|  | 202 | fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r)); | 
|  | 203 | } | 
|  | 204 |  | 
|  | 205 | finish: | 
|  | 206 | sd_bus_error_free(&error); | 
|  | 207 | sd_bus_message_unref(m); | 
|  | 208 | sd_bus_message_unref(reply); | 
|  | 209 | sd_bus_unref(mbus); | 
|  | 210 |  | 
|  | 211 | return r; | 
|  | 212 |  | 
|  | 213 | } | 
|  | 214 |  | 
|  | 215 |  | 
|  | 216 | void send_esel(uint16_t recordid) { | 
|  | 217 | char *desc, *assoc, *ascii; | 
|  | 218 | const char *sev; | 
|  | 219 | uint8_t *buffer = NULL; | 
|  | 220 | char *path; | 
|  | 221 | size_t sz; | 
|  | 222 |  | 
|  | 223 | uint8_t hack[] = {0x30, 0x32, 0x34}; | 
|  | 224 |  | 
|  | 225 | asprintf(&path,"%s%04x", "/tmp/esel", recordid); | 
|  | 226 |  | 
|  | 227 | sz = getfilestream(path, &buffer); | 
|  | 228 |  | 
|  | 229 | if (sz == 0) { | 
|  | 230 | printf("Error file does not exist %d\n",__LINE__); | 
|  | 231 | free(path); | 
|  | 232 | return; | 
|  | 233 | } | 
|  | 234 |  | 
|  | 235 |  | 
|  | 236 | sev = create_esel_severity(buffer); | 
|  | 237 |  | 
|  | 238 | create_esel_association(buffer, &assoc); | 
|  | 239 |  | 
|  | 240 | create_esel_description(buffer, sev, &desc); | 
|  | 241 |  | 
|  | 242 |  | 
|  | 243 | // TODO until ISSUE https://github.com/openbmc/rest-dbus/issues/2 | 
|  | 244 | // I cant send extended ascii chars.  So 0,2,4 for now... | 
|  | 245 | send_esel_to_dbus(desc, sev, assoc, hack, 3); | 
|  | 246 |  | 
|  | 247 |  | 
|  | 248 | free(path); | 
|  | 249 | free(assoc); | 
|  | 250 | free(desc); | 
|  | 251 |  | 
|  | 252 | delete[] buffer; | 
|  | 253 |  | 
|  | 254 | return; | 
|  | 255 | } |