xref: /openbmc/hiomapd/control_dbus.c (revision 5320f6e02453261e6c75d3bef101ad1bef6de82e)
155f4d6f9SAndrew Jeffery // SPDX-License-Identifier: Apache-2.0
255f4d6f9SAndrew Jeffery // Copyright (C) 2018 IBM Corp.
355f4d6f9SAndrew Jeffery #include <assert.h>
455f4d6f9SAndrew Jeffery #include <errno.h>
5*5320f6e0SAndrew Jeffery #include <stdlib.h>
655f4d6f9SAndrew Jeffery #include <systemd/sd-bus.h>
755f4d6f9SAndrew Jeffery 
855f4d6f9SAndrew Jeffery #include "common.h"
955f4d6f9SAndrew Jeffery #include "dbus.h"
1055f4d6f9SAndrew Jeffery #include "control_dbus.h"
1126558dbbSAndrew Jeffery #include "mboxd.h"
12*5320f6e0SAndrew Jeffery #include "vpnor/mboxd_pnor_partition_table.h"
1355f4d6f9SAndrew Jeffery 
1455f4d6f9SAndrew Jeffery typedef int (*control_action)(struct mbox_context *context);
1555f4d6f9SAndrew Jeffery 
1655f4d6f9SAndrew Jeffery static int control_dbus_directive(sd_bus_message *m, void *userdata,
1755f4d6f9SAndrew Jeffery 					sd_bus_error *ret_error,
1855f4d6f9SAndrew Jeffery 					control_action action)
1955f4d6f9SAndrew Jeffery {
2055f4d6f9SAndrew Jeffery 	struct mbox_context *context;
2155f4d6f9SAndrew Jeffery 	sd_bus_message *n;
2255f4d6f9SAndrew Jeffery 	int rc;
2355f4d6f9SAndrew Jeffery 
2455f4d6f9SAndrew Jeffery 	if (!action) {
2555f4d6f9SAndrew Jeffery 		MSG_ERR("No action provided\n");
2655f4d6f9SAndrew Jeffery 		return -EINVAL;
2755f4d6f9SAndrew Jeffery 	}
2855f4d6f9SAndrew Jeffery 
2955f4d6f9SAndrew Jeffery 	context = (struct mbox_context *) userdata;
3055f4d6f9SAndrew Jeffery 	if (!context) {
3155f4d6f9SAndrew Jeffery 		MSG_ERR("DBUS Internal Error\n");
3255f4d6f9SAndrew Jeffery 		return -EINVAL;
3355f4d6f9SAndrew Jeffery 	}
3455f4d6f9SAndrew Jeffery 
3555f4d6f9SAndrew Jeffery 	rc = action(context);
3655f4d6f9SAndrew Jeffery 	if (rc < 0) {
3755f4d6f9SAndrew Jeffery 		MSG_ERR("Action failed: %d\n", rc);
3855f4d6f9SAndrew Jeffery 		return rc;
3955f4d6f9SAndrew Jeffery 	}
4055f4d6f9SAndrew Jeffery 
4155f4d6f9SAndrew Jeffery 	rc = sd_bus_message_new_method_return(m, &n);
4255f4d6f9SAndrew Jeffery 	if (rc < 0) {
4355f4d6f9SAndrew Jeffery 		MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
4455f4d6f9SAndrew Jeffery 		return rc;
4555f4d6f9SAndrew Jeffery 	}
4655f4d6f9SAndrew Jeffery 
4755f4d6f9SAndrew Jeffery 	return sd_bus_send(NULL, n, NULL);
4855f4d6f9SAndrew Jeffery }
4955f4d6f9SAndrew Jeffery 
5055f4d6f9SAndrew Jeffery static int control_dbus_ping(sd_bus_message *m, void *userdata,
5155f4d6f9SAndrew Jeffery 				   sd_bus_error *ret_error)
5255f4d6f9SAndrew Jeffery {
5355f4d6f9SAndrew Jeffery 	return control_dbus_directive(m, userdata, ret_error, control_ping);
5455f4d6f9SAndrew Jeffery }
5555f4d6f9SAndrew Jeffery 
5655f4d6f9SAndrew Jeffery static int control_dbus_reset(sd_bus_message *m, void *userdata,
5755f4d6f9SAndrew Jeffery 				    sd_bus_error *ret_error)
5855f4d6f9SAndrew Jeffery {
5955f4d6f9SAndrew Jeffery 	return control_dbus_directive(m, userdata, ret_error, control_reset);
6055f4d6f9SAndrew Jeffery }
6155f4d6f9SAndrew Jeffery 
6255f4d6f9SAndrew Jeffery static int control_dbus_kill(sd_bus_message *m, void *userdata,
6355f4d6f9SAndrew Jeffery 				   sd_bus_error *ret_error)
6455f4d6f9SAndrew Jeffery {
6555f4d6f9SAndrew Jeffery 	return control_dbus_directive(m, userdata, ret_error, control_kill);
6655f4d6f9SAndrew Jeffery }
6755f4d6f9SAndrew Jeffery 
6855f4d6f9SAndrew Jeffery static int control_dbus_modified(sd_bus_message *m, void *userdata,
6955f4d6f9SAndrew Jeffery 				       sd_bus_error *ret_error)
7055f4d6f9SAndrew Jeffery {
7155f4d6f9SAndrew Jeffery 	return control_dbus_directive(m, userdata, ret_error, control_modified);
7255f4d6f9SAndrew Jeffery }
7355f4d6f9SAndrew Jeffery 
7455f4d6f9SAndrew Jeffery static int control_dbus_suspend(sd_bus_message *m, void *userdata,
7555f4d6f9SAndrew Jeffery 				      sd_bus_error *ret_error)
7655f4d6f9SAndrew Jeffery {
7755f4d6f9SAndrew Jeffery 	return control_dbus_directive(m, userdata, ret_error, control_suspend);
7855f4d6f9SAndrew Jeffery }
7955f4d6f9SAndrew Jeffery 
8055f4d6f9SAndrew Jeffery static int control_dbus_resume(sd_bus_message *m, void *userdata,
8155f4d6f9SAndrew Jeffery 				     sd_bus_error *ret_error)
8255f4d6f9SAndrew Jeffery {
8355f4d6f9SAndrew Jeffery 	struct mbox_context *context;
8455f4d6f9SAndrew Jeffery 	sd_bus_message *n;
8555f4d6f9SAndrew Jeffery 	bool modified;
8655f4d6f9SAndrew Jeffery 	int rc;
8755f4d6f9SAndrew Jeffery 
8855f4d6f9SAndrew Jeffery 	context = (struct mbox_context *) userdata;
8955f4d6f9SAndrew Jeffery 	if (!context) {
9055f4d6f9SAndrew Jeffery 		MSG_ERR("DBUS Internal Error\n");
9155f4d6f9SAndrew Jeffery 		return -EINVAL;
9255f4d6f9SAndrew Jeffery 	}
9355f4d6f9SAndrew Jeffery 
9455f4d6f9SAndrew Jeffery 	rc = sd_bus_message_read_basic(m, 'b', &modified);
9555f4d6f9SAndrew Jeffery 	if (rc < 0) {
9655f4d6f9SAndrew Jeffery 		MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
9755f4d6f9SAndrew Jeffery 		return rc;
9855f4d6f9SAndrew Jeffery 	}
9955f4d6f9SAndrew Jeffery 
10055f4d6f9SAndrew Jeffery 	rc = control_resume(context, modified);
10155f4d6f9SAndrew Jeffery 	if (rc < 0)
10255f4d6f9SAndrew Jeffery 		return rc;
10355f4d6f9SAndrew Jeffery 
10455f4d6f9SAndrew Jeffery 	rc = sd_bus_message_new_method_return(m, &n);
10555f4d6f9SAndrew Jeffery 	if (rc < 0) {
10655f4d6f9SAndrew Jeffery 		MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
10755f4d6f9SAndrew Jeffery 		return rc;
10855f4d6f9SAndrew Jeffery 	}
10955f4d6f9SAndrew Jeffery 
11055f4d6f9SAndrew Jeffery 	return sd_bus_send(NULL, n, NULL);
11155f4d6f9SAndrew Jeffery }
11255f4d6f9SAndrew Jeffery 
113*5320f6e0SAndrew Jeffery static int control_dbus_set_backend(sd_bus_message *m, void *userdata,
114*5320f6e0SAndrew Jeffery 				    sd_bus_error *ret_error)
115*5320f6e0SAndrew Jeffery {
116*5320f6e0SAndrew Jeffery 	struct mbox_context *context;
117*5320f6e0SAndrew Jeffery 	struct backend backend;
118*5320f6e0SAndrew Jeffery 	sd_bus_message *n;
119*5320f6e0SAndrew Jeffery 	const char *name;
120*5320f6e0SAndrew Jeffery 	int rc;
121*5320f6e0SAndrew Jeffery 
122*5320f6e0SAndrew Jeffery 	context = (struct mbox_context *) userdata;
123*5320f6e0SAndrew Jeffery 	if (!context) {
124*5320f6e0SAndrew Jeffery 		MSG_ERR("DBUS Internal Error\n");
125*5320f6e0SAndrew Jeffery 		return -EINVAL;
126*5320f6e0SAndrew Jeffery 	}
127*5320f6e0SAndrew Jeffery 
128*5320f6e0SAndrew Jeffery 	rc = sd_bus_message_read_basic(m, 's', &name);
129*5320f6e0SAndrew Jeffery 	if (rc < 0) {
130*5320f6e0SAndrew Jeffery 		MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
131*5320f6e0SAndrew Jeffery 		return rc;
132*5320f6e0SAndrew Jeffery 	}
133*5320f6e0SAndrew Jeffery 
134*5320f6e0SAndrew Jeffery 	if (!strcmp(name, "vpnor")) {
135*5320f6e0SAndrew Jeffery 		struct vpnor_partition_paths paths;
136*5320f6e0SAndrew Jeffery 
137*5320f6e0SAndrew Jeffery 		vpnor_default_paths(&paths);
138*5320f6e0SAndrew Jeffery 		backend = backend_get_vpnor();
139*5320f6e0SAndrew Jeffery 		rc = control_set_backend(context, &backend, &paths);
140*5320f6e0SAndrew Jeffery 		if (rc < 0)
141*5320f6e0SAndrew Jeffery 			return rc;
142*5320f6e0SAndrew Jeffery 	} else if (!strcmp(name, "mtd")) {
143*5320f6e0SAndrew Jeffery 		char **paths = NULL;
144*5320f6e0SAndrew Jeffery 		char *path = NULL;
145*5320f6e0SAndrew Jeffery 
146*5320f6e0SAndrew Jeffery 		rc = sd_bus_message_read_strv(m, &paths);
147*5320f6e0SAndrew Jeffery 		if (rc < 0)
148*5320f6e0SAndrew Jeffery 			return rc;
149*5320f6e0SAndrew Jeffery 
150*5320f6e0SAndrew Jeffery 		if (paths && *paths)
151*5320f6e0SAndrew Jeffery 			path = *paths;
152*5320f6e0SAndrew Jeffery 		else
153*5320f6e0SAndrew Jeffery 			path = get_dev_mtd();
154*5320f6e0SAndrew Jeffery 
155*5320f6e0SAndrew Jeffery 		backend = backend_get_mtd();
156*5320f6e0SAndrew Jeffery 
157*5320f6e0SAndrew Jeffery 		rc = control_set_backend(context, &backend, path);
158*5320f6e0SAndrew Jeffery 		if (rc < 0)
159*5320f6e0SAndrew Jeffery 			return rc;
160*5320f6e0SAndrew Jeffery 
161*5320f6e0SAndrew Jeffery 		free(path);
162*5320f6e0SAndrew Jeffery 		free(paths);
163*5320f6e0SAndrew Jeffery 	} else if (!strcmp(name, "file")) {
164*5320f6e0SAndrew Jeffery 		char **paths = NULL;
165*5320f6e0SAndrew Jeffery 		char *path = NULL;
166*5320f6e0SAndrew Jeffery 
167*5320f6e0SAndrew Jeffery 		rc = sd_bus_message_read_strv(m, &paths);
168*5320f6e0SAndrew Jeffery 		if (rc < 0)
169*5320f6e0SAndrew Jeffery 			return rc;
170*5320f6e0SAndrew Jeffery 
171*5320f6e0SAndrew Jeffery 		if (!(paths && *paths))
172*5320f6e0SAndrew Jeffery 			return -EINVAL;
173*5320f6e0SAndrew Jeffery 
174*5320f6e0SAndrew Jeffery 		path = *paths;
175*5320f6e0SAndrew Jeffery 
176*5320f6e0SAndrew Jeffery 		backend = backend_get_file();
177*5320f6e0SAndrew Jeffery 
178*5320f6e0SAndrew Jeffery 		rc = control_set_backend(context, &backend, path);
179*5320f6e0SAndrew Jeffery 		if (rc < 0)
180*5320f6e0SAndrew Jeffery 			return rc;
181*5320f6e0SAndrew Jeffery 
182*5320f6e0SAndrew Jeffery 		free(path);
183*5320f6e0SAndrew Jeffery 		free(paths);
184*5320f6e0SAndrew Jeffery 	} else {
185*5320f6e0SAndrew Jeffery 		return -EINVAL;
186*5320f6e0SAndrew Jeffery 	}
187*5320f6e0SAndrew Jeffery 
188*5320f6e0SAndrew Jeffery 	rc = sd_bus_message_new_method_return(m, &n);
189*5320f6e0SAndrew Jeffery 	if (rc < 0) {
190*5320f6e0SAndrew Jeffery 		MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
191*5320f6e0SAndrew Jeffery 		return rc;
192*5320f6e0SAndrew Jeffery 	}
193*5320f6e0SAndrew Jeffery 
194*5320f6e0SAndrew Jeffery 	return sd_bus_send(NULL, n, NULL);
195*5320f6e0SAndrew Jeffery }
196*5320f6e0SAndrew Jeffery 
19755f4d6f9SAndrew Jeffery static int control_dbus_get_u8(sd_bus *bus, const char *path,
19855f4d6f9SAndrew Jeffery 			       const char *interface, const char *property,
19955f4d6f9SAndrew Jeffery 			       sd_bus_message *reply, void *userdata,
20055f4d6f9SAndrew Jeffery 			       sd_bus_error *ret_error)
20155f4d6f9SAndrew Jeffery {
20255f4d6f9SAndrew Jeffery 	struct mbox_context *context = userdata;
20355f4d6f9SAndrew Jeffery 	uint8_t value;
20455f4d6f9SAndrew Jeffery 
20555f4d6f9SAndrew Jeffery 	assert(!strcmp(MBOX_DBUS_OBJECT, path));
20655f4d6f9SAndrew Jeffery 
20755f4d6f9SAndrew Jeffery 	if (!strcmp("DaemonState", property)) {
20855f4d6f9SAndrew Jeffery 		value = control_daemon_state(context);
20955f4d6f9SAndrew Jeffery 	} else if (!strcmp("LpcState", property)) {
21055f4d6f9SAndrew Jeffery 		value = control_lpc_state(context);
21155f4d6f9SAndrew Jeffery 	} else {
21255f4d6f9SAndrew Jeffery 		MSG_ERR("Unknown DBus property: %s\n", property);
21355f4d6f9SAndrew Jeffery 		return -EINVAL;
21455f4d6f9SAndrew Jeffery 	}
21555f4d6f9SAndrew Jeffery 
21655f4d6f9SAndrew Jeffery 	return sd_bus_message_append(reply, "y", value);
21755f4d6f9SAndrew Jeffery }
21855f4d6f9SAndrew Jeffery 
21955f4d6f9SAndrew Jeffery static const sd_bus_vtable mboxd_vtable[] = {
22055f4d6f9SAndrew Jeffery 	SD_BUS_VTABLE_START(0),
22155f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("Ping", NULL, NULL, &control_dbus_ping,
22255f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
22355f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("Reset", NULL, NULL, &control_dbus_reset,
22455f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
22555f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("Kill", NULL, NULL, &control_dbus_kill,
22655f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
22755f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("MarkFlashModified", NULL, NULL, &control_dbus_modified,
22855f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
22955f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("Suspend", NULL, NULL, &control_dbus_suspend,
23055f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
23155f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("Resume", "b", NULL, &control_dbus_resume,
23255f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
233*5320f6e0SAndrew Jeffery 	SD_BUS_METHOD("SetBackend", "sas", NULL, &control_dbus_set_backend,
234*5320f6e0SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
23555f4d6f9SAndrew Jeffery 	SD_BUS_PROPERTY("DaemonState", "y", &control_dbus_get_u8, 0,
23655f4d6f9SAndrew Jeffery 		        SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
23755f4d6f9SAndrew Jeffery 	SD_BUS_PROPERTY("LpcState", "y", &control_dbus_get_u8, 0,
23855f4d6f9SAndrew Jeffery 		        SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
23955f4d6f9SAndrew Jeffery 	SD_BUS_VTABLE_END
24055f4d6f9SAndrew Jeffery };
24155f4d6f9SAndrew Jeffery 
24255f4d6f9SAndrew Jeffery int control_dbus_init(struct mbox_context *context)
24355f4d6f9SAndrew Jeffery {
24455f4d6f9SAndrew Jeffery 	return sd_bus_add_object_vtable(context->bus, NULL,
24555f4d6f9SAndrew Jeffery 					MBOX_DBUS_OBJECT,
24655f4d6f9SAndrew Jeffery 					MBOX_DBUS_CONTROL_IFACE,
24755f4d6f9SAndrew Jeffery 					mboxd_vtable, context);
24855f4d6f9SAndrew Jeffery }
24955f4d6f9SAndrew Jeffery 
25055f4d6f9SAndrew Jeffery #define __unused __attribute__((unused))
25155f4d6f9SAndrew Jeffery void control_dbus_free(struct mbox_context *context __unused)
25255f4d6f9SAndrew Jeffery {
25355f4d6f9SAndrew Jeffery 	return;
25455f4d6f9SAndrew Jeffery }
255