Allow esels to be sent to dbus event log

Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
diff --git a/storageaddsel.C b/storageaddsel.C
new file mode 100644
index 0000000..c36e1d3
--- /dev/null
+++ b/storageaddsel.C
@@ -0,0 +1,255 @@
+#include <stdint.h>
+#include <cstdlib>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+#include <algorithm>
+#include <vector>
+#include <memory>
+#include <systemd/sd-bus.h>
+
+#include "ipmid.H"
+#include "storagehandler.h"
+#include "sensorhandler.h"
+
+using namespace std;
+
+extern int find_openbmc_path(const char *, const uint8_t , dbus_interface_t *);
+
+
+//////////////////////////
+struct esel_section_headers_t {
+	uint8_t sectionid[2];
+	uint8_t sectionlength[2];
+	uint8_t version;
+	uint8_t subsectiontype;
+	uint8_t compid;
+};
+
+struct severity_values_t {
+	uint8_t type;
+	const char *description;
+};
+
+
+const std::vector<severity_values_t> g_sev_desc = {
+	{0x10, "recoverable error"},
+	{0x20, "predictive error"},
+	{0x40, "unrecoverable error"},
+	{0x50, "critical error"},
+	{0x60, "error from a diagnostic test"},
+	{0x70, "recovered symptom "},
+	{0xFF, "Unknown"},
+};
+
+const char* sev_lookup(uint8_t n) {
+	auto i = std::find_if(std::begin(g_sev_desc), std::end(g_sev_desc),
+	                      [n](auto p){ return p.type == n || p.type == 0xFF; });
+	return i->description;
+}
+
+
+
+
+int find_sensor_type_string(uint8_t sensor_number, char **s) {
+
+	dbus_interface_t a;
+	const char *p;
+	char r;
+
+	r = find_openbmc_path("SENSOR", sensor_number, &a);
+
+	if ((r < 0) || (a.bus[0] == 0)) {
+		// Just make a generic message for errors that
+		// occur on sensors that dont exist
+		asprintf(s, "Unknown Sensor (0x%02x)", sensor_number);
+	} else {
+
+		if ((p = strrchr (a.path, '/')) == NULL) {
+			p = "/Unknown Sensor";
+		}
+
+		asprintf(s, "%s", p+1);
+	}
+
+	return 0;
+}
+
+
+size_t getfilestream(const char *fn, uint8_t **buffer) {
+
+	FILE *fp;
+	size_t size = 0;
+
+	if ((fp = fopen(fn, "rb")) != NULL) {
+
+		fseek(fp, 0, SEEK_END);
+		size = ftell(fp);
+		fseek(fp, 0, SEEK_SET);
+
+		size = 0x100;
+
+		*buffer = new uint8_t [size];
+
+		fread(*buffer, 1, size, fp);
+		fclose(fp);
+	}
+
+	return size;
+}
+
+
+const char *create_esel_severity(const uint8_t *buffer) {
+
+	uint8_t severity;
+	// Dive in to the IBM log to find the severity
+	severity = (0xF0  & buffer[0x4A]);
+
+	return sev_lookup(severity);
+}
+
+int create_esel_association(const uint8_t *buffer, char **m) {
+
+	ipmi_add_sel_request_t *p;
+	dbus_interface_t dbusint;
+	uint8_t sensor;
+
+	p = ( ipmi_add_sel_request_t *) buffer;
+
+	sensor = p->sensornumber;
+
+	find_openbmc_path("SENSOR", sensor, &dbusint);
+
+	if (strlen(dbusint.path) < 1) {
+		printf("Sensor not found\n");
+		snprintf(dbusint.path, sizeof(dbusint.path), "0x%x", sensor);
+	}
+
+	asprintf(m, "%s", dbusint.path);
+
+	return 0;
+}
+
+
+
+int create_esel_description(const uint8_t *buffer, const char *sev, char **message) {
+
+
+	ipmi_add_sel_request_t *p;
+	int r;
+	char *m;
+
+	p =  ( ipmi_add_sel_request_t *) buffer;
+
+	find_sensor_type_string(p->sensornumber,&m);
+
+	asprintf(message, "A %s has experienced a %s", m, sev );
+
+	free(m);
+
+	return 0;
+}
+
+
+int send_esel_to_dbus(const char *desc, const char *sev, const char *details, uint8_t *debug, size_t debuglen) {
+
+	sd_bus *mbus = NULL;
+    sd_bus_error error = SD_BUS_ERROR_NULL;
+    sd_bus_message *reply = NULL, *m=NULL;
+    uint16_t *pty;
+    int r;
+
+
+
+    /* Connect to system bus */
+    r = sd_bus_open_system(&mbus);
+    if (r < 0) {
+        fprintf(stderr, "Failed to connect to system bus: %s\n",
+                strerror(-r));
+        goto finish;
+    }
+    r = sd_bus_message_new_method_call(mbus,&m,
+    									"org.openbmc.records.events",
+    									"/org/openbmc/records/events",
+    									"org.openbmc.recordlog",
+    									"acceptHostMessage");
+    if (r < 0) {
+        fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
+        return -1;
+    }
+
+    r = sd_bus_message_append(m, "sss", desc, sev, details);
+    if (r < 0) {
+        fprintf(stderr, "Failed add the message strings : %s\n", strerror(-r));
+        return -1;
+    }
+
+    r = sd_bus_message_append_array(m, 'y', debug, debuglen);
+    if (r < 0) {
+        fprintf(stderr, "Failed to add the raw array of bytes: %s\n", strerror(-r));
+        return -1;
+    }
+
+    // Call the IPMI responder on the bus so the message can be sent to the CEC
+    r = sd_bus_call(mbus, m, 0, &error, &reply);
+    if (r < 0) {
+        fprintf(stderr, "Failed to call the method: %s", strerror(-r));
+        return -1;
+    }
+
+    r = sd_bus_message_read(reply, "q", &pty);
+    if (r < 0) {
+       fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
+    }
+
+finish:
+    sd_bus_error_free(&error);
+    sd_bus_message_unref(m);
+    sd_bus_message_unref(reply);
+    sd_bus_unref(mbus);
+
+    return r;
+
+}
+
+
+void send_esel(uint16_t recordid) {
+	char *desc, *assoc, *ascii;
+	const char *sev;
+	uint8_t *buffer = NULL;
+	char *path;
+	size_t sz;
+
+	uint8_t hack[] = {0x30, 0x32, 0x34};
+
+	asprintf(&path,"%s%04x", "/tmp/esel", recordid);
+
+	sz = getfilestream(path, &buffer);
+
+	if (sz == 0) {
+		printf("Error file does not exist %d\n",__LINE__);
+		free(path);
+		return;
+	}
+
+
+	sev = create_esel_severity(buffer);
+
+	create_esel_association(buffer, &assoc);
+
+	create_esel_description(buffer, sev, &desc);
+
+
+	// TODO until ISSUE https://github.com/openbmc/rest-dbus/issues/2
+	// I cant send extended ascii chars.  So 0,2,4 for now...
+	send_esel_to_dbus(desc, sev, assoc, hack, 3);
+
+
+	free(path);
+	free(assoc);
+	free(desc);
+
+	delete[] buffer;
+
+	return;
+}