xref: /openbmc/hiomapd/control_dbus.c (revision fac3689e)
1 // SPDX-License-Identifier: Apache-2.0
2 // Copyright (C) 2018 IBM Corp.
3 #include <assert.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <systemd/sd-bus.h>
7 
8 #include "common.h"
9 #include "dbus.h"
10 #include "control_dbus.h"
11 #include "mboxd.h"
12 
13 typedef int (*control_action)(struct mbox_context *context);
14 
15 static 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 	rc = sd_bus_send(NULL, n, NULL);
47 	sd_bus_message_unref(n);
48 	return rc;
49 }
50 
51 static 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 
57 static 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 
63 static 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 
69 static 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 
75 static 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 
81 static int control_dbus_resume(sd_bus_message *m, void *userdata,
82 				     sd_bus_error *ret_error)
83 {
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 
114 static int control_dbus_set_backend(sd_bus_message *m, void *userdata,
115 				    sd_bus_error *ret_error)
116 {
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 
195 	rc = sd_bus_send(NULL, n, NULL);
196 	sd_bus_message_unref(n);
197 	return rc;
198 }
199 
200 static int control_dbus_get_u8(sd_bus *bus, const char *path,
201 			       const char *interface, const char *property,
202 			       sd_bus_message *reply, void *userdata,
203 			       sd_bus_error *ret_error)
204 {
205 	struct mbox_context *context = userdata;
206 	uint8_t value;
207 
208 	assert(!strcmp(MBOX_DBUS_OBJECT, path));
209 
210 	if (!strcmp("DaemonState", property)) {
211 		value = control_daemon_state(context);
212 	} else if (!strcmp("LpcState", property)) {
213 		value = control_lpc_state(context);
214 	} else {
215 		MSG_ERR("Unknown DBus property: %s\n", property);
216 		return -EINVAL;
217 	}
218 
219 	return sd_bus_message_append(reply, "y", value);
220 }
221 
222 static const sd_bus_vtable mboxd_vtable[] = {
223 	SD_BUS_VTABLE_START(0),
224 	SD_BUS_METHOD("Ping", NULL, NULL, &control_dbus_ping,
225 		      SD_BUS_VTABLE_UNPRIVILEGED),
226 	SD_BUS_METHOD("Reset", NULL, NULL, &control_dbus_reset,
227 		      SD_BUS_VTABLE_UNPRIVILEGED),
228 	SD_BUS_METHOD("Kill", NULL, NULL, &control_dbus_kill,
229 		      SD_BUS_VTABLE_UNPRIVILEGED),
230 	SD_BUS_METHOD("MarkFlashModified", NULL, NULL, &control_dbus_modified,
231 		      SD_BUS_VTABLE_UNPRIVILEGED),
232 	SD_BUS_METHOD("Suspend", NULL, NULL, &control_dbus_suspend,
233 		      SD_BUS_VTABLE_UNPRIVILEGED),
234 	SD_BUS_METHOD("Resume", "b", NULL, &control_dbus_resume,
235 		      SD_BUS_VTABLE_UNPRIVILEGED),
236 	SD_BUS_METHOD("SetBackend", "sas", NULL, &control_dbus_set_backend,
237 		      SD_BUS_VTABLE_UNPRIVILEGED),
238 	SD_BUS_PROPERTY("DaemonState", "y", &control_dbus_get_u8, 0,
239 		        SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
240 	SD_BUS_PROPERTY("LpcState", "y", &control_dbus_get_u8, 0,
241 		        SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
242 	SD_BUS_VTABLE_END
243 };
244 
245 int control_dbus_init(struct mbox_context *context)
246 {
247 	return sd_bus_add_object_vtable(context->bus, NULL,
248 					MBOX_DBUS_OBJECT,
249 					MBOX_DBUS_CONTROL_IFACE,
250 					mboxd_vtable, context);
251 }
252 
253 #define __unused __attribute__((unused))
254 void control_dbus_free(struct mbox_context *context __unused)
255 {
256 	return;
257 }
258