xref: /openbmc/hiomapd/control_dbus.c (revision 68a24c9ea5ce11c87fab22a3f4648c7d88c98fee)
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>
55320f6e0SAndrew 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"
1255f4d6f9SAndrew Jeffery 
1355f4d6f9SAndrew Jeffery typedef int (*control_action)(struct mbox_context *context);
1455f4d6f9SAndrew Jeffery 
control_dbus_directive(sd_bus_message * m,void * userdata,sd_bus_error * ret_error,control_action action)1555f4d6f9SAndrew Jeffery static int control_dbus_directive(sd_bus_message *m, void *userdata,
16*68a24c9eSPatrick Williams 					sd_bus_error *ret_error __attribute__((unused)),
1755f4d6f9SAndrew Jeffery 					control_action action)
1855f4d6f9SAndrew Jeffery {
1955f4d6f9SAndrew Jeffery 	struct mbox_context *context;
2055f4d6f9SAndrew Jeffery 	sd_bus_message *n;
2155f4d6f9SAndrew Jeffery 	int rc;
2255f4d6f9SAndrew Jeffery 
2355f4d6f9SAndrew Jeffery 	if (!action) {
2455f4d6f9SAndrew Jeffery 		MSG_ERR("No action provided\n");
2555f4d6f9SAndrew Jeffery 		return -EINVAL;
2655f4d6f9SAndrew Jeffery 	}
2755f4d6f9SAndrew Jeffery 
2855f4d6f9SAndrew Jeffery 	context = (struct mbox_context *) userdata;
2955f4d6f9SAndrew Jeffery 	if (!context) {
3055f4d6f9SAndrew Jeffery 		MSG_ERR("DBUS Internal Error\n");
3155f4d6f9SAndrew Jeffery 		return -EINVAL;
3255f4d6f9SAndrew Jeffery 	}
3355f4d6f9SAndrew Jeffery 
3455f4d6f9SAndrew Jeffery 	rc = action(context);
3555f4d6f9SAndrew Jeffery 	if (rc < 0) {
3655f4d6f9SAndrew Jeffery 		MSG_ERR("Action failed: %d\n", rc);
3755f4d6f9SAndrew Jeffery 		return rc;
3855f4d6f9SAndrew Jeffery 	}
3955f4d6f9SAndrew Jeffery 
4055f4d6f9SAndrew Jeffery 	rc = sd_bus_message_new_method_return(m, &n);
4155f4d6f9SAndrew Jeffery 	if (rc < 0) {
4255f4d6f9SAndrew Jeffery 		MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
4355f4d6f9SAndrew Jeffery 		return rc;
4455f4d6f9SAndrew Jeffery 	}
4555f4d6f9SAndrew Jeffery 
46fac3689eSAndrew Jeffery 	rc = sd_bus_send(NULL, n, NULL);
47fac3689eSAndrew Jeffery 	sd_bus_message_unref(n);
48fac3689eSAndrew Jeffery 	return rc;
4955f4d6f9SAndrew Jeffery }
5055f4d6f9SAndrew Jeffery 
control_dbus_ping(sd_bus_message * m,void * userdata,sd_bus_error * ret_error)5155f4d6f9SAndrew Jeffery static int control_dbus_ping(sd_bus_message *m, void *userdata,
5255f4d6f9SAndrew Jeffery 				   sd_bus_error *ret_error)
5355f4d6f9SAndrew Jeffery {
5455f4d6f9SAndrew Jeffery 	return control_dbus_directive(m, userdata, ret_error, control_ping);
5555f4d6f9SAndrew Jeffery }
5655f4d6f9SAndrew Jeffery 
control_dbus_reset(sd_bus_message * m,void * userdata,sd_bus_error * ret_error)5755f4d6f9SAndrew Jeffery static int control_dbus_reset(sd_bus_message *m, void *userdata,
5855f4d6f9SAndrew Jeffery 				    sd_bus_error *ret_error)
5955f4d6f9SAndrew Jeffery {
6055f4d6f9SAndrew Jeffery 	return control_dbus_directive(m, userdata, ret_error, control_reset);
6155f4d6f9SAndrew Jeffery }
6255f4d6f9SAndrew Jeffery 
control_dbus_kill(sd_bus_message * m,void * userdata,sd_bus_error * ret_error)6355f4d6f9SAndrew Jeffery static int control_dbus_kill(sd_bus_message *m, void *userdata,
6455f4d6f9SAndrew Jeffery 				   sd_bus_error *ret_error)
6555f4d6f9SAndrew Jeffery {
6655f4d6f9SAndrew Jeffery 	return control_dbus_directive(m, userdata, ret_error, control_kill);
6755f4d6f9SAndrew Jeffery }
6855f4d6f9SAndrew Jeffery 
control_dbus_modified(sd_bus_message * m,void * userdata,sd_bus_error * ret_error)6955f4d6f9SAndrew Jeffery static int control_dbus_modified(sd_bus_message *m, void *userdata,
7055f4d6f9SAndrew Jeffery 				       sd_bus_error *ret_error)
7155f4d6f9SAndrew Jeffery {
7255f4d6f9SAndrew Jeffery 	return control_dbus_directive(m, userdata, ret_error, control_modified);
7355f4d6f9SAndrew Jeffery }
7455f4d6f9SAndrew Jeffery 
control_dbus_suspend(sd_bus_message * m,void * userdata,sd_bus_error * ret_error)7555f4d6f9SAndrew Jeffery static int control_dbus_suspend(sd_bus_message *m, void *userdata,
7655f4d6f9SAndrew Jeffery 				      sd_bus_error *ret_error)
7755f4d6f9SAndrew Jeffery {
7855f4d6f9SAndrew Jeffery 	return control_dbus_directive(m, userdata, ret_error, control_suspend);
7955f4d6f9SAndrew Jeffery }
8055f4d6f9SAndrew Jeffery 
control_dbus_resume(sd_bus_message * m,void * userdata,sd_bus_error * ret_error)8155f4d6f9SAndrew Jeffery static int control_dbus_resume(sd_bus_message *m, void *userdata,
82*68a24c9eSPatrick Williams 			       sd_bus_error *ret_error __attribute__((unused)))
8355f4d6f9SAndrew Jeffery {
8455f4d6f9SAndrew Jeffery 	struct mbox_context *context;
8555f4d6f9SAndrew Jeffery 	sd_bus_message *n;
8655f4d6f9SAndrew Jeffery 	bool modified;
8755f4d6f9SAndrew Jeffery 	int rc;
8855f4d6f9SAndrew Jeffery 
8955f4d6f9SAndrew Jeffery 	context = (struct mbox_context *) userdata;
9055f4d6f9SAndrew Jeffery 	if (!context) {
9155f4d6f9SAndrew Jeffery 		MSG_ERR("DBUS Internal Error\n");
9255f4d6f9SAndrew Jeffery 		return -EINVAL;
9355f4d6f9SAndrew Jeffery 	}
9455f4d6f9SAndrew Jeffery 
9555f4d6f9SAndrew Jeffery 	rc = sd_bus_message_read_basic(m, 'b', &modified);
9655f4d6f9SAndrew Jeffery 	if (rc < 0) {
9755f4d6f9SAndrew Jeffery 		MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
9855f4d6f9SAndrew Jeffery 		return rc;
9955f4d6f9SAndrew Jeffery 	}
10055f4d6f9SAndrew Jeffery 
10155f4d6f9SAndrew Jeffery 	rc = control_resume(context, modified);
10255f4d6f9SAndrew Jeffery 	if (rc < 0)
10355f4d6f9SAndrew Jeffery 		return rc;
10455f4d6f9SAndrew Jeffery 
10555f4d6f9SAndrew Jeffery 	rc = sd_bus_message_new_method_return(m, &n);
10655f4d6f9SAndrew Jeffery 	if (rc < 0) {
10755f4d6f9SAndrew Jeffery 		MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
10855f4d6f9SAndrew Jeffery 		return rc;
10955f4d6f9SAndrew Jeffery 	}
11055f4d6f9SAndrew Jeffery 
11155f4d6f9SAndrew Jeffery 	return sd_bus_send(NULL, n, NULL);
11255f4d6f9SAndrew Jeffery }
11355f4d6f9SAndrew Jeffery 
control_dbus_set_backend(sd_bus_message * m,void * userdata,sd_bus_error * ret_error)1145320f6e0SAndrew Jeffery static int control_dbus_set_backend(sd_bus_message *m, void *userdata,
115*68a24c9eSPatrick Williams 				    sd_bus_error *ret_error __attribute__((unused)))
1165320f6e0SAndrew Jeffery {
1175320f6e0SAndrew Jeffery 	struct mbox_context *context;
1185320f6e0SAndrew Jeffery 	struct backend backend;
1195320f6e0SAndrew Jeffery 	sd_bus_message *n;
1205320f6e0SAndrew Jeffery 	const char *name;
1215320f6e0SAndrew Jeffery 	int rc;
1225320f6e0SAndrew Jeffery 
1235320f6e0SAndrew Jeffery 	context = (struct mbox_context *) userdata;
1245320f6e0SAndrew Jeffery 	if (!context) {
1255320f6e0SAndrew Jeffery 		MSG_ERR("DBUS Internal Error\n");
1265320f6e0SAndrew Jeffery 		return -EINVAL;
1275320f6e0SAndrew Jeffery 	}
1285320f6e0SAndrew Jeffery 
1295320f6e0SAndrew Jeffery 	rc = sd_bus_message_read_basic(m, 's', &name);
1305320f6e0SAndrew Jeffery 	if (rc < 0) {
1315320f6e0SAndrew Jeffery 		MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
1325320f6e0SAndrew Jeffery 		return rc;
1335320f6e0SAndrew Jeffery 	}
1345320f6e0SAndrew Jeffery 
1355320f6e0SAndrew Jeffery 	if (!strcmp(name, "vpnor")) {
1365320f6e0SAndrew Jeffery 		struct vpnor_partition_paths paths;
1375320f6e0SAndrew Jeffery 
1385320f6e0SAndrew Jeffery 		vpnor_default_paths(&paths);
1395320f6e0SAndrew Jeffery 		backend = backend_get_vpnor();
1405320f6e0SAndrew Jeffery 		rc = control_set_backend(context, &backend, &paths);
1415320f6e0SAndrew Jeffery 		if (rc < 0)
1425320f6e0SAndrew Jeffery 			return rc;
1435320f6e0SAndrew Jeffery 	} else if (!strcmp(name, "mtd")) {
1445320f6e0SAndrew Jeffery 		char **paths = NULL;
1455320f6e0SAndrew Jeffery 		char *path = NULL;
1465320f6e0SAndrew Jeffery 
1475320f6e0SAndrew Jeffery 		rc = sd_bus_message_read_strv(m, &paths);
1485320f6e0SAndrew Jeffery 		if (rc < 0)
1495320f6e0SAndrew Jeffery 			return rc;
1505320f6e0SAndrew Jeffery 
1515320f6e0SAndrew Jeffery 		if (paths && *paths)
1525320f6e0SAndrew Jeffery 			path = *paths;
1535320f6e0SAndrew Jeffery 		else
1545320f6e0SAndrew Jeffery 			path = get_dev_mtd();
1555320f6e0SAndrew Jeffery 
1565320f6e0SAndrew Jeffery 		backend = backend_get_mtd();
1575320f6e0SAndrew Jeffery 
1585320f6e0SAndrew Jeffery 		rc = control_set_backend(context, &backend, path);
1595320f6e0SAndrew Jeffery 		if (rc < 0)
1605320f6e0SAndrew Jeffery 			return rc;
1615320f6e0SAndrew Jeffery 
1625320f6e0SAndrew Jeffery 		free(path);
1635320f6e0SAndrew Jeffery 		free(paths);
1645320f6e0SAndrew Jeffery 	} else if (!strcmp(name, "file")) {
1655320f6e0SAndrew Jeffery 		char **paths = NULL;
1665320f6e0SAndrew Jeffery 		char *path = NULL;
1675320f6e0SAndrew Jeffery 
1685320f6e0SAndrew Jeffery 		rc = sd_bus_message_read_strv(m, &paths);
1695320f6e0SAndrew Jeffery 		if (rc < 0)
1705320f6e0SAndrew Jeffery 			return rc;
1715320f6e0SAndrew Jeffery 
1725320f6e0SAndrew Jeffery 		if (!(paths && *paths))
1735320f6e0SAndrew Jeffery 			return -EINVAL;
1745320f6e0SAndrew Jeffery 
1755320f6e0SAndrew Jeffery 		path = *paths;
1765320f6e0SAndrew Jeffery 
1775320f6e0SAndrew Jeffery 		backend = backend_get_file();
1785320f6e0SAndrew Jeffery 
1795320f6e0SAndrew Jeffery 		rc = control_set_backend(context, &backend, path);
1805320f6e0SAndrew Jeffery 		if (rc < 0)
1815320f6e0SAndrew Jeffery 			return rc;
1825320f6e0SAndrew Jeffery 
1835320f6e0SAndrew Jeffery 		free(path);
1845320f6e0SAndrew Jeffery 		free(paths);
1855320f6e0SAndrew Jeffery 	} else {
1865320f6e0SAndrew Jeffery 		return -EINVAL;
1875320f6e0SAndrew Jeffery 	}
1885320f6e0SAndrew Jeffery 
1895320f6e0SAndrew Jeffery 	rc = sd_bus_message_new_method_return(m, &n);
1905320f6e0SAndrew Jeffery 	if (rc < 0) {
1915320f6e0SAndrew Jeffery 		MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
1925320f6e0SAndrew Jeffery 		return rc;
1935320f6e0SAndrew Jeffery 	}
1945320f6e0SAndrew Jeffery 
195fac3689eSAndrew Jeffery 	rc = sd_bus_send(NULL, n, NULL);
196fac3689eSAndrew Jeffery 	sd_bus_message_unref(n);
197fac3689eSAndrew Jeffery 	return rc;
1985320f6e0SAndrew Jeffery }
1995320f6e0SAndrew Jeffery 
control_dbus_get_u8(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * ret_error)200*68a24c9eSPatrick Williams static int control_dbus_get_u8(sd_bus *bus __attribute__((unused)),
201*68a24c9eSPatrick Williams 			       const char *path,
202*68a24c9eSPatrick Williams 			       const char *interface __attribute__((unused)),
203*68a24c9eSPatrick Williams 			       const char *property,
20455f4d6f9SAndrew Jeffery 			       sd_bus_message *reply, void *userdata,
205*68a24c9eSPatrick Williams 			       sd_bus_error *ret_error __attribute__((unused)))
20655f4d6f9SAndrew Jeffery {
20755f4d6f9SAndrew Jeffery 	struct mbox_context *context = userdata;
20855f4d6f9SAndrew Jeffery 	uint8_t value;
20955f4d6f9SAndrew Jeffery 
21055f4d6f9SAndrew Jeffery 	assert(!strcmp(MBOX_DBUS_OBJECT, path));
21155f4d6f9SAndrew Jeffery 
21255f4d6f9SAndrew Jeffery 	if (!strcmp("DaemonState", property)) {
21355f4d6f9SAndrew Jeffery 		value = control_daemon_state(context);
21455f4d6f9SAndrew Jeffery 	} else if (!strcmp("LpcState", property)) {
21555f4d6f9SAndrew Jeffery 		value = control_lpc_state(context);
21655f4d6f9SAndrew Jeffery 	} else {
21755f4d6f9SAndrew Jeffery 		MSG_ERR("Unknown DBus property: %s\n", property);
21855f4d6f9SAndrew Jeffery 		return -EINVAL;
21955f4d6f9SAndrew Jeffery 	}
22055f4d6f9SAndrew Jeffery 
22155f4d6f9SAndrew Jeffery 	return sd_bus_message_append(reply, "y", value);
22255f4d6f9SAndrew Jeffery }
22355f4d6f9SAndrew Jeffery 
22455f4d6f9SAndrew Jeffery static const sd_bus_vtable mboxd_vtable[] = {
22555f4d6f9SAndrew Jeffery 	SD_BUS_VTABLE_START(0),
22655f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("Ping", NULL, NULL, &control_dbus_ping,
22755f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
22855f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("Reset", NULL, NULL, &control_dbus_reset,
22955f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
23055f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("Kill", NULL, NULL, &control_dbus_kill,
23155f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
23255f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("MarkFlashModified", NULL, NULL, &control_dbus_modified,
23355f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
23455f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("Suspend", NULL, NULL, &control_dbus_suspend,
23555f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
23655f4d6f9SAndrew Jeffery 	SD_BUS_METHOD("Resume", "b", NULL, &control_dbus_resume,
23755f4d6f9SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
2385320f6e0SAndrew Jeffery 	SD_BUS_METHOD("SetBackend", "sas", NULL, &control_dbus_set_backend,
2395320f6e0SAndrew Jeffery 		      SD_BUS_VTABLE_UNPRIVILEGED),
24055f4d6f9SAndrew Jeffery 	SD_BUS_PROPERTY("DaemonState", "y", &control_dbus_get_u8, 0,
24155f4d6f9SAndrew Jeffery 		        SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
24255f4d6f9SAndrew Jeffery 	SD_BUS_PROPERTY("LpcState", "y", &control_dbus_get_u8, 0,
24355f4d6f9SAndrew Jeffery 		        SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
24455f4d6f9SAndrew Jeffery 	SD_BUS_VTABLE_END
24555f4d6f9SAndrew Jeffery };
24655f4d6f9SAndrew Jeffery 
control_dbus_init(struct mbox_context * context)24755f4d6f9SAndrew Jeffery int control_dbus_init(struct mbox_context *context)
24855f4d6f9SAndrew Jeffery {
24955f4d6f9SAndrew Jeffery 	return sd_bus_add_object_vtable(context->bus, NULL,
25055f4d6f9SAndrew Jeffery 					MBOX_DBUS_OBJECT,
25155f4d6f9SAndrew Jeffery 					MBOX_DBUS_CONTROL_IFACE,
25255f4d6f9SAndrew Jeffery 					mboxd_vtable, context);
25355f4d6f9SAndrew Jeffery }
25455f4d6f9SAndrew Jeffery 
25555f4d6f9SAndrew Jeffery #define __unused __attribute__((unused))
control_dbus_free(struct mbox_context * context __unused)25655f4d6f9SAndrew Jeffery void control_dbus_free(struct mbox_context *context __unused)
25755f4d6f9SAndrew Jeffery {
25855f4d6f9SAndrew Jeffery 	return;
25955f4d6f9SAndrew Jeffery }
260