diff options
-rw-r--r-- | Makefile.am | 13 | ||||
-rw-r--r-- | host-interface.cpp | 9 | ||||
-rw-r--r-- | host-interface.hpp | 34 | ||||
-rw-r--r-- | host-services.c | 144 | ||||
-rw-r--r-- | host-services.h | 3 |
5 files changed, 203 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 5cc9059..409cd3f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,6 +47,19 @@ libsysintfcmds_la_SOURCES = \ libsysintfcmds_la_LDFLAGS = $(SYSTEMD_LIBS) $(libmapper_LIBS) -version-info 0:0:0 -shared libsysintfcmds_la_CXXFLAGS = $(SYSTEMD_CFLAGS) $(libmapper_CFLAGS) +libhostservicedir = ${libdir}/ipmid-providers +libhostservice_LTLIBRARIES = libhostservice.la +libhostservice_la_SOURCES = \ + host-services.c \ + host-interface.cpp +libhostservice_la_LDFLAGS = $(SYSTEMD_LIBS) \ + $(libmapper_LIBS) \ + $(PHOSPHOR_DBUS_INTERFACES_LIBS) \ + -version-info 0:0:0 -shared +libhostservice_la_CXXFLAGS = $(SYSTEMD_CFLAGS) \ + $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \ + $(libmapper_CFLAGS) + nobase_include_HEADERS = \ host-ipmid/ipmid-api.h diff --git a/host-interface.cpp b/host-interface.cpp new file mode 100644 index 0000000..010eef1 --- /dev/null +++ b/host-interface.cpp @@ -0,0 +1,9 @@ +#include "host-interface.hpp" + +namespace phosphor +{ +namespace host +{ + +} // namespace host +} // namepsace phosphor diff --git a/host-interface.hpp b/host-interface.hpp new file mode 100644 index 0000000..793a5cb --- /dev/null +++ b/host-interface.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include <sdbusplus/bus.hpp> +#include <xyz/openbmc_project/Control/Host/server.hpp> + +namespace phosphor +{ +namespace host +{ + +/** @class Host + * @brief OpenBMC control host interface implementation. + * @details A concrete implementation for xyz.openbmc_project.Control.Host + * DBus API. + */ +class Host : public sdbusplus::server::object::object< + sdbusplus::xyz::openbmc_project::Control::server::Host> +{ + public: + /** @brief Constructs Host Control Interface + * + * @param[in] bus - The Dbus bus object + * @param[in] objPath - The Dbus object path + */ + Host(sdbusplus::bus::bus& bus, + const char* objPath) : + sdbusplus::server::object::object< + sdbusplus::xyz::openbmc_project::Control::server::Host>( + bus, objPath) + {} +}; + +} // namespace host +} // namespace phosphor diff --git a/host-services.c b/host-services.c new file mode 100644 index 0000000..b0b12ae --- /dev/null +++ b/host-services.c @@ -0,0 +1,144 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <systemd/sd-bus.h> +#include <mapper.h> +#include "host-ipmid/ipmid-api.h" + +void register_host_services() __attribute__((constructor)); + +// OpenBMC Host IPMI dbus framework +const char *object_name = "/org/openbmc/HostIpmi/1"; +const char *intf_name = "org.openbmc.HostIpmi"; + +//------------------------------------------------------------------- +// Gets called by PowerOff handler when a Soft Power off is requested +//------------------------------------------------------------------- +static int soft_power_off(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) +{ + int64_t bt_resp = -1; + int rc = 0; + char *bus_name = NULL; + + // Steps to be taken when we get this. + // 1: Send a SMS_ATN to the Host + // 2: Host receives it and sends a GetMsgFlags IPMI command + // 3: IPMID app handler will respond to that with a MSgFlag with bit:0x2 + // set indicating we have a message for Host + // 4: Host sends a GetMsgBuffer command and app handler will respond to + // that with a OEM-SEL with certain fields packed indicating to the + // host that it do a shutdown of the partitions. + // 5: Host does the partition shutdown and calls Chassis Power off command + // 6: App handler handles the command by making a call to ChassisManager + // Dbus + + // Now the job is to send the SMS_ATTN. + + // Req message contains the specifics about which method etc that we want to + // access on which bus, object + sd_bus_message *response = NULL; + + // Error return mechanism + sd_bus_error bus_error = SD_BUS_ERROR_NULL; + + // Gets a hook onto either a SYSTEM or SESSION bus + sd_bus *bus = ipmid_get_sd_bus_connection(); + rc = mapper_get_service(bus, object_name, &bus_name); + if (rc < 0) { + fprintf(stderr, "Failed to get %s bus name: %s\n", + object_name, strerror(-rc)); + goto finish; + } + rc = sd_bus_call_method(bus, // In the System Bus + bus_name, // Service to contact + object_name, // Object path + intf_name, // Interface name + "setAttention", // 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); + goto finish; + } + + // See if we were able to successfully raise SMS_ATN + rc = sd_bus_message_read(response, "x", &bt_resp); + if (rc < 0) + { + fprintf(stderr, "Failed to get a rc from BT for SMS_ATN: %s\n", strerror(-rc)); + goto finish; + } + +finish: + sd_bus_error_free(&bus_error); + response = sd_bus_message_unref(response); + free(bus_name); + + if(rc < 0) + { + return sd_bus_reply_method_return(m, "x", rc); + } + else + { + return sd_bus_reply_method_return(m, "x", bt_resp); + } +} + +//------------------------------------------- +// Function pointer of APIs exposed via Dbus +//------------------------------------------- +static const sd_bus_vtable host_services_vtable[] = +{ + SD_BUS_VTABLE_START(0), + // Takes No("") arguments -but- returns a value of type 64 bit integer("x") + SD_BUS_METHOD("SoftPowerOff", "", "x", &soft_power_off, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END, +}; + +//------------------------------------------------------ +// Called by IPMID as part of the start up +// ----------------------------------------------------- +int start_host_service(sd_bus *bus, sd_bus_slot *slot) +{ + int rc = 0; + + /* Install the object */ + rc = sd_bus_add_object_vtable(bus, + &slot, + "/org/openbmc/HostServices", /* object path */ + "org.openbmc.HostServices", /* interface name */ + host_services_vtable, + NULL); + if (rc < 0) + { + fprintf(stderr, "Failed to issue method call: %s\n", strerror(-rc)); + } + else + { + /* Take one in OpenBmc */ + rc = sd_bus_request_name(bus, "org.openbmc.HostServices", 0); + if (rc < 0) + { + fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-rc)); + } + } + + return rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} + +//------------------------------------------------------ +// Callback register function +// ----------------------------------------------------- +void register_host_services() +{ + // Gets a hook onto SYSTEM bus used by host-ipmid + sd_bus *bus = ipmid_get_sd_bus_connection(); + + // Gets a hook onto SYSTEM bus slot used by host-ipmid + sd_bus_slot *ipmid_slot = ipmid_get_sd_bus_slot(); + + //start_host_service(bus, ipmid_slot); + start_host_service(bus, ipmid_slot); +} diff --git a/host-services.h b/host-services.h new file mode 100644 index 0000000..0d93480 --- /dev/null +++ b/host-services.h @@ -0,0 +1,3 @@ +#include <systemd/sd-bus.h> + +extern "C" int start_host_service(sd_bus *, sd_bus_slot *); |