blob: 74c940e37efbabd2640c47d772aac156791b0781 [file] [log] [blame]
Brad Bishopf6c85682016-06-27 11:56:39 -04001#include <openbmc_intf.h>
2#include <openbmc.h>
3#include <gpio.h>
Adriana Kobylak25009cf2016-06-16 08:39:24 -05004
5static const gchar* dbus_object_path = "/org/openbmc/control";
6static const gchar* object_name = "/org/openbmc/control/checkstop0";
7static const gchar* dbus_name = "org.openbmc.control.Checkstop";
8
9static GDBusObjectManagerServer *manager = NULL;
10
11GPIO checkstop = (GPIO){ "CHECKSTOP" };
12
13static bool
14is_host_booted(GDBusConnection* connection)
15{
16 GDBusProxy *proxy;
17 GError *error;
18 GVariant *parm = NULL;
19 GVariant *result = NULL;
20
21 error = NULL;
22 proxy = g_dbus_proxy_new_sync(connection,
23 G_DBUS_PROXY_FLAGS_NONE,
24 NULL, /* GDBusInterfaceInfo* */
25 "org.openbmc.managers.System", /* name */
26 "/org/openbmc/managers/System", /* object path */
27 "org.openbmc.managers.System", /* interface name */
28 NULL, /* GCancellable */
29 &error);
30 g_assert_no_error(error);
31
32 error = NULL;
33 result = g_dbus_proxy_call_sync(proxy,
34 "getSystemState",
35 parm,
36 G_DBUS_CALL_FLAGS_NONE,
37 -1,
38 NULL,
39 &error);
40 g_assert_no_error(error);
41
42 gchar *system_state;
43 g_variant_get(result,"(s)",&system_state);
44 g_variant_unref(result);
45
46 if ((strcmp(system_state, "HOST_BOOTED") == 0) ||
47 (strcmp(system_state, "HOST_BOOTING")== 0)) {
48 return true;
49 }
50
51 return false;
52}
53
54static gboolean
55chassis_reboot(gpointer connection)
56{
57 int rc = 0;
58 uint8_t gpio = 0;
59 GDBusProxy *proxy;
60 GError *error;
61 GVariant *parm = NULL;
62 GVariant *result = NULL;
63
64 // The gpio line may flicker during power on/off, so check that the value
65 // is still 0 (checkstopped) and that host is booted in order to reboot
66 rc = gpio_open(&checkstop);
67 if (rc != GPIO_OK) {
68 return FALSE;
69 }
70 rc = gpio_read(&checkstop, &gpio);
71 if (rc != GPIO_OK) {
72 gpio_close(&checkstop);
73 return FALSE;
74 }
75 gpio_close(&checkstop);
76 if ((!gpio) && (is_host_booted(connection)))
77 {
78 printf("Host Checkstop, rebooting host\n");
79 error = NULL;
80 proxy = g_dbus_proxy_new_sync((GDBusConnection*)connection,
81 G_DBUS_PROXY_FLAGS_NONE,
82 NULL, /* GDBusInterfaceInfo* */
83 "org.openbmc.control.Chassis", /* name */
84 "/org/openbmc/control/chassis0", /* object path */
85 "org.openbmc.control.Chassis", /* interface name */
86 NULL, /* GCancellable */
87 &error);
88 g_assert_no_error(error);
89
90 error = NULL;
91 result = g_dbus_proxy_call_sync(proxy,
92 "reboot",
93 parm,
94 G_DBUS_CALL_FLAGS_NONE,
95 -1,
96 NULL,
97 &error);
98 g_assert_no_error(error);
99 }
100
101 return FALSE;
102}
103
104static gboolean
105on_checkstop_interrupt(GIOChannel *channel,
106 GIOCondition condition,
107 gpointer connection)
108{
109 GError *error = 0;
110 gsize bytes_read = 0;
111 gchar buf[2];
112 buf[1] = '\0';
113
114 g_io_channel_seek_position( channel, 0, G_SEEK_SET, 0 );
115 g_io_channel_read_chars(channel,
116 buf, 1,
117 &bytes_read,
118 &error );
119 printf("checkstop gpio: %s\n",buf);
120
121 if(checkstop.irq_inited) {
122 // Need to wait at least 10s for the SBE to gather failure data.
123 // Also the user may be monitoring the system and reset the system
124 // themselves. So wait an arbitrary time of 30s (and check that the
125 // gpio value is still 0) before issuing reboot.
126 g_timeout_add(30000, chassis_reboot, connection);
127 }
128 else {
129 checkstop.irq_inited = true;
130 }
131
132 return TRUE;
133}
134
135static void
136on_bus_acquired(GDBusConnection *connection,
137 const gchar *name,
138 gpointer object)
139{
140 int rc = GPIO_OK;
141 manager = g_dbus_object_manager_server_new(dbus_object_path);
142
143 ControlCheckstop* control_checkstop = control_checkstop_skeleton_new();
144 object_skeleton_set_control_checkstop(object, control_checkstop);
145 g_object_unref(control_checkstop);
146
147 g_dbus_object_manager_server_set_connection(manager, connection);
148
149 rc = gpio_init(connection, &checkstop);
150 if (rc == GPIO_OK) {
151 rc = gpio_open_interrupt(&checkstop, on_checkstop_interrupt, connection);
152 }
153 if (rc != GPIO_OK) {
154 printf("ERROR Checkstop: GPIO setup (rc=%d)\n", rc);
155 }
156}
157
158static void
159on_name_acquired(GDBusConnection *connection,
160 const gchar *name,
161 gpointer object)
162{
163 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
164}
165
166static void
167on_name_lost(GDBusConnection *connection,
168 const gchar *name,
169 gpointer object)
170{
171 g_dbus_object_manager_server_unexport(manager, dbus_object_path);
172}
173
174gint
175main(gint argc, gchar *argv[])
176{
177 GMainLoop *loop;
178 ObjectSkeleton *newobject;
179
180 newobject = object_skeleton_new(object_name);
181
182 guint id;
183 loop = g_main_loop_new(NULL, FALSE);
184
185 id = g_bus_own_name(DBUS_TYPE,
186 dbus_name,
187 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
188 G_BUS_NAME_OWNER_FLAGS_REPLACE,
189 on_bus_acquired,
190 on_name_acquired,
191 on_name_lost,
192 newobject,
193 NULL);
194
195 g_main_loop_run(loop);
196
197 g_bus_unown_name(id);
198 g_object_unref(newobject);
199 g_main_loop_unref(loop);
200 return 0;
201}
202