xref: /openbmc/hiomapd/control_dbus.c (revision f4bc335b)
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 	return sd_bus_send(NULL, n, NULL);
47 }
48 
49 static 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 
55 static 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 
61 static 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 
67 static 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 
73 static 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 
79 static 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 
112 static 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 
196 static 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 
218 static 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),
232 	SD_BUS_METHOD("SetBackend", "sas", NULL, &control_dbus_set_backend,
233 		      SD_BUS_VTABLE_UNPRIVILEGED),
234 	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 
241 int 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))
250 void control_dbus_free(struct mbox_context *context __unused)
251 {
252 	return;
253 }
254