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" 8*55f4d6f9SAndrew Jeffery #include "control_dbus.h" 968023074SAndrew Jeffery #include "mbox.h" 1068023074SAndrew Jeffery 1168023074SAndrew Jeffery /* 1268023074SAndrew Jeffery * Command: DBUS Ping 1368023074SAndrew Jeffery * Ping the daemon 1468023074SAndrew Jeffery * 1568023074SAndrew Jeffery * Args: NONE 1668023074SAndrew Jeffery * Resp: NONE 1768023074SAndrew Jeffery */ 1868023074SAndrew Jeffery static int control_legacy_ping(struct mbox_context *context, 1968023074SAndrew Jeffery struct mbox_dbus_msg *req, 2068023074SAndrew Jeffery struct mbox_dbus_msg *resp) 2168023074SAndrew Jeffery { 2268023074SAndrew Jeffery return control_ping(context); 2368023074SAndrew Jeffery } 2468023074SAndrew Jeffery 2568023074SAndrew Jeffery /* 2668023074SAndrew Jeffery * Command: DBUS Status 2768023074SAndrew Jeffery * Get the status of the daemon 2868023074SAndrew Jeffery * 2968023074SAndrew Jeffery * Args: NONE 3068023074SAndrew Jeffery * Resp[0]: Status Code 3168023074SAndrew Jeffery */ 3268023074SAndrew Jeffery static int control_legacy_daemon_state(struct mbox_context *context, 3368023074SAndrew Jeffery struct mbox_dbus_msg *req, 3468023074SAndrew Jeffery struct mbox_dbus_msg *resp) 3568023074SAndrew Jeffery { 3668023074SAndrew Jeffery resp->num_args = DAEMON_STATE_NUM_ARGS; 3768023074SAndrew Jeffery resp->args = calloc(resp->num_args, sizeof(*resp->args)); 3868023074SAndrew Jeffery resp->args[0] = control_daemon_state(context); 3968023074SAndrew Jeffery 4068023074SAndrew Jeffery return 0; 4168023074SAndrew Jeffery } 4268023074SAndrew Jeffery 4368023074SAndrew Jeffery /* 4468023074SAndrew Jeffery * Command: DBUS LPC State 4568023074SAndrew Jeffery * Get the state of the lpc bus mapping (whether it points to memory or flash 4668023074SAndrew Jeffery * 4768023074SAndrew Jeffery * Args: NONE 4868023074SAndrew Jeffery * Resp[0]: LPC Bus State Code 4968023074SAndrew Jeffery */ 5068023074SAndrew Jeffery static int control_legacy_lpc_state(struct mbox_context *context, 5168023074SAndrew Jeffery struct mbox_dbus_msg *req, 5268023074SAndrew Jeffery struct mbox_dbus_msg *resp) 5368023074SAndrew Jeffery { 5468023074SAndrew Jeffery resp->num_args = LPC_STATE_NUM_ARGS; 5568023074SAndrew Jeffery resp->args = calloc(resp->num_args, sizeof(*resp->args)); 5668023074SAndrew Jeffery resp->args[0] = control_lpc_state(context); 5768023074SAndrew Jeffery 5868023074SAndrew Jeffery return 0; 5968023074SAndrew Jeffery } 6068023074SAndrew Jeffery 6168023074SAndrew Jeffery /* 6268023074SAndrew Jeffery * Command: DBUS Reset 6368023074SAndrew Jeffery * Reset the daemon state, final operation TBA. 6468023074SAndrew Jeffery * For now we just point the lpc mapping back at the flash. 6568023074SAndrew Jeffery * 6668023074SAndrew Jeffery * Args: NONE 6768023074SAndrew Jeffery * Resp: NONE 6868023074SAndrew Jeffery */ 6968023074SAndrew Jeffery static int control_legacy_reset(struct mbox_context *context, 7068023074SAndrew Jeffery struct mbox_dbus_msg *req, 7168023074SAndrew Jeffery struct mbox_dbus_msg *resp) 7268023074SAndrew Jeffery { 7368023074SAndrew Jeffery int rc; 7468023074SAndrew Jeffery 7568023074SAndrew Jeffery rc = control_reset(context); 7668023074SAndrew Jeffery 7768023074SAndrew Jeffery /* Map return codes for compatibility */ 7868023074SAndrew Jeffery if (rc == -EBUSY) { 7968023074SAndrew Jeffery return -E_DBUS_REJECTED; 8068023074SAndrew Jeffery } else if (rc < 0) { 8168023074SAndrew Jeffery return -E_DBUS_HARDWARE; 8268023074SAndrew Jeffery } 8368023074SAndrew Jeffery 8468023074SAndrew Jeffery return rc; 8568023074SAndrew Jeffery } 8668023074SAndrew Jeffery 8768023074SAndrew Jeffery /* 8868023074SAndrew Jeffery * Command: DBUS Kill 8968023074SAndrew Jeffery * Stop the daemon 9068023074SAndrew Jeffery * 9168023074SAndrew Jeffery * Args: NONE 9268023074SAndrew Jeffery * Resp: NONE 9368023074SAndrew Jeffery */ 9468023074SAndrew Jeffery static int control_legacy_kill(struct mbox_context *context, 9568023074SAndrew Jeffery struct mbox_dbus_msg *req, 9668023074SAndrew Jeffery struct mbox_dbus_msg *resp) 9768023074SAndrew Jeffery { 9868023074SAndrew Jeffery return control_kill(context); 9968023074SAndrew Jeffery } 10068023074SAndrew Jeffery 10168023074SAndrew Jeffery /* 10268023074SAndrew Jeffery * Command: DBUS Flash Modified 10368023074SAndrew Jeffery * Used to notify the daemon that the flash has been modified out from under 10468023074SAndrew Jeffery * it - We need to reset all out windows to ensure flash will be reloaded 10568023074SAndrew Jeffery * when a new window is opened. 10668023074SAndrew Jeffery * Note: We don't flush any previously opened windows 10768023074SAndrew Jeffery * 10868023074SAndrew Jeffery * Args: NONE 10968023074SAndrew Jeffery * Resp: NONE 11068023074SAndrew Jeffery */ 11168023074SAndrew Jeffery static int control_legacy_modified(struct mbox_context *context, 11268023074SAndrew Jeffery struct mbox_dbus_msg *req, 11368023074SAndrew Jeffery struct mbox_dbus_msg *resp) 11468023074SAndrew Jeffery { 11568023074SAndrew Jeffery return control_modified(context); 11668023074SAndrew Jeffery } 11768023074SAndrew Jeffery 11868023074SAndrew Jeffery /* 11968023074SAndrew Jeffery * Command: DBUS Suspend 12068023074SAndrew Jeffery * Suspend the daemon to inhibit it from performing flash accesses. 12168023074SAndrew Jeffery * This is used to synchronise access to the flash between the daemon and 12268023074SAndrew Jeffery * directly from the BMC. 12368023074SAndrew Jeffery * 12468023074SAndrew Jeffery * Args: NONE 12568023074SAndrew Jeffery * Resp: NONE 12668023074SAndrew Jeffery */ 12768023074SAndrew Jeffery static int control_legacy_suspend(struct mbox_context *context, 12868023074SAndrew Jeffery struct mbox_dbus_msg *req, 12968023074SAndrew Jeffery struct mbox_dbus_msg *resp) 13068023074SAndrew Jeffery { 13168023074SAndrew Jeffery int rc; 13268023074SAndrew Jeffery 13368023074SAndrew Jeffery rc = control_suspend(context); 13468023074SAndrew Jeffery if (rc < 0) { 13568023074SAndrew Jeffery /* Map return codes for compatibility */ 13668023074SAndrew Jeffery return -E_DBUS_HARDWARE; 13768023074SAndrew Jeffery } 13868023074SAndrew Jeffery 13968023074SAndrew Jeffery return rc; 14068023074SAndrew Jeffery } 14168023074SAndrew Jeffery 14268023074SAndrew Jeffery /* 14368023074SAndrew Jeffery * Command: DBUS Resume 14468023074SAndrew Jeffery * Resume the daemon to let it perform flash accesses again. 14568023074SAndrew Jeffery * 14668023074SAndrew Jeffery * Args[0]: Flash Modified (0 - no | 1 - yes) 14768023074SAndrew Jeffery * Resp: NONE 14868023074SAndrew Jeffery */ 14968023074SAndrew Jeffery static int control_legacy_resume(struct mbox_context *context, 15068023074SAndrew Jeffery struct mbox_dbus_msg *req, 15168023074SAndrew Jeffery struct mbox_dbus_msg *resp) 15268023074SAndrew Jeffery { 15368023074SAndrew Jeffery int rc; 15468023074SAndrew Jeffery 15568023074SAndrew Jeffery if (req->num_args != 1) { 15668023074SAndrew Jeffery return -E_DBUS_INVAL; 15768023074SAndrew Jeffery } 15868023074SAndrew Jeffery 15968023074SAndrew Jeffery rc = control_resume(context, req->args[0] == RESUME_FLASH_MODIFIED); 16068023074SAndrew Jeffery if (rc < 0) { 16168023074SAndrew Jeffery /* Map return codes for compatibility */ 16268023074SAndrew Jeffery rc = -E_DBUS_HARDWARE; 16368023074SAndrew Jeffery } 16468023074SAndrew Jeffery 16568023074SAndrew Jeffery return rc; 16668023074SAndrew Jeffery } 16768023074SAndrew Jeffery 16868023074SAndrew Jeffery typedef int (*control_action)(struct mbox_context *context, 16968023074SAndrew Jeffery struct mbox_dbus_msg *req, 17068023074SAndrew Jeffery struct mbox_dbus_msg *resp); 17168023074SAndrew Jeffery static const control_action dbus_handlers[NUM_DBUS_CMDS] = { 17268023074SAndrew Jeffery control_legacy_ping, 17368023074SAndrew Jeffery control_legacy_daemon_state, 17468023074SAndrew Jeffery control_legacy_reset, 17568023074SAndrew Jeffery control_legacy_suspend, 17668023074SAndrew Jeffery control_legacy_resume, 17768023074SAndrew Jeffery control_legacy_modified, 17868023074SAndrew Jeffery control_legacy_kill, 17968023074SAndrew Jeffery control_legacy_lpc_state 18068023074SAndrew Jeffery }; 18168023074SAndrew Jeffery 18268023074SAndrew Jeffery static int method_cmd(sd_bus_message *m, void *userdata, 18368023074SAndrew Jeffery sd_bus_error *ret_error) 18468023074SAndrew Jeffery { 18568023074SAndrew Jeffery struct mbox_dbus_msg req = { 0 }, resp = { 0 }; 18668023074SAndrew Jeffery struct mbox_context *context; 18768023074SAndrew Jeffery sd_bus_message *n; 18868023074SAndrew Jeffery int rc, i; 18968023074SAndrew Jeffery 19068023074SAndrew Jeffery context = (struct mbox_context *) userdata; 19168023074SAndrew Jeffery if (!context) { 19268023074SAndrew Jeffery MSG_ERR("DBUS Internal Error\n"); 19368023074SAndrew Jeffery rc = -E_DBUS_INTERNAL; 19468023074SAndrew Jeffery goto out; 19568023074SAndrew Jeffery } 19668023074SAndrew Jeffery 19768023074SAndrew Jeffery /* Read the command */ 19868023074SAndrew Jeffery rc = sd_bus_message_read(m, "y", &req.cmd); 19968023074SAndrew Jeffery if (rc < 0) { 20068023074SAndrew Jeffery MSG_ERR("DBUS error reading message: %s\n", strerror(-rc)); 20168023074SAndrew Jeffery rc = -E_DBUS_INTERNAL; 20268023074SAndrew Jeffery goto out; 20368023074SAndrew Jeffery } 20468023074SAndrew Jeffery MSG_DBG("DBUS request: %u\n", req.cmd); 20568023074SAndrew Jeffery 20668023074SAndrew Jeffery /* Read the args */ 20768023074SAndrew Jeffery rc = sd_bus_message_read_array(m, 'y', (const void **) &req.args, 20868023074SAndrew Jeffery &req.num_args); 20968023074SAndrew Jeffery if (rc < 0) { 21068023074SAndrew Jeffery MSG_ERR("DBUS error reading message: %s\n", strerror(-rc)); 21168023074SAndrew Jeffery rc = -E_DBUS_INTERNAL; 21268023074SAndrew Jeffery goto out; 21368023074SAndrew Jeffery } 21468023074SAndrew Jeffery MSG_DBG("DBUS num_args: %u\n", (unsigned) req.num_args); 21568023074SAndrew Jeffery for (i = 0; i < req.num_args; i++) { 21668023074SAndrew Jeffery MSG_DBG("DBUS arg[%d]: %u\n", i, req.args[i]); 21768023074SAndrew Jeffery } 21868023074SAndrew Jeffery 21968023074SAndrew Jeffery /* Handle the command */ 22068023074SAndrew Jeffery if (req.cmd >= NUM_DBUS_CMDS) { 22168023074SAndrew Jeffery rc = -E_DBUS_INVAL; 22268023074SAndrew Jeffery MSG_ERR("Received unknown dbus cmd: %d\n", req.cmd); 22368023074SAndrew Jeffery } else { 22468023074SAndrew Jeffery rc = dbus_handlers[req.cmd](context, &req, &resp); 22568023074SAndrew Jeffery } 22668023074SAndrew Jeffery 22768023074SAndrew Jeffery out: 22868023074SAndrew Jeffery if (rc < 0) { 22968023074SAndrew Jeffery resp.cmd = -rc; 23068023074SAndrew Jeffery } 23168023074SAndrew Jeffery rc = sd_bus_message_new_method_return(m, &n); /* Generate response */ 23268023074SAndrew Jeffery if (rc < 0) { 23368023074SAndrew Jeffery MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc); 23468023074SAndrew Jeffery goto cleanup; 23568023074SAndrew Jeffery } 23668023074SAndrew Jeffery 23768023074SAndrew Jeffery rc = sd_bus_message_append(n, "y", resp.cmd); /* Set return code */ 23868023074SAndrew Jeffery if (rc < 0) { 23968023074SAndrew Jeffery MSG_ERR("sd_bus_message_append failed: %d\n", rc); 24068023074SAndrew Jeffery goto cleanup; 24168023074SAndrew Jeffery } 24268023074SAndrew Jeffery 24368023074SAndrew Jeffery rc = sd_bus_message_append_array(n, 'y', resp.args, resp.num_args); 24468023074SAndrew Jeffery if (rc < 0) { 24568023074SAndrew Jeffery MSG_ERR("sd_bus_message_append_array failed: %d\n", rc); 24668023074SAndrew Jeffery goto cleanup; 24768023074SAndrew Jeffery } 24868023074SAndrew Jeffery 24968023074SAndrew Jeffery MSG_DBG("DBUS response: %u\n", resp.cmd); 25068023074SAndrew Jeffery MSG_DBG("DBUS num_args: %u\n", (unsigned) resp.num_args); 25168023074SAndrew Jeffery for (i = 0; i < resp.num_args; i++) { 25268023074SAndrew Jeffery MSG_DBG("DBUS arg[%d]: %u\n", i, resp.args[i]); 25368023074SAndrew Jeffery } 25468023074SAndrew Jeffery 25568023074SAndrew Jeffery rc = sd_bus_send(NULL, n, NULL); /* Send response */ 25668023074SAndrew Jeffery if (rc < 0) 25768023074SAndrew Jeffery MSG_ERR("sd_bus_send failed: %d\n", rc); 25868023074SAndrew Jeffery 25968023074SAndrew Jeffery cleanup: 26068023074SAndrew Jeffery free(resp.args); 26168023074SAndrew Jeffery return rc; 26268023074SAndrew Jeffery } 26368023074SAndrew Jeffery 26468023074SAndrew Jeffery static const sd_bus_vtable control_legacy_vtable[] = { 26568023074SAndrew Jeffery SD_BUS_VTABLE_START(0), 26668023074SAndrew Jeffery SD_BUS_METHOD("cmd", "yay", "yay", &method_cmd, 26768023074SAndrew Jeffery SD_BUS_VTABLE_UNPRIVILEGED), 26868023074SAndrew Jeffery SD_BUS_VTABLE_END 26968023074SAndrew Jeffery }; 27068023074SAndrew Jeffery 27168023074SAndrew Jeffery int control_legacy_init(struct mbox_context *context) 27268023074SAndrew Jeffery { 27368023074SAndrew Jeffery int rc; 27468023074SAndrew Jeffery 27568023074SAndrew Jeffery rc = sd_bus_add_object_vtable(context->bus, NULL, 27668023074SAndrew Jeffery MBOX_DBUS_LEGACY_OBJECT, 27768023074SAndrew Jeffery MBOX_DBUS_LEGACY_NAME, 27868023074SAndrew Jeffery control_legacy_vtable, context); 27968023074SAndrew Jeffery if (rc < 0) { 28068023074SAndrew Jeffery MSG_ERR("Failed to register vtable: %s\n", strerror(-rc)); 28168023074SAndrew Jeffery return rc; 28268023074SAndrew Jeffery } 28368023074SAndrew Jeffery 28468023074SAndrew Jeffery return sd_bus_request_name(context->bus, MBOX_DBUS_LEGACY_NAME, 28568023074SAndrew Jeffery SD_BUS_NAME_ALLOW_REPLACEMENT | 28668023074SAndrew Jeffery SD_BUS_NAME_REPLACE_EXISTING); 28768023074SAndrew Jeffery } 28868023074SAndrew Jeffery 28968023074SAndrew Jeffery void control_legacy_free(struct mbox_context *context __attribute__((unused))) 29068023074SAndrew Jeffery { 29168023074SAndrew Jeffery return; 29268023074SAndrew Jeffery } 293