blob: e22d73686c9e3b090f0bc39b3cd3082754469b7a [file] [log] [blame]
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +09301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
3#include <assert.h>
4#include <errno.h>
Andrew Jeffery5320f6e2019-03-15 12:40:41 +10305#include <stdlib.h>
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +09306#include <systemd/sd-bus.h>
7
8#include "common.h"
9#include "dbus.h"
10#include "control_dbus.h"
Andrew Jeffery26558db2018-08-10 00:22:38 +093011#include "mboxd.h"
Andrew Jeffery5320f6e2019-03-15 12:40:41 +103012#include "vpnor/mboxd_pnor_partition_table.h"
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +093013
14typedef int (*control_action)(struct mbox_context *context);
15
16static int control_dbus_directive(sd_bus_message *m, void *userdata,
17 sd_bus_error *ret_error,
18 control_action action)
19{
20 struct mbox_context *context;
21 sd_bus_message *n;
22 int rc;
23
24 if (!action) {
25 MSG_ERR("No action provided\n");
26 return -EINVAL;
27 }
28
29 context = (struct mbox_context *) userdata;
30 if (!context) {
31 MSG_ERR("DBUS Internal Error\n");
32 return -EINVAL;
33 }
34
35 rc = action(context);
36 if (rc < 0) {
37 MSG_ERR("Action failed: %d\n", rc);
38 return rc;
39 }
40
41 rc = sd_bus_message_new_method_return(m, &n);
42 if (rc < 0) {
43 MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
44 return rc;
45 }
46
47 return sd_bus_send(NULL, n, NULL);
48}
49
50static int control_dbus_ping(sd_bus_message *m, void *userdata,
51 sd_bus_error *ret_error)
52{
53 return control_dbus_directive(m, userdata, ret_error, control_ping);
54}
55
56static int control_dbus_reset(sd_bus_message *m, void *userdata,
57 sd_bus_error *ret_error)
58{
59 return control_dbus_directive(m, userdata, ret_error, control_reset);
60}
61
62static int control_dbus_kill(sd_bus_message *m, void *userdata,
63 sd_bus_error *ret_error)
64{
65 return control_dbus_directive(m, userdata, ret_error, control_kill);
66}
67
68static int control_dbus_modified(sd_bus_message *m, void *userdata,
69 sd_bus_error *ret_error)
70{
71 return control_dbus_directive(m, userdata, ret_error, control_modified);
72}
73
74static int control_dbus_suspend(sd_bus_message *m, void *userdata,
75 sd_bus_error *ret_error)
76{
77 return control_dbus_directive(m, userdata, ret_error, control_suspend);
78}
79
80static int control_dbus_resume(sd_bus_message *m, void *userdata,
81 sd_bus_error *ret_error)
82{
83 struct mbox_context *context;
84 sd_bus_message *n;
85 bool modified;
86 int rc;
87
88 context = (struct mbox_context *) userdata;
89 if (!context) {
90 MSG_ERR("DBUS Internal Error\n");
91 return -EINVAL;
92 }
93
94 rc = sd_bus_message_read_basic(m, 'b', &modified);
95 if (rc < 0) {
96 MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
97 return rc;
98 }
99
100 rc = control_resume(context, modified);
101 if (rc < 0)
102 return rc;
103
104 rc = sd_bus_message_new_method_return(m, &n);
105 if (rc < 0) {
106 MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
107 return rc;
108 }
109
110 return sd_bus_send(NULL, n, NULL);
111}
112
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030113static int control_dbus_set_backend(sd_bus_message *m, void *userdata,
114 sd_bus_error *ret_error)
115{
116 struct mbox_context *context;
117 struct backend backend;
118 sd_bus_message *n;
119 const char *name;
120 int rc;
121
122 context = (struct mbox_context *) userdata;
123 if (!context) {
124 MSG_ERR("DBUS Internal Error\n");
125 return -EINVAL;
126 }
127
128 rc = sd_bus_message_read_basic(m, 's', &name);
129 if (rc < 0) {
130 MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
131 return rc;
132 }
133
134 if (!strcmp(name, "vpnor")) {
135 struct vpnor_partition_paths paths;
136
137 vpnor_default_paths(&paths);
138 backend = backend_get_vpnor();
139 rc = control_set_backend(context, &backend, &paths);
140 if (rc < 0)
141 return rc;
142 } else if (!strcmp(name, "mtd")) {
143 char **paths = NULL;
144 char *path = NULL;
145
146 rc = sd_bus_message_read_strv(m, &paths);
147 if (rc < 0)
148 return rc;
149
150 if (paths && *paths)
151 path = *paths;
152 else
153 path = get_dev_mtd();
154
155 backend = backend_get_mtd();
156
157 rc = control_set_backend(context, &backend, path);
158 if (rc < 0)
159 return rc;
160
161 free(path);
162 free(paths);
163 } else if (!strcmp(name, "file")) {
164 char **paths = NULL;
165 char *path = NULL;
166
167 rc = sd_bus_message_read_strv(m, &paths);
168 if (rc < 0)
169 return rc;
170
171 if (!(paths && *paths))
172 return -EINVAL;
173
174 path = *paths;
175
176 backend = backend_get_file();
177
178 rc = control_set_backend(context, &backend, path);
179 if (rc < 0)
180 return rc;
181
182 free(path);
183 free(paths);
184 } else {
185 return -EINVAL;
186 }
187
188 rc = sd_bus_message_new_method_return(m, &n);
189 if (rc < 0) {
190 MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
191 return rc;
192 }
193
194 return sd_bus_send(NULL, n, NULL);
195}
196
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +0930197static int control_dbus_get_u8(sd_bus *bus, const char *path,
198 const char *interface, const char *property,
199 sd_bus_message *reply, void *userdata,
200 sd_bus_error *ret_error)
201{
202 struct mbox_context *context = userdata;
203 uint8_t value;
204
205 assert(!strcmp(MBOX_DBUS_OBJECT, path));
206
207 if (!strcmp("DaemonState", property)) {
208 value = control_daemon_state(context);
209 } else if (!strcmp("LpcState", property)) {
210 value = control_lpc_state(context);
211 } else {
212 MSG_ERR("Unknown DBus property: %s\n", property);
213 return -EINVAL;
214 }
215
216 return sd_bus_message_append(reply, "y", value);
217}
218
219static const sd_bus_vtable mboxd_vtable[] = {
220 SD_BUS_VTABLE_START(0),
221 SD_BUS_METHOD("Ping", NULL, NULL, &control_dbus_ping,
222 SD_BUS_VTABLE_UNPRIVILEGED),
223 SD_BUS_METHOD("Reset", NULL, NULL, &control_dbus_reset,
224 SD_BUS_VTABLE_UNPRIVILEGED),
225 SD_BUS_METHOD("Kill", NULL, NULL, &control_dbus_kill,
226 SD_BUS_VTABLE_UNPRIVILEGED),
227 SD_BUS_METHOD("MarkFlashModified", NULL, NULL, &control_dbus_modified,
228 SD_BUS_VTABLE_UNPRIVILEGED),
229 SD_BUS_METHOD("Suspend", NULL, NULL, &control_dbus_suspend,
230 SD_BUS_VTABLE_UNPRIVILEGED),
231 SD_BUS_METHOD("Resume", "b", NULL, &control_dbus_resume,
232 SD_BUS_VTABLE_UNPRIVILEGED),
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030233 SD_BUS_METHOD("SetBackend", "sas", NULL, &control_dbus_set_backend,
234 SD_BUS_VTABLE_UNPRIVILEGED),
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +0930235 SD_BUS_PROPERTY("DaemonState", "y", &control_dbus_get_u8, 0,
236 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
237 SD_BUS_PROPERTY("LpcState", "y", &control_dbus_get_u8, 0,
238 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
239 SD_BUS_VTABLE_END
240};
241
242int control_dbus_init(struct mbox_context *context)
243{
244 return sd_bus_add_object_vtable(context->bus, NULL,
245 MBOX_DBUS_OBJECT,
246 MBOX_DBUS_CONTROL_IFACE,
247 mboxd_vtable, context);
248}
249
250#define __unused __attribute__((unused))
251void control_dbus_free(struct mbox_context *context __unused)
252{
253 return;
254}