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