summaryrefslogtreecommitdiffstats
path: root/host-services.c
blob: 89f0b6cf89409d3a4721724cc988b3c3f7eed4bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <systemd/sd-bus.h>

// OpenBMC Host IPMI dbus framework
const char  *bus_name      =  "org.openbmc.HostIpmi";
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;

	// 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 = (sd_bus *)ipmid_get_sd_bus_connection();

	rc = sd_bus_call_method(bus,        // On 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);
    sd_bus_message_unref(response);

	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;
}
OpenPOWER on IntegriCloud