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