blob: 89f0b6cf89409d3a4721724cc988b3c3f7eed4bf [file] [log] [blame]
vishwa36993272015-11-20 12:43:49 -06001#include <stdio.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <systemd/sd-bus.h>
5
6// OpenBMC Host IPMI dbus framework
7const char *bus_name = "org.openbmc.HostIpmi";
8const char *object_name = "/org/openbmc/HostIpmi/1";
9const char *intf_name = "org.openbmc.HostIpmi";
10
11//-------------------------------------------------------------------
12// Gets called by PowerOff handler when a Soft Power off is requested
13//-------------------------------------------------------------------
14static int soft_power_off(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
15{
16 int64_t bt_resp = -1;
17 int rc = 0;
18
19 // Steps to be taken when we get this.
20 // 1: Send a SMS_ATN to the Host
21 // 2: Host receives it and sends a GetMsgFlags IPMI command
22 // 3: IPMID app handler will respond to that with a MSgFlag with bit:0x2
23 // set indicating we have a message for Host
24 // 4: Host sends a GetMsgBuffer command and app handler will respond to
25 // that with a OEM-SEL with certain fields packed indicating to the
26 // host that it do a shutdown of the partitions.
27 // 5: Host does the partition shutdown and calls Chassis Power off command
28 // 6: App handler handles the command by making a call to ChassisManager
29 // Dbus
30
31 // Now the job is to send the SMS_ATTN.
32
33 // Req message contains the specifics about which method etc that we want to
34 // access on which bus, object
35 sd_bus_message *response = NULL;
36
37 // Error return mechanism
38 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
39
40 // Gets a hook onto either a SYSTEM or SESSION bus
41 sd_bus *bus = (sd_bus *)ipmid_get_sd_bus_connection();
42
43 rc = sd_bus_call_method(bus, // On the System Bus
44 bus_name, // Service to contact
45 object_name, // Object path
46 intf_name, // Interface name
47 "setAttention", // Method to be called
48 &bus_error, // object to return error
49 &response, // Response buffer if any
50 NULL); // No input arguments
51 if(rc < 0)
52 {
53 fprintf(stderr,"ERROR initiating Power Off:[%s]\n",bus_error.message);
54 goto finish;
55 }
56
57 // See if we were able to successfully raise SMS_ATN
58 rc = sd_bus_message_read(response, "x", &bt_resp);
59 if (rc < 0)
60 {
61 fprintf(stderr, "Failed to get a rc from BT for SMS_ATN: %s\n", strerror(-rc));
62 goto finish;
63 }
64
65finish:
66 sd_bus_error_free(&bus_error);
67 sd_bus_message_unref(response);
68
69 if(rc < 0)
70 {
71 return sd_bus_reply_method_return(m, "x", rc);
72 }
73 else
74 {
75 return sd_bus_reply_method_return(m, "x", bt_resp);
76 }
77}
78
79//-------------------------------------------
80// Function pointer of APIs exposed via Dbus
81//-------------------------------------------
82static const sd_bus_vtable host_services_vtable[] =
83{
84 SD_BUS_VTABLE_START(0),
85 // Takes No("") arguments -but- returns a value of type 64 bit integer("x")
86 SD_BUS_METHOD("SoftPowerOff", "", "x", &soft_power_off, SD_BUS_VTABLE_UNPRIVILEGED),
87 SD_BUS_VTABLE_END,
88};
89
90//------------------------------------------------------
91// Called by IPMID as part of the start up
92// -----------------------------------------------------
93int start_host_service(sd_bus *bus, sd_bus_slot *slot)
94{
95 int rc = 0;
96
97 /* Install the object */
98 rc = sd_bus_add_object_vtable(bus,
99 &slot,
100 "/org/openbmc/HostServices", /* object path */
101 "org.openbmc.HostServices", /* interface name */
102 host_services_vtable,
103 NULL);
104 if (rc < 0)
105 {
106 fprintf(stderr, "Failed to issue method call: %s\n", strerror(-rc));
107 }
108 else
109 {
110 /* Take one in OpenBmc */
111 rc = sd_bus_request_name(bus, "org.openbmc.HostServices", 0);
112 if (rc < 0)
113 {
114 fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-rc));
115 }
116 }
117
118 return rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
119}