168023074SAndrew Jeffery // SPDX-License-Identifier: Apache-2.0 268023074SAndrew Jeffery // Copyright (C) 2018 IBM Corp. 368023074SAndrew Jeffery #include <errno.h> 468023074SAndrew Jeffery #include <stdlib.h> 568023074SAndrew Jeffery 668023074SAndrew Jeffery #include "common.h" 768023074SAndrew Jeffery #include "dbus.h" 855f4d6f9SAndrew Jeffery #include "control_dbus.h" 9*26558dbbSAndrew Jeffery #include "mboxd.h" 1068023074SAndrew Jeffery 11ef9e62d3SAndrew Jeffery /* Command IDs (Legacy interface) */ 12ef9e62d3SAndrew Jeffery #define DBUS_C_PING 0x00 13ef9e62d3SAndrew Jeffery #define DBUS_C_DAEMON_STATE 0x01 14ef9e62d3SAndrew Jeffery #define DBUS_C_RESET 0x02 15ef9e62d3SAndrew Jeffery #define DBUS_C_SUSPEND 0x03 16ef9e62d3SAndrew Jeffery #define DBUS_C_RESUME 0x04 17ef9e62d3SAndrew Jeffery #define DBUS_C_MODIFIED 0x05 18ef9e62d3SAndrew Jeffery #define DBUS_C_KILL 0x06 19ef9e62d3SAndrew Jeffery #define DBUS_C_LPC_STATE 0x07 20ef9e62d3SAndrew Jeffery #define NUM_DBUS_CMDS (DBUS_C_LPC_STATE + 1) 21ef9e62d3SAndrew Jeffery 22ef9e62d3SAndrew Jeffery /* Return Values (Legacy interface) */ 23ef9e62d3SAndrew Jeffery #define DBUS_SUCCESS 0x00 /* Command Succeded */ 24ef9e62d3SAndrew Jeffery #define E_DBUS_INTERNAL 0x01 /* Internal DBUS Error */ 25ef9e62d3SAndrew Jeffery #define E_DBUS_INVAL 0x02 /* Invalid Command */ 26ef9e62d3SAndrew Jeffery #define E_DBUS_REJECTED 0x03 /* Daemon Rejected Request */ 27ef9e62d3SAndrew Jeffery #define E_DBUS_HARDWARE 0x04 /* BMC Hardware Error */ 28ef9e62d3SAndrew Jeffery #define E_DBUS_NO_MEM 0x05 /* Failed Memory Allocation */ 29ef9e62d3SAndrew Jeffery 30ef9e62d3SAndrew Jeffery struct mbox_dbus_msg { 31ef9e62d3SAndrew Jeffery uint8_t cmd; 32ef9e62d3SAndrew Jeffery size_t num_args; 33ef9e62d3SAndrew Jeffery uint8_t *args; 34ef9e62d3SAndrew Jeffery }; 35ef9e62d3SAndrew Jeffery 3668023074SAndrew Jeffery /* 3768023074SAndrew Jeffery * Command: DBUS Ping 3868023074SAndrew Jeffery * Ping the daemon 3968023074SAndrew Jeffery * 4068023074SAndrew Jeffery * Args: NONE 4168023074SAndrew Jeffery * Resp: NONE 4268023074SAndrew Jeffery */ 4368023074SAndrew Jeffery static int control_legacy_ping(struct mbox_context *context, 4468023074SAndrew Jeffery struct mbox_dbus_msg *req, 4568023074SAndrew Jeffery struct mbox_dbus_msg *resp) 4668023074SAndrew Jeffery { 4768023074SAndrew Jeffery return control_ping(context); 4868023074SAndrew Jeffery } 4968023074SAndrew Jeffery 5068023074SAndrew Jeffery /* 5168023074SAndrew Jeffery * Command: DBUS Status 5268023074SAndrew Jeffery * Get the status of the daemon 5368023074SAndrew Jeffery * 5468023074SAndrew Jeffery * Args: NONE 5568023074SAndrew Jeffery * Resp[0]: Status Code 5668023074SAndrew Jeffery */ 5768023074SAndrew Jeffery static int control_legacy_daemon_state(struct mbox_context *context, 5868023074SAndrew Jeffery struct mbox_dbus_msg *req, 5968023074SAndrew Jeffery struct mbox_dbus_msg *resp) 6068023074SAndrew Jeffery { 6168023074SAndrew Jeffery resp->num_args = DAEMON_STATE_NUM_ARGS; 6268023074SAndrew Jeffery resp->args = calloc(resp->num_args, sizeof(*resp->args)); 6368023074SAndrew Jeffery resp->args[0] = control_daemon_state(context); 6468023074SAndrew Jeffery 6568023074SAndrew Jeffery return 0; 6668023074SAndrew Jeffery } 6768023074SAndrew Jeffery 6868023074SAndrew Jeffery /* 6968023074SAndrew Jeffery * Command: DBUS LPC State 7068023074SAndrew Jeffery * Get the state of the lpc bus mapping (whether it points to memory or flash 7168023074SAndrew Jeffery * 7268023074SAndrew Jeffery * Args: NONE 7368023074SAndrew Jeffery * Resp[0]: LPC Bus State Code 7468023074SAndrew Jeffery */ 7568023074SAndrew Jeffery static int control_legacy_lpc_state(struct mbox_context *context, 7668023074SAndrew Jeffery struct mbox_dbus_msg *req, 7768023074SAndrew Jeffery struct mbox_dbus_msg *resp) 7868023074SAndrew Jeffery { 7968023074SAndrew Jeffery resp->num_args = LPC_STATE_NUM_ARGS; 8068023074SAndrew Jeffery resp->args = calloc(resp->num_args, sizeof(*resp->args)); 8168023074SAndrew Jeffery resp->args[0] = control_lpc_state(context); 8268023074SAndrew Jeffery 8368023074SAndrew Jeffery return 0; 8468023074SAndrew Jeffery } 8568023074SAndrew Jeffery 8668023074SAndrew Jeffery /* 8768023074SAndrew Jeffery * Command: DBUS Reset 8868023074SAndrew Jeffery * Reset the daemon state, final operation TBA. 8968023074SAndrew Jeffery * For now we just point the lpc mapping back at the flash. 9068023074SAndrew Jeffery * 9168023074SAndrew Jeffery * Args: NONE 9268023074SAndrew Jeffery * Resp: NONE 9368023074SAndrew Jeffery */ 9468023074SAndrew Jeffery static int control_legacy_reset(struct mbox_context *context, 9568023074SAndrew Jeffery struct mbox_dbus_msg *req, 9668023074SAndrew Jeffery struct mbox_dbus_msg *resp) 9768023074SAndrew Jeffery { 9868023074SAndrew Jeffery int rc; 9968023074SAndrew Jeffery 10068023074SAndrew Jeffery rc = control_reset(context); 10168023074SAndrew Jeffery 10268023074SAndrew Jeffery /* Map return codes for compatibility */ 10368023074SAndrew Jeffery if (rc == -EBUSY) { 10468023074SAndrew Jeffery return -E_DBUS_REJECTED; 10568023074SAndrew Jeffery } else if (rc < 0) { 10668023074SAndrew Jeffery return -E_DBUS_HARDWARE; 10768023074SAndrew Jeffery } 10868023074SAndrew Jeffery 10968023074SAndrew Jeffery return rc; 11068023074SAndrew Jeffery } 11168023074SAndrew Jeffery 11268023074SAndrew Jeffery /* 11368023074SAndrew Jeffery * Command: DBUS Kill 11468023074SAndrew Jeffery * Stop the daemon 11568023074SAndrew Jeffery * 11668023074SAndrew Jeffery * Args: NONE 11768023074SAndrew Jeffery * Resp: NONE 11868023074SAndrew Jeffery */ 11968023074SAndrew Jeffery static int control_legacy_kill(struct mbox_context *context, 12068023074SAndrew Jeffery struct mbox_dbus_msg *req, 12168023074SAndrew Jeffery struct mbox_dbus_msg *resp) 12268023074SAndrew Jeffery { 12368023074SAndrew Jeffery return control_kill(context); 12468023074SAndrew Jeffery } 12568023074SAndrew Jeffery 12668023074SAndrew Jeffery /* 12768023074SAndrew Jeffery * Command: DBUS Flash Modified 12868023074SAndrew Jeffery * Used to notify the daemon that the flash has been modified out from under 12968023074SAndrew Jeffery * it - We need to reset all out windows to ensure flash will be reloaded 13068023074SAndrew Jeffery * when a new window is opened. 13168023074SAndrew Jeffery * Note: We don't flush any previously opened windows 13268023074SAndrew Jeffery * 13368023074SAndrew Jeffery * Args: NONE 13468023074SAndrew Jeffery * Resp: NONE 13568023074SAndrew Jeffery */ 13668023074SAndrew Jeffery static int control_legacy_modified(struct mbox_context *context, 13768023074SAndrew Jeffery struct mbox_dbus_msg *req, 13868023074SAndrew Jeffery struct mbox_dbus_msg *resp) 13968023074SAndrew Jeffery { 14068023074SAndrew Jeffery return control_modified(context); 14168023074SAndrew Jeffery } 14268023074SAndrew Jeffery 14368023074SAndrew Jeffery /* 14468023074SAndrew Jeffery * Command: DBUS Suspend 14568023074SAndrew Jeffery * Suspend the daemon to inhibit it from performing flash accesses. 14668023074SAndrew Jeffery * This is used to synchronise access to the flash between the daemon and 14768023074SAndrew Jeffery * directly from the BMC. 14868023074SAndrew Jeffery * 14968023074SAndrew Jeffery * Args: NONE 15068023074SAndrew Jeffery * Resp: NONE 15168023074SAndrew Jeffery */ 15268023074SAndrew Jeffery static int control_legacy_suspend(struct mbox_context *context, 15368023074SAndrew Jeffery struct mbox_dbus_msg *req, 15468023074SAndrew Jeffery struct mbox_dbus_msg *resp) 15568023074SAndrew Jeffery { 15668023074SAndrew Jeffery int rc; 15768023074SAndrew Jeffery 15868023074SAndrew Jeffery rc = control_suspend(context); 15968023074SAndrew Jeffery if (rc < 0) { 16068023074SAndrew Jeffery /* Map return codes for compatibility */ 16168023074SAndrew Jeffery return -E_DBUS_HARDWARE; 16268023074SAndrew Jeffery } 16368023074SAndrew Jeffery 16468023074SAndrew Jeffery return rc; 16568023074SAndrew Jeffery } 16668023074SAndrew Jeffery 16768023074SAndrew Jeffery /* 16868023074SAndrew Jeffery * Command: DBUS Resume 16968023074SAndrew Jeffery * Resume the daemon to let it perform flash accesses again. 17068023074SAndrew Jeffery * 17168023074SAndrew Jeffery * Args[0]: Flash Modified (0 - no | 1 - yes) 17268023074SAndrew Jeffery * Resp: NONE 17368023074SAndrew Jeffery */ 17468023074SAndrew Jeffery static int control_legacy_resume(struct mbox_context *context, 17568023074SAndrew Jeffery struct mbox_dbus_msg *req, 17668023074SAndrew Jeffery struct mbox_dbus_msg *resp) 17768023074SAndrew Jeffery { 17868023074SAndrew Jeffery int rc; 17968023074SAndrew Jeffery 18068023074SAndrew Jeffery if (req->num_args != 1) { 18168023074SAndrew Jeffery return -E_DBUS_INVAL; 18268023074SAndrew Jeffery } 18368023074SAndrew Jeffery 18468023074SAndrew Jeffery rc = control_resume(context, req->args[0] == RESUME_FLASH_MODIFIED); 18568023074SAndrew Jeffery if (rc < 0) { 18668023074SAndrew Jeffery /* Map return codes for compatibility */ 18768023074SAndrew Jeffery rc = -E_DBUS_HARDWARE; 18868023074SAndrew Jeffery } 18968023074SAndrew Jeffery 19068023074SAndrew Jeffery return rc; 19168023074SAndrew Jeffery } 19268023074SAndrew Jeffery 19368023074SAndrew Jeffery typedef int (*control_action)(struct mbox_context *context, 19468023074SAndrew Jeffery struct mbox_dbus_msg *req, 19568023074SAndrew Jeffery struct mbox_dbus_msg *resp); 19668023074SAndrew Jeffery static const control_action dbus_handlers[NUM_DBUS_CMDS] = { 19768023074SAndrew Jeffery control_legacy_ping, 19868023074SAndrew Jeffery control_legacy_daemon_state, 19968023074SAndrew Jeffery control_legacy_reset, 20068023074SAndrew Jeffery control_legacy_suspend, 20168023074SAndrew Jeffery control_legacy_resume, 20268023074SAndrew Jeffery control_legacy_modified, 20368023074SAndrew Jeffery control_legacy_kill, 20468023074SAndrew Jeffery control_legacy_lpc_state 20568023074SAndrew Jeffery }; 20668023074SAndrew Jeffery 20768023074SAndrew Jeffery static int method_cmd(sd_bus_message *m, void *userdata, 20868023074SAndrew Jeffery sd_bus_error *ret_error) 20968023074SAndrew Jeffery { 21068023074SAndrew Jeffery struct mbox_dbus_msg req = { 0 }, resp = { 0 }; 21168023074SAndrew Jeffery struct mbox_context *context; 21268023074SAndrew Jeffery sd_bus_message *n; 21368023074SAndrew Jeffery int rc, i; 21468023074SAndrew Jeffery 21568023074SAndrew Jeffery context = (struct mbox_context *) userdata; 21668023074SAndrew Jeffery if (!context) { 21768023074SAndrew Jeffery MSG_ERR("DBUS Internal Error\n"); 21868023074SAndrew Jeffery rc = -E_DBUS_INTERNAL; 21968023074SAndrew Jeffery goto out; 22068023074SAndrew Jeffery } 22168023074SAndrew Jeffery 22268023074SAndrew Jeffery /* Read the command */ 22368023074SAndrew Jeffery rc = sd_bus_message_read(m, "y", &req.cmd); 22468023074SAndrew Jeffery if (rc < 0) { 22568023074SAndrew Jeffery MSG_ERR("DBUS error reading message: %s\n", strerror(-rc)); 22668023074SAndrew Jeffery rc = -E_DBUS_INTERNAL; 22768023074SAndrew Jeffery goto out; 22868023074SAndrew Jeffery } 22968023074SAndrew Jeffery MSG_DBG("DBUS request: %u\n", req.cmd); 23068023074SAndrew Jeffery 23168023074SAndrew Jeffery /* Read the args */ 23268023074SAndrew Jeffery rc = sd_bus_message_read_array(m, 'y', (const void **) &req.args, 23368023074SAndrew Jeffery &req.num_args); 23468023074SAndrew Jeffery if (rc < 0) { 23568023074SAndrew Jeffery MSG_ERR("DBUS error reading message: %s\n", strerror(-rc)); 23668023074SAndrew Jeffery rc = -E_DBUS_INTERNAL; 23768023074SAndrew Jeffery goto out; 23868023074SAndrew Jeffery } 23968023074SAndrew Jeffery MSG_DBG("DBUS num_args: %u\n", (unsigned) req.num_args); 24068023074SAndrew Jeffery for (i = 0; i < req.num_args; i++) { 24168023074SAndrew Jeffery MSG_DBG("DBUS arg[%d]: %u\n", i, req.args[i]); 24268023074SAndrew Jeffery } 24368023074SAndrew Jeffery 24468023074SAndrew Jeffery /* Handle the command */ 24568023074SAndrew Jeffery if (req.cmd >= NUM_DBUS_CMDS) { 24668023074SAndrew Jeffery rc = -E_DBUS_INVAL; 24768023074SAndrew Jeffery MSG_ERR("Received unknown dbus cmd: %d\n", req.cmd); 24868023074SAndrew Jeffery } else { 24968023074SAndrew Jeffery rc = dbus_handlers[req.cmd](context, &req, &resp); 25068023074SAndrew Jeffery } 25168023074SAndrew Jeffery 25268023074SAndrew Jeffery out: 25368023074SAndrew Jeffery if (rc < 0) { 25468023074SAndrew Jeffery resp.cmd = -rc; 25568023074SAndrew Jeffery } 25668023074SAndrew Jeffery rc = sd_bus_message_new_method_return(m, &n); /* Generate response */ 25768023074SAndrew Jeffery if (rc < 0) { 25868023074SAndrew Jeffery MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc); 25968023074SAndrew Jeffery goto cleanup; 26068023074SAndrew Jeffery } 26168023074SAndrew Jeffery 26268023074SAndrew Jeffery rc = sd_bus_message_append(n, "y", resp.cmd); /* Set return code */ 26368023074SAndrew Jeffery if (rc < 0) { 26468023074SAndrew Jeffery MSG_ERR("sd_bus_message_append failed: %d\n", rc); 26568023074SAndrew Jeffery goto cleanup; 26668023074SAndrew Jeffery } 26768023074SAndrew Jeffery 26868023074SAndrew Jeffery rc = sd_bus_message_append_array(n, 'y', resp.args, resp.num_args); 26968023074SAndrew Jeffery if (rc < 0) { 27068023074SAndrew Jeffery MSG_ERR("sd_bus_message_append_array failed: %d\n", rc); 27168023074SAndrew Jeffery goto cleanup; 27268023074SAndrew Jeffery } 27368023074SAndrew Jeffery 27468023074SAndrew Jeffery MSG_DBG("DBUS response: %u\n", resp.cmd); 27568023074SAndrew Jeffery MSG_DBG("DBUS num_args: %u\n", (unsigned) resp.num_args); 27668023074SAndrew Jeffery for (i = 0; i < resp.num_args; i++) { 27768023074SAndrew Jeffery MSG_DBG("DBUS arg[%d]: %u\n", i, resp.args[i]); 27868023074SAndrew Jeffery } 27968023074SAndrew Jeffery 28068023074SAndrew Jeffery rc = sd_bus_send(NULL, n, NULL); /* Send response */ 28168023074SAndrew Jeffery if (rc < 0) 28268023074SAndrew Jeffery MSG_ERR("sd_bus_send failed: %d\n", rc); 28368023074SAndrew Jeffery 28468023074SAndrew Jeffery cleanup: 28568023074SAndrew Jeffery free(resp.args); 28668023074SAndrew Jeffery return rc; 28768023074SAndrew Jeffery } 28868023074SAndrew Jeffery 28968023074SAndrew Jeffery static const sd_bus_vtable control_legacy_vtable[] = { 29068023074SAndrew Jeffery SD_BUS_VTABLE_START(0), 29168023074SAndrew Jeffery SD_BUS_METHOD("cmd", "yay", "yay", &method_cmd, 29268023074SAndrew Jeffery SD_BUS_VTABLE_UNPRIVILEGED), 29368023074SAndrew Jeffery SD_BUS_VTABLE_END 29468023074SAndrew Jeffery }; 29568023074SAndrew Jeffery 29668023074SAndrew Jeffery int control_legacy_init(struct mbox_context *context) 29768023074SAndrew Jeffery { 29868023074SAndrew Jeffery int rc; 29968023074SAndrew Jeffery 30068023074SAndrew Jeffery rc = sd_bus_add_object_vtable(context->bus, NULL, 30168023074SAndrew Jeffery MBOX_DBUS_LEGACY_OBJECT, 30268023074SAndrew Jeffery MBOX_DBUS_LEGACY_NAME, 30368023074SAndrew Jeffery control_legacy_vtable, context); 30468023074SAndrew Jeffery if (rc < 0) { 30568023074SAndrew Jeffery MSG_ERR("Failed to register vtable: %s\n", strerror(-rc)); 30668023074SAndrew Jeffery return rc; 30768023074SAndrew Jeffery } 30868023074SAndrew Jeffery 30968023074SAndrew Jeffery return sd_bus_request_name(context->bus, MBOX_DBUS_LEGACY_NAME, 31068023074SAndrew Jeffery SD_BUS_NAME_ALLOW_REPLACEMENT | 31168023074SAndrew Jeffery SD_BUS_NAME_REPLACE_EXISTING); 31268023074SAndrew Jeffery } 31368023074SAndrew Jeffery 31468023074SAndrew Jeffery void control_legacy_free(struct mbox_context *context __attribute__((unused))) 31568023074SAndrew Jeffery { 31668023074SAndrew Jeffery return; 31768023074SAndrew Jeffery } 318