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