From 98a238406ff5765cc6db3e61ba787c27144dad1d Mon Sep 17 00:00:00 2001 From: Matthew Barth Date: Mon, 8 Aug 2016 15:26:29 -0500 Subject: Switch C++ source files to .cpp extension Change-Id: I495186b4afd58ec1e5d9d5c6472394f96541d17d Signed-off-by: Matthew Barth --- Makefile | 2 +- apphandler.C | 539 ------------------------------------ apphandler.cpp | 539 ++++++++++++++++++++++++++++++++++++ chassishandler.C | 453 ------------------------------- chassishandler.cpp | 453 +++++++++++++++++++++++++++++++ dcmihandler.C | 40 --- dcmihandler.cpp | 40 +++ globalhandler.C | 152 ----------- globalhandler.cpp | 152 +++++++++++ groupext.C | 31 --- groupext.cpp | 31 +++ ipmid.C | 752 --------------------------------------------------- ipmid.cpp | 752 +++++++++++++++++++++++++++++++++++++++++++++++++++ ipmisensor.C | 302 --------------------- ipmisensor.cpp | 302 +++++++++++++++++++++ sensorhandler.C | 262 ------------------ sensorhandler.cpp | 262 ++++++++++++++++++ storageaddsel.C | 253 ----------------- storageaddsel.cpp | 253 +++++++++++++++++ storagehandler.C | 171 ------------ storagehandler.cpp | 171 ++++++++++++ testaddsel.C | 107 -------- testaddsel.cpp | 107 ++++++++ testit.C | 120 -------- testit.cpp | 120 ++++++++ transporthandler.C | 395 --------------------------- transporthandler.cpp | 395 +++++++++++++++++++++++++++ 27 files changed, 3578 insertions(+), 3578 deletions(-) delete mode 100644 apphandler.C create mode 100644 apphandler.cpp delete mode 100644 chassishandler.C create mode 100644 chassishandler.cpp delete mode 100644 dcmihandler.C create mode 100644 dcmihandler.cpp delete mode 100644 globalhandler.C create mode 100644 globalhandler.cpp delete mode 100644 groupext.C create mode 100644 groupext.cpp delete mode 100644 ipmid.C create mode 100644 ipmid.cpp delete mode 100644 ipmisensor.C create mode 100644 ipmisensor.cpp delete mode 100644 sensorhandler.C create mode 100644 sensorhandler.cpp delete mode 100644 storageaddsel.C create mode 100644 storageaddsel.cpp delete mode 100644 storagehandler.C create mode 100644 storagehandler.cpp delete mode 100644 testaddsel.C create mode 100644 testaddsel.cpp delete mode 100644 testit.C create mode 100644 testit.cpp delete mode 100644 transporthandler.C create mode 100644 transporthandler.cpp diff --git a/Makefile b/Makefile index 447b129..8652658 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ all: $(DAEMON) $(LIB_APP) $(LIB_HOST_SRV) $(TESTER) $(WHITELIST_SRC) : generate_whitelist.sh $(WHITELIST_CONF) ./$^ > $@ -%.o: %.C +%.o: %.cpp $(CXX) -std=c++14 -fpic -c $< $(CXXFLAGS) $(INC_FLAG) $(IPMID_PATH) -o $@ $(LIB_APP): $(LIB_APP_OBJ) diff --git a/apphandler.C b/apphandler.C deleted file mode 100644 index b8cc0aa..0000000 --- a/apphandler.C +++ /dev/null @@ -1,539 +0,0 @@ -#include "apphandler.h" -#include "ipmid-api.h" -#include "ipmid.H" -#include -#include -#include -#include - -extern sd_bus *bus; - -void register_netfn_app_functions() __attribute__((constructor)); - -#define DEVICE_FW1 2 -#define DEVICE_FW2 3 -#define DEVICE_AUX 11 - -//--------------------------------------------------------------------- -// Called by Host on seeing a SMS_ATN bit set. Return a hardcoded -// value of 0x2 indicating we need Host read some data. -//------------------------------------------------------------------- -ipmi_ret_t ipmi_app_get_msg_flags(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) -{ - // Generic return from IPMI commands. - ipmi_ret_t rc = IPMI_CC_OK; - - printf("IPMI APP GET MSG FLAGS returning with [bit:2] set\n"); - - // From IPMI spec V2.0 for Get Message Flags Command : - // bit:[1] from LSB : 1b = Event Message Buffer Full. - // Return as 0 if Event Message Buffer is not supported, - // or when the Event Message buffer is disabled. - // TODO. For now. assume its not disabled and send "0x2" anyway: - - uint8_t set_event_msg_buffer_full = 0x2; - *data_len = sizeof(set_event_msg_buffer_full); - - // Pack the actual response - memcpy(response, &set_event_msg_buffer_full, *data_len); - - return rc; -} - -//------------------------------------------------------------------- -// Called by Host post response from Get_Message_Flags -//------------------------------------------------------------------- -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; - printf("IPMI APP READ EVENT command received\n"); - - // TODO : For now, this is catering only to the Soft Power Off via OEM SEL - // mechanism. If we need to make this generically used for some - // other conditions, then we can take advantage of context pointer. - - struct oem_sel_timestamped soft_off = {0}; - *data_len = sizeof(struct oem_sel_timestamped); - - // either id[0] -or- id[1] can be filled in. We will use id[0] - soft_off.id[0] = SEL_OEM_ID_0; - soft_off.id[1] = SEL_OEM_ID_0; - soft_off.type = SEL_RECORD_TYPE_OEM; - - // Following 3 bytes are from IANA Manufactre_Id field. See below - soft_off.manuf_id[0]= 0x41; - soft_off.manuf_id[1]= 0xA7; - soft_off.manuf_id[2]= 0x00; - - // per IPMI spec NetFuntion for OEM - soft_off.netfun = 0x3A; - - // Mechanism to kick start soft shutdown. - soft_off.cmd = CMD_POWER; - soft_off.data[0] = SOFT_OFF; - - // All '0xFF' since unused. - memset(&soft_off.data[1], 0xFF, 3); - - // Pack the actual response - memcpy(response, &soft_off, *data_len); - 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; -} - - -typedef struct -{ - char major; - char minor; - uint16_t d[2]; -} rev_t; - - -/* Currently only supports the vx.x-x-[-x] format Will return -1 if not in */ -/* the format this routine knows how to parse */ -/* version = v0.6-19-gf363f61-dirty */ -/* ^ ^ ^^ ^ */ -/* | | |----------|-- additional details */ -/* | |---------------- Minor */ -/* |------------------ Major */ -/* Additional details : If the option group exists it will force Auxiliary */ -/* Firmware Revision Information 4th byte to 1 indicating the build was */ -/* derived with additional edits */ -int convert_version(const char *p, rev_t *rev) -{ - char *s, *token; - char hexbyte[5]; - int l; - uint16_t commits; - - if (*p != 'v') - return -1; - p++; - - s = strdup(p); - token = strtok(s,".-"); - - rev->major = (int8_t) atoi(token); - - token = strtok(NULL, ".-"); - rev->minor = (int8_t) atoi(token); - - // Capture the number of commits on top of the minor tag. - // I'm using BE format like the ipmi spec asked for - token = strtok(NULL,".-"); - - if (token) { - commits = (int16_t) atoi(token); - rev->d[0] = (commits>>8) | (commits<<8); - - // commit number we skip - token = strtok(NULL,".-"); - - } else { - rev->d[0] = 0; - } - - // Any value of the optional parameter forces it to 1 - if (token) - token = strtok(NULL,".-"); - - rev->d[1] = (token != NULL) ? 1 : 0; - - free(s); - return 0; -} - -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; - const char *busname = "org.openbmc.Inventory"; - const char *objname = "/org/openbmc/inventory/system/chassis/motherboard/bmc"; - const char *iface = "org.openbmc.InventoryItem"; - char *ver = NULL; - int r; - rev_t rev = {0}; - - // TODO: - // This value is the IANA number assigned to "IBM Platform Firmware - // Division", which is also used by our service processor. We may want - // a different number or at least a different version? - uint8_t dev_id[] = {0, 0, 0, 0, 2, 0xD, 0x41, 0xA7, 0x00, 0x43, 0x40, 0, 0, 0, 0}; - - // Data length - *data_len = sizeof(dev_id); - - r = sd_bus_get_property_string(bus,busname,objname,iface,"version", NULL, &ver); - if ( r < 0 ) { - fprintf(stderr, "Failed to obtain version property: %s\n", strerror(-r)); - } else { - r = convert_version(ver, &rev); - if( r >= 0 ) { - // bit7 identifies state of SDR repository, hence the mask - dev_id[DEVICE_FW1] |= 0x7F & rev.major; - - rev.minor = (rev.minor > 99 ? 99 : rev.minor); - dev_id[DEVICE_FW2] = rev.minor % 10 + (rev.minor / 10) * 16; - memcpy(&dev_id[DEVICE_AUX], rev.d, 4); - } - } - - // Pack the actual response - memcpy(response, &dev_id, *data_len); - return rc; -} - -ipmi_ret_t ipmi_app_get_device_guid(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) -{ - const char *busname = "org.openbmc.control.Chassis"; - const char *objname = "/org/openbmc/control/chassis0"; - const char *iface = "org.freedesktop.DBus.Properties"; - const char *chassis_iface = "org.openbmc.control.Chassis"; - sd_bus_message *reply = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - int r = 0; - char *uuid = NULL; - - // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223 - // Per IPMI Spec 2.0 need to convert to 16 hex bytes and reverse the byte order - // Ex: 0x2332fc2c40e66298e511f2782395a361 - - const int resp_size = 16; // Response is 16 hex bytes per IPMI Spec - uint8_t resp_uuid[resp_size]; // Array to hold the formatted response - int resp_loc = resp_size-1; // Point resp end of array to save in reverse order - int i = 0; - char *tokptr = NULL; - char *id_octet = NULL; - - // Status code. - ipmi_ret_t rc = IPMI_CC_OK; - *data_len = 0; - - printf("IPMI GET DEVICE GUID\n"); - - // Call Get properties method with the interface and property name - r = sd_bus_call_method(bus,busname,objname,iface, - "Get",&error, &reply, "ss", - chassis_iface, "uuid"); - if (r < 0) - { - fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto finish; - } - - r = sd_bus_message_read(reply, "v", "s", &uuid); - if (r < 0 || uuid == NULL) - { - fprintf(stderr, "Failed to get a response: %s", strerror(-r)); - rc = IPMI_CC_RESPONSE_ERROR; - goto finish; - } - - // Traverse the UUID - id_octet = strtok_r(uuid, "-", &tokptr); // Get the UUID octects separated by dash - - if (id_octet == NULL) - { - // Error - fprintf(stderr, "Unexpected UUID format: %s", uuid); - rc = IPMI_CC_RESPONSE_ERROR; - goto finish; - } - - while (id_octet != NULL) - { - // Calculate the octet string size since it varies - // Divide it by 2 for the array size since 1 byte is built from 2 chars - int tmp_size = strlen(id_octet)/2; - - for(i = 0; i < tmp_size; i++) - { - char tmp_array[3] = {0}; // Holder of the 2 chars that will become a byte - strncpy(tmp_array, id_octet, 2); // 2 chars at a time - - int resp_byte = strtoul(tmp_array, NULL, 16); // Convert to hex byte - memcpy((void*)&resp_uuid[resp_loc], &resp_byte, 1); // Copy end to first - resp_loc--; - id_octet+=2; // Finished with the 2 chars, advance - } - id_octet=strtok_r(NULL, "-", &tokptr); // Get next octet - } - - // Data length - *data_len = resp_size; - - // Pack the actual response - memcpy(response, &resp_uuid, *data_len); - -finish: - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - - 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) -{ - printf("Handling Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd); - - // Status code. - ipmi_ret_t rc = IPMI_CC_OK; - - uint8_t str[] = {0x01, MAX_IPMI_BUFFER, MAX_IPMI_BUFFER, 0x0A, 0x01}; - - // Data length - *data_len = sizeof(str); - - // Pack the actual response - memcpy(response, &str, *data_len); - - 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) -{ - const char *busname = "org.openbmc.watchdog.Host"; - const char *objname = "/org/openbmc/watchdog/host0"; - const char *iface = "org.openbmc.Watchdog"; - sd_bus_message *reply = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - int r = 0; - - set_wd_data_t *reqptr = (set_wd_data_t*) request; - uint16_t timer = 0; - uint32_t timer_ms = 0; - - *data_len = 0; - - // Get number of 100ms intervals - timer = (((uint16_t)reqptr->ms) << 8) + reqptr->ls; - // Get timer value in ms - timer_ms = timer * 100; - - printf("WATCHDOG SET Timer:[0x%X] 100ms intervals\n",timer); - - // Set watchdog timer - r = sd_bus_call_method(bus, busname, objname, iface, - "set", &error, &reply, "i", timer_ms); - if(r < 0) - { - fprintf(stderr, "Failed to call the SET method: %s\n", strerror(-r)); - goto finish; - } - - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - - // Stop the current watchdog if any - r = sd_bus_call_method(bus, busname, objname, iface, - "stop", &error, &reply, NULL); - if(r < 0) - { - fprintf(stderr, "Failed to call the STOP method: %s\n", strerror(-r)); - goto finish; - } - - if (reqptr->t_use & 0x40) - { - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - - // Start the watchdog if requested - r = sd_bus_call_method(bus, busname, objname, iface, - "start", &error, &reply, NULL); - if(r < 0) - { - fprintf(stderr, "Failed to call the START method: %s\n", strerror(-r)); - } - } - -finish: - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - - return (r < 0) ? -1 : IPMI_CC_OK; -} - - -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) -{ - const char *busname = "org.openbmc.watchdog.Host"; - const char *objname = "/org/openbmc/watchdog/host0"; - const char *iface = "org.openbmc.Watchdog"; - sd_bus_message *reply = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - int r = 0; - - // Status code. - ipmi_ret_t rc = IPMI_CC_OK; - *data_len = 0; - - printf("WATCHDOG RESET\n"); - - // Refresh watchdog - r = sd_bus_call_method(bus, busname, objname, iface, - "poke", &error, &reply, NULL); - if (r < 0) { - fprintf(stderr, "Failed to add reset watchdog: %s\n", strerror(-r)); - rc = -1; - } - - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - - return rc; -} - -// ATTENTION: This ipmi function is very hardcoded on purpose -// OpenBMC does not fully support IPMI. This command is useful -// to have around because it enables testing of interfaces with -// the IPMI tool. -#define GET_CHANNEL_INFO_CHANNEL_OFFSET 0 -// IPMI Table 6-2 -#define IPMI_CHANNEL_TYPE_IPMB 1 -// IPMI Table 6-3 -#define IPMI_CHANNEL_MEDIUM_TYPE_OTHER 6 - -ipmi_ret_t ipmi_app_channel_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; - uint8_t resp[] = { - 1, - IPMI_CHANNEL_MEDIUM_TYPE_OTHER, - IPMI_CHANNEL_TYPE_IPMB, - 1,0x41,0xA7,0x00,0,0}; - uint8_t *p = (uint8_t*) request; - - printf("IPMI APP GET CHANNEL INFO\n"); - - // The supported channels numbers are 1 and 8. - // Channel Number E is used as way to identify the current channel - // that the command is being is received from. - if (*p == 0xe || *p == 1 || *p == 8) { - - *data_len = sizeof(resp); - memcpy(response, resp, *data_len); - - } else { - rc = IPMI_CC_PARM_OUT_OF_RANGE; - *data_len = 0; - } - - return rc; -} - -ipmi_ret_t ipmi_app_set_bmc_global_enables(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; - - // Event and message logging enabled by default so return for now - printf("IPMI APP SET BMC GLOBAL ENABLES Ignoring for now\n"); - - 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) -{ - printf("Handling WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd); - - // Status code. - ipmi_ret_t rc = IPMI_CC_OK; - - *data_len = strlen("THIS IS WILDCARD"); - - // Now pack actual response - memcpy(response, "THIS IS WILDCARD", *data_len); - - return rc; -} - -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_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_GET_DEVICE_GUID); - ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_DEVICE_GUID, NULL, ipmi_app_get_device_guid); - - 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); - - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, - IPMI_CMD_SET_BMC_GLOBAL_ENABLES); - ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_BMC_GLOBAL_ENABLES, NULL, - ipmi_app_set_bmc_global_enables); - - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS); - ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS, NULL, ipmi_app_get_msg_flags); - - - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CHAN_INFO); - ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_INFO, NULL, ipmi_app_channel_info); - - - - return; -} - - diff --git a/apphandler.cpp b/apphandler.cpp new file mode 100644 index 0000000..b8cc0aa --- /dev/null +++ b/apphandler.cpp @@ -0,0 +1,539 @@ +#include "apphandler.h" +#include "ipmid-api.h" +#include "ipmid.H" +#include +#include +#include +#include + +extern sd_bus *bus; + +void register_netfn_app_functions() __attribute__((constructor)); + +#define DEVICE_FW1 2 +#define DEVICE_FW2 3 +#define DEVICE_AUX 11 + +//--------------------------------------------------------------------- +// Called by Host on seeing a SMS_ATN bit set. Return a hardcoded +// value of 0x2 indicating we need Host read some data. +//------------------------------------------------------------------- +ipmi_ret_t ipmi_app_get_msg_flags(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) +{ + // Generic return from IPMI commands. + ipmi_ret_t rc = IPMI_CC_OK; + + printf("IPMI APP GET MSG FLAGS returning with [bit:2] set\n"); + + // From IPMI spec V2.0 for Get Message Flags Command : + // bit:[1] from LSB : 1b = Event Message Buffer Full. + // Return as 0 if Event Message Buffer is not supported, + // or when the Event Message buffer is disabled. + // TODO. For now. assume its not disabled and send "0x2" anyway: + + uint8_t set_event_msg_buffer_full = 0x2; + *data_len = sizeof(set_event_msg_buffer_full); + + // Pack the actual response + memcpy(response, &set_event_msg_buffer_full, *data_len); + + return rc; +} + +//------------------------------------------------------------------- +// Called by Host post response from Get_Message_Flags +//------------------------------------------------------------------- +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; + printf("IPMI APP READ EVENT command received\n"); + + // TODO : For now, this is catering only to the Soft Power Off via OEM SEL + // mechanism. If we need to make this generically used for some + // other conditions, then we can take advantage of context pointer. + + struct oem_sel_timestamped soft_off = {0}; + *data_len = sizeof(struct oem_sel_timestamped); + + // either id[0] -or- id[1] can be filled in. We will use id[0] + soft_off.id[0] = SEL_OEM_ID_0; + soft_off.id[1] = SEL_OEM_ID_0; + soft_off.type = SEL_RECORD_TYPE_OEM; + + // Following 3 bytes are from IANA Manufactre_Id field. See below + soft_off.manuf_id[0]= 0x41; + soft_off.manuf_id[1]= 0xA7; + soft_off.manuf_id[2]= 0x00; + + // per IPMI spec NetFuntion for OEM + soft_off.netfun = 0x3A; + + // Mechanism to kick start soft shutdown. + soft_off.cmd = CMD_POWER; + soft_off.data[0] = SOFT_OFF; + + // All '0xFF' since unused. + memset(&soft_off.data[1], 0xFF, 3); + + // Pack the actual response + memcpy(response, &soft_off, *data_len); + 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; +} + + +typedef struct +{ + char major; + char minor; + uint16_t d[2]; +} rev_t; + + +/* Currently only supports the vx.x-x-[-x] format Will return -1 if not in */ +/* the format this routine knows how to parse */ +/* version = v0.6-19-gf363f61-dirty */ +/* ^ ^ ^^ ^ */ +/* | | |----------|-- additional details */ +/* | |---------------- Minor */ +/* |------------------ Major */ +/* Additional details : If the option group exists it will force Auxiliary */ +/* Firmware Revision Information 4th byte to 1 indicating the build was */ +/* derived with additional edits */ +int convert_version(const char *p, rev_t *rev) +{ + char *s, *token; + char hexbyte[5]; + int l; + uint16_t commits; + + if (*p != 'v') + return -1; + p++; + + s = strdup(p); + token = strtok(s,".-"); + + rev->major = (int8_t) atoi(token); + + token = strtok(NULL, ".-"); + rev->minor = (int8_t) atoi(token); + + // Capture the number of commits on top of the minor tag. + // I'm using BE format like the ipmi spec asked for + token = strtok(NULL,".-"); + + if (token) { + commits = (int16_t) atoi(token); + rev->d[0] = (commits>>8) | (commits<<8); + + // commit number we skip + token = strtok(NULL,".-"); + + } else { + rev->d[0] = 0; + } + + // Any value of the optional parameter forces it to 1 + if (token) + token = strtok(NULL,".-"); + + rev->d[1] = (token != NULL) ? 1 : 0; + + free(s); + return 0; +} + +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; + const char *busname = "org.openbmc.Inventory"; + const char *objname = "/org/openbmc/inventory/system/chassis/motherboard/bmc"; + const char *iface = "org.openbmc.InventoryItem"; + char *ver = NULL; + int r; + rev_t rev = {0}; + + // TODO: + // This value is the IANA number assigned to "IBM Platform Firmware + // Division", which is also used by our service processor. We may want + // a different number or at least a different version? + uint8_t dev_id[] = {0, 0, 0, 0, 2, 0xD, 0x41, 0xA7, 0x00, 0x43, 0x40, 0, 0, 0, 0}; + + // Data length + *data_len = sizeof(dev_id); + + r = sd_bus_get_property_string(bus,busname,objname,iface,"version", NULL, &ver); + if ( r < 0 ) { + fprintf(stderr, "Failed to obtain version property: %s\n", strerror(-r)); + } else { + r = convert_version(ver, &rev); + if( r >= 0 ) { + // bit7 identifies state of SDR repository, hence the mask + dev_id[DEVICE_FW1] |= 0x7F & rev.major; + + rev.minor = (rev.minor > 99 ? 99 : rev.minor); + dev_id[DEVICE_FW2] = rev.minor % 10 + (rev.minor / 10) * 16; + memcpy(&dev_id[DEVICE_AUX], rev.d, 4); + } + } + + // Pack the actual response + memcpy(response, &dev_id, *data_len); + return rc; +} + +ipmi_ret_t ipmi_app_get_device_guid(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) +{ + const char *busname = "org.openbmc.control.Chassis"; + const char *objname = "/org/openbmc/control/chassis0"; + const char *iface = "org.freedesktop.DBus.Properties"; + const char *chassis_iface = "org.openbmc.control.Chassis"; + sd_bus_message *reply = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + int r = 0; + char *uuid = NULL; + + // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223 + // Per IPMI Spec 2.0 need to convert to 16 hex bytes and reverse the byte order + // Ex: 0x2332fc2c40e66298e511f2782395a361 + + const int resp_size = 16; // Response is 16 hex bytes per IPMI Spec + uint8_t resp_uuid[resp_size]; // Array to hold the formatted response + int resp_loc = resp_size-1; // Point resp end of array to save in reverse order + int i = 0; + char *tokptr = NULL; + char *id_octet = NULL; + + // Status code. + ipmi_ret_t rc = IPMI_CC_OK; + *data_len = 0; + + printf("IPMI GET DEVICE GUID\n"); + + // Call Get properties method with the interface and property name + r = sd_bus_call_method(bus,busname,objname,iface, + "Get",&error, &reply, "ss", + chassis_iface, "uuid"); + if (r < 0) + { + fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); + rc = IPMI_CC_UNSPECIFIED_ERROR; + goto finish; + } + + r = sd_bus_message_read(reply, "v", "s", &uuid); + if (r < 0 || uuid == NULL) + { + fprintf(stderr, "Failed to get a response: %s", strerror(-r)); + rc = IPMI_CC_RESPONSE_ERROR; + goto finish; + } + + // Traverse the UUID + id_octet = strtok_r(uuid, "-", &tokptr); // Get the UUID octects separated by dash + + if (id_octet == NULL) + { + // Error + fprintf(stderr, "Unexpected UUID format: %s", uuid); + rc = IPMI_CC_RESPONSE_ERROR; + goto finish; + } + + while (id_octet != NULL) + { + // Calculate the octet string size since it varies + // Divide it by 2 for the array size since 1 byte is built from 2 chars + int tmp_size = strlen(id_octet)/2; + + for(i = 0; i < tmp_size; i++) + { + char tmp_array[3] = {0}; // Holder of the 2 chars that will become a byte + strncpy(tmp_array, id_octet, 2); // 2 chars at a time + + int resp_byte = strtoul(tmp_array, NULL, 16); // Convert to hex byte + memcpy((void*)&resp_uuid[resp_loc], &resp_byte, 1); // Copy end to first + resp_loc--; + id_octet+=2; // Finished with the 2 chars, advance + } + id_octet=strtok_r(NULL, "-", &tokptr); // Get next octet + } + + // Data length + *data_len = resp_size; + + // Pack the actual response + memcpy(response, &resp_uuid, *data_len); + +finish: + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + + 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) +{ + printf("Handling Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd); + + // Status code. + ipmi_ret_t rc = IPMI_CC_OK; + + uint8_t str[] = {0x01, MAX_IPMI_BUFFER, MAX_IPMI_BUFFER, 0x0A, 0x01}; + + // Data length + *data_len = sizeof(str); + + // Pack the actual response + memcpy(response, &str, *data_len); + + 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) +{ + const char *busname = "org.openbmc.watchdog.Host"; + const char *objname = "/org/openbmc/watchdog/host0"; + const char *iface = "org.openbmc.Watchdog"; + sd_bus_message *reply = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + int r = 0; + + set_wd_data_t *reqptr = (set_wd_data_t*) request; + uint16_t timer = 0; + uint32_t timer_ms = 0; + + *data_len = 0; + + // Get number of 100ms intervals + timer = (((uint16_t)reqptr->ms) << 8) + reqptr->ls; + // Get timer value in ms + timer_ms = timer * 100; + + printf("WATCHDOG SET Timer:[0x%X] 100ms intervals\n",timer); + + // Set watchdog timer + r = sd_bus_call_method(bus, busname, objname, iface, + "set", &error, &reply, "i", timer_ms); + if(r < 0) + { + fprintf(stderr, "Failed to call the SET method: %s\n", strerror(-r)); + goto finish; + } + + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + + // Stop the current watchdog if any + r = sd_bus_call_method(bus, busname, objname, iface, + "stop", &error, &reply, NULL); + if(r < 0) + { + fprintf(stderr, "Failed to call the STOP method: %s\n", strerror(-r)); + goto finish; + } + + if (reqptr->t_use & 0x40) + { + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + + // Start the watchdog if requested + r = sd_bus_call_method(bus, busname, objname, iface, + "start", &error, &reply, NULL); + if(r < 0) + { + fprintf(stderr, "Failed to call the START method: %s\n", strerror(-r)); + } + } + +finish: + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + + return (r < 0) ? -1 : IPMI_CC_OK; +} + + +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) +{ + const char *busname = "org.openbmc.watchdog.Host"; + const char *objname = "/org/openbmc/watchdog/host0"; + const char *iface = "org.openbmc.Watchdog"; + sd_bus_message *reply = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + int r = 0; + + // Status code. + ipmi_ret_t rc = IPMI_CC_OK; + *data_len = 0; + + printf("WATCHDOG RESET\n"); + + // Refresh watchdog + r = sd_bus_call_method(bus, busname, objname, iface, + "poke", &error, &reply, NULL); + if (r < 0) { + fprintf(stderr, "Failed to add reset watchdog: %s\n", strerror(-r)); + rc = -1; + } + + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + + return rc; +} + +// ATTENTION: This ipmi function is very hardcoded on purpose +// OpenBMC does not fully support IPMI. This command is useful +// to have around because it enables testing of interfaces with +// the IPMI tool. +#define GET_CHANNEL_INFO_CHANNEL_OFFSET 0 +// IPMI Table 6-2 +#define IPMI_CHANNEL_TYPE_IPMB 1 +// IPMI Table 6-3 +#define IPMI_CHANNEL_MEDIUM_TYPE_OTHER 6 + +ipmi_ret_t ipmi_app_channel_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; + uint8_t resp[] = { + 1, + IPMI_CHANNEL_MEDIUM_TYPE_OTHER, + IPMI_CHANNEL_TYPE_IPMB, + 1,0x41,0xA7,0x00,0,0}; + uint8_t *p = (uint8_t*) request; + + printf("IPMI APP GET CHANNEL INFO\n"); + + // The supported channels numbers are 1 and 8. + // Channel Number E is used as way to identify the current channel + // that the command is being is received from. + if (*p == 0xe || *p == 1 || *p == 8) { + + *data_len = sizeof(resp); + memcpy(response, resp, *data_len); + + } else { + rc = IPMI_CC_PARM_OUT_OF_RANGE; + *data_len = 0; + } + + return rc; +} + +ipmi_ret_t ipmi_app_set_bmc_global_enables(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; + + // Event and message logging enabled by default so return for now + printf("IPMI APP SET BMC GLOBAL ENABLES Ignoring for now\n"); + + 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) +{ + printf("Handling WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd); + + // Status code. + ipmi_ret_t rc = IPMI_CC_OK; + + *data_len = strlen("THIS IS WILDCARD"); + + // Now pack actual response + memcpy(response, "THIS IS WILDCARD", *data_len); + + return rc; +} + +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_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_GET_DEVICE_GUID); + ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_DEVICE_GUID, NULL, ipmi_app_get_device_guid); + + 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); + + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, + IPMI_CMD_SET_BMC_GLOBAL_ENABLES); + ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_BMC_GLOBAL_ENABLES, NULL, + ipmi_app_set_bmc_global_enables); + + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS); + ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS, NULL, ipmi_app_get_msg_flags); + + + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CHAN_INFO); + ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_INFO, NULL, ipmi_app_channel_info); + + + + return; +} + + diff --git a/chassishandler.C b/chassishandler.C deleted file mode 100644 index ded9157..0000000 --- a/chassishandler.C +++ /dev/null @@ -1,453 +0,0 @@ -#include "chassishandler.h" -#include "ipmid-api.h" -#include -#include -#include -#include - - -//Defines -#define SET_PARM_VERSION 1 -#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on -#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80 //boot flags data1 8th bit on -#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0 //boot flags data1 7 & 8 bit on - - - -// OpenBMC Chassis Manager dbus framework -const char *chassis_bus_name = "org.openbmc.control.Chassis"; -const char *chassis_object_name = "/org/openbmc/control/chassis0"; -const char *chassis_intf_name = "org.openbmc.control.Chassis"; - - -void register_netfn_chassis_functions() __attribute__((constructor)); - -// Host settings in dbus -// Service name should be referenced by connection name got via object mapper -const char *settings_object_name = "/org/openbmc/settings/host0"; -const char *settings_intf_name = "org.freedesktop.DBus.Properties"; -const char *host_intf_name = "org.openbmc.settings.Host"; - -int dbus_get_property(const char *name, char **buf) -{ - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *m = NULL; - sd_bus *bus = NULL; - char *temp_buf = NULL; - char *connection = NULL; - int r; - - // Get the system bus where most system services are provided. - bus = ipmid_get_sd_bus_connection(); - - r = mapper_get_service(bus, settings_object_name, &connection); - if (r < 0) { - fprintf(stderr, "Failed to get connection, return value: %d.\n", r); - goto finish; - } - - /* - * Bus, service, object path, interface and method are provided to call - * the method. - * Signatures and input arguments are provided by the arguments at the - * end. - */ - r = sd_bus_call_method(bus, - connection, /* service to contact */ - settings_object_name, /* object path */ - settings_intf_name, /* interface name */ - "Get", /* method name */ - &error, /* object to return error in */ - &m, /* return message on success */ - "ss", /* input signature */ - host_intf_name, /* first argument */ - name); /* second argument */ - - if (r < 0) { - fprintf(stderr, "Failed to issue method call: %s\n", error.message); - goto finish; - } - - /* - * The output should be parsed exactly the same as the output formatting - * specified. - */ - r = sd_bus_message_read(m, "v", "s", &temp_buf); - if (r < 0) { - fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r)); - goto finish; - } - - asprintf(buf, "%s", temp_buf); -/* *buf = (char*) malloc(strlen(temp_buf)); - if (*buf) { - strcpy(*buf, temp_buf); - } -*/ - printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf); - -finish: - sd_bus_error_free(&error); - sd_bus_message_unref(m); - free(connection); - - return r; -} - -int dbus_set_property(const char * name, const char *value) -{ - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *m = NULL; - sd_bus *bus = NULL; - char *connection = NULL; - int r; - - // Get the system bus where most system services are provided. - bus = ipmid_get_sd_bus_connection(); - - r = mapper_get_service(bus, settings_object_name, &connection); - if (r < 0) { - fprintf(stderr, "Failed to get connection, return value: %d.\n", r); - goto finish; - } - - /* - * Bus, service, object path, interface and method are provided to call - * the method. - * Signatures and input arguments are provided by the arguments at the - * end. - */ - r = sd_bus_call_method(bus, - connection, /* service to contact */ - settings_object_name, /* object path */ - settings_intf_name, /* interface name */ - "Set", /* method name */ - &error, /* object to return error in */ - &m, /* return message on success */ - "ssv", /* input signature */ - host_intf_name, /* first argument */ - name, /* second argument */ - "s", /* third argument */ - value); /* fourth argument */ - - if (r < 0) { - fprintf(stderr, "Failed to issue method call: %s\n", error.message); - goto finish; - } - - printf("IPMID boot option property set: {%s}.\n", value); - -finish: - sd_bus_error_free(&error); - sd_bus_message_unref(m); - free(connection); - - return r; -} - -struct get_sys_boot_options_t { - uint8_t parameter; - uint8_t set; - uint8_t block; -} __attribute__ ((packed)); - -struct get_sys_boot_options_response_t { - uint8_t version; - uint8_t parm; - uint8_t data[5]; -} __attribute__ ((packed)); - -struct set_sys_boot_options_t { - uint8_t parameter; - uint8_t data[8]; -} __attribute__ ((packed)); - -ipmi_ret_t ipmi_chassis_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 CHASSIS WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd); - // Status code. - ipmi_ret_t rc = IPMI_CC_OK; - *data_len = 0; - return rc; -} - -//------------------------------------------------------------ -// Calls into Chassis Control Dbus object to do the power off -//------------------------------------------------------------ -int ipmi_chassis_power_control(const char *method) -{ - // sd_bus error - int rc = 0; - - // SD Bus error report mechanism. - sd_bus_error bus_error = SD_BUS_ERROR_NULL; - - // Response from the call. Although there is no response for this call, - // obligated to mention this to make compiler happy. - sd_bus_message *response = NULL; - - // Gets a hook onto either a SYSTEM or SESSION bus - sd_bus *bus_type = ipmid_get_sd_bus_connection(); - - rc = sd_bus_call_method(bus_type, // On the System Bus - chassis_bus_name, // Service to contact - chassis_object_name, // Object path - chassis_intf_name, // Interface name - method, // Method to be called - &bus_error, // object to return error - &response, // Response buffer if any - NULL); // No input arguments - if(rc < 0) - { - fprintf(stderr,"ERROR initiating Power Off:[%s]\n",bus_error.message); - } - else - { - printf("Chassis Power Off initiated successfully\n"); - } - - sd_bus_error_free(&bus_error); - sd_bus_message_unref(response); - - return rc; -} - - -//---------------------------------------------------------------------- -// Chassis Control commands -//---------------------------------------------------------------------- -ipmi_ret_t ipmi_chassis_control(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) -{ - // Error from power off. - int rc = 0; - - // No response for this command. - *data_len = 0; - - // Catch the actual operaton by peeking into request buffer - uint8_t chassis_ctrl_cmd = *(uint8_t *)request; - printf("Chassis Control Command: Operation:[0x%X]\n",chassis_ctrl_cmd); - - switch(chassis_ctrl_cmd) - { - case CMD_POWER_OFF: - rc = ipmi_chassis_power_control("powerOff"); - break; - case CMD_HARD_RESET: - rc = ipmi_chassis_power_control("reboot"); - break; - default: - { - fprintf(stderr, "Invalid Chassis Control command:[0x%X] received\n",chassis_ctrl_cmd); - rc = -1; - } - } - - return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK); -} - -struct bootOptionTypeMap_t { - uint8_t ipmibootflag; - char dbusname[8]; -}; - -#define INVALID_STRING "Invalid" -// dbus supports this list of boot devices. -bootOptionTypeMap_t g_bootOptionTypeMap_t[] = { - - {0x01, "Network"}, - {0x02, "Disk"}, - {0x03, "Safe"}, - {0x05, "CDROM"}, - {0x06, "Setup"}, - {0x00, "Default"}, - {0xFF, INVALID_STRING} -}; - -uint8_t get_ipmi_boot_option(char *p) { - - bootOptionTypeMap_t *s = g_bootOptionTypeMap_t; - - while (s->ipmibootflag != 0xFF) { - if (!strcmp(s->dbusname,p)) - break; - s++; - } - - if (!s->ipmibootflag) - printf("Failed to find Sensor Type %s\n", p); - - return s->ipmibootflag; -} - -char* get_boot_option_by_ipmi(uint8_t p) { - - bootOptionTypeMap_t *s = g_bootOptionTypeMap_t; - - while (s->ipmibootflag != 0xFF) { - - if (s->ipmibootflag == p) - break; - - s++; - } - - - if (!s->ipmibootflag) - printf("Failed to find Sensor Type 0x%x\n", p); - - return s->dbusname; -} - -ipmi_ret_t ipmi_chassis_get_sys_boot_options(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_PARM_NOT_SUPPORTED; - char *p = NULL; - get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response; - get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request; - uint8_t s; - - printf("IPMI GET_SYS_BOOT_OPTIONS\n"); - - memset(resp,0,sizeof(*resp)); - resp->version = SET_PARM_VERSION; - resp->parm = 5; - resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME; - - *data_len = sizeof(*resp); - - /* - * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc. - * This is the only parameter used by petitboot. - */ - if (reqptr->parameter == 5) { - - /* Get the boot device */ - int r = dbus_get_property("boot_flags",&p); - - if (r < 0) { - fprintf(stderr, "Dbus get property(boot_flags) failed for get_sys_boot_options.\n"); - rc = IPMI_CC_UNSPECIFIED_ERROR; - - } else { - - s = get_ipmi_boot_option(p); - resp->data[1] = (s << 2); - rc = IPMI_CC_OK; - - } - - if (p) - { - free(p); - p = NULL; - } - - /* Get the boot policy */ - r = dbus_get_property("boot_policy",&p); - - if (r < 0) { - fprintf(stderr, "Dbus get property(boot_policy) failed for get_sys_boot_options.\n"); - rc = IPMI_CC_UNSPECIFIED_ERROR; - - } else { - - printf("BootPolicy is[%s]", p); - resp->data[0] = (strncmp(p,"ONETIME",strlen("ONETIME"))==0) ? - SET_PARM_BOOT_FLAGS_VALID_ONE_TIME: - SET_PARM_BOOT_FLAGS_VALID_PERMANENT; - rc = IPMI_CC_OK; - - } - - - } else { - fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); - } - - if (p) - free(p); - - return rc; -} - - - -ipmi_ret_t ipmi_chassis_set_sys_boot_options(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; - char *s; - - printf("IPMI SET_SYS_BOOT_OPTIONS\n"); - - set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request; - - // This IPMI command does not have any resposne data - *data_len = 0; - - /* 000101 - * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc. - * This is the only parameter used by petitboot. - */ - if (reqptr->parameter == 5) { - - s = get_boot_option_by_ipmi(((reqptr->data[1] & 0x3C) >> 2)); - - printf("%d: %s\n", __LINE__, s); - if (!strcmp(s,INVALID_STRING)) { - - rc = IPMI_CC_PARM_NOT_SUPPORTED; - - } else { - - int r = dbus_set_property("boot_flags",s); - - if (r < 0) { - fprintf(stderr, "Dbus set property(boot_flags) failed for set_sys_boot_options.\n"); - rc = IPMI_CC_UNSPECIFIED_ERROR; - } - } - - /* setting the boot policy */ - s = (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) == - SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME"); - - printf ( "\nBoot Policy is %s",s); - int r = dbus_set_property("boot_policy",s); - - if (r < 0) { - fprintf(stderr, "Dbus set property(boot_policy) failed for set_sys_boot_options.\n"); - rc = IPMI_CC_UNSPECIFIED_ERROR; - } - - } else { - fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); - rc = IPMI_CC_PARM_NOT_SUPPORTED; - } - - return rc; -} - -void register_netfn_chassis_functions() -{ - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_WILDCARD); - ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard); - - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS); - ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL, ipmi_chassis_get_sys_boot_options); - - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL); - ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control); - - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS); - ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL, ipmi_chassis_set_sys_boot_options); -} - diff --git a/chassishandler.cpp b/chassishandler.cpp new file mode 100644 index 0000000..ded9157 --- /dev/null +++ b/chassishandler.cpp @@ -0,0 +1,453 @@ +#include "chassishandler.h" +#include "ipmid-api.h" +#include +#include +#include +#include + + +//Defines +#define SET_PARM_VERSION 1 +#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on +#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80 //boot flags data1 8th bit on +#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0 //boot flags data1 7 & 8 bit on + + + +// OpenBMC Chassis Manager dbus framework +const char *chassis_bus_name = "org.openbmc.control.Chassis"; +const char *chassis_object_name = "/org/openbmc/control/chassis0"; +const char *chassis_intf_name = "org.openbmc.control.Chassis"; + + +void register_netfn_chassis_functions() __attribute__((constructor)); + +// Host settings in dbus +// Service name should be referenced by connection name got via object mapper +const char *settings_object_name = "/org/openbmc/settings/host0"; +const char *settings_intf_name = "org.freedesktop.DBus.Properties"; +const char *host_intf_name = "org.openbmc.settings.Host"; + +int dbus_get_property(const char *name, char **buf) +{ + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *m = NULL; + sd_bus *bus = NULL; + char *temp_buf = NULL; + char *connection = NULL; + int r; + + // Get the system bus where most system services are provided. + bus = ipmid_get_sd_bus_connection(); + + r = mapper_get_service(bus, settings_object_name, &connection); + if (r < 0) { + fprintf(stderr, "Failed to get connection, return value: %d.\n", r); + goto finish; + } + + /* + * Bus, service, object path, interface and method are provided to call + * the method. + * Signatures and input arguments are provided by the arguments at the + * end. + */ + r = sd_bus_call_method(bus, + connection, /* service to contact */ + settings_object_name, /* object path */ + settings_intf_name, /* interface name */ + "Get", /* method name */ + &error, /* object to return error in */ + &m, /* return message on success */ + "ss", /* input signature */ + host_intf_name, /* first argument */ + name); /* second argument */ + + if (r < 0) { + fprintf(stderr, "Failed to issue method call: %s\n", error.message); + goto finish; + } + + /* + * The output should be parsed exactly the same as the output formatting + * specified. + */ + r = sd_bus_message_read(m, "v", "s", &temp_buf); + if (r < 0) { + fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r)); + goto finish; + } + + asprintf(buf, "%s", temp_buf); +/* *buf = (char*) malloc(strlen(temp_buf)); + if (*buf) { + strcpy(*buf, temp_buf); + } +*/ + printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf); + +finish: + sd_bus_error_free(&error); + sd_bus_message_unref(m); + free(connection); + + return r; +} + +int dbus_set_property(const char * name, const char *value) +{ + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *m = NULL; + sd_bus *bus = NULL; + char *connection = NULL; + int r; + + // Get the system bus where most system services are provided. + bus = ipmid_get_sd_bus_connection(); + + r = mapper_get_service(bus, settings_object_name, &connection); + if (r < 0) { + fprintf(stderr, "Failed to get connection, return value: %d.\n", r); + goto finish; + } + + /* + * Bus, service, object path, interface and method are provided to call + * the method. + * Signatures and input arguments are provided by the arguments at the + * end. + */ + r = sd_bus_call_method(bus, + connection, /* service to contact */ + settings_object_name, /* object path */ + settings_intf_name, /* interface name */ + "Set", /* method name */ + &error, /* object to return error in */ + &m, /* return message on success */ + "ssv", /* input signature */ + host_intf_name, /* first argument */ + name, /* second argument */ + "s", /* third argument */ + value); /* fourth argument */ + + if (r < 0) { + fprintf(stderr, "Failed to issue method call: %s\n", error.message); + goto finish; + } + + printf("IPMID boot option property set: {%s}.\n", value); + +finish: + sd_bus_error_free(&error); + sd_bus_message_unref(m); + free(connection); + + return r; +} + +struct get_sys_boot_options_t { + uint8_t parameter; + uint8_t set; + uint8_t block; +} __attribute__ ((packed)); + +struct get_sys_boot_options_response_t { + uint8_t version; + uint8_t parm; + uint8_t data[5]; +} __attribute__ ((packed)); + +struct set_sys_boot_options_t { + uint8_t parameter; + uint8_t data[8]; +} __attribute__ ((packed)); + +ipmi_ret_t ipmi_chassis_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 CHASSIS WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd); + // Status code. + ipmi_ret_t rc = IPMI_CC_OK; + *data_len = 0; + return rc; +} + +//------------------------------------------------------------ +// Calls into Chassis Control Dbus object to do the power off +//------------------------------------------------------------ +int ipmi_chassis_power_control(const char *method) +{ + // sd_bus error + int rc = 0; + + // SD Bus error report mechanism. + sd_bus_error bus_error = SD_BUS_ERROR_NULL; + + // Response from the call. Although there is no response for this call, + // obligated to mention this to make compiler happy. + sd_bus_message *response = NULL; + + // Gets a hook onto either a SYSTEM or SESSION bus + sd_bus *bus_type = ipmid_get_sd_bus_connection(); + + rc = sd_bus_call_method(bus_type, // On the System Bus + chassis_bus_name, // Service to contact + chassis_object_name, // Object path + chassis_intf_name, // Interface name + method, // Method to be called + &bus_error, // object to return error + &response, // Response buffer if any + NULL); // No input arguments + if(rc < 0) + { + fprintf(stderr,"ERROR initiating Power Off:[%s]\n",bus_error.message); + } + else + { + printf("Chassis Power Off initiated successfully\n"); + } + + sd_bus_error_free(&bus_error); + sd_bus_message_unref(response); + + return rc; +} + + +//---------------------------------------------------------------------- +// Chassis Control commands +//---------------------------------------------------------------------- +ipmi_ret_t ipmi_chassis_control(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) +{ + // Error from power off. + int rc = 0; + + // No response for this command. + *data_len = 0; + + // Catch the actual operaton by peeking into request buffer + uint8_t chassis_ctrl_cmd = *(uint8_t *)request; + printf("Chassis Control Command: Operation:[0x%X]\n",chassis_ctrl_cmd); + + switch(chassis_ctrl_cmd) + { + case CMD_POWER_OFF: + rc = ipmi_chassis_power_control("powerOff"); + break; + case CMD_HARD_RESET: + rc = ipmi_chassis_power_control("reboot"); + break; + default: + { + fprintf(stderr, "Invalid Chassis Control command:[0x%X] received\n",chassis_ctrl_cmd); + rc = -1; + } + } + + return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK); +} + +struct bootOptionTypeMap_t { + uint8_t ipmibootflag; + char dbusname[8]; +}; + +#define INVALID_STRING "Invalid" +// dbus supports this list of boot devices. +bootOptionTypeMap_t g_bootOptionTypeMap_t[] = { + + {0x01, "Network"}, + {0x02, "Disk"}, + {0x03, "Safe"}, + {0x05, "CDROM"}, + {0x06, "Setup"}, + {0x00, "Default"}, + {0xFF, INVALID_STRING} +}; + +uint8_t get_ipmi_boot_option(char *p) { + + bootOptionTypeMap_t *s = g_bootOptionTypeMap_t; + + while (s->ipmibootflag != 0xFF) { + if (!strcmp(s->dbusname,p)) + break; + s++; + } + + if (!s->ipmibootflag) + printf("Failed to find Sensor Type %s\n", p); + + return s->ipmibootflag; +} + +char* get_boot_option_by_ipmi(uint8_t p) { + + bootOptionTypeMap_t *s = g_bootOptionTypeMap_t; + + while (s->ipmibootflag != 0xFF) { + + if (s->ipmibootflag == p) + break; + + s++; + } + + + if (!s->ipmibootflag) + printf("Failed to find Sensor Type 0x%x\n", p); + + return s->dbusname; +} + +ipmi_ret_t ipmi_chassis_get_sys_boot_options(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_PARM_NOT_SUPPORTED; + char *p = NULL; + get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response; + get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request; + uint8_t s; + + printf("IPMI GET_SYS_BOOT_OPTIONS\n"); + + memset(resp,0,sizeof(*resp)); + resp->version = SET_PARM_VERSION; + resp->parm = 5; + resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME; + + *data_len = sizeof(*resp); + + /* + * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc. + * This is the only parameter used by petitboot. + */ + if (reqptr->parameter == 5) { + + /* Get the boot device */ + int r = dbus_get_property("boot_flags",&p); + + if (r < 0) { + fprintf(stderr, "Dbus get property(boot_flags) failed for get_sys_boot_options.\n"); + rc = IPMI_CC_UNSPECIFIED_ERROR; + + } else { + + s = get_ipmi_boot_option(p); + resp->data[1] = (s << 2); + rc = IPMI_CC_OK; + + } + + if (p) + { + free(p); + p = NULL; + } + + /* Get the boot policy */ + r = dbus_get_property("boot_policy",&p); + + if (r < 0) { + fprintf(stderr, "Dbus get property(boot_policy) failed for get_sys_boot_options.\n"); + rc = IPMI_CC_UNSPECIFIED_ERROR; + + } else { + + printf("BootPolicy is[%s]", p); + resp->data[0] = (strncmp(p,"ONETIME",strlen("ONETIME"))==0) ? + SET_PARM_BOOT_FLAGS_VALID_ONE_TIME: + SET_PARM_BOOT_FLAGS_VALID_PERMANENT; + rc = IPMI_CC_OK; + + } + + + } else { + fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); + } + + if (p) + free(p); + + return rc; +} + + + +ipmi_ret_t ipmi_chassis_set_sys_boot_options(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; + char *s; + + printf("IPMI SET_SYS_BOOT_OPTIONS\n"); + + set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request; + + // This IPMI command does not have any resposne data + *data_len = 0; + + /* 000101 + * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc. + * This is the only parameter used by petitboot. + */ + if (reqptr->parameter == 5) { + + s = get_boot_option_by_ipmi(((reqptr->data[1] & 0x3C) >> 2)); + + printf("%d: %s\n", __LINE__, s); + if (!strcmp(s,INVALID_STRING)) { + + rc = IPMI_CC_PARM_NOT_SUPPORTED; + + } else { + + int r = dbus_set_property("boot_flags",s); + + if (r < 0) { + fprintf(stderr, "Dbus set property(boot_flags) failed for set_sys_boot_options.\n"); + rc = IPMI_CC_UNSPECIFIED_ERROR; + } + } + + /* setting the boot policy */ + s = (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) == + SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME"); + + printf ( "\nBoot Policy is %s",s); + int r = dbus_set_property("boot_policy",s); + + if (r < 0) { + fprintf(stderr, "Dbus set property(boot_policy) failed for set_sys_boot_options.\n"); + rc = IPMI_CC_UNSPECIFIED_ERROR; + } + + } else { + fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); + rc = IPMI_CC_PARM_NOT_SUPPORTED; + } + + return rc; +} + +void register_netfn_chassis_functions() +{ + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_WILDCARD); + ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard); + + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS); + ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL, ipmi_chassis_get_sys_boot_options); + + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL); + ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control); + + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS); + ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL, ipmi_chassis_set_sys_boot_options); +} + diff --git a/dcmihandler.C b/dcmihandler.C deleted file mode 100644 index fafebdc..0000000 --- a/dcmihandler.C +++ /dev/null @@ -1,40 +0,0 @@ -#include "dcmihandler.h" -#include "ipmid-api.h" -#include -#include -#include - -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.cpp b/dcmihandler.cpp new file mode 100644 index 0000000..fafebdc --- /dev/null +++ b/dcmihandler.cpp @@ -0,0 +1,40 @@ +#include "dcmihandler.h" +#include "ipmid-api.h" +#include +#include +#include + +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/globalhandler.C b/globalhandler.C deleted file mode 100644 index 889d127..0000000 --- a/globalhandler.C +++ /dev/null @@ -1,152 +0,0 @@ -#include "globalhandler.h" -#include "ipmid-api.h" -#include -#include -#include - -const char *control_object_name = "/org/openbmc/control/bmc0"; -const char *control_intf_name = "org.openbmc.control.Bmc"; - -const char *objectmapper_service_name = "org.openbmc.ObjectMapper"; -const char *objectmapper_object_name = "/org/openbmc/ObjectMapper"; -const char *objectmapper_intf_name = "org.openbmc.ObjectMapper"; - -void register_netfn_global_functions() __attribute__((constructor)); - -int obj_mapper_get_connection(char** buf, const char* obj_path) -{ - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *m = NULL; - sd_bus *bus = NULL; - char *temp_buf = NULL, *intf = NULL; - size_t buf_size = 0; - int r; - - //Get the system bus where most system services are provided. - bus = ipmid_get_sd_bus_connection(); - - /* - * Bus, service, object path, interface and method are provided to call - * the method. - * Signatures and input arguments are provided by the arguments at the - * end. - */ - r = sd_bus_call_method(bus, - objectmapper_service_name, /* service to contact */ - objectmapper_object_name, /* object path */ - objectmapper_intf_name, /* interface name */ - "GetObject", /* method name */ - &error, /* object to return error in */ - &m, /* return message on success */ - "s", /* input signature */ - obj_path /* first argument */ - ); - - if (r < 0) { - fprintf(stderr, "Failed to issue method call: %s\n", error.message); - goto finish; - } - - // Get the key, aka, the connection name - sd_bus_message_read(m, "a{sas}", 1, &temp_buf, 1, &intf); - - /* - * TODO: check the return code. Currently for no reason the message - * parsing of object mapper is always complaining about - * "Device or resource busy", but the result seems OK for now. Need - * further checks. - */ - - buf_size = strlen(temp_buf) + 1; - printf("IPMID connection name: %s\n", temp_buf); - *buf = (char*)malloc(buf_size); - - if (*buf == NULL) { - fprintf(stderr, "Malloc failed for warm reset"); - r = -1; - goto finish; - } - - memcpy(*buf, temp_buf, buf_size); - -finish: - sd_bus_error_free(&error); - sd_bus_message_unref(m); - - return r; -} - -int dbus_warm_reset() -{ - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *m = NULL; - sd_bus *bus = NULL; - char* temp_buf = NULL; - uint8_t* get_value = NULL; - char* connection = NULL; - int r, i; - - r = obj_mapper_get_connection(&connection, control_object_name); - if (r < 0) { - fprintf(stderr, "Failed to get connection, return value: %d.\n", r); - goto finish; - } - - printf("connection: %s\n", connection); - - // Open the system bus where most system services are provided. - bus = ipmid_get_sd_bus_connection(); - - /* - * Bus, service, object path, interface and method are provided to call - * the method. - * Signatures and input arguments are provided by the arguments at the - * end. - */ - r = sd_bus_call_method(bus, - connection, /* service to contact */ - control_object_name, /* object path */ - control_intf_name, /* interface name */ - "warmReset", /* method name */ - &error, /* object to return error in */ - &m, /* return message on success */ - NULL, - NULL - ); - - if (r < 0) { - fprintf(stderr, "Failed to issue method call: %s\n", error.message); - goto finish; - } - -finish: - sd_bus_error_free(&error); - sd_bus_message_unref(m); - free(connection); - - return r; -} - -ipmi_ret_t ipmi_global_warm_reset(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 GLOBAL warmReset Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd); - - // TODO: call the correct dbus method for warmReset. - dbus_warm_reset(); - - // Status code. - ipmi_ret_t rc = IPMI_CC_OK; - *data_len = 0; - return rc; -} - - -void register_netfn_global_functions() -{ - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_WARM_RESET); - ipmi_register_callback(NETFUN_APP, IPMI_CMD_WARM_RESET, NULL, ipmi_global_warm_reset); - - return; -} diff --git a/globalhandler.cpp b/globalhandler.cpp new file mode 100644 index 0000000..889d127 --- /dev/null +++ b/globalhandler.cpp @@ -0,0 +1,152 @@ +#include "globalhandler.h" +#include "ipmid-api.h" +#include +#include +#include + +const char *control_object_name = "/org/openbmc/control/bmc0"; +const char *control_intf_name = "org.openbmc.control.Bmc"; + +const char *objectmapper_service_name = "org.openbmc.ObjectMapper"; +const char *objectmapper_object_name = "/org/openbmc/ObjectMapper"; +const char *objectmapper_intf_name = "org.openbmc.ObjectMapper"; + +void register_netfn_global_functions() __attribute__((constructor)); + +int obj_mapper_get_connection(char** buf, const char* obj_path) +{ + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *m = NULL; + sd_bus *bus = NULL; + char *temp_buf = NULL, *intf = NULL; + size_t buf_size = 0; + int r; + + //Get the system bus where most system services are provided. + bus = ipmid_get_sd_bus_connection(); + + /* + * Bus, service, object path, interface and method are provided to call + * the method. + * Signatures and input arguments are provided by the arguments at the + * end. + */ + r = sd_bus_call_method(bus, + objectmapper_service_name, /* service to contact */ + objectmapper_object_name, /* object path */ + objectmapper_intf_name, /* interface name */ + "GetObject", /* method name */ + &error, /* object to return error in */ + &m, /* return message on success */ + "s", /* input signature */ + obj_path /* first argument */ + ); + + if (r < 0) { + fprintf(stderr, "Failed to issue method call: %s\n", error.message); + goto finish; + } + + // Get the key, aka, the connection name + sd_bus_message_read(m, "a{sas}", 1, &temp_buf, 1, &intf); + + /* + * TODO: check the return code. Currently for no reason the message + * parsing of object mapper is always complaining about + * "Device or resource busy", but the result seems OK for now. Need + * further checks. + */ + + buf_size = strlen(temp_buf) + 1; + printf("IPMID connection name: %s\n", temp_buf); + *buf = (char*)malloc(buf_size); + + if (*buf == NULL) { + fprintf(stderr, "Malloc failed for warm reset"); + r = -1; + goto finish; + } + + memcpy(*buf, temp_buf, buf_size); + +finish: + sd_bus_error_free(&error); + sd_bus_message_unref(m); + + return r; +} + +int dbus_warm_reset() +{ + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *m = NULL; + sd_bus *bus = NULL; + char* temp_buf = NULL; + uint8_t* get_value = NULL; + char* connection = NULL; + int r, i; + + r = obj_mapper_get_connection(&connection, control_object_name); + if (r < 0) { + fprintf(stderr, "Failed to get connection, return value: %d.\n", r); + goto finish; + } + + printf("connection: %s\n", connection); + + // Open the system bus where most system services are provided. + bus = ipmid_get_sd_bus_connection(); + + /* + * Bus, service, object path, interface and method are provided to call + * the method. + * Signatures and input arguments are provided by the arguments at the + * end. + */ + r = sd_bus_call_method(bus, + connection, /* service to contact */ + control_object_name, /* object path */ + control_intf_name, /* interface name */ + "warmReset", /* method name */ + &error, /* object to return error in */ + &m, /* return message on success */ + NULL, + NULL + ); + + if (r < 0) { + fprintf(stderr, "Failed to issue method call: %s\n", error.message); + goto finish; + } + +finish: + sd_bus_error_free(&error); + sd_bus_message_unref(m); + free(connection); + + return r; +} + +ipmi_ret_t ipmi_global_warm_reset(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 GLOBAL warmReset Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd); + + // TODO: call the correct dbus method for warmReset. + dbus_warm_reset(); + + // Status code. + ipmi_ret_t rc = IPMI_CC_OK; + *data_len = 0; + return rc; +} + + +void register_netfn_global_functions() +{ + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_WARM_RESET); + ipmi_register_callback(NETFUN_APP, IPMI_CMD_WARM_RESET, NULL, ipmi_global_warm_reset); + + return; +} diff --git a/groupext.C b/groupext.C deleted file mode 100644 index b834f9b..0000000 --- a/groupext.C +++ /dev/null @@ -1,31 +0,0 @@ -#include "ipmid-api.h" -#include "ipmid.H" -#include -#include - -#define GRPEXT_GET_GROUP_CMD 0 -void register_netfn_groupext_functions() __attribute__((constructor)); - -ipmi_ret_t ipmi_groupext(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) -{ - // Generic return from IPMI commands. - ipmi_ret_t rc = IPMI_CC_OK; - uint8_t *p = (uint8_t*) response; - - printf("IPMI GROUP EXTENTIONS\n"); - - *data_len = 1; - *p = 0; - - return rc; -} - -void register_netfn_groupext_functions() -{ - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_GRPEXT, GRPEXT_GET_GROUP_CMD); - ipmi_register_callback(NETFUN_GRPEXT, GRPEXT_GET_GROUP_CMD, NULL, ipmi_groupext); - - return; -} diff --git a/groupext.cpp b/groupext.cpp new file mode 100644 index 0000000..b834f9b --- /dev/null +++ b/groupext.cpp @@ -0,0 +1,31 @@ +#include "ipmid-api.h" +#include "ipmid.H" +#include +#include + +#define GRPEXT_GET_GROUP_CMD 0 +void register_netfn_groupext_functions() __attribute__((constructor)); + +ipmi_ret_t ipmi_groupext(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) +{ + // Generic return from IPMI commands. + ipmi_ret_t rc = IPMI_CC_OK; + uint8_t *p = (uint8_t*) response; + + printf("IPMI GROUP EXTENTIONS\n"); + + *data_len = 1; + *p = 0; + + return rc; +} + +void register_netfn_groupext_functions() +{ + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_GRPEXT, GRPEXT_GET_GROUP_CMD); + ipmi_register_callback(NETFUN_GRPEXT, GRPEXT_GET_GROUP_CMD, NULL, ipmi_groupext); + + return; +} diff --git a/ipmid.C b/ipmid.C deleted file mode 100644 index 7848afe..0000000 --- a/ipmid.C +++ /dev/null @@ -1,752 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ipmid.H" -#include -#include -#include -#include "sensorhandler.h" -#include -#include -#include -#include - -sd_bus *bus = NULL; -sd_bus_slot *ipmid_slot = NULL; - -// Initialise restricted mode to true -bool restricted_mode = true; - -FILE *ipmiio, *ipmidbus, *ipmicmddetails; - -void print_usage(void) { - fprintf(stderr, "Options: [-d mask]\n"); - fprintf(stderr, " mask : 0x01 - Print ipmi packets\n"); - fprintf(stderr, " mask : 0x02 - Print DBUS operations\n"); - fprintf(stderr, " mask : 0x04 - Print ipmi command details\n"); - fprintf(stderr, " mask : 0xFF - Print all trace\n"); -} - -// Host settings in DBUS -constexpr char settings_host_bus[] = "org.openbmc.settings.Host"; -constexpr char settings_host_object[] = "/org/openbmc/settings/host0"; -constexpr char settings_host_intf[] = "org.freedesktop.DBus.Properties"; - -const char * DBUS_INTF = "org.openbmc.HostIpmi"; - -const char * FILTER = "type='signal',interface='org.openbmc.HostIpmi',member='ReceivedMessage'"; -constexpr char RESTRICTED_MODE_FILTER[] = "type='signal',interface='org.freedesktop.DBus.Properties',path='/org/openbmc/settings/host0'"; - -typedef std::pair ipmi_fn_cmd_t; -typedef std::pair ipmi_fn_context_t; - -// Global data structure that contains the IPMI command handler's registrations. -std::map g_ipmid_router_map; - -// IPMI Spec, shared Reservation ID. -unsigned short g_sel_reserve = 0xFFFF; - -unsigned short get_sel_reserve_id(void) -{ - return g_sel_reserve; -} - -#ifndef HEXDUMP_COLS -#define HEXDUMP_COLS 16 -#endif - -void hexdump(FILE *s, 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) - { - fprintf(s,"0x%06x: ", i); - } - - /* print hex data */ - if(i < len) - { - fprintf(s,"%02x ", 0xFF & ((char*)mem)[i]); - } - else /* end of block, just aligning for ASCII dump */ - { - fprintf(s," "); - } - - /* 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 */ - { - fputc(' ', s); - } - else if(isprint(((char*)mem)[j])) /* printable char */ - { - fputc(0xFF & ((char*)mem)[j], s); - } - else /* other char */ - { - fputc('.',s); - } - } - fputc('\n',s); - } - } -} - - -// 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) -{ - // Pack NetFn and Command in one. - auto netfn_and_cmd = std::make_pair(netfn, cmd); - - // Pack Function handler and Data in another. - auto handler_and_context = std::make_pair(handler, context); - - // Check if the registration has already been made.. - auto iter = g_ipmid_router_map.find(netfn_and_cmd); - if(iter != g_ipmid_router_map.end()) - { - fprintf(stderr,"ERROR : Duplicate registration for NetFn [0x%X], Cmd:[0x%X]\n",netfn, cmd); - } - else - { - // This is a fresh registration.. Add it to the map. - g_ipmid_router_map.emplace(netfn_and_cmd, handler_and_context); - } - - return; -} - -// Looks at the map and calls corresponding handler functions. -ipmi_ret_t ipmi_netfn_router(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, - ipmi_response_t response, ipmi_data_len_t data_len) -{ - // return from the Command handlers. - ipmi_ret_t rc = IPMI_CC_INVALID; - - // If restricted mode is true and command is not whitelisted, don't - // execute the command - if(restricted_mode) - { - if (!std::binary_search(whitelist.cbegin(), whitelist.cend(), - std::make_pair(netfn, cmd))) - { - printf("Net function:[0x%X], Command:[0x%X] is not whitelisted\n", - netfn, cmd); - rc = IPMI_CC_INSUFFICIENT_PRIVILEGE; - memcpy(response, &rc, IPMI_CC_LEN); - *data_len = IPMI_CC_LEN; - return rc; - } - } - - // Walk the map that has the registered handlers and invoke the approprite - // handlers for matching commands. - auto iter = g_ipmid_router_map.find(std::make_pair(netfn, cmd)); - if(iter == g_ipmid_router_map.end()) - { - fprintf(stderr, "No registered handlers for NetFn:[0x%X], Cmd:[0x%X]" - " trying Wilcard implementation \n",netfn, cmd); - - // Now that we did not find any specific [NetFn,Cmd], tuple, check for - // NetFn, WildCard command present. - iter = g_ipmid_router_map.find(std::make_pair(netfn, IPMI_CMD_WILDCARD)); - if(iter == g_ipmid_router_map.end()) - { - fprintf(stderr, "No Registered handlers for NetFn:[0x%X],Cmd:[0x%X]\n",netfn, IPMI_CMD_WILDCARD); - - // Respond with a 0xC1 - memcpy(response, &rc, IPMI_CC_LEN); - *data_len = IPMI_CC_LEN; - return rc; - } - } - -#ifdef __IPMI_DEBUG__ - // We have either a perfect match -OR- a wild card atleast, - printf("Calling Net function:[0x%X], Command:[0x%X]\n", netfn, cmd); -#endif - - // Extract the map data onto appropriate containers - auto handler_and_context = iter->second; - - // Creating a pointer type casted to char* to make sure we advance 1 byte - // when we advance pointer to next's address. advancing void * would not - // make sense. - char *respo = &((char *)response)[IPMI_CC_LEN]; - - // Response message from the plugin goes into a byte post the base response - rc = (handler_and_context.first) (netfn, cmd, request, respo, - data_len, handler_and_context.second); - - // Now copy the return code that we got from handler and pack it in first - // byte. - memcpy(response, &rc, IPMI_CC_LEN); - - // Data length is now actual data + completion code. - *data_len = *data_len + IPMI_CC_LEN; - - return rc; -} - - - - -static int send_ipmi_message(sd_bus_message *req, unsigned char seq, unsigned char netfn, unsigned char lun, unsigned char cmd, unsigned char cc, unsigned char *buf, unsigned char len) { - - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *reply = NULL, *m=NULL; - const char *dest, *path; - int r, pty; - - dest = sd_bus_message_get_sender(req); - path = sd_bus_message_get_path(req); - - r = sd_bus_message_new_method_call(bus,&m,dest,path,DBUS_INTF,"sendMessage"); - if (r < 0) { - fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r)); - return -1; - } - - - // Responses in IPMI require a bit set. So there ya go... - netfn |= 0x01; - - - // Add the bytes needed for the methods to be called - r = sd_bus_message_append(m, "yyyyy", seq, netfn, lun, cmd, cc); - if (r < 0) { - fprintf(stderr, "Failed add the netfn and others : %s\n", strerror(-r)); - goto final; - } - - 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)); - goto final; - } - - - - // 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\n", strerror(-r)); - fprintf(stderr, "Dest: %s, Path: %s\n", dest, path); - goto final; - } - - r = sd_bus_message_read(reply, "x", &pty); - if (r < 0) { - fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r)); - } - -final: - sd_bus_error_free(&error); - m = sd_bus_message_unref(m); - reply = sd_bus_message_unref(reply); - - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -} - -void cache_restricted_mode() -{ - sd_bus *bus = ipmid_get_sd_bus_connection(); - sd_bus_message *reply = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - int rc = 0; - - rc = sd_bus_call_method(bus, - settings_host_bus, - settings_host_object, - settings_host_intf, - "Get", - &error, - &reply, - "ss", - settings_host_bus, - "restricted_mode"); - if(rc < 0) - { - fprintf(stderr, "Failed sd_bus_call_method method for restricted mode: %s\n", - strerror(-rc)); - goto cleanup; - } - - rc = sd_bus_message_read(reply, "v", "b", &restricted_mode); - if(rc < 0) - { - fprintf(stderr, "Failed to parse response message for restricted mode: %s\n", - strerror(-rc)); - // Fail-safe to restricted mode - restricted_mode = true; - } - - printf("Restricted mode = %d\n", restricted_mode); - -cleanup: - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); -} - -static int handle_restricted_mode_change(sd_bus_message *m, void *user_data, - sd_bus_error *ret_error) -{ - cache_restricted_mode(); - return 0; -} - -static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error - *ret_error) { - int r = 0; - unsigned char sequence, netfn, lun, cmd; - const void *request; - size_t sz; - size_t resplen =MAX_IPMI_BUFFER; - unsigned char response[MAX_IPMI_BUFFER]; - - memset(response, 0, MAX_IPMI_BUFFER); - - r = sd_bus_message_read(m, "yyyy", &sequence, &netfn, &lun, &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; - } - - fprintf(ipmiio, "IPMI Incoming: Seq 0x%02x, NetFn 0x%02x, CMD: 0x%02x \n", sequence, netfn, cmd); - hexdump(ipmiio, (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... - r = ipmi_netfn_router(netfn, cmd, (void *)request, (void *)response, &resplen); - if(r != 0) - { - fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",r, netfn, cmd); - - if(r < 0) { - response[0] = IPMI_CC_UNSPECIFIED_ERROR; - } - } - - fprintf(ipmiio, "IPMI Response:\n"); - hexdump(ipmiio, (void*)response, resplen); - - // Send the response buffer from the ipmi command - r = send_ipmi_message(m, sequence, netfn, lun, cmd, response[0], - ((unsigned char *)response) + 1, resplen - 1); - if (r < 0) { - fprintf(stderr, "Failed to send the response message\n"); - return -1; - } - - - return 0; -} - - -//---------------------------------------------------------------------- -// handler_select -// Select all the files ending with with .so. in the given diretcory -// @d: dirent structure containing the file name -//---------------------------------------------------------------------- -int handler_select(const struct dirent *entry) -{ - // To hold ".so" from entry->d_name; - char dname_copy[4] = {0}; - - // We want to avoid checking for everything and isolate to the ones having - // .so.* or .so in them. - // Check for versioned libraries .so.* - if(strstr(entry->d_name, IPMI_PLUGIN_SONAME_EXTN)) - { - return 1; - } - // Check for non versioned libraries .so - else if(strstr(entry->d_name, IPMI_PLUGIN_EXTN)) - { - // It is possible that .so could be anywhere in the string but unlikely - // But being careful here. Get the base address of the string, move - // until end and come back 3 steps and that gets what we need. - strcpy(dname_copy, (entry->d_name + strlen(entry->d_name)-strlen(IPMI_PLUGIN_EXTN))); - if(strcmp(dname_copy, IPMI_PLUGIN_EXTN) == 0) - { - return 1; - } - } - return 0; -} - -// This will do a dlopen of every .so in ipmi_lib_path and will dlopen everything so that they will -// register a callback handler -void ipmi_register_callback_handlers(const char* ipmi_lib_path) -{ - // For walking the ipmi_lib_path - struct dirent **handler_list; - int num_handlers = 0; - - // This is used to check and abort if someone tries to register a bad one. - void *lib_handler = NULL; - - if(ipmi_lib_path == NULL) - { - fprintf(stderr,"ERROR; No handlers to be registered for ipmi.. Aborting\n"); - assert(0); - } - else - { - // 1: Open ipmi_lib_path. Its usually "/usr/lib/phosphor-host-ipmid" - // 2: Scan the directory for the files that end with .so - // 3: For each one of them, just do a 'dlopen' so that they register - // the handlers for callback routines. - - std::string handler_fqdn = ipmi_lib_path; - - // Append a "/" since we need to add the name of the .so. If there is - // already a .so, adding one more is not any harm. - handler_fqdn += "/"; - - num_handlers = scandir(ipmi_lib_path, &handler_list, handler_select, alphasort); - if (num_handlers < 0) - return; - - while(num_handlers--) - { - 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]: %s\n", - handler_fqdn.c_str(), dlerror()); - } - // Wipe the memory allocated for this particular entry. - free(handler_list[num_handlers]); - } - - // Done with all registration. - free(handler_list); - } - - // TODO : What to be done on the memory that is given by dlopen ?. - return; -} - -sd_bus *ipmid_get_sd_bus_connection(void) { - return bus; -} - -sd_bus_slot *ipmid_get_sd_bus_slot(void) { - return ipmid_slot; -} - -int main(int argc, char *argv[]) -{ - int r; - unsigned long tvalue; - int c; - - - - // This file and subsequient switch is for turning on levels - // of trace - ipmicmddetails = ipmiio = ipmidbus = fopen("/dev/null", "w"); - - while ((c = getopt (argc, argv, "h:d:")) != -1) - switch (c) { - case 'd': - tvalue = strtoul(optarg, NULL, 16); - if (1&tvalue) { - ipmiio = stdout; - } - if (2&tvalue) { - ipmidbus = stdout; - } - if (4&tvalue) { - ipmicmddetails = stdout; - } - break; - case 'h': - case '?': - print_usage(); - return 1; - } - - - /* 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; - } - - // Register all the handlers that provider implementation to IPMI commands. - ipmi_register_callback_handlers(HOST_IPMI_LIB_PATH); - - // Watch for BT messages - r = sd_bus_add_match(bus, &ipmid_slot, FILTER, handle_ipmi_command, NULL); - if (r < 0) { - fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), FILTER); - goto finish; - } - - // Wait for changes on Restricted mode - r = sd_bus_add_match(bus, &ipmid_slot, RESTRICTED_MODE_FILTER, handle_restricted_mode_change, NULL); - if (r < 0) { - fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), RESTRICTED_MODE_FILTER); - goto finish; - } - - // Initialise restricted mode - cache_restricted_mode(); - - 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(ipmid_slot); - sd_bus_unref(bus); - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; - -} - -// Use a lookup table to find the interface name of a specific sensor -// This will be used until an alternative is found. this is the first -// step for mapping IPMI -int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) { - - char *str1; - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *reply = NULL, *m=NULL; - - - int r; - - r = sd_bus_message_new_method_call(bus,&m,interface->bus,interface->path,"org.freedesktop.DBus.Properties","Get"); - if (r < 0) { - fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); - fprintf(stderr,"Bus: %s Path: %s Interface: %s \n", - interface->bus, interface->path, interface->interface); - goto final; - } - - r = sd_bus_message_append(m, "ss", "org.openbmc.InventoryItem", property_name); - if (r < 0) { - fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); - fprintf(stderr,"Bus: %s Path: %s Interface: %s \n", - interface->bus, interface->path, interface->interface); - goto final; - } - - r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) { - fprintf(stderr, "Failed to call the method: %s", strerror(-r)); - goto final; - } - - r = sd_bus_message_read(reply, "v", "s", &str1) ; - if (r < 0) { - fprintf(stderr, "Failed to get a response: %s", strerror(-r)); - goto final; - } - - strcpy(property_value, str1); - -final: - - sd_bus_error_free(&error); - m = sd_bus_message_unref(m); - reply = sd_bus_message_unref(reply); - - return r; -} - - -// Use a lookup table to find the interface name of a specific sensor -// This will be used until an alternative is found. this is the first -// step for mapping IPMI -int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) { - char *busname = NULL; - const char *iface = "org.openbmc.managers.System"; - const char *objname = "/org/openbmc/managers/System"; - char *str1 = NULL, *str2, *str3; - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *reply = NULL; - - - int r; - r = mapper_get_service(bus, objname, &busname); - if (r < 0) { - fprintf(stderr, "Failed to get system manager busname: %s\n", strerror(-r)); - goto final; - } - - r = sd_bus_call_method(bus,busname,objname,iface, "getObjectFromByteId", - &error, &reply, "sy", type, num); - if (r < 0) { - fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); - goto final; - } - - r = sd_bus_message_read(reply, "(ss)", &str2, &str3); - if (r < 0) { - fprintf(stderr, "Failed to get a response: %s", strerror(-r)); - goto final; - } - - r = mapper_get_service(bus, str2, &str1); - if (r < 0) { - fprintf(stderr, "Failed to get item busname: %s\n", strerror(-r)); - goto final; - } - - strncpy(interface->bus, str1, MAX_DBUS_PATH); - strncpy(interface->path, str2, MAX_DBUS_PATH); - strncpy(interface->interface, str3, MAX_DBUS_PATH); - - interface->sensornumber = num; - -final: - - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - free(busname); - free(str1); - - return r; -} - - -///////////////////////////////////////////////////////////////////// -// -// Routines used by ipmi commands wanting to interact on the dbus -// -///////////////////////////////////////////////////////////////////// -int set_sensor_dbus_state_s(uint8_t number, const char *method, const char *value) { - - - dbus_interface_t a; - int r; - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *m=NULL; - - fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of %s\n", - number, method, value); - - r = find_openbmc_path("SENSOR", number, &a); - - if (r < 0) { - fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); - return 0; - } - - r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method); - if (r < 0) { - fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); - goto final; - } - - r = sd_bus_message_append(m, "v", "s", value); - if (r < 0) { - fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); - goto final; - } - - - r = sd_bus_call(bus, m, 0, &error, NULL); - if (r < 0) { - fprintf(stderr, "Failed to call the method: %s", strerror(-r)); - } - -final: - sd_bus_error_free(&error); - m = sd_bus_message_unref(m); - - return 0; -} -int set_sensor_dbus_state_y(uint8_t number, const char *method, const uint8_t value) { - - - dbus_interface_t a; - int r; - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *m=NULL; - - fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of 0x%02x\n", - number, method, value); - - r = find_openbmc_path("SENSOR", number, &a); - - if (r < 0) { - fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); - return 0; - } - - r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method); - if (r < 0) { - fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); - goto final; - } - - r = sd_bus_message_append(m, "v", "i", value); - if (r < 0) { - fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); - goto final; - } - - - r = sd_bus_call(bus, m, 0, &error, NULL); - if (r < 0) { - fprintf(stderr, "12 Failed to call the method: %s", strerror(-r)); - } - -final: - sd_bus_error_free(&error); - m = sd_bus_message_unref(m); - - return 0; -} diff --git a/ipmid.cpp b/ipmid.cpp new file mode 100644 index 0000000..7848afe --- /dev/null +++ b/ipmid.cpp @@ -0,0 +1,752 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ipmid.H" +#include +#include +#include +#include "sensorhandler.h" +#include +#include +#include +#include + +sd_bus *bus = NULL; +sd_bus_slot *ipmid_slot = NULL; + +// Initialise restricted mode to true +bool restricted_mode = true; + +FILE *ipmiio, *ipmidbus, *ipmicmddetails; + +void print_usage(void) { + fprintf(stderr, "Options: [-d mask]\n"); + fprintf(stderr, " mask : 0x01 - Print ipmi packets\n"); + fprintf(stderr, " mask : 0x02 - Print DBUS operations\n"); + fprintf(stderr, " mask : 0x04 - Print ipmi command details\n"); + fprintf(stderr, " mask : 0xFF - Print all trace\n"); +} + +// Host settings in DBUS +constexpr char settings_host_bus[] = "org.openbmc.settings.Host"; +constexpr char settings_host_object[] = "/org/openbmc/settings/host0"; +constexpr char settings_host_intf[] = "org.freedesktop.DBus.Properties"; + +const char * DBUS_INTF = "org.openbmc.HostIpmi"; + +const char * FILTER = "type='signal',interface='org.openbmc.HostIpmi',member='ReceivedMessage'"; +constexpr char RESTRICTED_MODE_FILTER[] = "type='signal',interface='org.freedesktop.DBus.Properties',path='/org/openbmc/settings/host0'"; + +typedef std::pair ipmi_fn_cmd_t; +typedef std::pair ipmi_fn_context_t; + +// Global data structure that contains the IPMI command handler's registrations. +std::map g_ipmid_router_map; + +// IPMI Spec, shared Reservation ID. +unsigned short g_sel_reserve = 0xFFFF; + +unsigned short get_sel_reserve_id(void) +{ + return g_sel_reserve; +} + +#ifndef HEXDUMP_COLS +#define HEXDUMP_COLS 16 +#endif + +void hexdump(FILE *s, 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) + { + fprintf(s,"0x%06x: ", i); + } + + /* print hex data */ + if(i < len) + { + fprintf(s,"%02x ", 0xFF & ((char*)mem)[i]); + } + else /* end of block, just aligning for ASCII dump */ + { + fprintf(s," "); + } + + /* 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 */ + { + fputc(' ', s); + } + else if(isprint(((char*)mem)[j])) /* printable char */ + { + fputc(0xFF & ((char*)mem)[j], s); + } + else /* other char */ + { + fputc('.',s); + } + } + fputc('\n',s); + } + } +} + + +// 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) +{ + // Pack NetFn and Command in one. + auto netfn_and_cmd = std::make_pair(netfn, cmd); + + // Pack Function handler and Data in another. + auto handler_and_context = std::make_pair(handler, context); + + // Check if the registration has already been made.. + auto iter = g_ipmid_router_map.find(netfn_and_cmd); + if(iter != g_ipmid_router_map.end()) + { + fprintf(stderr,"ERROR : Duplicate registration for NetFn [0x%X], Cmd:[0x%X]\n",netfn, cmd); + } + else + { + // This is a fresh registration.. Add it to the map. + g_ipmid_router_map.emplace(netfn_and_cmd, handler_and_context); + } + + return; +} + +// Looks at the map and calls corresponding handler functions. +ipmi_ret_t ipmi_netfn_router(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, + ipmi_response_t response, ipmi_data_len_t data_len) +{ + // return from the Command handlers. + ipmi_ret_t rc = IPMI_CC_INVALID; + + // If restricted mode is true and command is not whitelisted, don't + // execute the command + if(restricted_mode) + { + if (!std::binary_search(whitelist.cbegin(), whitelist.cend(), + std::make_pair(netfn, cmd))) + { + printf("Net function:[0x%X], Command:[0x%X] is not whitelisted\n", + netfn, cmd); + rc = IPMI_CC_INSUFFICIENT_PRIVILEGE; + memcpy(response, &rc, IPMI_CC_LEN); + *data_len = IPMI_CC_LEN; + return rc; + } + } + + // Walk the map that has the registered handlers and invoke the approprite + // handlers for matching commands. + auto iter = g_ipmid_router_map.find(std::make_pair(netfn, cmd)); + if(iter == g_ipmid_router_map.end()) + { + fprintf(stderr, "No registered handlers for NetFn:[0x%X], Cmd:[0x%X]" + " trying Wilcard implementation \n",netfn, cmd); + + // Now that we did not find any specific [NetFn,Cmd], tuple, check for + // NetFn, WildCard command present. + iter = g_ipmid_router_map.find(std::make_pair(netfn, IPMI_CMD_WILDCARD)); + if(iter == g_ipmid_router_map.end()) + { + fprintf(stderr, "No Registered handlers for NetFn:[0x%X],Cmd:[0x%X]\n",netfn, IPMI_CMD_WILDCARD); + + // Respond with a 0xC1 + memcpy(response, &rc, IPMI_CC_LEN); + *data_len = IPMI_CC_LEN; + return rc; + } + } + +#ifdef __IPMI_DEBUG__ + // We have either a perfect match -OR- a wild card atleast, + printf("Calling Net function:[0x%X], Command:[0x%X]\n", netfn, cmd); +#endif + + // Extract the map data onto appropriate containers + auto handler_and_context = iter->second; + + // Creating a pointer type casted to char* to make sure we advance 1 byte + // when we advance pointer to next's address. advancing void * would not + // make sense. + char *respo = &((char *)response)[IPMI_CC_LEN]; + + // Response message from the plugin goes into a byte post the base response + rc = (handler_and_context.first) (netfn, cmd, request, respo, + data_len, handler_and_context.second); + + // Now copy the return code that we got from handler and pack it in first + // byte. + memcpy(response, &rc, IPMI_CC_LEN); + + // Data length is now actual data + completion code. + *data_len = *data_len + IPMI_CC_LEN; + + return rc; +} + + + + +static int send_ipmi_message(sd_bus_message *req, unsigned char seq, unsigned char netfn, unsigned char lun, unsigned char cmd, unsigned char cc, unsigned char *buf, unsigned char len) { + + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *reply = NULL, *m=NULL; + const char *dest, *path; + int r, pty; + + dest = sd_bus_message_get_sender(req); + path = sd_bus_message_get_path(req); + + r = sd_bus_message_new_method_call(bus,&m,dest,path,DBUS_INTF,"sendMessage"); + if (r < 0) { + fprintf(stderr, "Failed to add the method object: %s\n", strerror(-r)); + return -1; + } + + + // Responses in IPMI require a bit set. So there ya go... + netfn |= 0x01; + + + // Add the bytes needed for the methods to be called + r = sd_bus_message_append(m, "yyyyy", seq, netfn, lun, cmd, cc); + if (r < 0) { + fprintf(stderr, "Failed add the netfn and others : %s\n", strerror(-r)); + goto final; + } + + 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)); + goto final; + } + + + + // 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\n", strerror(-r)); + fprintf(stderr, "Dest: %s, Path: %s\n", dest, path); + goto final; + } + + r = sd_bus_message_read(reply, "x", &pty); + if (r < 0) { + fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r)); + } + +final: + sd_bus_error_free(&error); + m = sd_bus_message_unref(m); + reply = sd_bus_message_unref(reply); + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} + +void cache_restricted_mode() +{ + sd_bus *bus = ipmid_get_sd_bus_connection(); + sd_bus_message *reply = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + int rc = 0; + + rc = sd_bus_call_method(bus, + settings_host_bus, + settings_host_object, + settings_host_intf, + "Get", + &error, + &reply, + "ss", + settings_host_bus, + "restricted_mode"); + if(rc < 0) + { + fprintf(stderr, "Failed sd_bus_call_method method for restricted mode: %s\n", + strerror(-rc)); + goto cleanup; + } + + rc = sd_bus_message_read(reply, "v", "b", &restricted_mode); + if(rc < 0) + { + fprintf(stderr, "Failed to parse response message for restricted mode: %s\n", + strerror(-rc)); + // Fail-safe to restricted mode + restricted_mode = true; + } + + printf("Restricted mode = %d\n", restricted_mode); + +cleanup: + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); +} + +static int handle_restricted_mode_change(sd_bus_message *m, void *user_data, + sd_bus_error *ret_error) +{ + cache_restricted_mode(); + return 0; +} + +static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error + *ret_error) { + int r = 0; + unsigned char sequence, netfn, lun, cmd; + const void *request; + size_t sz; + size_t resplen =MAX_IPMI_BUFFER; + unsigned char response[MAX_IPMI_BUFFER]; + + memset(response, 0, MAX_IPMI_BUFFER); + + r = sd_bus_message_read(m, "yyyy", &sequence, &netfn, &lun, &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; + } + + fprintf(ipmiio, "IPMI Incoming: Seq 0x%02x, NetFn 0x%02x, CMD: 0x%02x \n", sequence, netfn, cmd); + hexdump(ipmiio, (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... + r = ipmi_netfn_router(netfn, cmd, (void *)request, (void *)response, &resplen); + if(r != 0) + { + fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",r, netfn, cmd); + + if(r < 0) { + response[0] = IPMI_CC_UNSPECIFIED_ERROR; + } + } + + fprintf(ipmiio, "IPMI Response:\n"); + hexdump(ipmiio, (void*)response, resplen); + + // Send the response buffer from the ipmi command + r = send_ipmi_message(m, sequence, netfn, lun, cmd, response[0], + ((unsigned char *)response) + 1, resplen - 1); + if (r < 0) { + fprintf(stderr, "Failed to send the response message\n"); + return -1; + } + + + return 0; +} + + +//---------------------------------------------------------------------- +// handler_select +// Select all the files ending with with .so. in the given diretcory +// @d: dirent structure containing the file name +//---------------------------------------------------------------------- +int handler_select(const struct dirent *entry) +{ + // To hold ".so" from entry->d_name; + char dname_copy[4] = {0}; + + // We want to avoid checking for everything and isolate to the ones having + // .so.* or .so in them. + // Check for versioned libraries .so.* + if(strstr(entry->d_name, IPMI_PLUGIN_SONAME_EXTN)) + { + return 1; + } + // Check for non versioned libraries .so + else if(strstr(entry->d_name, IPMI_PLUGIN_EXTN)) + { + // It is possible that .so could be anywhere in the string but unlikely + // But being careful here. Get the base address of the string, move + // until end and come back 3 steps and that gets what we need. + strcpy(dname_copy, (entry->d_name + strlen(entry->d_name)-strlen(IPMI_PLUGIN_EXTN))); + if(strcmp(dname_copy, IPMI_PLUGIN_EXTN) == 0) + { + return 1; + } + } + return 0; +} + +// This will do a dlopen of every .so in ipmi_lib_path and will dlopen everything so that they will +// register a callback handler +void ipmi_register_callback_handlers(const char* ipmi_lib_path) +{ + // For walking the ipmi_lib_path + struct dirent **handler_list; + int num_handlers = 0; + + // This is used to check and abort if someone tries to register a bad one. + void *lib_handler = NULL; + + if(ipmi_lib_path == NULL) + { + fprintf(stderr,"ERROR; No handlers to be registered for ipmi.. Aborting\n"); + assert(0); + } + else + { + // 1: Open ipmi_lib_path. Its usually "/usr/lib/phosphor-host-ipmid" + // 2: Scan the directory for the files that end with .so + // 3: For each one of them, just do a 'dlopen' so that they register + // the handlers for callback routines. + + std::string handler_fqdn = ipmi_lib_path; + + // Append a "/" since we need to add the name of the .so. If there is + // already a .so, adding one more is not any harm. + handler_fqdn += "/"; + + num_handlers = scandir(ipmi_lib_path, &handler_list, handler_select, alphasort); + if (num_handlers < 0) + return; + + while(num_handlers--) + { + 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]: %s\n", + handler_fqdn.c_str(), dlerror()); + } + // Wipe the memory allocated for this particular entry. + free(handler_list[num_handlers]); + } + + // Done with all registration. + free(handler_list); + } + + // TODO : What to be done on the memory that is given by dlopen ?. + return; +} + +sd_bus *ipmid_get_sd_bus_connection(void) { + return bus; +} + +sd_bus_slot *ipmid_get_sd_bus_slot(void) { + return ipmid_slot; +} + +int main(int argc, char *argv[]) +{ + int r; + unsigned long tvalue; + int c; + + + + // This file and subsequient switch is for turning on levels + // of trace + ipmicmddetails = ipmiio = ipmidbus = fopen("/dev/null", "w"); + + while ((c = getopt (argc, argv, "h:d:")) != -1) + switch (c) { + case 'd': + tvalue = strtoul(optarg, NULL, 16); + if (1&tvalue) { + ipmiio = stdout; + } + if (2&tvalue) { + ipmidbus = stdout; + } + if (4&tvalue) { + ipmicmddetails = stdout; + } + break; + case 'h': + case '?': + print_usage(); + return 1; + } + + + /* 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; + } + + // Register all the handlers that provider implementation to IPMI commands. + ipmi_register_callback_handlers(HOST_IPMI_LIB_PATH); + + // Watch for BT messages + r = sd_bus_add_match(bus, &ipmid_slot, FILTER, handle_ipmi_command, NULL); + if (r < 0) { + fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), FILTER); + goto finish; + } + + // Wait for changes on Restricted mode + r = sd_bus_add_match(bus, &ipmid_slot, RESTRICTED_MODE_FILTER, handle_restricted_mode_change, NULL); + if (r < 0) { + fprintf(stderr, "Failed: sd_bus_add_match: %s : %s\n", strerror(-r), RESTRICTED_MODE_FILTER); + goto finish; + } + + // Initialise restricted mode + cache_restricted_mode(); + + 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(ipmid_slot); + sd_bus_unref(bus); + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + +} + +// Use a lookup table to find the interface name of a specific sensor +// This will be used until an alternative is found. this is the first +// step for mapping IPMI +int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) { + + char *str1; + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *reply = NULL, *m=NULL; + + + int r; + + r = sd_bus_message_new_method_call(bus,&m,interface->bus,interface->path,"org.freedesktop.DBus.Properties","Get"); + if (r < 0) { + fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); + fprintf(stderr,"Bus: %s Path: %s Interface: %s \n", + interface->bus, interface->path, interface->interface); + goto final; + } + + r = sd_bus_message_append(m, "ss", "org.openbmc.InventoryItem", property_name); + if (r < 0) { + fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); + fprintf(stderr,"Bus: %s Path: %s Interface: %s \n", + interface->bus, interface->path, interface->interface); + goto final; + } + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) { + fprintf(stderr, "Failed to call the method: %s", strerror(-r)); + goto final; + } + + r = sd_bus_message_read(reply, "v", "s", &str1) ; + if (r < 0) { + fprintf(stderr, "Failed to get a response: %s", strerror(-r)); + goto final; + } + + strcpy(property_value, str1); + +final: + + sd_bus_error_free(&error); + m = sd_bus_message_unref(m); + reply = sd_bus_message_unref(reply); + + return r; +} + + +// Use a lookup table to find the interface name of a specific sensor +// This will be used until an alternative is found. this is the first +// step for mapping IPMI +int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) { + char *busname = NULL; + const char *iface = "org.openbmc.managers.System"; + const char *objname = "/org/openbmc/managers/System"; + char *str1 = NULL, *str2, *str3; + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *reply = NULL; + + + int r; + r = mapper_get_service(bus, objname, &busname); + if (r < 0) { + fprintf(stderr, "Failed to get system manager busname: %s\n", strerror(-r)); + goto final; + } + + r = sd_bus_call_method(bus,busname,objname,iface, "getObjectFromByteId", + &error, &reply, "sy", type, num); + if (r < 0) { + fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); + goto final; + } + + r = sd_bus_message_read(reply, "(ss)", &str2, &str3); + if (r < 0) { + fprintf(stderr, "Failed to get a response: %s", strerror(-r)); + goto final; + } + + r = mapper_get_service(bus, str2, &str1); + if (r < 0) { + fprintf(stderr, "Failed to get item busname: %s\n", strerror(-r)); + goto final; + } + + strncpy(interface->bus, str1, MAX_DBUS_PATH); + strncpy(interface->path, str2, MAX_DBUS_PATH); + strncpy(interface->interface, str3, MAX_DBUS_PATH); + + interface->sensornumber = num; + +final: + + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + free(busname); + free(str1); + + return r; +} + + +///////////////////////////////////////////////////////////////////// +// +// Routines used by ipmi commands wanting to interact on the dbus +// +///////////////////////////////////////////////////////////////////// +int set_sensor_dbus_state_s(uint8_t number, const char *method, const char *value) { + + + dbus_interface_t a; + int r; + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *m=NULL; + + fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of %s\n", + number, method, value); + + r = find_openbmc_path("SENSOR", number, &a); + + if (r < 0) { + fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); + return 0; + } + + r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method); + if (r < 0) { + fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); + goto final; + } + + r = sd_bus_message_append(m, "v", "s", value); + if (r < 0) { + fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); + goto final; + } + + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) { + fprintf(stderr, "Failed to call the method: %s", strerror(-r)); + } + +final: + sd_bus_error_free(&error); + m = sd_bus_message_unref(m); + + return 0; +} +int set_sensor_dbus_state_y(uint8_t number, const char *method, const uint8_t value) { + + + dbus_interface_t a; + int r; + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *m=NULL; + + fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of 0x%02x\n", + number, method, value); + + r = find_openbmc_path("SENSOR", number, &a); + + if (r < 0) { + fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); + return 0; + } + + r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method); + if (r < 0) { + fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); + goto final; + } + + r = sd_bus_message_append(m, "v", "i", value); + if (r < 0) { + fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); + goto final; + } + + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) { + fprintf(stderr, "12 Failed to call the method: %s", strerror(-r)); + } + +final: + sd_bus_error_free(&error); + m = sd_bus_message_unref(m); + + return 0; +} diff --git a/ipmisensor.C b/ipmisensor.C deleted file mode 100644 index b6927ac..0000000 --- a/ipmisensor.C +++ /dev/null @@ -1,302 +0,0 @@ -#include -#include -#include -#include -#include -#include "sensorhandler.h" - -extern uint8_t find_sensor(uint8_t); - - -struct sensorRES_t { - uint8_t sensor_number; - uint8_t operation; - uint8_t sensor_reading; - uint8_t assert_state7_0; - uint8_t assert_state14_8; - uint8_t deassert_state7_0; - uint8_t deassert_state14_8; - uint8_t event_data1; - uint8_t event_data2; - uint8_t event_data3; -} __attribute__ ((packed)); - -#define ISBITSET(x,y) (((x)>>(y))&0x01) -#define ASSERTINDEX 0 -#define DEASSERTINDEX 1 - -// Sensor Type, Offset, function handler, Dbus Method, Assert value, Deassert value -struct lookup_t { - uint8_t sensor_type; - uint8_t offset; - int (*func)(const sensorRES_t *, const lookup_t *, const char *); - char member[16]; - char assertion[64]; - char deassertion[64]; -}; - -extern int updateDbusInterface(uint8_t , const char *, const char *); -extern int find_openbmc_path(const char *, const uint8_t , dbus_interface_t *) ; - - -int set_sensor_dbus_state_simple(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { - - return set_sensor_dbus_state_s(pRec->sensor_number, - pTable->member, - value); -} - -struct event_data_t { - uint8_t data; - char text[64]; -}; - -event_data_t g_fwprogress02h[] = { - {0x00, "Unspecified"}, - {0x01, "Memory Init"}, - {0x02, "HD Init"}, - {0x03, "Secondary Proc Init"}, - {0x04, "User Authentication"}, - {0x05, "User init system setup"}, - {0x06, "USB configuration"}, - {0x07, "PCI configuration"}, - {0x08, "Option ROM Init"}, - {0x09, "Video Init"}, - {0x0A, "Cache Init"}, - {0x0B, "SM Bus init"}, - {0x0C, "Keyboard Init"}, - {0x0D, "Embedded ctrl init"}, - {0x0E, "Docking station attachment"}, - {0x0F, "Enable docking station"}, - {0x10, "Docking station ejection"}, - {0x11, "Disabling docking station"}, - {0x12, "Calling OS Wakeup"}, - {0x13, "Starting OS"}, - {0x14, "Baseboard Init"}, - {0x15, ""}, - {0x16, "Floppy Init"}, - {0x17, "Keyboard Test"}, - {0x18, "Pointing Device Test"}, - {0x19, "Primary Proc Init"}, - {0xFF, "Unknown"} -}; - -event_data_t g_fwprogress00h[] = { - {0x00, "Unspecified."}, - {0x01, "No system memory detected"}, - {0x02, "No usable system memory"}, - {0x03, "Unrecoverable hard-disk/ATAPI/IDE"}, - {0x04, "Unrecoverable system-board"}, - {0x05, "Unrecoverable diskette"}, - {0x06, "Unrecoverable hard-disk controller"}, - {0x07, "Unrecoverable PS/2 or USB keyboard"}, - {0x08, "Removable boot media not found"}, - {0x09, "Unrecoverable video controller"}, - {0x0A, "No video device detected"}, - {0x0B, "Firmware ROM corruption detected"}, - {0x0C, "CPU voltage mismatch"}, - {0x0D, "CPU speed matching"}, - {0xFF, "unknown"}, -}; - - -char *event_data_lookup(event_data_t *p, uint8_t b) { - - while(p->data != 0xFF) { - if (p->data == b) { - break; - } - p++; - } - - return p->text; -} - - - -// The fw progress sensor contains some additional information that needs to be processed -// prior to calling the dbus code. -int set_sensor_dbus_state_fwprogress(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { - - char valuestring[128]; - char* p = valuestring; - - switch (pTable->offset) { - - case 0x00 : snprintf(p, sizeof(valuestring), "POST Error, %s", event_data_lookup(g_fwprogress00h, pRec->event_data2)); - break; - case 0x01 : /* Using g_fwprogress02h for 0x01 because thats what the ipmi spec says to do */ - snprintf(p, sizeof(valuestring), "FW Hang, %s", event_data_lookup(g_fwprogress02h, pRec->event_data2)); - break; - case 0x02 : snprintf(p, sizeof(valuestring), "FW Progress, %s", event_data_lookup(g_fwprogress02h, pRec->event_data2)); - break; - default : snprintf(p, sizeof(valuestring), "Internal warning, fw_progres offset unknown (0x%02x)", pTable->offset); - break; - } - - return set_sensor_dbus_state_s(pRec->sensor_number, - pTable->member, - p); -} - -// Handling this special OEM sensor by coping what is in byte 4. I also think that is odd -// considering byte 3 is for sensor reading. This seems like a misuse of the IPMI spec -int set_sensor_dbus_state_osbootcount(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { - return set_sensor_dbus_state_y(pRec->sensor_number, - "setValue", - pRec->assert_state7_0); -} - -int set_sensor_dbus_state_system_event(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { - char valuestring[128]; - char* p = valuestring; - - switch (pTable->offset) { - - case 0x00 : snprintf(p, sizeof(valuestring), "System Reconfigured"); - break; - case 0x01 : snprintf(p, sizeof(valuestring), "OEM Boot Event"); - break; - case 0x02 : snprintf(p, sizeof(valuestring), "Undetermine System Hardware Failure"); - break; - case 0x03 : snprintf(p, sizeof(valuestring), "System Failure see error log for more details (0x%02x)", pRec->event_data2); - break; - case 0x04 : snprintf(p, sizeof(valuestring), "System Failure see PEF error log for more details (0x%02x)", pRec->event_data2); - break; - default : snprintf(p, sizeof(valuestring), "Internal warning, system_event offset unknown (0x%02x)", pTable->offset); - break; - } - - return set_sensor_dbus_state_s(pRec->sensor_number, - pTable->member, - p); -} - - -// This table lists only senors we care about telling dbus about. -// Offset definition cab be found in section 42.2 of the IPMI 2.0 -// spec. Add more if/when there are more items of interest. -lookup_t g_ipmidbuslookup[] = { - - {0xe9, 0x00, set_sensor_dbus_state_simple, "setValue", "Disabled", ""}, // OCC Inactive 0 - {0xe9, 0x01, set_sensor_dbus_state_simple, "setValue", "Enabled", ""}, // OCC Active 1 - {0x07, 0x07, set_sensor_dbus_state_simple, "setPresent", "True", "False"}, - {0x07, 0x08, set_sensor_dbus_state_simple, "setFault", "True", "False"}, - {0x0C, 0x06, set_sensor_dbus_state_simple, "setPresent", "True", "False"}, - {0x0C, 0x04, set_sensor_dbus_state_simple, "setFault", "True", "False"}, - {0x0F, 0x02, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, - {0x0F, 0x01, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, - {0x0F, 0x00, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, - {0xC7, 0x01, set_sensor_dbus_state_simple, "setFault", "True", "False"}, - {0xc3, 0x00, set_sensor_dbus_state_osbootcount, "setValue", "" ,""}, - {0x1F, 0x00, set_sensor_dbus_state_simple, "setValue", "Boot completed (00)", ""}, - {0x1F, 0x01, set_sensor_dbus_state_simple, "setValue", "Boot completed (01)", ""}, - {0x1F, 0x02, set_sensor_dbus_state_simple, "setValue", "PXE boot completed", ""}, - {0x1F, 0x03, set_sensor_dbus_state_simple, "setValue", "Diagnostic boot completed", ""}, - {0x1F, 0x04, set_sensor_dbus_state_simple, "setValue", "CD-ROM boot completed", ""}, - {0x1F, 0x05, set_sensor_dbus_state_simple, "setValue", "ROM boot completed", ""}, - {0x1F, 0x06, set_sensor_dbus_state_simple, "setValue", "Boot completed (06)", ""}, - {0x12, 0x00, set_sensor_dbus_state_system_event, "setValue", "", ""}, - {0x12, 0x01, set_sensor_dbus_state_system_event, "setValue", "", ""}, - {0x12, 0x02, set_sensor_dbus_state_system_event, "setValue", "", ""}, - {0x12, 0x03, set_sensor_dbus_state_system_event, "setValue", "", ""}, - {0x12, 0x04, set_sensor_dbus_state_system_event, "setValue", "", ""}, - - {0xFF, 0xFF, NULL, "", "", ""} -}; - - -void reportSensorEventAssert(sensorRES_t *pRec, int index) { - lookup_t *pTable = &g_ipmidbuslookup[index]; - (*pTable->func)(pRec, pTable, pTable->assertion); -} -void reportSensorEventDeassert(sensorRES_t *pRec, int index) { - lookup_t *pTable = &g_ipmidbuslookup[index]; - (*pTable->func)(pRec, pTable, pTable->deassertion); -} - - -int findindex(const uint8_t sensor_type, int offset, int *index) { - - int i=0, rc=0; - lookup_t *pTable = g_ipmidbuslookup; - - do { - if ( ((pTable+i)->sensor_type == sensor_type) && - ((pTable+i)->offset == offset) ) { - rc = 1; - *index = i; - break; - } - i++; - } while ((pTable+i)->sensor_type != 0xFF); - - return rc; -} - -void debug_print_ok_to_dont_care(uint8_t stype, int offset) -{ - printf("LOOKATME: Sensor should not be reported: Type 0x%02x, Offset 0x%02x\n", - stype, offset); -} - -bool shouldReport(uint8_t sensorType, int offset, int *index) { - - bool rc = false; - - if (findindex(sensorType, offset, index)) { rc = true; } - - if (rc==false) { debug_print_ok_to_dont_care(sensorType, offset); } - - return rc; -} - - -int updateSensorRecordFromSSRAESC(const void *record) { - - sensorRES_t *pRec = (sensorRES_t *) record; - uint8_t stype; - int index, i=0; - - stype = find_sensor(pRec->sensor_number); - - // 0xC3 types use the assertion7_0 for the value to be set - // so skip the reseach and call the correct event reporting - // function - if (stype == 0xC3) { - - shouldReport(stype, 0x00, &index); - reportSensorEventAssert(pRec, index); - - } else { - // Scroll through each bit position . Determine - // if any bit is either asserted or Deasserted. - for(i=0;i<8;i++) { - - if ((ISBITSET(pRec->assert_state7_0,i)) && - (shouldReport(stype, i, &index))) - { - reportSensorEventAssert(pRec, index); - } - if ((ISBITSET(pRec->assert_state14_8,i)) && - (shouldReport(stype, i+8, &index))) - { - reportSensorEventAssert(pRec, index); - } - if ((ISBITSET(pRec->deassert_state7_0,i)) && - (shouldReport(stype, i, &index))) - { - reportSensorEventDeassert(pRec, index); - } - if ((ISBITSET(pRec->deassert_state14_8,i)) && - (shouldReport(stype, i+8, &index))) - { - reportSensorEventDeassert(pRec, index); - } - } - - } - - - return 0; -} diff --git a/ipmisensor.cpp b/ipmisensor.cpp new file mode 100644 index 0000000..b6927ac --- /dev/null +++ b/ipmisensor.cpp @@ -0,0 +1,302 @@ +#include +#include +#include +#include +#include +#include "sensorhandler.h" + +extern uint8_t find_sensor(uint8_t); + + +struct sensorRES_t { + uint8_t sensor_number; + uint8_t operation; + uint8_t sensor_reading; + uint8_t assert_state7_0; + uint8_t assert_state14_8; + uint8_t deassert_state7_0; + uint8_t deassert_state14_8; + uint8_t event_data1; + uint8_t event_data2; + uint8_t event_data3; +} __attribute__ ((packed)); + +#define ISBITSET(x,y) (((x)>>(y))&0x01) +#define ASSERTINDEX 0 +#define DEASSERTINDEX 1 + +// Sensor Type, Offset, function handler, Dbus Method, Assert value, Deassert value +struct lookup_t { + uint8_t sensor_type; + uint8_t offset; + int (*func)(const sensorRES_t *, const lookup_t *, const char *); + char member[16]; + char assertion[64]; + char deassertion[64]; +}; + +extern int updateDbusInterface(uint8_t , const char *, const char *); +extern int find_openbmc_path(const char *, const uint8_t , dbus_interface_t *) ; + + +int set_sensor_dbus_state_simple(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { + + return set_sensor_dbus_state_s(pRec->sensor_number, + pTable->member, + value); +} + +struct event_data_t { + uint8_t data; + char text[64]; +}; + +event_data_t g_fwprogress02h[] = { + {0x00, "Unspecified"}, + {0x01, "Memory Init"}, + {0x02, "HD Init"}, + {0x03, "Secondary Proc Init"}, + {0x04, "User Authentication"}, + {0x05, "User init system setup"}, + {0x06, "USB configuration"}, + {0x07, "PCI configuration"}, + {0x08, "Option ROM Init"}, + {0x09, "Video Init"}, + {0x0A, "Cache Init"}, + {0x0B, "SM Bus init"}, + {0x0C, "Keyboard Init"}, + {0x0D, "Embedded ctrl init"}, + {0x0E, "Docking station attachment"}, + {0x0F, "Enable docking station"}, + {0x10, "Docking station ejection"}, + {0x11, "Disabling docking station"}, + {0x12, "Calling OS Wakeup"}, + {0x13, "Starting OS"}, + {0x14, "Baseboard Init"}, + {0x15, ""}, + {0x16, "Floppy Init"}, + {0x17, "Keyboard Test"}, + {0x18, "Pointing Device Test"}, + {0x19, "Primary Proc Init"}, + {0xFF, "Unknown"} +}; + +event_data_t g_fwprogress00h[] = { + {0x00, "Unspecified."}, + {0x01, "No system memory detected"}, + {0x02, "No usable system memory"}, + {0x03, "Unrecoverable hard-disk/ATAPI/IDE"}, + {0x04, "Unrecoverable system-board"}, + {0x05, "Unrecoverable diskette"}, + {0x06, "Unrecoverable hard-disk controller"}, + {0x07, "Unrecoverable PS/2 or USB keyboard"}, + {0x08, "Removable boot media not found"}, + {0x09, "Unrecoverable video controller"}, + {0x0A, "No video device detected"}, + {0x0B, "Firmware ROM corruption detected"}, + {0x0C, "CPU voltage mismatch"}, + {0x0D, "CPU speed matching"}, + {0xFF, "unknown"}, +}; + + +char *event_data_lookup(event_data_t *p, uint8_t b) { + + while(p->data != 0xFF) { + if (p->data == b) { + break; + } + p++; + } + + return p->text; +} + + + +// The fw progress sensor contains some additional information that needs to be processed +// prior to calling the dbus code. +int set_sensor_dbus_state_fwprogress(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { + + char valuestring[128]; + char* p = valuestring; + + switch (pTable->offset) { + + case 0x00 : snprintf(p, sizeof(valuestring), "POST Error, %s", event_data_lookup(g_fwprogress00h, pRec->event_data2)); + break; + case 0x01 : /* Using g_fwprogress02h for 0x01 because thats what the ipmi spec says to do */ + snprintf(p, sizeof(valuestring), "FW Hang, %s", event_data_lookup(g_fwprogress02h, pRec->event_data2)); + break; + case 0x02 : snprintf(p, sizeof(valuestring), "FW Progress, %s", event_data_lookup(g_fwprogress02h, pRec->event_data2)); + break; + default : snprintf(p, sizeof(valuestring), "Internal warning, fw_progres offset unknown (0x%02x)", pTable->offset); + break; + } + + return set_sensor_dbus_state_s(pRec->sensor_number, + pTable->member, + p); +} + +// Handling this special OEM sensor by coping what is in byte 4. I also think that is odd +// considering byte 3 is for sensor reading. This seems like a misuse of the IPMI spec +int set_sensor_dbus_state_osbootcount(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { + return set_sensor_dbus_state_y(pRec->sensor_number, + "setValue", + pRec->assert_state7_0); +} + +int set_sensor_dbus_state_system_event(const sensorRES_t *pRec, const lookup_t *pTable, const char *value) { + char valuestring[128]; + char* p = valuestring; + + switch (pTable->offset) { + + case 0x00 : snprintf(p, sizeof(valuestring), "System Reconfigured"); + break; + case 0x01 : snprintf(p, sizeof(valuestring), "OEM Boot Event"); + break; + case 0x02 : snprintf(p, sizeof(valuestring), "Undetermine System Hardware Failure"); + break; + case 0x03 : snprintf(p, sizeof(valuestring), "System Failure see error log for more details (0x%02x)", pRec->event_data2); + break; + case 0x04 : snprintf(p, sizeof(valuestring), "System Failure see PEF error log for more details (0x%02x)", pRec->event_data2); + break; + default : snprintf(p, sizeof(valuestring), "Internal warning, system_event offset unknown (0x%02x)", pTable->offset); + break; + } + + return set_sensor_dbus_state_s(pRec->sensor_number, + pTable->member, + p); +} + + +// This table lists only senors we care about telling dbus about. +// Offset definition cab be found in section 42.2 of the IPMI 2.0 +// spec. Add more if/when there are more items of interest. +lookup_t g_ipmidbuslookup[] = { + + {0xe9, 0x00, set_sensor_dbus_state_simple, "setValue", "Disabled", ""}, // OCC Inactive 0 + {0xe9, 0x01, set_sensor_dbus_state_simple, "setValue", "Enabled", ""}, // OCC Active 1 + {0x07, 0x07, set_sensor_dbus_state_simple, "setPresent", "True", "False"}, + {0x07, 0x08, set_sensor_dbus_state_simple, "setFault", "True", "False"}, + {0x0C, 0x06, set_sensor_dbus_state_simple, "setPresent", "True", "False"}, + {0x0C, 0x04, set_sensor_dbus_state_simple, "setFault", "True", "False"}, + {0x0F, 0x02, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, + {0x0F, 0x01, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, + {0x0F, 0x00, set_sensor_dbus_state_fwprogress, "setValue", "True", "False"}, + {0xC7, 0x01, set_sensor_dbus_state_simple, "setFault", "True", "False"}, + {0xc3, 0x00, set_sensor_dbus_state_osbootcount, "setValue", "" ,""}, + {0x1F, 0x00, set_sensor_dbus_state_simple, "setValue", "Boot completed (00)", ""}, + {0x1F, 0x01, set_sensor_dbus_state_simple, "setValue", "Boot completed (01)", ""}, + {0x1F, 0x02, set_sensor_dbus_state_simple, "setValue", "PXE boot completed", ""}, + {0x1F, 0x03, set_sensor_dbus_state_simple, "setValue", "Diagnostic boot completed", ""}, + {0x1F, 0x04, set_sensor_dbus_state_simple, "setValue", "CD-ROM boot completed", ""}, + {0x1F, 0x05, set_sensor_dbus_state_simple, "setValue", "ROM boot completed", ""}, + {0x1F, 0x06, set_sensor_dbus_state_simple, "setValue", "Boot completed (06)", ""}, + {0x12, 0x00, set_sensor_dbus_state_system_event, "setValue", "", ""}, + {0x12, 0x01, set_sensor_dbus_state_system_event, "setValue", "", ""}, + {0x12, 0x02, set_sensor_dbus_state_system_event, "setValue", "", ""}, + {0x12, 0x03, set_sensor_dbus_state_system_event, "setValue", "", ""}, + {0x12, 0x04, set_sensor_dbus_state_system_event, "setValue", "", ""}, + + {0xFF, 0xFF, NULL, "", "", ""} +}; + + +void reportSensorEventAssert(sensorRES_t *pRec, int index) { + lookup_t *pTable = &g_ipmidbuslookup[index]; + (*pTable->func)(pRec, pTable, pTable->assertion); +} +void reportSensorEventDeassert(sensorRES_t *pRec, int index) { + lookup_t *pTable = &g_ipmidbuslookup[index]; + (*pTable->func)(pRec, pTable, pTable->deassertion); +} + + +int findindex(const uint8_t sensor_type, int offset, int *index) { + + int i=0, rc=0; + lookup_t *pTable = g_ipmidbuslookup; + + do { + if ( ((pTable+i)->sensor_type == sensor_type) && + ((pTable+i)->offset == offset) ) { + rc = 1; + *index = i; + break; + } + i++; + } while ((pTable+i)->sensor_type != 0xFF); + + return rc; +} + +void debug_print_ok_to_dont_care(uint8_t stype, int offset) +{ + printf("LOOKATME: Sensor should not be reported: Type 0x%02x, Offset 0x%02x\n", + stype, offset); +} + +bool shouldReport(uint8_t sensorType, int offset, int *index) { + + bool rc = false; + + if (findindex(sensorType, offset, index)) { rc = true; } + + if (rc==false) { debug_print_ok_to_dont_care(sensorType, offset); } + + return rc; +} + + +int updateSensorRecordFromSSRAESC(const void *record) { + + sensorRES_t *pRec = (sensorRES_t *) record; + uint8_t stype; + int index, i=0; + + stype = find_sensor(pRec->sensor_number); + + // 0xC3 types use the assertion7_0 for the value to be set + // so skip the reseach and call the correct event reporting + // function + if (stype == 0xC3) { + + shouldReport(stype, 0x00, &index); + reportSensorEventAssert(pRec, index); + + } else { + // Scroll through each bit position . Determine + // if any bit is either asserted or Deasserted. + for(i=0;i<8;i++) { + + if ((ISBITSET(pRec->assert_state7_0,i)) && + (shouldReport(stype, i, &index))) + { + reportSensorEventAssert(pRec, index); + } + if ((ISBITSET(pRec->assert_state14_8,i)) && + (shouldReport(stype, i+8, &index))) + { + reportSensorEventAssert(pRec, index); + } + if ((ISBITSET(pRec->deassert_state7_0,i)) && + (shouldReport(stype, i, &index))) + { + reportSensorEventDeassert(pRec, index); + } + if ((ISBITSET(pRec->deassert_state14_8,i)) && + (shouldReport(stype, i+8, &index))) + { + reportSensorEventDeassert(pRec, index); + } + } + + } + + + return 0; +} diff --git a/sensorhandler.C b/sensorhandler.C deleted file mode 100644 index 39de660..0000000 --- a/sensorhandler.C +++ /dev/null @@ -1,262 +0,0 @@ -#include "sensorhandler.h" -#include "ipmid-api.h" -#include -#include -#include -#include - -extern int updateSensorRecordFromSSRAESC(const void *); -extern int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) ; -extern int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) ; - -void register_netfn_sen_functions() __attribute__((constructor)); - -struct sensorTypemap_t { - uint8_t number; - uint8_t typecode; - char dbusname[32]; -} ; - - -sensorTypemap_t g_SensorTypeMap[] = { - - {0x01, 0x6F, "Temp"}, - {0x0C, 0x6F, "DIMM"}, - {0x0C, 0x6F, "MEMORY_BUFFER"}, - {0x07, 0x6F, "PROC"}, - {0x07, 0x6F, "CORE"}, - {0x07, 0x6F, "CPU"}, - {0x0F, 0x6F, "BootProgress"}, - {0xe9, 0x09, "OccStatus"}, // E9 is an internal mapping to handle sensor type code os 0x09 - {0xC3, 0x6F, "BootCount"}, - {0x1F, 0x6F, "OperatingSystemStatus"}, - {0x12, 0x6F, "SYSTEM_EVENT"}, - {0xC7, 0x03, "SYSTEM"}, - {0xC7, 0x03, "MAIN_PLANAR"}, - {0xC2, 0x6F, "PowerCap"}, - {0xFF, 0x00, ""}, -}; - - -struct sensor_data_t { - uint8_t sennum; -} __attribute__ ((packed)) ; - -struct sensorreadingresp_t { - uint8_t value; - uint8_t operation; - uint8_t indication[2]; -} __attribute__ ((packed)) ; - -uint8_t dbus_to_sensor_type(char *p) { - - sensorTypemap_t *s = g_SensorTypeMap; - char r=0; - - while (s->number != 0xFF) { - if (!strcmp(s->dbusname,p)) { - r = s->number; - break; - } - s++; - } - - - if (s->number == 0xFF) - printf("Failed to find Sensor Type %s\n", p); - - return r; -} - - -uint8_t dbus_to_sensor_type_from_dbus(dbus_interface_t *a) { - char fru_type_name[64]; - int r= 0; - - r = find_interface_property_fru_type(a, "fru_type", fru_type_name); - if (r<0) { - fprintf(stderr, "Failed to get a fru type: %s", strerror(-r)); - return -1; - } else { - return dbus_to_sensor_type(fru_type_name); - } -} - - -uint8_t find_sensor(uint8_t sensor_number) { - - dbus_interface_t a; - char *p; - char r; - - r = find_openbmc_path("SENSOR", sensor_number, &a); - - if (r < 0) { return 0; } - - // This is where sensors that do not exist in dbus but do - // exist in the host code stop. This should indicate it - // is not a supported sensor - if (a.interface[0] == 0) { return 0;} - - if (strstr(a.interface, "InventoryItem")) { - // InventoryItems are real frus. So need to get the - // fru_type property - r = dbus_to_sensor_type_from_dbus(&a); - } else { - // Non InventoryItems - p = strrchr (a.path, '/'); - r = dbus_to_sensor_type(p+1); - } - - return r; - } - - - - - -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] = find_sensor(reqptr->sennum); - - // HACK UNTIL Dbus gets updated or we find a better way - if (buf[0] == 0) { - rc = IPMI_CC_SENSOR_INVALID; - } - - - *data_len = sizeof(buf); - memcpy(response, &buf, *data_len); - - return rc; -} - - - -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) -{ - sensor_data_t *reqptr = (sensor_data_t*)request; - ipmi_ret_t rc = IPMI_CC_OK; - - printf("IPMI SET_SENSOR [0x%02x]\n",reqptr->sennum); - - updateSensorRecordFromSSRAESC(reqptr); - - *data_len=0; - - return rc; -} - - -ipmi_ret_t ipmi_sen_get_sensor_reading(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_SENSOR_INVALID; - uint8_t type; - sensorreadingresp_t *resp = (sensorreadingresp_t*) response; - int r; - dbus_interface_t a; - sd_bus *bus = ipmid_get_sd_bus_connection(); - sd_bus_message *reply = NULL; - int reading = 0; - - - printf("IPMI GET_SENSOR_READING [0x%02x]\n",reqptr->sennum); - - r = find_openbmc_path("SENSOR", reqptr->sennum, &a); - - if (r < 0) { - fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum); - return IPMI_CC_SENSOR_INVALID; - } - - type = find_sensor(reqptr->sennum); - - fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", a.bus, a.path, a.interface); - - *data_len=0; - - switch(type) { - case 0xC3: - case 0xC2: - r = sd_bus_get_property(bus,a.bus, a.path, a.interface, "value", NULL, &reply, "i"); - if (r < 0) { - fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r)); - fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", - a.bus, a.path, a.interface); - break; - } - - r = sd_bus_message_read(reply, "i", &reading); - if (r < 0) { - fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r)); - break; - } - - printf("Contents of a 0x%02x is 0x%02x\n", type, reading); - - rc = IPMI_CC_OK; - *data_len=sizeof(sensorreadingresp_t); - - resp->value = (uint8_t)reading; - resp->operation = 0; - resp->indication[0] = 0; - resp->indication[1] = 0; - break; - - default: - *data_len=0; - rc = IPMI_CC_SENSOR_INVALID; - break; - } - - - reply = sd_bus_message_unref(reply); - - 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); - - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING); - ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, NULL, ipmi_sen_get_sensor_reading); - - return; -} diff --git a/sensorhandler.cpp b/sensorhandler.cpp new file mode 100644 index 0000000..39de660 --- /dev/null +++ b/sensorhandler.cpp @@ -0,0 +1,262 @@ +#include "sensorhandler.h" +#include "ipmid-api.h" +#include +#include +#include +#include + +extern int updateSensorRecordFromSSRAESC(const void *); +extern int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) ; +extern int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) ; + +void register_netfn_sen_functions() __attribute__((constructor)); + +struct sensorTypemap_t { + uint8_t number; + uint8_t typecode; + char dbusname[32]; +} ; + + +sensorTypemap_t g_SensorTypeMap[] = { + + {0x01, 0x6F, "Temp"}, + {0x0C, 0x6F, "DIMM"}, + {0x0C, 0x6F, "MEMORY_BUFFER"}, + {0x07, 0x6F, "PROC"}, + {0x07, 0x6F, "CORE"}, + {0x07, 0x6F, "CPU"}, + {0x0F, 0x6F, "BootProgress"}, + {0xe9, 0x09, "OccStatus"}, // E9 is an internal mapping to handle sensor type code os 0x09 + {0xC3, 0x6F, "BootCount"}, + {0x1F, 0x6F, "OperatingSystemStatus"}, + {0x12, 0x6F, "SYSTEM_EVENT"}, + {0xC7, 0x03, "SYSTEM"}, + {0xC7, 0x03, "MAIN_PLANAR"}, + {0xC2, 0x6F, "PowerCap"}, + {0xFF, 0x00, ""}, +}; + + +struct sensor_data_t { + uint8_t sennum; +} __attribute__ ((packed)) ; + +struct sensorreadingresp_t { + uint8_t value; + uint8_t operation; + uint8_t indication[2]; +} __attribute__ ((packed)) ; + +uint8_t dbus_to_sensor_type(char *p) { + + sensorTypemap_t *s = g_SensorTypeMap; + char r=0; + + while (s->number != 0xFF) { + if (!strcmp(s->dbusname,p)) { + r = s->number; + break; + } + s++; + } + + + if (s->number == 0xFF) + printf("Failed to find Sensor Type %s\n", p); + + return r; +} + + +uint8_t dbus_to_sensor_type_from_dbus(dbus_interface_t *a) { + char fru_type_name[64]; + int r= 0; + + r = find_interface_property_fru_type(a, "fru_type", fru_type_name); + if (r<0) { + fprintf(stderr, "Failed to get a fru type: %s", strerror(-r)); + return -1; + } else { + return dbus_to_sensor_type(fru_type_name); + } +} + + +uint8_t find_sensor(uint8_t sensor_number) { + + dbus_interface_t a; + char *p; + char r; + + r = find_openbmc_path("SENSOR", sensor_number, &a); + + if (r < 0) { return 0; } + + // This is where sensors that do not exist in dbus but do + // exist in the host code stop. This should indicate it + // is not a supported sensor + if (a.interface[0] == 0) { return 0;} + + if (strstr(a.interface, "InventoryItem")) { + // InventoryItems are real frus. So need to get the + // fru_type property + r = dbus_to_sensor_type_from_dbus(&a); + } else { + // Non InventoryItems + p = strrchr (a.path, '/'); + r = dbus_to_sensor_type(p+1); + } + + return r; + } + + + + + +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] = find_sensor(reqptr->sennum); + + // HACK UNTIL Dbus gets updated or we find a better way + if (buf[0] == 0) { + rc = IPMI_CC_SENSOR_INVALID; + } + + + *data_len = sizeof(buf); + memcpy(response, &buf, *data_len); + + return rc; +} + + + +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) +{ + sensor_data_t *reqptr = (sensor_data_t*)request; + ipmi_ret_t rc = IPMI_CC_OK; + + printf("IPMI SET_SENSOR [0x%02x]\n",reqptr->sennum); + + updateSensorRecordFromSSRAESC(reqptr); + + *data_len=0; + + return rc; +} + + +ipmi_ret_t ipmi_sen_get_sensor_reading(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_SENSOR_INVALID; + uint8_t type; + sensorreadingresp_t *resp = (sensorreadingresp_t*) response; + int r; + dbus_interface_t a; + sd_bus *bus = ipmid_get_sd_bus_connection(); + sd_bus_message *reply = NULL; + int reading = 0; + + + printf("IPMI GET_SENSOR_READING [0x%02x]\n",reqptr->sennum); + + r = find_openbmc_path("SENSOR", reqptr->sennum, &a); + + if (r < 0) { + fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum); + return IPMI_CC_SENSOR_INVALID; + } + + type = find_sensor(reqptr->sennum); + + fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", a.bus, a.path, a.interface); + + *data_len=0; + + switch(type) { + case 0xC3: + case 0xC2: + r = sd_bus_get_property(bus,a.bus, a.path, a.interface, "value", NULL, &reply, "i"); + if (r < 0) { + fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r)); + fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", + a.bus, a.path, a.interface); + break; + } + + r = sd_bus_message_read(reply, "i", &reading); + if (r < 0) { + fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r)); + break; + } + + printf("Contents of a 0x%02x is 0x%02x\n", type, reading); + + rc = IPMI_CC_OK; + *data_len=sizeof(sensorreadingresp_t); + + resp->value = (uint8_t)reading; + resp->operation = 0; + resp->indication[0] = 0; + resp->indication[1] = 0; + break; + + default: + *data_len=0; + rc = IPMI_CC_SENSOR_INVALID; + break; + } + + + reply = sd_bus_message_unref(reply); + + 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); + + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING); + ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, NULL, ipmi_sen_get_sensor_reading); + + return; +} diff --git a/storageaddsel.C b/storageaddsel.C deleted file mode 100644 index 3343772..0000000 --- a/storageaddsel.C +++ /dev/null @@ -1,253 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 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; - int r; - - if ((fp = fopen(fn, "rb")) != NULL) { - - r = fseek(fp, 0, SEEK_END); - if (r) { - fprintf(stderr,"Fseek failed\n"); - goto fclose_fp; - } - - size = ftell(fp); - if (size == -1L) { - fprintf(stderr,"Ftell failed for %s\n", strerror(errno)); - size = 0; - goto fclose_fp; - } - - r = fseek(fp, 0, SEEK_SET); - if (r) { - fprintf(stderr,"Fseek failed\n"); - size = 0; - goto fclose_fp; - } - - *buffer = new uint8_t [size]; - - r = fread(*buffer, 1, size, fp); - if ( r != size) { - size = 0; - fprintf(stderr,"Fread failed\n"); - } - -fclose_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); - - // Simply no associations if the sensor can not be found - if (strlen(dbusint.path) < 1) { - printf("Sensor 0x%x not found\n", sensor); - memset(dbusint.path,0,sizeof(dbusint.path)); - } - - 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; - 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 x; - int r; - - mbus = ipmid_get_sd_bus_connection(); - - 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)); - goto finish; - } - - r = sd_bus_message_append(m, "sss", desc, sev, details); - if (r < 0) { - fprintf(stderr, "Failed add the message strings : %s\n", strerror(-r)); - goto finish; - } - - 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)); - goto finish; - } - // 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 %s\n", __FUNCTION__, strerror(-r)); - goto finish; - } - r = sd_bus_message_read(reply, "q", &x); - if (r < 0) { - fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r)); - } - -finish: - sd_bus_error_free(&error); - m = sd_bus_message_unref(m); - reply = sd_bus_message_unref(reply); - return r; -} - - -void send_esel(uint16_t recordid) { - char *desc, *assoc; - const char *sev; - uint8_t *buffer = NULL; - const char *path = "/tmp/esel"; - size_t sz; - int r; - - sz = getfilestream(path, &buffer); - if (sz == 0) { - printf("Error file does not exist %d\n",__LINE__); - return; - } - - sev = create_esel_severity(buffer); - create_esel_association(buffer, &assoc); - create_esel_description(buffer, sev, &desc); - - r = send_esel_to_dbus(desc, sev, assoc, buffer, sz); - if (r < 0) { - fprintf(stderr, "Failed to send esel to dbus\n"); - } - - free(assoc); - free(desc); - delete[] buffer; - - return; -} diff --git a/storageaddsel.cpp b/storageaddsel.cpp new file mode 100644 index 0000000..3343772 --- /dev/null +++ b/storageaddsel.cpp @@ -0,0 +1,253 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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; + int r; + + if ((fp = fopen(fn, "rb")) != NULL) { + + r = fseek(fp, 0, SEEK_END); + if (r) { + fprintf(stderr,"Fseek failed\n"); + goto fclose_fp; + } + + size = ftell(fp); + if (size == -1L) { + fprintf(stderr,"Ftell failed for %s\n", strerror(errno)); + size = 0; + goto fclose_fp; + } + + r = fseek(fp, 0, SEEK_SET); + if (r) { + fprintf(stderr,"Fseek failed\n"); + size = 0; + goto fclose_fp; + } + + *buffer = new uint8_t [size]; + + r = fread(*buffer, 1, size, fp); + if ( r != size) { + size = 0; + fprintf(stderr,"Fread failed\n"); + } + +fclose_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); + + // Simply no associations if the sensor can not be found + if (strlen(dbusint.path) < 1) { + printf("Sensor 0x%x not found\n", sensor); + memset(dbusint.path,0,sizeof(dbusint.path)); + } + + 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; + 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 x; + int r; + + mbus = ipmid_get_sd_bus_connection(); + + 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)); + goto finish; + } + + r = sd_bus_message_append(m, "sss", desc, sev, details); + if (r < 0) { + fprintf(stderr, "Failed add the message strings : %s\n", strerror(-r)); + goto finish; + } + + 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)); + goto finish; + } + // 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 %s\n", __FUNCTION__, strerror(-r)); + goto finish; + } + r = sd_bus_message_read(reply, "q", &x); + if (r < 0) { + fprintf(stderr, "Failed to get a rc from the method: %s\n", strerror(-r)); + } + +finish: + sd_bus_error_free(&error); + m = sd_bus_message_unref(m); + reply = sd_bus_message_unref(reply); + return r; +} + + +void send_esel(uint16_t recordid) { + char *desc, *assoc; + const char *sev; + uint8_t *buffer = NULL; + const char *path = "/tmp/esel"; + size_t sz; + int r; + + sz = getfilestream(path, &buffer); + if (sz == 0) { + printf("Error file does not exist %d\n",__LINE__); + return; + } + + sev = create_esel_severity(buffer); + create_esel_association(buffer, &assoc); + create_esel_description(buffer, sev, &desc); + + r = send_esel_to_dbus(desc, sev, assoc, buffer, sz); + if (r < 0) { + fprintf(stderr, "Failed to send esel to dbus\n"); + } + + free(assoc); + free(desc); + delete[] buffer; + + return; +} diff --git a/storagehandler.C b/storagehandler.C deleted file mode 100644 index 9622ed9..0000000 --- a/storagehandler.C +++ /dev/null @@ -1,171 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "storagehandler.h" -#include "storageaddsel.h" -#include "ipmid-api.h" - -void register_netfn_storage_functions() __attribute__((constructor)); - - -unsigned int g_sel_time = 0xFFFFFFFF; -extern unsigned short g_sel_reserve; - -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_get_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) -{ - time_t currtime; - ipmi_ret_t rc = IPMI_CC_OK; - - // Get current time in seconds since jan 1 1970 - time(&currtime); - uint32_t resp = (uint32_t)currtime; - resp = htole32(resp); - - printf("IPMI Handling GET-SEL-TIME\n"); - - // From the IPMI Spec 2.0, response should be a 32-bit value - *data_len = sizeof(resp); - - // Pack the actual response - memcpy(response, &resp, *data_len); - - 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) -{ - uint32_t* secs = (uint32_t*)request; - - printf("Handling Set-SEL-Time:[0x%X], Cmd:[0x%X]\n",netfn, cmd); - printf("Data: 0x%X]\n",*secs); - - struct timeval sel_time; - sel_time.tv_sec = le32toh(*secs); - sel_time.tv_usec = 0; - ipmi_ret_t rc = IPMI_CC_OK; - int rct = settimeofday(&sel_time, NULL); - - if(rct == 0) - { - system("hwclock -w"); - } - else - { - printf("settimeofday() failed\n"); - rc = IPMI_CC_UNSPECIFIED_ERROR; - } - *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) -{ - unsigned short res_id; - - ipmi_ret_t rc = IPMI_CC_OK; - - // IPMI spec, Reservation ID, the value simply increases against each execution of reserve_sel command. - if( ++g_sel_reserve == 0) - g_sel_reserve = 1; - - 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; - ipmi_add_sel_request_t *p = (ipmi_add_sel_request_t*) request; - uint16_t recordid; - - recordid = ((uint16_t)p->eventdata[1] << 8) | p->eventdata[2]; - - printf("IPMI Handling ADD-SEL for record 0x%04x\n", recordid); - - *data_len = sizeof(g_sel_reserve); - - // Pack the actual response - memcpy(response, &p->eventdata[1], 2); - - send_esel(recordid); - - 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_GET_SEL_TIME); - ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_TIME, NULL, ipmi_storage_get_sel_time); - - 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_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.cpp b/storagehandler.cpp new file mode 100644 index 0000000..9622ed9 --- /dev/null +++ b/storagehandler.cpp @@ -0,0 +1,171 @@ +#include +#include +#include +#include +#include +#include + +#include "storagehandler.h" +#include "storageaddsel.h" +#include "ipmid-api.h" + +void register_netfn_storage_functions() __attribute__((constructor)); + + +unsigned int g_sel_time = 0xFFFFFFFF; +extern unsigned short g_sel_reserve; + +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_get_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) +{ + time_t currtime; + ipmi_ret_t rc = IPMI_CC_OK; + + // Get current time in seconds since jan 1 1970 + time(&currtime); + uint32_t resp = (uint32_t)currtime; + resp = htole32(resp); + + printf("IPMI Handling GET-SEL-TIME\n"); + + // From the IPMI Spec 2.0, response should be a 32-bit value + *data_len = sizeof(resp); + + // Pack the actual response + memcpy(response, &resp, *data_len); + + 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) +{ + uint32_t* secs = (uint32_t*)request; + + printf("Handling Set-SEL-Time:[0x%X], Cmd:[0x%X]\n",netfn, cmd); + printf("Data: 0x%X]\n",*secs); + + struct timeval sel_time; + sel_time.tv_sec = le32toh(*secs); + sel_time.tv_usec = 0; + ipmi_ret_t rc = IPMI_CC_OK; + int rct = settimeofday(&sel_time, NULL); + + if(rct == 0) + { + system("hwclock -w"); + } + else + { + printf("settimeofday() failed\n"); + rc = IPMI_CC_UNSPECIFIED_ERROR; + } + *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) +{ + unsigned short res_id; + + ipmi_ret_t rc = IPMI_CC_OK; + + // IPMI spec, Reservation ID, the value simply increases against each execution of reserve_sel command. + if( ++g_sel_reserve == 0) + g_sel_reserve = 1; + + 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; + ipmi_add_sel_request_t *p = (ipmi_add_sel_request_t*) request; + uint16_t recordid; + + recordid = ((uint16_t)p->eventdata[1] << 8) | p->eventdata[2]; + + printf("IPMI Handling ADD-SEL for record 0x%04x\n", recordid); + + *data_len = sizeof(g_sel_reserve); + + // Pack the actual response + memcpy(response, &p->eventdata[1], 2); + + send_esel(recordid); + + 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_GET_SEL_TIME); + ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_TIME, NULL, ipmi_storage_get_sel_time); + + 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_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/testaddsel.C b/testaddsel.C deleted file mode 100644 index 202200a..0000000 --- a/testaddsel.C +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "sensorhandler.h" - - -extern void send_esel(uint16_t recordid); - -sd_bus *bus = NULL; - -// Use a lookup table to find the interface name of a specific sensor -// This will be used until an alternative is found. this is the first -// step for mapping IPMI -int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) { - - const char *busname = "org.openbmc.managers.System"; - const char *objname = "/org/openbmc/managers/System"; - - char *str1, *str2, *str3; - sd_bus_error error = SD_BUS_ERROR_NULL; - sd_bus_message *reply = NULL, *m=NULL; - - - int r; - - r = sd_bus_message_new_method_call(bus,&m,busname,objname,busname,"getObjectFromByteId"); - if (r < 0) { - fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); - } - - r = sd_bus_message_append(m, "sy", type, num); - if (r < 0) { - fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); - } - - // 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)); - goto final; - } - - - r = sd_bus_message_read(reply, "(sss)", &str1, &str2, &str3); - if (r < 0) { - fprintf(stderr, "Failed to get a response: %s", strerror(-r)); - goto final; - } - - strncpy(interface->bus, str1, MAX_DBUS_PATH); - strncpy(interface->path, str2, MAX_DBUS_PATH); - strncpy(interface->interface, str3, MAX_DBUS_PATH); - - interface->sensornumber = num; - -final: - - sd_bus_error_free(&error); - sd_bus_message_unref(m); - - return r; -} - - - - -int main(int argc, char *argv[]) -{ - int base; - char *endptr, *str; - long val; - uint16_t num; - int r; - - if (argc < 2) { - fprintf(stderr, "Usage: %s sensornumber\n", argv[0]); - return -1; - } - - str = argv[1]; - base = (argc > 2) ? atoi(argv[2]) : 10; - - val = strtol(str, &endptr, base); - - num = (uint16_t) val; - - - - /* 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; - } - - send_esel(num); - - -finish: - sd_bus_unref(bus); - - return 0; -} \ No newline at end of file diff --git a/testaddsel.cpp b/testaddsel.cpp new file mode 100644 index 0000000..202200a --- /dev/null +++ b/testaddsel.cpp @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include "sensorhandler.h" + + +extern void send_esel(uint16_t recordid); + +sd_bus *bus = NULL; + +// Use a lookup table to find the interface name of a specific sensor +// This will be used until an alternative is found. this is the first +// step for mapping IPMI +int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) { + + const char *busname = "org.openbmc.managers.System"; + const char *objname = "/org/openbmc/managers/System"; + + char *str1, *str2, *str3; + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *reply = NULL, *m=NULL; + + + int r; + + r = sd_bus_message_new_method_call(bus,&m,busname,objname,busname,"getObjectFromByteId"); + if (r < 0) { + fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); + } + + r = sd_bus_message_append(m, "sy", type, num); + if (r < 0) { + fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); + } + + // 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)); + goto final; + } + + + r = sd_bus_message_read(reply, "(sss)", &str1, &str2, &str3); + if (r < 0) { + fprintf(stderr, "Failed to get a response: %s", strerror(-r)); + goto final; + } + + strncpy(interface->bus, str1, MAX_DBUS_PATH); + strncpy(interface->path, str2, MAX_DBUS_PATH); + strncpy(interface->interface, str3, MAX_DBUS_PATH); + + interface->sensornumber = num; + +final: + + sd_bus_error_free(&error); + sd_bus_message_unref(m); + + return r; +} + + + + +int main(int argc, char *argv[]) +{ + int base; + char *endptr, *str; + long val; + uint16_t num; + int r; + + if (argc < 2) { + fprintf(stderr, "Usage: %s sensornumber\n", argv[0]); + return -1; + } + + str = argv[1]; + base = (argc > 2) ? atoi(argv[2]) : 10; + + val = strtol(str, &endptr, base); + + num = (uint16_t) val; + + + + /* 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; + } + + send_esel(num); + + +finish: + sd_bus_unref(bus); + + return 0; +} \ No newline at end of file diff --git a/testit.C b/testit.C deleted file mode 100644 index a0cd2c1..0000000 --- a/testit.C +++ /dev/null @@ -1,120 +0,0 @@ - -#include -#include -#include - - -unsigned char g_sensortype [][2] = { - {0xC3, 0x01}, - {0x07, 0x02}, - {0x0F, 0x05}, - {0x0c, 0x1F}, - {0xFF ,0xff} -}; - -uint8_t find_sensor(uint8_t sensor_number) { - - int i=0; - uint8_t rc; - - while (g_sensortype[i][0] != 0xff) { - if (g_sensortype[i][1] == sensor_number) { - break; - } else { - i++; - } - } - - rc = g_sensortype[i][0]; - - if (rc == 0xFF) { - rc = 0; - } - return rc; -} - -char g_results_method[64]; -char g_results_value[64]; - - -int set_sensor_dbus_state_s(unsigned char number, const char *member, const char *value) { - printf("Attempting to log 0x%02x via %s with a value of %s\n", - number, member, value); - - strcpy(g_results_method, member); - strcpy(g_results_value, value); - - return 0; -} - -int set_sensor_dbus_state_y(unsigned char number, char const* member, uint8_t value) { - - char val[2]; - - - printf("Attempting to log Variant Sensor 0x%02x via %s with a value of 0x%02x\n", - number, member, value); - - - snprintf(val, 2, "%d", value); - - strcpy(g_results_method, member); - strcpy(g_results_value, val); - - return 0; -} - - -extern int updateSensorRecordFromSSRAESC(const void *record); - - - -// DIMM Present -uint8_t testrec_sensor1[] = {0x1F, 0xa9, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -// DIMM Not present -uint8_t testrec_sensor2[] = {0x1F, 0xa9, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00}; - -// DIMM Not present -uint8_t testrec_procfailed[] = {0x02, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; - -// Virtual Sensor 5, setting a Value of 0h -uint8_t testrec_bootprogress[] = {0x05, 0xa9, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00}; - -// Virtual Sensor setting a boot count -uint8_t testrec_bootcount[] = {0x01, 0x09, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -// Invalid sensor number -uint8_t testrec_invalidnumber[]= {0x35, 0xa9, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00}; - - -int check_results(int rc, const char *method, const char *value) { - if (strcmp(g_results_method, method)) { - printf("ERROR: Method Failed, expect %s found %s\n", method, g_results_method); - return -1; - } - if (strcmp(g_results_value, value)) { - printf("ERROR: Value failed, expected %s found %s\n", value, g_results_value); - return -2; - } - - return 0; -} - -void testprep(void) { - memset(g_results_method, 0, sizeof(g_results_method)); - memset(g_results_value, 0, sizeof(g_results_value)); -} - - -int main() { - - testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_bootprogress), "setValue", "FW Progress, Docking station attachment"); - testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_sensor1), "setPresent", "True"); - testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_sensor2), "setPresent", "False"); - testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_procfailed), "setFault", "False"); - testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_bootcount), "setValue", "3"); - testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_invalidnumber), "", ""); - - return 0; -} \ No newline at end of file diff --git a/testit.cpp b/testit.cpp new file mode 100644 index 0000000..a0cd2c1 --- /dev/null +++ b/testit.cpp @@ -0,0 +1,120 @@ + +#include +#include +#include + + +unsigned char g_sensortype [][2] = { + {0xC3, 0x01}, + {0x07, 0x02}, + {0x0F, 0x05}, + {0x0c, 0x1F}, + {0xFF ,0xff} +}; + +uint8_t find_sensor(uint8_t sensor_number) { + + int i=0; + uint8_t rc; + + while (g_sensortype[i][0] != 0xff) { + if (g_sensortype[i][1] == sensor_number) { + break; + } else { + i++; + } + } + + rc = g_sensortype[i][0]; + + if (rc == 0xFF) { + rc = 0; + } + return rc; +} + +char g_results_method[64]; +char g_results_value[64]; + + +int set_sensor_dbus_state_s(unsigned char number, const char *member, const char *value) { + printf("Attempting to log 0x%02x via %s with a value of %s\n", + number, member, value); + + strcpy(g_results_method, member); + strcpy(g_results_value, value); + + return 0; +} + +int set_sensor_dbus_state_y(unsigned char number, char const* member, uint8_t value) { + + char val[2]; + + + printf("Attempting to log Variant Sensor 0x%02x via %s with a value of 0x%02x\n", + number, member, value); + + + snprintf(val, 2, "%d", value); + + strcpy(g_results_method, member); + strcpy(g_results_value, val); + + return 0; +} + + +extern int updateSensorRecordFromSSRAESC(const void *record); + + + +// DIMM Present +uint8_t testrec_sensor1[] = {0x1F, 0xa9, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// DIMM Not present +uint8_t testrec_sensor2[] = {0x1F, 0xa9, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00}; + +// DIMM Not present +uint8_t testrec_procfailed[] = {0x02, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; + +// Virtual Sensor 5, setting a Value of 0h +uint8_t testrec_bootprogress[] = {0x05, 0xa9, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00}; + +// Virtual Sensor setting a boot count +uint8_t testrec_bootcount[] = {0x01, 0x09, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// Invalid sensor number +uint8_t testrec_invalidnumber[]= {0x35, 0xa9, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00}; + + +int check_results(int rc, const char *method, const char *value) { + if (strcmp(g_results_method, method)) { + printf("ERROR: Method Failed, expect %s found %s\n", method, g_results_method); + return -1; + } + if (strcmp(g_results_value, value)) { + printf("ERROR: Value failed, expected %s found %s\n", value, g_results_value); + return -2; + } + + return 0; +} + +void testprep(void) { + memset(g_results_method, 0, sizeof(g_results_method)); + memset(g_results_value, 0, sizeof(g_results_value)); +} + + +int main() { + + testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_bootprogress), "setValue", "FW Progress, Docking station attachment"); + testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_sensor1), "setPresent", "True"); + testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_sensor2), "setPresent", "False"); + testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_procfailed), "setFault", "False"); + testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_bootcount), "setValue", "3"); + testprep(); check_results(updateSensorRecordFromSSRAESC(testrec_invalidnumber), "", ""); + + return 0; +} \ No newline at end of file diff --git a/transporthandler.C b/transporthandler.C deleted file mode 100644 index 3b4cf07..0000000 --- a/transporthandler.C +++ /dev/null @@ -1,395 +0,0 @@ -#include -#include -#include -#include -#include - -#include "ipmid-api.h" -#include "ipmid.H" -#include "transporthandler.h" - -#define SYSTEMD_NETWORKD_DBUS 1 - -#ifdef SYSTEMD_NETWORKD_DBUS -#include -#endif - -// OpenBMC System Manager dbus framework -const char *app = "org.openbmc.NetworkManager"; -const char *obj = "/org/openbmc/NetworkManager/Interface"; -const char *ifc = "org.openbmc.NetworkManager"; - -const char *nwinterface = "eth0"; - -const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx - -char new_ipaddr [INET_ADDRSTRLEN] = ""; -char new_netmask [INET_ADDRSTRLEN] = ""; -char new_gateway [INET_ADDRSTRLEN] = ""; - -const uint8_t SET_COMPLETE = 0; -const uint8_t SET_IN_PROGRESS = 1; -const uint8_t SET_COMMIT_WRITE = 2; //Optional -const uint8_t SET_IN_PROGRESS_RESERVED = 3; //Reserved - -// Status of Set-In-Progress Parameter (# 0) -uint8_t lan_set_in_progress = SET_COMPLETE; - - - -void register_netfn_transport_functions() __attribute__((constructor)); - -// Helper Function to get IP Address/NetMask/Gateway from Network Manager or Cache -// based on Set-In-Progress State -ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data) -{ - sd_bus *bus = ipmid_get_sd_bus_connection(); - sd_bus_message *reply = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - int family; - unsigned char prefixlen; - char* ipaddr = NULL; - unsigned long mask = 0xFFFFFFFF; - char* gateway = NULL; - int r = 0; - ipmi_ret_t rc = IPMI_CC_OK; - - r = sd_bus_call_method(bus, app, obj, ifc, "GetAddress4", &error, - &reply, "s", nwinterface); - if(r < 0) - { - fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto cleanup; - } - - r = sd_bus_message_read(reply, "iyss", &family, &prefixlen, &ipaddr, &gateway); - if(r < 0) - { - fprintf(stderr, "Failed to get a response: %s\n", strerror(-rc)); - rc = IPMI_CC_RESPONSE_ERROR; - goto cleanup; - } - - printf("N/W data from HW %s:%d:%s:%s\n", family==AF_INET?"IPv4":"IPv6", prefixlen, ipaddr,gateway); - printf("N/W data from Cache: %s:%s:%s\n", new_ipaddr, new_netmask, new_gateway); - - if(lan_param == LAN_PARM_IP) - { - if(lan_set_in_progress == SET_COMPLETE) - { - std::string ipaddrstr(ipaddr); - inet_pton(AF_INET, ipaddrstr.c_str(),(void *)data); - } - else if(lan_set_in_progress == SET_IN_PROGRESS) - { - inet_pton(AF_INET, new_ipaddr, (void *)data); - } - } - else if(lan_param == LAN_PARM_SUBNET) - { - if(lan_set_in_progress == SET_COMPLETE) - { - mask = htonl(mask<<(32-prefixlen)); - memcpy(data, &mask, 4); - } - else if(lan_set_in_progress == SET_IN_PROGRESS) - { - inet_pton(AF_INET, new_netmask, (void *)data); - } - } - else if(lan_param == LAN_PARM_GATEWAY) - { - if(lan_set_in_progress == SET_COMPLETE) - { - std::string gatewaystr(gateway); - inet_pton(AF_INET, gatewaystr.c_str(), (void *)data); - } - else if(lan_set_in_progress == SET_IN_PROGRESS) - { - inet_pton(AF_INET, new_gateway,(void *)data); - } - } - else - { - rc = IPMI_CC_PARM_OUT_OF_RANGE; - } - -cleanup: - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - - return rc; -} - -ipmi_ret_t ipmi_transport_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 TRANSPORT WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd); - // Status code. - ipmi_ret_t rc = IPMI_CC_OK; - *data_len = 0; - return rc; -} - -struct set_lan_t { - uint8_t channel; - uint8_t parameter; - uint8_t data[8]; // Per IPMI spec, not expecting more than this size -} __attribute__ ((packed)); - -ipmi_ret_t ipmi_transport_set_lan(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; - sd_bus *bus = ipmid_get_sd_bus_connection(); - sd_bus_message *reply = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - int r = 0; - - printf("IPMI SET_LAN\n"); - - set_lan_t *reqptr = (set_lan_t*) request; - - // TODO Use dbus interface once available. For now use cmd line. - // TODO Add the rest of the parameters like setting auth type - // TODO Add error handling - - if (reqptr->parameter == LAN_PARM_IP) - { - snprintf(new_ipaddr, INET_ADDRSTRLEN, "%d.%d.%d.%d", - reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); - } - else if (reqptr->parameter == LAN_PARM_MAC) - { - char mac[SIZE_MAC]; - - snprintf(mac, SIZE_MAC, "%02x:%02x:%02x:%02x:%02x:%02x", - reqptr->data[0], - reqptr->data[1], - reqptr->data[2], - reqptr->data[3], - reqptr->data[4], - reqptr->data[5]); - - r = sd_bus_call_method(bus, app, obj, ifc, "SetHwAddress", &error, - &reply, "ss", nwinterface, mac); - if(r < 0) - { - fprintf(stderr, "Failed to call the method: %s\n", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - } - } - else if (reqptr->parameter == LAN_PARM_SUBNET) - { - snprintf(new_netmask, INET_ADDRSTRLEN, "%d.%d.%d.%d", - reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); - } - else if (reqptr->parameter == LAN_PARM_GATEWAY) - { - snprintf(new_gateway, INET_ADDRSTRLEN, "%d.%d.%d.%d", - reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); - } - else if (reqptr->parameter == LAN_PARM_INPROGRESS) - { - if(reqptr->data[0] == SET_COMPLETE) // Set Complete - { - lan_set_in_progress = SET_COMPLETE; - // Apply the IP settings once IP Address, Netmask and Gateway is set - if (!strcmp(new_ipaddr, "") || !strcmp (new_netmask, "") || !strcmp (new_gateway, "")) - { - printf("ERROR: Incomplete LAN Parameters\n"); - } - else - { - - r = sd_bus_call_method(bus, // On the System Bus - app, // Service to contact - obj, // Object path - ifc, // Interface name - "SetAddress4", // Method to be called - &error, // object to return error - &reply, // Response message on success - "ssss", // input message (Interface, IP Address, Netmask, Gateway) - nwinterface, // eth0 - new_ipaddr, - new_netmask, - new_gateway); - if(r < 0) - { - fprintf(stderr, "Failed to set network data %s:%s:%s %s\n", new_ipaddr, new_netmask, new_gateway, error.message); - rc = IPMI_CC_UNSPECIFIED_ERROR; - } - memset(new_ipaddr, 0, INET_ADDRSTRLEN); - memset(new_netmask, 0, INET_ADDRSTRLEN); - memset(new_gateway, 0, INET_ADDRSTRLEN); - } - } - else if(reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress - { - lan_set_in_progress = SET_IN_PROGRESS; - } - } - else - { - fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); - rc = IPMI_CC_PARM_NOT_SUPPORTED; - } - - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - - return rc; -} - -struct get_lan_t { - uint8_t rev_channel; - uint8_t parameter; - uint8_t parameter_set; - uint8_t parameter_block; -} __attribute__ ((packed)); - -ipmi_ret_t ipmi_transport_get_lan(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; - sd_bus *bus = ipmid_get_sd_bus_connection(); - sd_bus_message *reply = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - int r = 0; - const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0 - int i = 0; - - printf("IPMI GET_LAN\n"); - - get_lan_t *reqptr = (get_lan_t*) request; - - if (reqptr->rev_channel & 0x80) // Revision is bit 7 - { - // Only current revision was requested - *data_len = sizeof(current_revision); - memcpy(response, ¤t_revision, *data_len); - return IPMI_CC_OK; - } - - // TODO Use dbus interface once available. For now use ip cmd. - // TODO Add the rest of the parameters, like gateway - - if (reqptr->parameter == LAN_PARM_INPROGRESS) - { - uint8_t buf[] = {current_revision, lan_set_in_progress}; - *data_len = sizeof(buf); - memcpy(response, &buf, *data_len); - } - else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT) - { - uint8_t buf[] = {current_revision,0x04}; - *data_len = sizeof(buf); - memcpy(response, &buf, *data_len); - } - else if (reqptr->parameter == LAN_PARM_AUTHENABLES) - { - uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04}; - *data_len = sizeof(buf); - memcpy(response, &buf, *data_len); - } - else if ((reqptr->parameter == LAN_PARM_IP) || (reqptr->parameter == LAN_PARM_SUBNET) || (reqptr->parameter == LAN_PARM_GATEWAY)) - { - uint8_t buf[5]; - - *data_len = sizeof(current_revision); - memcpy(buf, ¤t_revision, *data_len); - - if(getNetworkData(reqptr->parameter, &buf[1]) == IPMI_CC_OK) - { - *data_len = sizeof(buf); - memcpy(response, &buf, *data_len); - } - else - { - rc = IPMI_CC_UNSPECIFIED_ERROR; - } - } - else if (reqptr->parameter == LAN_PARM_MAC) - { - //string to parse: link/ether xx:xx:xx:xx:xx:xx - uint8_t buf[7]; - char *eaddr1 = NULL; - - r = sd_bus_call_method(bus, app, obj, ifc, "GetHwAddress", &error, - &reply, "s", nwinterface); - if(r < 0) - { - fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto cleanup; - } - - r = sd_bus_message_read(reply, "s", &eaddr1); - if (r < 0) - { - fprintf(stderr, "Failed to get a response: %s", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto cleanup; - } - if (eaddr1 == NULL) - { - fprintf(stderr, "Failed to get a valid response: %s", strerror(-r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto cleanup; - } - - memcpy((void*)&buf[0], ¤t_revision, 1); - - char *tokptr = NULL; - char* digit = strtok_r(eaddr1, ":", &tokptr); - if (digit == NULL) - { - fprintf(stderr, "Unexpected MAC format: %s", eaddr1); - rc = IPMI_CC_RESPONSE_ERROR; - goto cleanup; - } - - i=0; - while (digit != NULL) - { - int resp_byte = strtoul(digit, NULL, 16); - memcpy((void*)&buf[i+1], &resp_byte, 1); - i++; - digit = strtok_r(NULL, ":", &tokptr); - } - - *data_len = sizeof(buf); - memcpy(response, &buf, *data_len); - } - else - { - fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); - rc = IPMI_CC_PARM_NOT_SUPPORTED; - } - -cleanup: - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - - return rc; -} - -void register_netfn_transport_functions() -{ - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_WILDCARD); - ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard); - - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_SET_LAN); - ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan); - - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_GET_LAN); - ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan); - - return; -} diff --git a/transporthandler.cpp b/transporthandler.cpp new file mode 100644 index 0000000..3b4cf07 --- /dev/null +++ b/transporthandler.cpp @@ -0,0 +1,395 @@ +#include +#include +#include +#include +#include + +#include "ipmid-api.h" +#include "ipmid.H" +#include "transporthandler.h" + +#define SYSTEMD_NETWORKD_DBUS 1 + +#ifdef SYSTEMD_NETWORKD_DBUS +#include +#endif + +// OpenBMC System Manager dbus framework +const char *app = "org.openbmc.NetworkManager"; +const char *obj = "/org/openbmc/NetworkManager/Interface"; +const char *ifc = "org.openbmc.NetworkManager"; + +const char *nwinterface = "eth0"; + +const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx + +char new_ipaddr [INET_ADDRSTRLEN] = ""; +char new_netmask [INET_ADDRSTRLEN] = ""; +char new_gateway [INET_ADDRSTRLEN] = ""; + +const uint8_t SET_COMPLETE = 0; +const uint8_t SET_IN_PROGRESS = 1; +const uint8_t SET_COMMIT_WRITE = 2; //Optional +const uint8_t SET_IN_PROGRESS_RESERVED = 3; //Reserved + +// Status of Set-In-Progress Parameter (# 0) +uint8_t lan_set_in_progress = SET_COMPLETE; + + + +void register_netfn_transport_functions() __attribute__((constructor)); + +// Helper Function to get IP Address/NetMask/Gateway from Network Manager or Cache +// based on Set-In-Progress State +ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data) +{ + sd_bus *bus = ipmid_get_sd_bus_connection(); + sd_bus_message *reply = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + int family; + unsigned char prefixlen; + char* ipaddr = NULL; + unsigned long mask = 0xFFFFFFFF; + char* gateway = NULL; + int r = 0; + ipmi_ret_t rc = IPMI_CC_OK; + + r = sd_bus_call_method(bus, app, obj, ifc, "GetAddress4", &error, + &reply, "s", nwinterface); + if(r < 0) + { + fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); + rc = IPMI_CC_UNSPECIFIED_ERROR; + goto cleanup; + } + + r = sd_bus_message_read(reply, "iyss", &family, &prefixlen, &ipaddr, &gateway); + if(r < 0) + { + fprintf(stderr, "Failed to get a response: %s\n", strerror(-rc)); + rc = IPMI_CC_RESPONSE_ERROR; + goto cleanup; + } + + printf("N/W data from HW %s:%d:%s:%s\n", family==AF_INET?"IPv4":"IPv6", prefixlen, ipaddr,gateway); + printf("N/W data from Cache: %s:%s:%s\n", new_ipaddr, new_netmask, new_gateway); + + if(lan_param == LAN_PARM_IP) + { + if(lan_set_in_progress == SET_COMPLETE) + { + std::string ipaddrstr(ipaddr); + inet_pton(AF_INET, ipaddrstr.c_str(),(void *)data); + } + else if(lan_set_in_progress == SET_IN_PROGRESS) + { + inet_pton(AF_INET, new_ipaddr, (void *)data); + } + } + else if(lan_param == LAN_PARM_SUBNET) + { + if(lan_set_in_progress == SET_COMPLETE) + { + mask = htonl(mask<<(32-prefixlen)); + memcpy(data, &mask, 4); + } + else if(lan_set_in_progress == SET_IN_PROGRESS) + { + inet_pton(AF_INET, new_netmask, (void *)data); + } + } + else if(lan_param == LAN_PARM_GATEWAY) + { + if(lan_set_in_progress == SET_COMPLETE) + { + std::string gatewaystr(gateway); + inet_pton(AF_INET, gatewaystr.c_str(), (void *)data); + } + else if(lan_set_in_progress == SET_IN_PROGRESS) + { + inet_pton(AF_INET, new_gateway,(void *)data); + } + } + else + { + rc = IPMI_CC_PARM_OUT_OF_RANGE; + } + +cleanup: + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + + return rc; +} + +ipmi_ret_t ipmi_transport_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 TRANSPORT WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd); + // Status code. + ipmi_ret_t rc = IPMI_CC_OK; + *data_len = 0; + return rc; +} + +struct set_lan_t { + uint8_t channel; + uint8_t parameter; + uint8_t data[8]; // Per IPMI spec, not expecting more than this size +} __attribute__ ((packed)); + +ipmi_ret_t ipmi_transport_set_lan(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; + sd_bus *bus = ipmid_get_sd_bus_connection(); + sd_bus_message *reply = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + int r = 0; + + printf("IPMI SET_LAN\n"); + + set_lan_t *reqptr = (set_lan_t*) request; + + // TODO Use dbus interface once available. For now use cmd line. + // TODO Add the rest of the parameters like setting auth type + // TODO Add error handling + + if (reqptr->parameter == LAN_PARM_IP) + { + snprintf(new_ipaddr, INET_ADDRSTRLEN, "%d.%d.%d.%d", + reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); + } + else if (reqptr->parameter == LAN_PARM_MAC) + { + char mac[SIZE_MAC]; + + snprintf(mac, SIZE_MAC, "%02x:%02x:%02x:%02x:%02x:%02x", + reqptr->data[0], + reqptr->data[1], + reqptr->data[2], + reqptr->data[3], + reqptr->data[4], + reqptr->data[5]); + + r = sd_bus_call_method(bus, app, obj, ifc, "SetHwAddress", &error, + &reply, "ss", nwinterface, mac); + if(r < 0) + { + fprintf(stderr, "Failed to call the method: %s\n", strerror(-r)); + rc = IPMI_CC_UNSPECIFIED_ERROR; + } + } + else if (reqptr->parameter == LAN_PARM_SUBNET) + { + snprintf(new_netmask, INET_ADDRSTRLEN, "%d.%d.%d.%d", + reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); + } + else if (reqptr->parameter == LAN_PARM_GATEWAY) + { + snprintf(new_gateway, INET_ADDRSTRLEN, "%d.%d.%d.%d", + reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); + } + else if (reqptr->parameter == LAN_PARM_INPROGRESS) + { + if(reqptr->data[0] == SET_COMPLETE) // Set Complete + { + lan_set_in_progress = SET_COMPLETE; + // Apply the IP settings once IP Address, Netmask and Gateway is set + if (!strcmp(new_ipaddr, "") || !strcmp (new_netmask, "") || !strcmp (new_gateway, "")) + { + printf("ERROR: Incomplete LAN Parameters\n"); + } + else + { + + r = sd_bus_call_method(bus, // On the System Bus + app, // Service to contact + obj, // Object path + ifc, // Interface name + "SetAddress4", // Method to be called + &error, // object to return error + &reply, // Response message on success + "ssss", // input message (Interface, IP Address, Netmask, Gateway) + nwinterface, // eth0 + new_ipaddr, + new_netmask, + new_gateway); + if(r < 0) + { + fprintf(stderr, "Failed to set network data %s:%s:%s %s\n", new_ipaddr, new_netmask, new_gateway, error.message); + rc = IPMI_CC_UNSPECIFIED_ERROR; + } + memset(new_ipaddr, 0, INET_ADDRSTRLEN); + memset(new_netmask, 0, INET_ADDRSTRLEN); + memset(new_gateway, 0, INET_ADDRSTRLEN); + } + } + else if(reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress + { + lan_set_in_progress = SET_IN_PROGRESS; + } + } + else + { + fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); + rc = IPMI_CC_PARM_NOT_SUPPORTED; + } + + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + + return rc; +} + +struct get_lan_t { + uint8_t rev_channel; + uint8_t parameter; + uint8_t parameter_set; + uint8_t parameter_block; +} __attribute__ ((packed)); + +ipmi_ret_t ipmi_transport_get_lan(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; + sd_bus *bus = ipmid_get_sd_bus_connection(); + sd_bus_message *reply = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + int r = 0; + const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0 + int i = 0; + + printf("IPMI GET_LAN\n"); + + get_lan_t *reqptr = (get_lan_t*) request; + + if (reqptr->rev_channel & 0x80) // Revision is bit 7 + { + // Only current revision was requested + *data_len = sizeof(current_revision); + memcpy(response, ¤t_revision, *data_len); + return IPMI_CC_OK; + } + + // TODO Use dbus interface once available. For now use ip cmd. + // TODO Add the rest of the parameters, like gateway + + if (reqptr->parameter == LAN_PARM_INPROGRESS) + { + uint8_t buf[] = {current_revision, lan_set_in_progress}; + *data_len = sizeof(buf); + memcpy(response, &buf, *data_len); + } + else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT) + { + uint8_t buf[] = {current_revision,0x04}; + *data_len = sizeof(buf); + memcpy(response, &buf, *data_len); + } + else if (reqptr->parameter == LAN_PARM_AUTHENABLES) + { + uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04}; + *data_len = sizeof(buf); + memcpy(response, &buf, *data_len); + } + else if ((reqptr->parameter == LAN_PARM_IP) || (reqptr->parameter == LAN_PARM_SUBNET) || (reqptr->parameter == LAN_PARM_GATEWAY)) + { + uint8_t buf[5]; + + *data_len = sizeof(current_revision); + memcpy(buf, ¤t_revision, *data_len); + + if(getNetworkData(reqptr->parameter, &buf[1]) == IPMI_CC_OK) + { + *data_len = sizeof(buf); + memcpy(response, &buf, *data_len); + } + else + { + rc = IPMI_CC_UNSPECIFIED_ERROR; + } + } + else if (reqptr->parameter == LAN_PARM_MAC) + { + //string to parse: link/ether xx:xx:xx:xx:xx:xx + uint8_t buf[7]; + char *eaddr1 = NULL; + + r = sd_bus_call_method(bus, app, obj, ifc, "GetHwAddress", &error, + &reply, "s", nwinterface); + if(r < 0) + { + fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); + rc = IPMI_CC_UNSPECIFIED_ERROR; + goto cleanup; + } + + r = sd_bus_message_read(reply, "s", &eaddr1); + if (r < 0) + { + fprintf(stderr, "Failed to get a response: %s", strerror(-r)); + rc = IPMI_CC_UNSPECIFIED_ERROR; + goto cleanup; + } + if (eaddr1 == NULL) + { + fprintf(stderr, "Failed to get a valid response: %s", strerror(-r)); + rc = IPMI_CC_UNSPECIFIED_ERROR; + goto cleanup; + } + + memcpy((void*)&buf[0], ¤t_revision, 1); + + char *tokptr = NULL; + char* digit = strtok_r(eaddr1, ":", &tokptr); + if (digit == NULL) + { + fprintf(stderr, "Unexpected MAC format: %s", eaddr1); + rc = IPMI_CC_RESPONSE_ERROR; + goto cleanup; + } + + i=0; + while (digit != NULL) + { + int resp_byte = strtoul(digit, NULL, 16); + memcpy((void*)&buf[i+1], &resp_byte, 1); + i++; + digit = strtok_r(NULL, ":", &tokptr); + } + + *data_len = sizeof(buf); + memcpy(response, &buf, *data_len); + } + else + { + fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); + rc = IPMI_CC_PARM_NOT_SUPPORTED; + } + +cleanup: + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + + return rc; +} + +void register_netfn_transport_functions() +{ + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_WILDCARD); + ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard); + + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_SET_LAN); + ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan); + + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_GET_LAN); + ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan); + + return; +} -- cgit v1.2.1