blob: 178248380f9b9e48b2cf68c0868e7cfe458db808 [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 {
Michael Tritz6d2f6c32017-02-02 17:03:18 -060080 printf("Host Checkstop, going to quiesce\n");
Adriana Kobylak25009cf2016-06-16 08:39:24 -050081 error = NULL;
82 proxy = g_dbus_proxy_new_sync((GDBusConnection*)connection,
83 G_DBUS_PROXY_FLAGS_NONE,
84 NULL, /* GDBusInterfaceInfo* */
Michael Tritz6d2f6c32017-02-02 17:03:18 -060085 "org.freedesktop.systemd1", /* name */
86 "/org/freedesktop/systemd1", /* object path */
87 "org.freedesktop.systemd1.Manager", /* interface name */
Adriana Kobylak25009cf2016-06-16 08:39:24 -050088 NULL, /* GCancellable */
89 &error);
90 g_assert_no_error(error);
91
92 error = NULL;
93 result = g_dbus_proxy_call_sync(proxy,
Michael Tritz6d2f6c32017-02-02 17:03:18 -060094 "StartUnit",
95 g_variant_new("(ss)", "obmc-quiesce-host@0.target", "replace"),
Adriana Kobylak25009cf2016-06-16 08:39:24 -050096 G_DBUS_CALL_FLAGS_NONE,
97 -1,
98 NULL,
99 &error);
100 g_assert_no_error(error);
Michael Tritz6d2f6c32017-02-02 17:03:18 -0600101 g_variant_unref(result);
Adriana Kobylak25009cf2016-06-16 08:39:24 -0500102 }
103
104 return FALSE;
105}
106
107static gboolean
108on_checkstop_interrupt(GIOChannel *channel,
109 GIOCondition condition,
110 gpointer connection)
111{
112 GError *error = 0;
113 gsize bytes_read = 0;
114 gchar buf[2];
115 buf[1] = '\0';
116
117 g_io_channel_seek_position( channel, 0, G_SEEK_SET, 0 );
118 g_io_channel_read_chars(channel,
119 buf, 1,
120 &bytes_read,
121 &error );
122 printf("checkstop gpio: %s\n",buf);
123
124 if(checkstop.irq_inited) {
125 // Need to wait at least 10s for the SBE to gather failure data.
126 // Also the user may be monitoring the system and reset the system
127 // themselves. So wait an arbitrary time of 30s (and check that the
128 // gpio value is still 0) before issuing reboot.
129 g_timeout_add(30000, chassis_reboot, connection);
130 }
131 else {
132 checkstop.irq_inited = true;
133 }
134
135 return TRUE;
136}
137
138static void
139on_bus_acquired(GDBusConnection *connection,
140 const gchar *name,
141 gpointer object)
142{
143 int rc = GPIO_OK;
144 manager = g_dbus_object_manager_server_new(dbus_object_path);
145
146 ControlCheckstop* control_checkstop = control_checkstop_skeleton_new();
147 object_skeleton_set_control_checkstop(object, control_checkstop);
148 g_object_unref(control_checkstop);
149
150 g_dbus_object_manager_server_set_connection(manager, connection);
151
152 rc = gpio_init(connection, &checkstop);
153 if (rc == GPIO_OK) {
154 rc = gpio_open_interrupt(&checkstop, on_checkstop_interrupt, connection);
155 }
156 if (rc != GPIO_OK) {
157 printf("ERROR Checkstop: GPIO setup (rc=%d)\n", rc);
158 }
Brad Bishopf81b6a42016-06-29 23:23:31 -0400159 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
Adriana Kobylak25009cf2016-06-16 08:39:24 -0500160}
161
162static void
163on_name_acquired(GDBusConnection *connection,
164 const gchar *name,
165 gpointer object)
166{
Adriana Kobylak25009cf2016-06-16 08:39:24 -0500167}
168
169static void
170on_name_lost(GDBusConnection *connection,
171 const gchar *name,
172 gpointer object)
173{
Adriana Kobylak25009cf2016-06-16 08:39:24 -0500174}
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}