Merge pull request #3 from causten/ipmibu
Moved to sdbus and more
diff --git a/Makefile b/Makefile
index 4baf209..2177c9d 100755
--- a/Makefile
+++ b/Makefile
@@ -1,20 +1,24 @@
CXX ?= $(CROSS_COMPILE)g++
DAEMON = ipmid
-DAEMON_OBJ = $(DAEMON).o
-LIB_OBJ = apphandler.o
-LIBS = libapphandler.so
+DAEMON_OBJ = $(DAEMON).o
+LIB_APP_OBJ = apphandler.o \
+ sensorhandler.o \
+ storagehandler.o \
+ dcmihandler.o
-INC_FLAG += $(shell pkg-config --cflags glib-2.0 gio-unix-2.0) -I. -O2 --std=gnu++11
-LIB_FLAG += $(shell pkg-config --libs glib-2.0 gio-unix-2.0) -rdynamic
+LIB_APP = libapphandler.so
+
+INC_FLAG += $(shell pkg-config --cflags --libs libsystemd) -I. -O2 --std=gnu++11
+LIB_FLAG += $(shell pkg-config --libs libsystemd) -rdynamic
IPMID_PATH ?= -DHOST_IPMI_LIB_PATH=\"/usr/lib/host-ipmid/\"
-all: $(DAEMON) $(LIBS)
+all: $(DAEMON) $(LIB_APP)
%.o: %.C
$(CXX) -fpic -c $< $(CXXFLAGS) $(INC_FLAG) $(IPMID_PATH) -o $@
-$(LIBS): $(LIB_OBJ)
+$(LIB_APP): $(LIB_APP_OBJ)
$(CXX) $^ -shared $(LDFLAGS) $(LIB_FLAG) -o $@
$(DAEMON): $(DAEMON_OBJ)
diff --git a/apphandler.C b/apphandler.C
index c86997f..596ec9c 100755
--- a/apphandler.C
+++ b/apphandler.C
@@ -1,12 +1,62 @@
#include "apphandler.h"
#include "ipmid-api.h"
+#include "ipmid.H"
#include <stdio.h>
#include <string.h>
+#include <stdint.h>
-void register_netfn_app_cap_bit() __attribute__((constructor));
-void register_netfn_app_wildcard() __attribute__((constructor));
+void register_netfn_app_functions() __attribute__((constructor));
-ipmi_ret_t ipmi_app_cap_bit_handler(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ipmi_ret_t ipmi_app_read_event(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ ipmi_ret_t rc = IPMI_CC_OK;
+ *data_len = 0;
+
+ printf("IPMI APP READ EVENT Ignoring for now\n");
+ return rc;
+
+}
+
+
+ipmi_ret_t ipmi_app_set_acpi_power_state(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ ipmi_ret_t rc = IPMI_CC_OK;
+ *data_len = 0;
+
+ printf("IPMI SET ACPI STATE Ignoring for now\n");
+ return rc;
+}
+
+ipmi_ret_t ipmi_app_get_device_id(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ ipmi_ret_t rc = IPMI_CC_OK;
+
+ // TODO GET REAL VALUES HERE.... I made these ones up because
+ // we are in bringup mode. Version Major and Minor can be what we
+ // want like v1.03 but the IANA really should be something that
+ // we own. I would suggest getting the IANA from Hostboot as
+ // long as IBM owns it then no problem. If some other company
+ // gave us the IANA to use then use the one we have from the
+ // FSP ipmi code.
+ uint8_t str[] = {0x00, 0, 1, 1,2, 0xD, 0x41, 0xA7, 0x00, 0x43, 0x40};
+
+ // Data length
+ *data_len = sizeof(str);
+
+ // Pack the actual response
+ memcpy(response, &str, *data_len);
+ return rc;
+}
+
+
+ipmi_ret_t ipmi_app_get_bt_capabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
ipmi_request_t request, ipmi_response_t response,
ipmi_data_len_t data_len, ipmi_context_t context)
{
@@ -15,7 +65,7 @@
// Status code.
ipmi_ret_t rc = IPMI_CC_OK;
- unsigned char str[] = {0x00, 0x01, 0xFE, 0xFF, 0x0A, 0x01};
+ uint8_t str[] = {0x01, MAX_IPMI_BUFFER, MAX_IPMI_BUFFER, 0x0A, 0x01};
// Data length
*data_len = sizeof(str);
@@ -26,6 +76,60 @@
return rc;
}
+
+struct set_wd_data_t {
+ uint8_t t_use;
+ uint8_t t_action;
+ uint8_t preset;
+ uint8_t flags;
+ uint8_t ls;
+ uint8_t ms;
+} __attribute__ ((packed));
+
+
+
+ipmi_ret_t ipmi_app_set_watchdog(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+
+ set_wd_data_t *reqptr = (set_wd_data_t*) request;
+ uint16_t timer = 0;
+ // Status code.
+ ipmi_ret_t rc = IPMI_CC_OK;
+
+ *data_len = 0;
+
+ timer = (((uint16_t)reqptr->ms) << 8) + reqptr->ls;
+
+ printf("WATCHDOG SET Timer:[0x%X] 100ms intervals\n",timer);
+
+ // TODO: Right here is where we would call some dbus method as a timer.
+ // If the timer expires it would iniate a reboot of the host.
+
+ return rc;
+}
+
+
+ipmi_ret_t ipmi_app_reset_watchdog(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ // Status code.
+ ipmi_ret_t rc = IPMI_CC_OK;
+ *data_len = 0;
+
+ printf("WATCHDOG RESET\n");
+ // TODO Right here is where we would call some sdbus timer.
+ // If your are experiencing dejavu you are right. the
+ // set and the reset do similar things
+ return rc;
+}
+
+
+
+
+
ipmi_ret_t ipmi_app_wildcard_handler(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
ipmi_request_t request, ipmi_response_t response,
ipmi_data_len_t data_len, ipmi_context_t context)
@@ -43,16 +147,29 @@
return rc;
}
-void register_netfn_app_cap_bit()
+void register_netfn_app_functions()
{
printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CAP_BIT);
- ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CAP_BIT, NULL, ipmi_app_cap_bit_handler);
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CAP_BIT, NULL, ipmi_app_get_bt_capabilities);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_WILDCARD);
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_WILDCARD, NULL, ipmi_app_wildcard_handler);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_RESET_WD);
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_RESET_WD, NULL, ipmi_app_reset_watchdog);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_SET_WD);
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_WD, NULL, ipmi_app_set_watchdog);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_DEVICE_ID);
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_DEVICE_ID, NULL, ipmi_app_get_device_id);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_SET_ACPI);
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_ACPI, NULL, ipmi_app_set_acpi_power_state);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_READ_EVENT);
+ ipmi_register_callback(NETFUN_APP, IPMI_CMD_READ_EVENT, NULL, ipmi_app_read_event);
return;
}
-void register_netfn_app_wildcard()
-{
- printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_WILDCARD);
- ipmi_register_callback(NETFUN_APP, IPMI_CMD_WILDCARD, NULL, ipmi_app_wildcard_handler);
- return;
-}
+
diff --git a/apphandler.h b/apphandler.h
index 602801b..2c4ea22 100644
--- a/apphandler.h
+++ b/apphandler.h
@@ -5,7 +5,13 @@
enum ipmi_netfn_app_cmds
{
// Get capability bits
+ IPMI_CMD_RESET_WD = 0x22,
+ IPMI_CMD_SET_WD = 0x24,
IPMI_CMD_GET_CAP_BIT = 0x36,
+ IPMI_CMD_GET_DEVICE_ID = 0x00,
+ IPMI_CMD_SET_ACPI = 0x06,
+ IPMI_CMD_READ_EVENT = 0x35,
+
};
#endif
diff --git a/dcmihandler.C b/dcmihandler.C
new file mode 100644
index 0000000..fafebdc
--- /dev/null
+++ b/dcmihandler.C
@@ -0,0 +1,40 @@
+#include "dcmihandler.h"
+#include "ipmid-api.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+void register_netfn_dcmi_functions() __attribute__((constructor));
+
+
+ipmi_ret_t ipmi_dcmi_get_power_limit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ ipmi_ret_t rc = IPMI_DCMI_CC_NO_ACTIVE_POWER_LIMIT;
+
+ // dcmi-v1-5-rev-spec.pdf 6.6.2.
+ // This is good enough for OpenBMC support for OpenPOWER based systems
+ // TODO research if more is needed
+ uint8_t data_response[] = { 0xDC, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01};
+
+
+
+ printf("IPMI DCMI_GET_POWER_LEVEL\n");
+
+ memcpy(response, data_response, sizeof(data_response));
+ *data_len = sizeof(data_response);
+
+ return rc;
+}
+
+
+void register_netfn_dcmi_functions()
+{
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_POWER);
+ ipmi_register_callback(NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_POWER, NULL, ipmi_dcmi_get_power_limit);
+ return;
+}
+// 956379
\ No newline at end of file
diff --git a/dcmihandler.h b/dcmihandler.h
new file mode 100644
index 0000000..5fc0c10
--- /dev/null
+++ b/dcmihandler.h
@@ -0,0 +1,12 @@
+#ifndef __HOST_IPMI_DCMI_HANDLER_H__
+#define __HOST_IPMI_DCMI_HANDLER_H__
+
+// IPMI commands for net functions.
+enum ipmi_netfn_sen_cmds
+{
+ // Get capability bits
+ IPMI_CMD_DCMI_GET_POWER = 0x03,
+
+};
+
+#endif
diff --git a/ipmid-api.h b/ipmid-api.h
index 615e0d5..caf18e8 100755
--- a/ipmid-api.h
+++ b/ipmid-api.h
@@ -85,6 +85,7 @@
enum ipmi_return_codes
{
IPMI_CC_OK = 0x00,
+ IPMI_DCMI_CC_NO_ACTIVE_POWER_LIMIT = 0x80,
IPMI_CC_INVALID = 0xC1
};
diff --git a/ipmid.C b/ipmid.C
index 37ac771..d0dfba8 100644
--- a/ipmid.C
+++ b/ipmid.C
@@ -4,22 +4,82 @@
#include <unistd.h>
#include <assert.h>
#include <dirent.h>
-#include <gio/gio.h>
+#include <systemd/sd-bus.h>
#include <string.h>
#include <stdlib.h>
#include <map>
#include "ipmid.H"
+#include <sys/time.h>
+#include <errno.h>
+
+
+sd_bus *bus = NULL;
// Channel that is used for OpenBMC Barreleye
const char * DBUS_NAME = "org.openbmc.HostIpmi";
const char * OBJ_NAME = "/org/openbmc/HostIpmi/1";
+const char * FILTER = "type='signal',sender='org.openbmc.HostIpmi',member='ReceivedMessage'";
+
+
typedef std::pair<ipmi_netfn_t, ipmi_cmd_t> ipmi_fn_cmd_t;
typedef std::pair<ipmid_callback_t, ipmi_context_t> ipmi_fn_context_t;
// Global data structure that contains the IPMI command handler's registrations.
std::map<ipmi_fn_cmd_t, ipmi_fn_context_t> g_ipmid_router_map;
+
+
+#ifndef HEXDUMP_COLS
+#define HEXDUMP_COLS 16
+#endif
+
+void hexdump(void *mem, size_t len)
+{
+ unsigned int i, j;
+
+ for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++)
+ {
+ /* print offset */
+ if(i % HEXDUMP_COLS == 0)
+ {
+ printf("0x%06x: ", i);
+ }
+
+ /* print hex data */
+ if(i < len)
+ {
+ printf("%02x ", 0xFF & ((char*)mem)[i]);
+ }
+ else /* end of block, just aligning for ASCII dump */
+ {
+ printf(" ");
+ }
+
+ /* print ASCII dump */
+ if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1))
+ {
+ for(j = i - (HEXDUMP_COLS - 1); j <= i; j++)
+ {
+ if(j >= len) /* end of block, not really printing */
+ {
+ putchar(' ');
+ }
+ else if(isprint(((char*)mem)[j])) /* printable char */
+ {
+ putchar(0xFF & ((char*)mem)[j]);
+ }
+ else /* other char */
+ {
+ putchar('.');
+ }
+ }
+ putchar('\n');
+ }
+ }
+}
+
+
// Method that gets called by shared libraries to get their command handlers registered
void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
ipmi_context_t context, ipmid_callback_t handler)
@@ -101,107 +161,130 @@
return rc;
}
-// This gets called by Glib loop on seeing a Dbus signal
-static void handle_ipmi_command(GDBusProxy *proxy,
- gchar *sender_name,
- gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
-{
- // Used to re-construct the message into IPMI specific ones.
- guchar *parameters_str;
- unsigned char sequence, netfn, cmd;
- // Request and Response buffer.
- unsigned char request[MAX_IPMI_BUFFER] = {0};
- unsigned char response[MAX_IPMI_BUFFER] = {0};
- size_t msg_length = 0;
- size_t data_len = 0;
- // Response from Net Function Router
- ipmi_ret_t rc = 0;
+static int send_ipmi_message(unsigned char seq, unsigned char netfn, unsigned char cmd, unsigned char *buf, unsigned char len) {
- // Variables to marshall and unmarshall the messages.
- GVariantIter *iter;
- guchar data;
- GVariant *dbus_response;
- GVariantBuilder *builder;
+ sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus_message *reply = NULL, *m=NULL;
- // Pretty print the message that came on Dbus
- parameters_str = (guchar *) g_variant_print (parameters, TRUE);
- printf ("*** Received Signal: %s: %s :%s\n",
- signal_name,
- sender_name,
- parameters_str);
- // Consume the data pattern "<bYte><bYte><bYte><Array_of_bYtes>
- g_variant_get(parameters, "(yyyay)", &sequence, &netfn, &cmd, &iter);
+ const char *path;
+ int r, pty;
- printf("Sequence: %x\n",sequence );
- printf("Netfn : %x\n",netfn );
- printf("Cmd : %x\n",cmd );
- // Further break down the GVariant byte array
- while (g_variant_iter_loop (iter, "y", &data))
- {
- request[msg_length++] = data;
+ r = sd_bus_message_new_method_call(bus,&m,DBUS_NAME,OBJ_NAME,DBUS_NAME,"sendMessage");
+ if (r < 0) {
+ fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r));
+ return -1;
}
- // Done with consuming data.
- g_free (parameters_str);
- // Needed to see what we get back from the handlers.
- data_len = msg_length;
+ // Responses in IPMI require a bit set. So there ya go...
+ netfn |= 0x04;
+
+
+ // Add the bytes needed for the methods to be called
+ r = sd_bus_message_append(m, "yyy", seq, netfn, cmd);
+ if (r < 0) {
+ fprintf(stderr, "Failed add the netfn and others : %s\n", strerror(-r));
+ return -1;
+ }
+
+ r = sd_bus_message_append_array(m, 'y', buf, len);
+ if (r < 0) {
+ fprintf(stderr, "Failed to add the string of response 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(bus, 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, "x", &pty);
+#ifdef __IPMI_DEBUG__
+ printf("RC from the ipmi dbus method :%d \n", pty);
+#endif
+ if (r < 0) {
+ fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r));
+
+ }
+
+
+ sd_bus_error_free(&error);
+ sd_bus_message_unref(m);
+
+
+#ifdef __IPMI_DEBUG__
+ printf("%d : %s\n", __LINE__, __PRETTY_FUNCTION__ );
+#endif
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+
+}
+
+static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error
+ *ret_error) {
+ int r = 0;
+ const char *msg = NULL;
+ char sequence, netfn, cmd;
+ const void *request;
+ size_t sz;
+ size_t resplen =MAX_IPMI_BUFFER;
+ unsigned char response[MAX_IPMI_BUFFER];
+
+ printf(" *** Received Signal: ");
+
+ memset(response, 0, MAX_IPMI_BUFFER);
+
+ r = sd_bus_message_read(m, "yyy", &sequence, &netfn, &cmd);
+ if (r < 0) {
+ fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
+ return -1;
+ }
+
+ r = sd_bus_message_read_array(m, 'y', &request, &sz );
+ if (r < 0) {
+ fprintf(stderr, "Failed to parse signal message: %s\n", strerror(-r));
+ return -1;
+ }
+
+
+ printf("Seq 0x%02x, NetFn 0x%02x, CMD: 0x%02x \n", sequence, netfn, cmd);
+ hexdump((void*)request, sz);
+
+ // Allow the length field to be used for both input and output of the
+ // ipmi call
+ resplen = sz;
// Now that we have parsed the entire byte array from the caller
// we can call the ipmi router to do the work...
- rc = ipmi_netfn_router(netfn, cmd, (void *)request, (void *)response, &data_len);
- if(rc == 0)
+ r = ipmi_netfn_router(netfn, cmd, (void *)request, (void *)response, &resplen);
+ if(r != 0)
{
- printf("SUCCESS handling NetFn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
- }
- else
- {
- fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",rc, netfn, cmd);
+ fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",r, netfn, cmd);
}
- // Now build a response Gvariant package
- // This example may help
- // http://stackoverflow.com/questions/22937588/how-to-send-byte-array-over-gdbus
+ printf("Response...\n");
+ hexdump((void*)response, resplen);
- printf("Bytes to return\n");
- // hexdump(response,data_len);
-
- // Now we need to put the data as "Array Of Bytes" as we got them.
- builder = g_variant_builder_new (G_VARIANT_TYPE ("ay"));
-
- for (uint out_data = 0; out_data < data_len; out_data++)
- {
- g_variant_builder_add (builder, "y", response[out_data]);
+ // Send the response buffer from the ipmi command
+ r = send_ipmi_message(sequence, netfn, cmd, response, resplen);
+ if (r < 0) {
+ fprintf(stderr, "Failed to send the response message\n");
+ return -1;
}
- dbus_response = g_variant_new ("(yyyay)", sequence, netfn+1, cmd, builder);
- // Variant builder is no longer needed.
- g_variant_builder_unref (builder);
-
- parameters_str = (guchar *) g_variant_print (dbus_response, TRUE);
- printf (" *** Response Signal :%s\n", parameters_str);
-
- // Done packing the data.
- g_free (parameters_str);
-
- // NOW send the respone message in the Dbus calling "sendMessage" interface.
- g_dbus_proxy_call_sync (proxy,
- "sendMessage",
- dbus_response,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- NULL);
+ return 0;
}
+
//----------------------------------------------------------------------
// handler_select
// Select all the files ending with with .so. in the given diretcory
@@ -260,13 +343,14 @@
num_handlers = scandir(ipmi_lib_path, &handler_list, handler_select, alphasort);
while(num_handlers--)
{
- printf("Registering handler:[%s]\n",handler_list[num_handlers]->d_name);
-
+ handler_fqdn = ipmi_lib_path;
handler_fqdn += handler_list[num_handlers]->d_name;
+ printf("Registering handler:[%s]\n",handler_fqdn.c_str());
+
lib_handler = dlopen(handler_fqdn.c_str(), RTLD_NOW);
if(lib_handler == NULL)
{
- fprintf(stderr,"ERROR opening:[%s]\n",handler_list[num_handlers]->d_name);
+ fprintf(stderr,"ERROR opening:[%s]\n",handler_fqdn.c_str());
dlerror();
}
// Wipe the memory allocated for this particular entry.
@@ -282,6 +366,11 @@
int main(int argc, char *argv[])
{
+ sd_bus_slot *slot = NULL;
+ int r;
+ char *mode = NULL;
+
+
// Register all the handlers that provider implementation to IPMI commands.
ipmi_register_callback_handlers(HOST_IPMI_LIB_PATH);
@@ -295,32 +384,45 @@
printf("NETFN:[0x%X], cmd[0x%X]\n", fn_and_cmd.first, fn_and_cmd.second);
}
#endif
-
- // Infrastructure that will wait for IPMi Dbus messages and will call
- // into the corresponding IPMI providers.
- GDBusProxy *proxy;
- GMainLoop *loop;
- loop = g_main_loop_new (NULL, FALSE);
- // Proxy to use GDbus for OpenBMC channel.
- proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
- G_DBUS_PROXY_FLAGS_NONE,
- NULL, /* GDBusInterfaceInfo */
- DBUS_NAME,
- OBJ_NAME,
- DBUS_NAME,
- NULL,
- NULL);
+ /* Connect to system bus */
+ r = sd_bus_open_system(&bus);
+ if (r < 0) {
+ fprintf(stderr, "Failed to connect to system bus: %s\n",
+ strerror(-r));
+ goto finish;
+ }
- // On receiving the Dbus Signal, handle_ipmi_command gets invoked.
- g_signal_connect (proxy,
- "g-signal",
- G_CALLBACK (handle_ipmi_command),
- NULL);
+ r = sd_bus_add_match(bus, &slot, FILTER, handle_ipmi_command, NULL);
+ if (r < 0) {
+ fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), FILTER);
+ goto finish;
+ }
- // This will not return unless we return false from the upmi_handler function.
- g_main_loop_run (loop);
- return 0;
+ for (;;) {
+ /* Process requests */
+
+ r = sd_bus_process(bus, NULL);
+ if (r < 0) {
+ fprintf(stderr, "Failed to process bus: %s\n", strerror(-r));
+ goto finish;
+ }
+ if (r > 0) {
+ continue;
+ }
+
+ r = sd_bus_wait(bus, (uint64_t) - 1);
+ if (r < 0) {
+ fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r));
+ goto finish;
+ }
+ }
+
+finish:
+ sd_bus_slot_unref(slot);
+ sd_bus_unref(bus);
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+
}
diff --git a/ipmid.H b/ipmid.H
index 6b7d2c9..1cfe4c3 100755
--- a/ipmid.H
+++ b/ipmid.H
@@ -10,6 +10,10 @@
// Plugin libraries need to _end_ with .so
#define IPMI_PLUGIN_EXTN ".so"
-#define MAX_IPMI_BUFFER 255
+
+// The BT FIFO in the AST2400 can only handle 64 bytes.
+// Can only allow 63 because the BT interface still
+// needs 1 byte for the length field.
+#define MAX_IPMI_BUFFER 63
#endif
diff --git a/sensorhandler.C b/sensorhandler.C
new file mode 100644
index 0000000..9f0c975
--- /dev/null
+++ b/sensorhandler.C
@@ -0,0 +1,213 @@
+#include "sensorhandler.h"
+#include "ipmid-api.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+
+void register_netfn_sen_functions() __attribute__((constructor));
+
+
+struct sensor_data_t {
+ uint8_t sennum;
+} __attribute__ ((packed)) ;
+
+unsigned char g_sensortype [][2] = {
+ {0xc7, 58},
+{0x01, 113},
+{0xc7, 56},
+{0x01, 114},
+{0xc6, 54},
+{0x07, 40},
+{0xC1, 121},
+{0xC2, 137},
+{0x07, 36},
+{0x07, 43},
+{0xC1, 122},
+{0xC1, 119},
+{0x01, 12},
+{0x01, 111},
+{0x01, 116},
+{0xC1, 127},
+{0xC2, 134},
+{0xC2, 130},
+{0xc, 33},
+{0xC1, 125},
+{0x01, 115},
+{0x22, 4},
+{0xC2, 138},
+{0x01, 108},
+{0x01, 102},
+{0xc, 46},
+{0x7, 11},
+{0xC1, 120},
+{0x07, 39},
+{0x07, 42},
+{0x5, 21},
+{0xC2, 131},
+{0xc1, 48},
+{0x12, 53},
+{0xC1, 124},
+{0x01, 117},
+{0xC1, 126},
+{0xf, 5},
+{0x23, 0},
+{0xC2, 139},
+{0x07, 34},
+{0x09, 146},
+{0x02, 178},
+{0xC2, 140},
+{0xC1, 118},
+{0xC2, 133},
+{0x07, 38},
+{0xC2, 143},
+{0x01, 101},
+{0xc3, 9},
+{0x7, 10},
+{0xc2, 51},
+{0x01, 109},
+{0xc, 32},
+{0x7, 8},
+{0xC1, 129},
+{0x01, 112},
+{0x01, 107},
+{0x07, 37},
+{0x07, 44},
+{0x1f, 50},
+{0xC2, 144},
+{0xc7, 52},
+{0xC2, 141},
+{0x01, 106},
+{0x01, 110},
+{0x01, 103},
+{0x9, 28},
+{0x07, 35},
+{0xc7, 55},
+{0x03, 179},
+{0x07, 41},
+{0xc, 30},
+{0x01, 100},
+{0xC1, 128},
+{0xC2, 135},
+{0x01, 105},
+{0x7, 47},
+{0xC2, 145},
+{0xc7, 57},
+{0x01, 104},
+{0x07, 45},
+{0xC2, 132},
+{0xc4, 49},
+{0xC1, 123},
+{0xC2, 142},
+{0x01, 13},
+{0xC2, 136},
+{0xc, 31},
+{0xff,0xff}
+};
+
+
+unsigned char findSensor(char sensor_number) {
+
+ int i=0;
+
+ // TODO : This function should actually call
+ // a dbus object and have it return the data
+ // it is not ready yet so use a Palmetto
+ // based lookup table for now. The g_sensortype
+ // can be removed once the dbus method exists
+ while (g_sensortype[i][0] != 0xff) {
+ if (g_sensortype[i][1] == sensor_number) {
+ break;
+ } else {
+ i++;
+ }
+
+ }
+
+ return g_sensortype[i][0];
+
+}
+
+ipmi_ret_t ipmi_sen_get_sensor_type(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ sensor_data_t *reqptr = (sensor_data_t*)request;
+ ipmi_ret_t rc = IPMI_CC_OK;
+
+ printf("IPMI GET_SENSOR_TYPE [0x%02X]\n",reqptr->sennum);
+
+ // TODO Not sure what the System-event-sensor is suppose to return
+ // need to ask Hostboot team
+ unsigned char buf[] = {0x00,0x6F};
+
+ buf[0] = findSensor(reqptr->sennum);
+
+ *data_len = sizeof(buf);
+ memcpy(response, &buf, *data_len);
+
+
+
+ return rc;
+}
+
+
+
+// TODO: Saves the sensor information to a file in /tmp. This
+// will need to change to calling the correct method
+// once it exists in the stack.
+ipmi_ret_t ipmi_sen_set_sensor(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ FILE *fp;
+ char string[16];
+ sensor_data_t *reqptr = (sensor_data_t*)request;
+ ipmi_ret_t rc = IPMI_CC_OK;
+ unsigned short rlen;
+
+ rlen = (unsigned short) *data_len - 1;
+
+ sprintf(string, "%s%02x", "/tmp/sen", reqptr->sennum);
+
+ printf("IPMI SET_SENSOR [%s]\n",string);
+
+ if ((fp = fopen(string, "wb")) != NULL) {
+ fwrite(reqptr+1,rlen,1,fp);
+ fclose(fp);
+ } else {
+ fprintf(stderr, "Error trying to write to sensor file %s\n",string);
+ ipmi_ret_t rc = IPMI_CC_INVALID;
+ }
+
+ *data_len=0;
+
+
+ return rc;
+}
+
+ipmi_ret_t ipmi_sen_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ ipmi_ret_t rc = IPMI_CC_OK;
+
+ printf("IPMI S/E Wildcard Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd);
+ *data_len = 0;
+
+ return rc;
+}
+
+
+void register_netfn_sen_functions()
+{
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_WILDCARD);
+ ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_WILDCARD, NULL, ipmi_sen_wildcard);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE);
+ ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE, NULL, ipmi_sen_get_sensor_type);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_SET_SENSOR);
+ ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_SET_SENSOR, NULL, ipmi_sen_set_sensor);
+ return;
+}
diff --git a/sensorhandler.h b/sensorhandler.h
new file mode 100644
index 0000000..da63bcb
--- /dev/null
+++ b/sensorhandler.h
@@ -0,0 +1,13 @@
+#ifndef __HOST_IPMI_SEN_HANDLER_H__
+#define __HOST_IPMI_SEN_HANDLER_H__
+
+// IPMI commands for net functions.
+enum ipmi_netfn_sen_cmds
+{
+ // Get capability bits
+ IPMI_CMD_GET_SENSOR_TYPE = 0x2F,
+ IPMI_CMD_SET_SENSOR = 0x30,
+
+};
+
+#endif
diff --git a/storagehandler.C b/storagehandler.C
new file mode 100644
index 0000000..659fff5
--- /dev/null
+++ b/storagehandler.C
@@ -0,0 +1,200 @@
+#include "storagehandler.h"
+#include "ipmid-api.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+void register_netfn_storage_functions() __attribute__((constructor));
+
+
+unsigned int g_sel_time = 0xFFFFFFFF;
+unsigned short g_sel_reserve = 0x1;
+
+ipmi_ret_t ipmi_storage_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ printf("Handling STORAGE WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
+ // Status code.
+ ipmi_ret_t rc = IPMI_CC_OK;
+ *data_len = 0;
+ return rc;
+}
+
+
+ipmi_ret_t ipmi_storage_set_sel_time(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ unsigned int *bufftype = (unsigned int *) request;
+
+ printf("Handling Set-SEL-Time:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
+ printf("Data: 0x%X]\n",*bufftype);
+
+ g_sel_time = *bufftype;
+
+ ipmi_ret_t rc = IPMI_CC_OK;
+ *data_len = 0;
+ return rc;
+}
+
+struct write_fru_data_t {
+ uint8_t frunum;
+ uint8_t offsetls;
+ uint8_t offsetms;
+ uint8_t data;
+} __attribute__ ((packed)) ;
+
+ipmi_ret_t ipmi_storage_write_fru_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ write_fru_data_t *reqptr = (write_fru_data_t*) request;
+ FILE *fp;
+ char string[16];
+ short offset = 0;
+ uint16_t rlen;
+ ipmi_ret_t rc = IPMI_CC_OK;
+ char iocmd[4];
+
+ sprintf(string, "%s%02x", "/tmp/fru", reqptr->frunum);
+
+ offset = ((uint16_t)reqptr->offsetms) << 8 | reqptr->offsetls;
+
+
+ // Length is the number of request bytes minus the header itself.
+ // The header contains an extra byte to indicate the start of
+ // the data (so didn't need to worry about word/byte boundaries)
+ // hence the -1...
+ rlen = ((uint16_t)*data_len) - (sizeof(write_fru_data_t)-1);
+
+
+ printf("IPMI WRITE-FRU-DATA for %s Offset = %d Length = %d\n",
+ string, offset, rlen);
+
+
+ // I was thinking "ab+" but it appears it doesn't
+ // do what fseek asks. Modify to rb+ and fseek
+ // works great...
+ if (offset == 0) {
+ strcpy(iocmd, "wb");
+ } else {
+ strcpy(iocmd, "rb+");
+ }
+
+ if ((fp = fopen(string, iocmd)) != NULL) {
+ fseek(fp, offset, SEEK_SET);
+ fwrite(&reqptr->data,rlen,1,fp);
+ fclose(fp);
+ } else {
+ fprintf(stderr, "Error trying to write to fru file %s\n",string);
+ ipmi_ret_t rc = IPMI_CC_INVALID;
+ }
+
+
+ // TODO : Here is where some validation code could determine if the
+ // fru data is a legitimate FRU record (not just a partial). Once
+ // the record is valid the code should call a parser routine to call
+ // the various methods updating interesting properties. Perhaps
+ // thinigs like Model#, Serial#, DIMM Size, etc
+
+
+ *data_len = 0;
+
+ return rc;
+}
+
+ipmi_ret_t ipmi_storage_get_sel_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+
+ ipmi_ret_t rc = IPMI_CC_OK;
+ unsigned char buf[] = {0x51,0,0,0xff, 0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0x06};
+
+ printf("IPMI Handling GET-SEL-INFO\n");
+
+ *data_len = sizeof(buf);
+
+ // TODO There is plently of work here. The SEL DB needs to hold a bunch
+ // of things in a header. Items like Time Stamp, number of entries, etc
+ // This is one place where the dbus object with the SEL information could
+ // mimic what IPMI needs.
+
+ // Pack the actual response
+ memcpy(response, &buf, *data_len);
+
+ return rc;
+}
+
+
+
+ipmi_ret_t ipmi_storage_reserve_sel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+
+ ipmi_ret_t rc = IPMI_CC_OK;
+
+ printf("IPMI Handling RESERVE-SEL 0x%04x\n", g_sel_reserve);
+
+ *data_len = sizeof(g_sel_reserve);
+
+ // Pack the actual response
+ memcpy(response, &g_sel_reserve, *data_len);
+
+ return rc;
+}
+
+
+ipmi_ret_t ipmi_storage_add_sel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+
+ ipmi_ret_t rc = IPMI_CC_OK;
+
+ printf("IPMI Handling ADD-SEL \n");
+
+ *data_len = sizeof(g_sel_reserve);
+
+ // Pack the actual response
+ memcpy(response, &g_sel_reserve, *data_len);
+
+ // TODO This code should grab the completed partial esel located in
+ // the /tmp/esel0100 file and commit it to the error log handler.
+
+
+ // TODO I advanced the sel reservation number so next time HB asks
+ // for a reservation they get a new number. This tech may change
+ // based on how the HB team currently uses sel reservations but
+ // for now provide the ability to get new reservations
+ g_sel_reserve++;
+
+ return rc;
+}
+
+
+
+void register_netfn_storage_functions()
+{
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_WILDCARD);
+ ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_WILDCARD, NULL, ipmi_storage_wildcard);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_SET_SEL_TIME);
+ ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_SET_SEL_TIME, NULL, ipmi_storage_set_sel_time);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_WRITE_FRU_DATA);
+ ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_WRITE_FRU_DATA, NULL, ipmi_storage_write_fru_data);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_GET_SEL_INFO);
+ ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_INFO, NULL, ipmi_storage_get_sel_info);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_RESERVE_SEL);
+ ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_RESERVE_SEL, NULL, ipmi_storage_reserve_sel);
+
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_ADD_SEL);
+ ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_ADD_SEL, NULL, ipmi_storage_add_sel);
+ return;
+}
+
diff --git a/storagehandler.h b/storagehandler.h
new file mode 100644
index 0000000..56c1a8b
--- /dev/null
+++ b/storagehandler.h
@@ -0,0 +1,16 @@
+#ifndef __HOST_IPMI_STORAGE_HANDLER_H__
+#define __HOST_IPMI_STORAGE_HANDLER_H__
+
+// IPMI commands for net functions.
+enum ipmi_netfn_storage_cmds
+{
+ // Get capability bits
+ IPMI_CMD_SET_SEL_TIME = 0x49,
+ IPMI_CMD_WRITE_FRU_DATA = 0x12,
+ IPMI_CMD_GET_SEL_INFO = 0x40,
+ IPMI_CMD_RESERVE_SEL = 0x42,
+ IPMI_CMD_ADD_SEL = 0x44,
+
+};
+
+#endif