blob: f463d69361d334cb4d2c3fed4286e97e1afaa83b [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,
Patrick Williams68a24c92023-07-25 12:02:16 -050016 sd_bus_error *ret_error __attribute__((unused)),
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +093017 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");
Patrick Williams68a24c92023-07-25 12:02:16 -050025 return -EINVAL;
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +093026 }
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
Andrew Jefferyfac36892019-05-17 16:34:04 +093046 rc = sd_bus_send(NULL, n, NULL);
47 sd_bus_message_unref(n);
48 return rc;
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +093049}
50
51static int control_dbus_ping(sd_bus_message *m, void *userdata,
52 sd_bus_error *ret_error)
53{
54 return control_dbus_directive(m, userdata, ret_error, control_ping);
55}
56
57static int control_dbus_reset(sd_bus_message *m, void *userdata,
58 sd_bus_error *ret_error)
59{
60 return control_dbus_directive(m, userdata, ret_error, control_reset);
61}
62
63static int control_dbus_kill(sd_bus_message *m, void *userdata,
64 sd_bus_error *ret_error)
65{
66 return control_dbus_directive(m, userdata, ret_error, control_kill);
67}
68
69static int control_dbus_modified(sd_bus_message *m, void *userdata,
70 sd_bus_error *ret_error)
71{
72 return control_dbus_directive(m, userdata, ret_error, control_modified);
73}
74
75static int control_dbus_suspend(sd_bus_message *m, void *userdata,
76 sd_bus_error *ret_error)
77{
78 return control_dbus_directive(m, userdata, ret_error, control_suspend);
79}
80
81static int control_dbus_resume(sd_bus_message *m, void *userdata,
Patrick Williams68a24c92023-07-25 12:02:16 -050082 sd_bus_error *ret_error __attribute__((unused)))
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +093083{
84 struct mbox_context *context;
85 sd_bus_message *n;
86 bool modified;
87 int rc;
88
89 context = (struct mbox_context *) userdata;
90 if (!context) {
91 MSG_ERR("DBUS Internal Error\n");
92 return -EINVAL;
93 }
94
95 rc = sd_bus_message_read_basic(m, 'b', &modified);
96 if (rc < 0) {
97 MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
98 return rc;
99 }
100
101 rc = control_resume(context, modified);
102 if (rc < 0)
103 return rc;
104
105 rc = sd_bus_message_new_method_return(m, &n);
106 if (rc < 0) {
107 MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
108 return rc;
109 }
110
111 return sd_bus_send(NULL, n, NULL);
112}
113
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030114static int control_dbus_set_backend(sd_bus_message *m, void *userdata,
Patrick Williams68a24c92023-07-25 12:02:16 -0500115 sd_bus_error *ret_error __attribute__((unused)))
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030116{
117 struct mbox_context *context;
118 struct backend backend;
119 sd_bus_message *n;
120 const char *name;
121 int rc;
122
123 context = (struct mbox_context *) userdata;
124 if (!context) {
125 MSG_ERR("DBUS Internal Error\n");
126 return -EINVAL;
127 }
128
129 rc = sd_bus_message_read_basic(m, 's', &name);
130 if (rc < 0) {
131 MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
132 return rc;
133 }
134
135 if (!strcmp(name, "vpnor")) {
136 struct vpnor_partition_paths paths;
137
138 vpnor_default_paths(&paths);
139 backend = backend_get_vpnor();
140 rc = control_set_backend(context, &backend, &paths);
141 if (rc < 0)
142 return rc;
143 } else if (!strcmp(name, "mtd")) {
144 char **paths = NULL;
145 char *path = NULL;
146
147 rc = sd_bus_message_read_strv(m, &paths);
148 if (rc < 0)
149 return rc;
150
151 if (paths && *paths)
152 path = *paths;
153 else
154 path = get_dev_mtd();
155
156 backend = backend_get_mtd();
157
158 rc = control_set_backend(context, &backend, path);
159 if (rc < 0)
160 return rc;
161
162 free(path);
163 free(paths);
164 } else if (!strcmp(name, "file")) {
165 char **paths = NULL;
166 char *path = NULL;
167
168 rc = sd_bus_message_read_strv(m, &paths);
169 if (rc < 0)
170 return rc;
171
172 if (!(paths && *paths))
173 return -EINVAL;
174
175 path = *paths;
176
177 backend = backend_get_file();
178
179 rc = control_set_backend(context, &backend, path);
180 if (rc < 0)
181 return rc;
182
183 free(path);
184 free(paths);
185 } else {
186 return -EINVAL;
187 }
188
189 rc = sd_bus_message_new_method_return(m, &n);
190 if (rc < 0) {
191 MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
192 return rc;
193 }
194
Andrew Jefferyfac36892019-05-17 16:34:04 +0930195 rc = sd_bus_send(NULL, n, NULL);
196 sd_bus_message_unref(n);
197 return rc;
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030198}
199
Patrick Williams68a24c92023-07-25 12:02:16 -0500200static int control_dbus_get_u8(sd_bus *bus __attribute__((unused)),
201 const char *path,
202 const char *interface __attribute__((unused)),
203 const char *property,
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +0930204 sd_bus_message *reply, void *userdata,
Patrick Williams68a24c92023-07-25 12:02:16 -0500205 sd_bus_error *ret_error __attribute__((unused)))
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +0930206{
207 struct mbox_context *context = userdata;
208 uint8_t value;
209
210 assert(!strcmp(MBOX_DBUS_OBJECT, path));
211
212 if (!strcmp("DaemonState", property)) {
213 value = control_daemon_state(context);
214 } else if (!strcmp("LpcState", property)) {
215 value = control_lpc_state(context);
216 } else {
217 MSG_ERR("Unknown DBus property: %s\n", property);
218 return -EINVAL;
219 }
220
221 return sd_bus_message_append(reply, "y", value);
222}
223
224static const sd_bus_vtable mboxd_vtable[] = {
225 SD_BUS_VTABLE_START(0),
226 SD_BUS_METHOD("Ping", NULL, NULL, &control_dbus_ping,
227 SD_BUS_VTABLE_UNPRIVILEGED),
228 SD_BUS_METHOD("Reset", NULL, NULL, &control_dbus_reset,
229 SD_BUS_VTABLE_UNPRIVILEGED),
230 SD_BUS_METHOD("Kill", NULL, NULL, &control_dbus_kill,
231 SD_BUS_VTABLE_UNPRIVILEGED),
232 SD_BUS_METHOD("MarkFlashModified", NULL, NULL, &control_dbus_modified,
233 SD_BUS_VTABLE_UNPRIVILEGED),
234 SD_BUS_METHOD("Suspend", NULL, NULL, &control_dbus_suspend,
235 SD_BUS_VTABLE_UNPRIVILEGED),
236 SD_BUS_METHOD("Resume", "b", NULL, &control_dbus_resume,
237 SD_BUS_VTABLE_UNPRIVILEGED),
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030238 SD_BUS_METHOD("SetBackend", "sas", NULL, &control_dbus_set_backend,
239 SD_BUS_VTABLE_UNPRIVILEGED),
Andrew Jeffery55f4d6f2018-08-06 12:26:44 +0930240 SD_BUS_PROPERTY("DaemonState", "y", &control_dbus_get_u8, 0,
241 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
242 SD_BUS_PROPERTY("LpcState", "y", &control_dbus_get_u8, 0,
243 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
244 SD_BUS_VTABLE_END
245};
246
247int control_dbus_init(struct mbox_context *context)
248{
249 return sd_bus_add_object_vtable(context->bus, NULL,
250 MBOX_DBUS_OBJECT,
251 MBOX_DBUS_CONTROL_IFACE,
252 mboxd_vtable, context);
253}
254
255#define __unused __attribute__((unused))
256void control_dbus_free(struct mbox_context *context __unused)
257{
258 return;
259}