1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright (C) 2018 IBM Corp. 3 #include <assert.h> 4 #include <errno.h> 5 #include <systemd/sd-bus.h> 6 7 #include "common.h" 8 #include "dbus.h" 9 #include "control_dbus.h" 10 #include "mboxd.h" 11 12 typedef int (*control_action)(struct mbox_context *context); 13 14 static int control_dbus_directive(sd_bus_message *m, void *userdata, 15 sd_bus_error *ret_error, 16 control_action action) 17 { 18 struct mbox_context *context; 19 sd_bus_message *n; 20 int rc; 21 22 if (!action) { 23 MSG_ERR("No action provided\n"); 24 return -EINVAL; 25 } 26 27 context = (struct mbox_context *) userdata; 28 if (!context) { 29 MSG_ERR("DBUS Internal Error\n"); 30 return -EINVAL; 31 } 32 33 rc = action(context); 34 if (rc < 0) { 35 MSG_ERR("Action failed: %d\n", rc); 36 return rc; 37 } 38 39 rc = sd_bus_message_new_method_return(m, &n); 40 if (rc < 0) { 41 MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc); 42 return rc; 43 } 44 45 return sd_bus_send(NULL, n, NULL); 46 } 47 48 static int control_dbus_ping(sd_bus_message *m, void *userdata, 49 sd_bus_error *ret_error) 50 { 51 return control_dbus_directive(m, userdata, ret_error, control_ping); 52 } 53 54 static int control_dbus_reset(sd_bus_message *m, void *userdata, 55 sd_bus_error *ret_error) 56 { 57 return control_dbus_directive(m, userdata, ret_error, control_reset); 58 } 59 60 static int control_dbus_kill(sd_bus_message *m, void *userdata, 61 sd_bus_error *ret_error) 62 { 63 return control_dbus_directive(m, userdata, ret_error, control_kill); 64 } 65 66 static int control_dbus_modified(sd_bus_message *m, void *userdata, 67 sd_bus_error *ret_error) 68 { 69 return control_dbus_directive(m, userdata, ret_error, control_modified); 70 } 71 72 static int control_dbus_suspend(sd_bus_message *m, void *userdata, 73 sd_bus_error *ret_error) 74 { 75 return control_dbus_directive(m, userdata, ret_error, control_suspend); 76 } 77 78 static int control_dbus_resume(sd_bus_message *m, void *userdata, 79 sd_bus_error *ret_error) 80 { 81 struct mbox_context *context; 82 sd_bus_message *n; 83 bool modified; 84 int rc; 85 86 context = (struct mbox_context *) userdata; 87 if (!context) { 88 MSG_ERR("DBUS Internal Error\n"); 89 return -EINVAL; 90 } 91 92 rc = sd_bus_message_read_basic(m, 'b', &modified); 93 if (rc < 0) { 94 MSG_ERR("DBUS error reading message: %s\n", strerror(-rc)); 95 return rc; 96 } 97 98 rc = control_resume(context, modified); 99 if (rc < 0) 100 return rc; 101 102 rc = sd_bus_message_new_method_return(m, &n); 103 if (rc < 0) { 104 MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc); 105 return rc; 106 } 107 108 return sd_bus_send(NULL, n, NULL); 109 } 110 111 static int control_dbus_get_u8(sd_bus *bus, const char *path, 112 const char *interface, const char *property, 113 sd_bus_message *reply, void *userdata, 114 sd_bus_error *ret_error) 115 { 116 struct mbox_context *context = userdata; 117 uint8_t value; 118 119 assert(!strcmp(MBOX_DBUS_OBJECT, path)); 120 121 if (!strcmp("DaemonState", property)) { 122 value = control_daemon_state(context); 123 } else if (!strcmp("LpcState", property)) { 124 value = control_lpc_state(context); 125 } else { 126 MSG_ERR("Unknown DBus property: %s\n", property); 127 return -EINVAL; 128 } 129 130 return sd_bus_message_append(reply, "y", value); 131 } 132 133 static const sd_bus_vtable mboxd_vtable[] = { 134 SD_BUS_VTABLE_START(0), 135 SD_BUS_METHOD("Ping", NULL, NULL, &control_dbus_ping, 136 SD_BUS_VTABLE_UNPRIVILEGED), 137 SD_BUS_METHOD("Reset", NULL, NULL, &control_dbus_reset, 138 SD_BUS_VTABLE_UNPRIVILEGED), 139 SD_BUS_METHOD("Kill", NULL, NULL, &control_dbus_kill, 140 SD_BUS_VTABLE_UNPRIVILEGED), 141 SD_BUS_METHOD("MarkFlashModified", NULL, NULL, &control_dbus_modified, 142 SD_BUS_VTABLE_UNPRIVILEGED), 143 SD_BUS_METHOD("Suspend", NULL, NULL, &control_dbus_suspend, 144 SD_BUS_VTABLE_UNPRIVILEGED), 145 SD_BUS_METHOD("Resume", "b", NULL, &control_dbus_resume, 146 SD_BUS_VTABLE_UNPRIVILEGED), 147 SD_BUS_PROPERTY("DaemonState", "y", &control_dbus_get_u8, 0, 148 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), 149 SD_BUS_PROPERTY("LpcState", "y", &control_dbus_get_u8, 0, 150 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), 151 SD_BUS_VTABLE_END 152 }; 153 154 int control_dbus_init(struct mbox_context *context) 155 { 156 return sd_bus_add_object_vtable(context->bus, NULL, 157 MBOX_DBUS_OBJECT, 158 MBOX_DBUS_CONTROL_IFACE, 159 mboxd_vtable, context); 160 } 161 162 #define __unused __attribute__((unused)) 163 void control_dbus_free(struct mbox_context *context __unused) 164 { 165 return; 166 } 167