xref: /openbmc/hiomapd/control_dbus.c (revision f4bc335b4fc899509c92c230f746fe90a5aa43d2)
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