xref: /openbmc/hiomapd/control_dbus.c (revision 5320f6e0)
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 #include "vpnor/mboxd_pnor_partition_table.h"
13 
14 typedef int (*control_action)(struct mbox_context *context);
15 
16 static 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 
50 static 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 
56 static 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 
62 static 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 
68 static 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 
74 static 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 
80 static 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 
113 static 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 
197 static 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 
219 static 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),
233 	SD_BUS_METHOD("SetBackend", "sas", NULL, &control_dbus_set_backend,
234 		      SD_BUS_VTABLE_UNPRIVILEGED),
235 	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 
242 int 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))
251 void control_dbus_free(struct mbox_context *context __unused)
252 {
253 	return;
254 }
255