blob: 587896a2940e3937338d651da70d1d60c8ae05c1 [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 }
Brad Bishopf81b6a42016-06-29 23:23:31 -0400158 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
Adriana Kobylak25009cf2016-06-16 08:39:24 -0500159}
160
161static void
162on_name_acquired(GDBusConnection *connection,
163 const gchar *name,
164 gpointer object)
165{
Adriana Kobylak25009cf2016-06-16 08:39:24 -0500166}
167
168static void
169on_name_lost(GDBusConnection *connection,
170 const gchar *name,
171 gpointer object)
172{
Adriana Kobylak25009cf2016-06-16 08:39:24 -0500173}
174
175gint
176main(gint argc, gchar *argv[])
177{
178 GMainLoop *loop;
179 ObjectSkeleton *newobject;
180
181 newobject = object_skeleton_new(object_name);
182
183 guint id;
184 loop = g_main_loop_new(NULL, FALSE);
185
186 id = g_bus_own_name(DBUS_TYPE,
187 dbus_name,
188 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
189 G_BUS_NAME_OWNER_FLAGS_REPLACE,
190 on_bus_acquired,
191 on_name_acquired,
192 on_name_lost,
193 newobject,
194 NULL);
195
196 g_main_loop_run(loop);
197
198 g_bus_unown_name(id);
199 g_object_unref(newobject);
200 g_main_loop_unref(loop);
201 return 0;
202}
203