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