1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright (C) 2018 IBM Corp. 3 #include <errno.h> 4 #include <stdlib.h> 5 6 #include "common.h" 7 #include "dbus.h" 8 #include "control_dbus.h" 9 #include "mboxd.h" 10 11 /* Command IDs (Legacy interface) */ 12 #define DBUS_C_PING 0x00 13 #define DBUS_C_DAEMON_STATE 0x01 14 #define DBUS_C_RESET 0x02 15 #define DBUS_C_SUSPEND 0x03 16 #define DBUS_C_RESUME 0x04 17 #define DBUS_C_MODIFIED 0x05 18 #define DBUS_C_KILL 0x06 19 #define DBUS_C_LPC_STATE 0x07 20 #define NUM_DBUS_CMDS (DBUS_C_LPC_STATE + 1) 21 22 /* Return Values (Legacy interface) */ 23 #define DBUS_SUCCESS 0x00 /* Command Succeded */ 24 #define E_DBUS_INTERNAL 0x01 /* Internal DBUS Error */ 25 #define E_DBUS_INVAL 0x02 /* Invalid Command */ 26 #define E_DBUS_REJECTED 0x03 /* Daemon Rejected Request */ 27 #define E_DBUS_HARDWARE 0x04 /* BMC Hardware Error */ 28 #define E_DBUS_NO_MEM 0x05 /* Failed Memory Allocation */ 29 30 struct mbox_dbus_msg { 31 uint8_t cmd; 32 size_t num_args; 33 uint8_t *args; 34 }; 35 36 /* 37 * Command: DBUS Ping 38 * Ping the daemon 39 * 40 * Args: NONE 41 * Resp: NONE 42 */ 43 static int control_legacy_ping(struct mbox_context *context, 44 struct mbox_dbus_msg *req, 45 struct mbox_dbus_msg *resp) 46 { 47 return control_ping(context); 48 } 49 50 /* 51 * Command: DBUS Status 52 * Get the status of the daemon 53 * 54 * Args: NONE 55 * Resp[0]: Status Code 56 */ 57 static int control_legacy_daemon_state(struct mbox_context *context, 58 struct mbox_dbus_msg *req, 59 struct mbox_dbus_msg *resp) 60 { 61 resp->num_args = DAEMON_STATE_NUM_ARGS; 62 resp->args = calloc(resp->num_args, sizeof(*resp->args)); 63 resp->args[0] = control_daemon_state(context); 64 65 return 0; 66 } 67 68 /* 69 * Command: DBUS LPC State 70 * Get the state of the lpc bus mapping (whether it points to memory or flash 71 * 72 * Args: NONE 73 * Resp[0]: LPC Bus State Code 74 */ 75 static int control_legacy_lpc_state(struct mbox_context *context, 76 struct mbox_dbus_msg *req, 77 struct mbox_dbus_msg *resp) 78 { 79 resp->num_args = LPC_STATE_NUM_ARGS; 80 resp->args = calloc(resp->num_args, sizeof(*resp->args)); 81 resp->args[0] = control_lpc_state(context); 82 83 return 0; 84 } 85 86 /* 87 * Command: DBUS Reset 88 * Reset the daemon state, final operation TBA. 89 * For now we just point the lpc mapping back at the flash. 90 * 91 * Args: NONE 92 * Resp: NONE 93 */ 94 static int control_legacy_reset(struct mbox_context *context, 95 struct mbox_dbus_msg *req, 96 struct mbox_dbus_msg *resp) 97 { 98 int rc; 99 100 rc = control_reset(context); 101 102 /* Map return codes for compatibility */ 103 if (rc == -EBUSY) { 104 return -E_DBUS_REJECTED; 105 } else if (rc < 0) { 106 return -E_DBUS_HARDWARE; 107 } 108 109 return rc; 110 } 111 112 /* 113 * Command: DBUS Kill 114 * Stop the daemon 115 * 116 * Args: NONE 117 * Resp: NONE 118 */ 119 static int control_legacy_kill(struct mbox_context *context, 120 struct mbox_dbus_msg *req, 121 struct mbox_dbus_msg *resp) 122 { 123 return control_kill(context); 124 } 125 126 /* 127 * Command: DBUS Flash Modified 128 * Used to notify the daemon that the flash has been modified out from under 129 * it - We need to reset all out windows to ensure flash will be reloaded 130 * when a new window is opened. 131 * Note: We don't flush any previously opened windows 132 * 133 * Args: NONE 134 * Resp: NONE 135 */ 136 static int control_legacy_modified(struct mbox_context *context, 137 struct mbox_dbus_msg *req, 138 struct mbox_dbus_msg *resp) 139 { 140 return control_modified(context); 141 } 142 143 /* 144 * Command: DBUS Suspend 145 * Suspend the daemon to inhibit it from performing flash accesses. 146 * This is used to synchronise access to the flash between the daemon and 147 * directly from the BMC. 148 * 149 * Args: NONE 150 * Resp: NONE 151 */ 152 static int control_legacy_suspend(struct mbox_context *context, 153 struct mbox_dbus_msg *req, 154 struct mbox_dbus_msg *resp) 155 { 156 int rc; 157 158 rc = control_suspend(context); 159 if (rc < 0) { 160 /* Map return codes for compatibility */ 161 return -E_DBUS_HARDWARE; 162 } 163 164 return rc; 165 } 166 167 /* 168 * Command: DBUS Resume 169 * Resume the daemon to let it perform flash accesses again. 170 * 171 * Args[0]: Flash Modified (0 - no | 1 - yes) 172 * Resp: NONE 173 */ 174 static int control_legacy_resume(struct mbox_context *context, 175 struct mbox_dbus_msg *req, 176 struct mbox_dbus_msg *resp) 177 { 178 int rc; 179 180 if (req->num_args != 1) { 181 return -E_DBUS_INVAL; 182 } 183 184 rc = control_resume(context, req->args[0] == RESUME_FLASH_MODIFIED); 185 if (rc < 0) { 186 /* Map return codes for compatibility */ 187 rc = -E_DBUS_HARDWARE; 188 } 189 190 return rc; 191 } 192 193 typedef int (*control_action)(struct mbox_context *context, 194 struct mbox_dbus_msg *req, 195 struct mbox_dbus_msg *resp); 196 static const control_action dbus_handlers[NUM_DBUS_CMDS] = { 197 control_legacy_ping, 198 control_legacy_daemon_state, 199 control_legacy_reset, 200 control_legacy_suspend, 201 control_legacy_resume, 202 control_legacy_modified, 203 control_legacy_kill, 204 control_legacy_lpc_state 205 }; 206 207 static int method_cmd(sd_bus_message *m, void *userdata, 208 sd_bus_error *ret_error) 209 { 210 struct mbox_dbus_msg req = { 0 }, resp = { 0 }; 211 struct mbox_context *context; 212 sd_bus_message *n; 213 int rc, i; 214 215 context = (struct mbox_context *) userdata; 216 if (!context) { 217 MSG_ERR("DBUS Internal Error\n"); 218 rc = -E_DBUS_INTERNAL; 219 goto out; 220 } 221 222 /* Read the command */ 223 rc = sd_bus_message_read(m, "y", &req.cmd); 224 if (rc < 0) { 225 MSG_ERR("DBUS error reading message: %s\n", strerror(-rc)); 226 rc = -E_DBUS_INTERNAL; 227 goto out; 228 } 229 MSG_DBG("DBUS request: %u\n", req.cmd); 230 231 /* Read the args */ 232 rc = sd_bus_message_read_array(m, 'y', (const void **) &req.args, 233 &req.num_args); 234 if (rc < 0) { 235 MSG_ERR("DBUS error reading message: %s\n", strerror(-rc)); 236 rc = -E_DBUS_INTERNAL; 237 goto out; 238 } 239 MSG_DBG("DBUS num_args: %u\n", (unsigned) req.num_args); 240 for (i = 0; i < req.num_args; i++) { 241 MSG_DBG("DBUS arg[%d]: %u\n", i, req.args[i]); 242 } 243 244 /* Handle the command */ 245 if (req.cmd >= NUM_DBUS_CMDS) { 246 rc = -E_DBUS_INVAL; 247 MSG_ERR("Received unknown dbus cmd: %d\n", req.cmd); 248 } else { 249 rc = dbus_handlers[req.cmd](context, &req, &resp); 250 } 251 252 out: 253 if (rc < 0) { 254 resp.cmd = -rc; 255 } 256 rc = sd_bus_message_new_method_return(m, &n); /* Generate response */ 257 if (rc < 0) { 258 MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc); 259 goto cleanup; 260 } 261 262 rc = sd_bus_message_append(n, "y", resp.cmd); /* Set return code */ 263 if (rc < 0) { 264 MSG_ERR("sd_bus_message_append failed: %d\n", rc); 265 goto cleanup; 266 } 267 268 rc = sd_bus_message_append_array(n, 'y', resp.args, resp.num_args); 269 if (rc < 0) { 270 MSG_ERR("sd_bus_message_append_array failed: %d\n", rc); 271 goto cleanup; 272 } 273 274 MSG_DBG("DBUS response: %u\n", resp.cmd); 275 MSG_DBG("DBUS num_args: %u\n", (unsigned) resp.num_args); 276 for (i = 0; i < resp.num_args; i++) { 277 MSG_DBG("DBUS arg[%d]: %u\n", i, resp.args[i]); 278 } 279 280 rc = sd_bus_send(NULL, n, NULL); /* Send response */ 281 if (rc < 0) 282 MSG_ERR("sd_bus_send failed: %d\n", rc); 283 284 cleanup: 285 free(resp.args); 286 return rc; 287 } 288 289 static const sd_bus_vtable control_legacy_vtable[] = { 290 SD_BUS_VTABLE_START(0), 291 SD_BUS_METHOD("cmd", "yay", "yay", &method_cmd, 292 SD_BUS_VTABLE_UNPRIVILEGED), 293 SD_BUS_VTABLE_END 294 }; 295 296 int control_legacy_init(struct mbox_context *context) 297 { 298 int rc; 299 300 rc = sd_bus_add_object_vtable(context->bus, NULL, 301 MBOX_DBUS_LEGACY_OBJECT, 302 MBOX_DBUS_LEGACY_NAME, 303 control_legacy_vtable, context); 304 if (rc < 0) { 305 MSG_ERR("Failed to register vtable: %s\n", strerror(-rc)); 306 return rc; 307 } 308 309 return sd_bus_request_name(context->bus, MBOX_DBUS_LEGACY_NAME, 310 SD_BUS_NAME_ALLOW_REPLACEMENT | 311 SD_BUS_NAME_REPLACE_EXISTING); 312 } 313 314 void control_legacy_free(struct mbox_context *context __attribute__((unused))) 315 { 316 return; 317 } 318