summaryrefslogtreecommitdiffstats
path: root/host-services.c
diff options
context:
space:
mode:
Diffstat (limited to 'host-services.c')
-rw-r--r--host-services.c144
1 files changed, 144 insertions, 0 deletions
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);
+}
OpenPOWER on IntegriCloud