From be37f2596adcfa92700577416345cf5b302ee352 Mon Sep 17 00:00:00 2001 From: Jonathan Currier Date: Thu, 29 Aug 2019 05:35:42 -0500 Subject: [PATCH] Migrate transport, and other mechanism away from poll, and to epoll. This will easy the transition to making transports compile time optional. NOTE: this commit if unfinished and should eventually be rebased & squashed. specifically, the shutdown code no longer works correctly. --- control.c | 2 +- control_dbus.c | 8 +- control_legacy.c | 9 +- dbus.h | 36 ++--- hiomapd-state.h | 23 ++++ lpc.c | 22 ++- mboxd.c | 341 ++++++++++++++++++++--------------------------- mboxd.h | 18 +-- protocol.c | 8 +- protocol.h | 3 +- transport.h | 41 +++++- transport_dbus.c | 159 ++++++++++++++++++---- transport_mbox.c | 170 +++++++++++++++-------- transport_mbox.h | 5 - 14 files changed, 507 insertions(+), 338 deletions(-) create mode 100644 hiomapd-state.h diff --git a/control.c b/control.c index 4b73efa..a55d335 100644 --- a/control.c +++ b/control.c @@ -5,11 +5,11 @@ #include "backend.h" #include "common.h" -#include "dbus.h" #include "lpc.h" #include "mboxd.h" #include "protocol.h" #include "windows.h" +#include "hiomapd-state.h" int control_ping(struct mbox_context *context) { diff --git a/control_dbus.c b/control_dbus.c index 4fb9e33..b504c58 100644 --- a/control_dbus.c +++ b/control_dbus.c @@ -202,7 +202,7 @@ static int control_dbus_get_u8(sd_bus *bus, const char *path, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); uint8_t value; assert(!strcmp(MBOX_DBUS_OBJECT, path)); @@ -242,12 +242,12 @@ static const sd_bus_vtable mboxd_vtable[] = { SD_BUS_VTABLE_END }; -int control_dbus_init(struct mbox_context *context) +int control_dbus_init(struct transport_dbus_context *dctx) { - return sd_bus_add_object_vtable(context->bus, NULL, + return sd_bus_add_object_vtable(dctx->bus, NULL, MBOX_DBUS_OBJECT, MBOX_DBUS_CONTROL_IFACE, - mboxd_vtable, context); + mboxd_vtable, dctx); } #define __unused __attribute__((unused)) diff --git a/control_legacy.c b/control_legacy.c index 2a3461d..1c469ac 100644 --- a/control_legacy.c +++ b/control_legacy.c @@ -294,20 +294,19 @@ static const sd_bus_vtable control_legacy_vtable[] = { SD_BUS_VTABLE_END }; -int control_legacy_init(struct mbox_context *context) +int control_legacy_init(struct transport_dbus_context *dctx) { int rc; - - rc = sd_bus_add_object_vtable(context->bus, NULL, + rc = sd_bus_add_object_vtable(dctx->bus, NULL, MBOX_DBUS_LEGACY_OBJECT, MBOX_DBUS_LEGACY_NAME, - control_legacy_vtable, context); + control_legacy_vtable, dctx); if (rc < 0) { MSG_ERR("Failed to register vtable: %s\n", strerror(-rc)); return rc; } - return sd_bus_request_name(context->bus, MBOX_DBUS_LEGACY_NAME, + return sd_bus_request_name(dctx->bus, MBOX_DBUS_LEGACY_NAME, SD_BUS_NAME_ALLOW_REPLACEMENT | SD_BUS_NAME_REPLACE_EXISTING); } diff --git a/dbus.h b/dbus.h index 676ec11..8f2c875 100644 --- a/dbus.h +++ b/dbus.h @@ -25,22 +25,24 @@ #define MBOX_DBUS_LEGACY_NAME "org.openbmc.mboxd" #define MBOX_DBUS_LEGACY_OBJECT "/org/openbmc/mboxd" -/* Command Args */ -/* Resume */ -#define RESUME_NUM_ARGS 1 -#define RESUME_NOT_MODIFIED 0x00 -#define RESUME_FLASH_MODIFIED 0x01 - -/* Response Args */ -/* Status */ -#define DAEMON_STATE_NUM_ARGS 1 -#define DAEMON_STATE_ACTIVE 0x00 /* Daemon Active */ -#define DAEMON_STATE_SUSPENDED 0x01 /* Daemon Suspended */ - -/* LPC State */ -#define LPC_STATE_NUM_ARGS 1 -#define LPC_STATE_INVALID 0x00 /* Invalid State */ -#define LPC_STATE_FLASH 0x01 /* LPC Maps Flash Directly */ -#define LPC_STATE_MEM 0x02 /* LPC Maps Memory */ +#include "hiomapd-state.h" + +struct transport_dbus_context { + struct ops_container w; + struct mbox_context *context; + sd_bus *bus; + int dbus_fd; +}; + +static inline struct mbox_context *dctx_to_mctx(struct transport_dbus_context *dctx) +{ + return dctx->context; +} + +static inline struct transport_dbus_context * +container_to_dctx(struct ops_container *container) +{ + return container_of(container, struct transport_dbus_context, w); +} #endif /* MBOX_DBUS_H */ diff --git a/hiomapd-state.h b/hiomapd-state.h new file mode 100644 index 0000000..d70bb12 --- /dev/null +++ b/hiomapd-state.h @@ -0,0 +1,23 @@ +#ifndef HIOMAPD_STATE_H +#define HIOMAPD_STATE_H + +/* Command Args */ +/* Resume */ +#define RESUME_NUM_ARGS 1 +#define RESUME_NOT_MODIFIED 0x00 +#define RESUME_FLASH_MODIFIED 0x01 + +/* Response Args */ +/* Status */ +#define DAEMON_STATE_NUM_ARGS 1 +#define DAEMON_STATE_ACTIVE 0x00 /* Daemon Active */ +#define DAEMON_STATE_SUSPENDED 0x01 /* Daemon Suspended */ + +/* LPC State */ +#define LPC_STATE_NUM_ARGS 1 +#define LPC_STATE_INVALID 0x00 /* Invalid State */ +#define LPC_STATE_FLASH 0x01 /* LPC Maps Flash Directly */ +#define LPC_STATE_MEM 0x02 /* LPC Maps Memory */ + + +#endif diff --git a/lpc.c b/lpc.c index f3f999f..61a9a11 100644 --- a/lpc.c +++ b/lpc.c @@ -32,6 +32,10 @@ #define LPC_CTRL_PATH "/dev/aspeed-lpc-ctrl" +struct host_lpc_link_context { + int lpcfd; +}; + int __lpc_dev_init(struct mbox_context *context, const char *path) { struct aspeed_lpc_ctrl_mapping map = { @@ -43,6 +47,13 @@ int __lpc_dev_init(struct mbox_context *context, const char *path) .size = 0 }; int fd; + struct host_lpc_link_context *lctx = calloc(1,sizeof(*lctx)); + if (!lctx) { + MSG_ERR("Couldn't allocate lpc link context\n"); + return -ENOMEM; + + } + context->host_link_ctx = lctx; /* Open LPC Device */ MSG_DBG("Opening %s\n", path); @@ -53,7 +64,7 @@ int __lpc_dev_init(struct mbox_context *context, const char *path) return -errno; } - context->fds[LPC_CTRL_FD].fd = fd; + lctx->lpcfd = fd; /* Find Size of Reserved Memory Region */ MSG_DBG("Getting buffer size...\n"); @@ -86,10 +97,11 @@ int lpc_dev_init(struct mbox_context *context) void lpc_dev_free(struct mbox_context *context) { + struct host_lpc_link_context *lctx = context->host_link_ctx; if (context->mem) { munmap(context->mem, context->mem_size); } - close(context->fds[LPC_CTRL_FD].fd); + close(lctx->lpcfd); } /* @@ -100,6 +112,7 @@ void lpc_dev_free(struct mbox_context *context) */ int lpc_map_flash(struct mbox_context *context) { + struct host_lpc_link_context *lctx = context->host_link_ctx; struct aspeed_lpc_ctrl_mapping map = { .window_type = ASPEED_LPC_CTRL_WINDOW_FLASH, .window_id = 0, /* Theres only one */ @@ -126,7 +139,7 @@ int lpc_map_flash(struct mbox_context *context) MSG_INFO("Assuming %dMB of flash: HOST LPC 0x%08x\n", context->backend.flash_size >> 20, map.addr); - if (ioctl(context->fds[LPC_CTRL_FD].fd, ASPEED_LPC_CTRL_IOCTL_MAP, &map) + if (ioctl(lctx->lpcfd, ASPEED_LPC_CTRL_IOCTL_MAP, &map) == -1) { MSG_ERR("Failed to point the LPC BUS at the actual flash: %s\n", strerror(errno)); @@ -150,6 +163,7 @@ int lpc_map_flash(struct mbox_context *context) */ int lpc_map_memory(struct mbox_context *context) { + struct host_lpc_link_context *lctx = context->host_link_ctx; struct aspeed_lpc_ctrl_mapping map = { .window_type = ASPEED_LPC_CTRL_WINDOW_MEMORY, .window_id = 0, /* There's only one */ @@ -167,7 +181,7 @@ int lpc_map_memory(struct mbox_context *context) context->mem, context->mem_size); MSG_INFO("LPC address 0x%.8x\n", map.addr); - if (ioctl(context->fds[LPC_CTRL_FD].fd, ASPEED_LPC_CTRL_IOCTL_MAP, + if (ioctl(lctx->lpcfd, ASPEED_LPC_CTRL_IOCTL_MAP, &map)) { MSG_ERR("Failed to point the LPC BUS to memory: %s\n", strerror(errno)); diff --git a/mboxd.c b/mboxd.c index c7f7d33..a0bd748 100644 --- a/mboxd.c +++ b/mboxd.c @@ -24,17 +24,13 @@ #include #include #include -#include +#include #include "config.h" #include "mboxd.h" #include "common.h" -#include "dbus.h" -#include "control_dbus.h" #include "backend.h" #include "lpc.h" -#include "transport_mbox.h" -#include "transport_dbus.h" #include "windows.h" #include "vpnor/backend.h" @@ -57,133 +53,33 @@ const char* USAGE = "\t-f | --flash\t\tSize of flash in [K|M] bytes\n\n" "\t-t | --trace\t\tFile to write trace data to (in blktrace format)\n\n"; -static int dbus_init(struct mbox_context *context, - const struct transport_ops **ops) -{ - int rc; - - rc = sd_bus_default_system(&context->bus); - if (rc < 0) { - MSG_ERR("Failed to connect to the system bus: %s\n", - strerror(-rc)); - return rc; - } - - rc = control_legacy_init(context); - if (rc < 0) { - MSG_ERR("Failed to initialise legacy DBus interface: %s\n", - strerror(-rc)); - return rc; - } - - rc = control_dbus_init(context); - if (rc < 0) { - MSG_ERR("Failed to initialise DBus control interface: %s\n", - strerror(-rc)); - return rc; - } - - rc = transport_dbus_init(context, ops); - if (rc < 0) { - MSG_ERR("Failed to initialise DBus protocol interface: %s\n", - strerror(-rc)); - return rc; - } - - rc = sd_bus_request_name(context->bus, MBOX_DBUS_NAME, - SD_BUS_NAME_ALLOW_REPLACEMENT | - SD_BUS_NAME_REPLACE_EXISTING); - if (rc < 0) { - MSG_ERR("Failed to request DBus name: %s\n", strerror(-rc)); - return rc; - } - - rc = sd_bus_get_fd(context->bus); - if (rc < 0) { - MSG_ERR("Failed to get bus fd: %s\n", strerror(-rc)); - return rc; - } - - context->fds[DBUS_FD].fd = rc; - - return 0; -} - -static void dbus_free(struct mbox_context *context) -{ - transport_dbus_free(context); - control_dbus_free(context); - control_legacy_free(context); - sd_bus_unref(context->bus); -} static int poll_loop(struct mbox_context *context) { int rc = 0, i; - - /* Set POLLIN on polling file descriptors */ - for (i = 0; i < POLL_FDS; i++) { - context->fds[i].events = POLLIN; - } - - while (1) { - rc = poll(context->fds, POLL_FDS, -1); - - if (rc < 0) { /* Error */ - MSG_ERR("Error from poll(): %s\n", strerror(errno)); - break; /* This should mean we clean up nicely */ - } - - /* Event on Polled File Descriptor - Handle It */ - if (context->fds[SIG_FD].revents & POLLIN) { /* Signal */ - struct signalfd_siginfo info = { 0 }; - - rc = read(context->fds[SIG_FD].fd, (void *) &info, - sizeof(info)); - if (rc != sizeof(info)) { - MSG_ERR("Error reading signal event: %s\n", - strerror(errno)); - } - - MSG_DBG("Received signal: %d\n", info.ssi_signo); - switch (info.ssi_signo) { - case SIGINT: - case SIGTERM: - MSG_INFO("Caught Signal - Exiting...\n"); - context->terminate = true; - break; - case SIGHUP: - rc = protocol_reset(context); - if (rc < 0) { - MSG_ERR("Failed to reset on SIGHUP\n"); - } - break; - default: - MSG_ERR("Unhandled Signal: %d\n", - info.ssi_signo); - break; - } - } - if (context->fds[DBUS_FD].revents & POLLIN) { /* DBUS */ - while ((rc = sd_bus_process(context->bus, NULL)) > 0) { - MSG_DBG("DBUS Event\n"); - } - if (rc < 0) { - MSG_ERR("Error handling DBUS event: %s\n", - strerror(-rc)); - } - } + int count; + /* This is a low throughput api, 0x10 events is huge, + * one would probably be sufficent.*/ + struct epoll_event evt[0x10] = { 0 }; + struct ops_container *w; + + while (true) { + count = epoll_wait(context->epollfd, evt, 0x10, -1); + if (count < 0) + { + MSG_ERR("Error from epoll_wait(): %s\n", strerror(errno)); + continue; + } + for (i = 0; i < count; i++) + { + w = evt[i].data.ptr; + if (w[0].ops->event(w, evt + i) < 0) + MSG_ERR("Error in event dispatch\n"); + } if (context->terminate) { break; /* This should mean we clean up nicely */ } - if (context->fds[MBOX_FD].revents & POLLIN) { /* MBOX */ - MSG_DBG("MBOX Event\n"); - rc = transport_mbox_dispatch(context); - if (rc < 0) { - MSG_ERR("Error handling MBOX event\n"); - } - } - } + } rc = protocol_reset(context); if (rc < 0) { @@ -193,32 +89,6 @@ static int poll_loop(struct mbox_context *context) return rc; } -static int init_signals(struct mbox_context *context, sigset_t *set) -{ - int rc; - - /* Block SIGHUPs, SIGTERMs and SIGINTs */ - sigemptyset(set); - sigaddset(set, SIGHUP); - sigaddset(set, SIGINT); - sigaddset(set, SIGTERM); - rc = sigprocmask(SIG_BLOCK, set, NULL); - if (rc < 0) { - MSG_ERR("Failed to set SIG_BLOCK mask %s\n", strerror(errno)); - return rc; - } - - /* Get Signal File Descriptor */ - rc = signalfd(-1, set, SFD_NONBLOCK); - if (rc < 0) { - MSG_ERR("Failed to get signalfd %s\n", strerror(errno)); - return rc; - } - - context->fds[SIG_FD].fd = rc; - return 0; -} - static void usage(const char *name) { printf(USAGE, name); @@ -387,14 +257,20 @@ static int mboxd_backend_init(struct mbox_context *context) return rc; } +extern void *__start_ops_array; +extern void *__stop_ops_array; +static struct transport_ops **ops_array = + (struct transport_ops **)&__start_ops_array; +static size_t ops_array_size; + int main(int argc, char **argv) { - const struct transport_ops *mbox_ops, *dbus_ops; struct mbox_context *context; - bool have_transport_mbox; char *name = argv[0]; - sigset_t set; int rc, i; + ops_array_size = + ((struct transport_ops **)&__stop_ops_array) - + ((struct transport_ops **)&__start_ops_array); context = calloc(1, sizeof(*context)); if (!context) { @@ -408,17 +284,10 @@ int main(int argc, char **argv) exit(0); } - for (i = 0; i < TOTAL_FDS; i++) { - context->fds[i].fd = -1; - } + context->epollfd = epoll_create1(EPOLL_CLOEXEC); MSG_INFO("Starting Daemon\n"); - rc = init_signals(context, &set); - if (rc) { - goto cleanup_context; - } - rc = mboxd_backend_init(context); if (rc) { goto cleanup_context; @@ -429,16 +298,6 @@ int main(int argc, char **argv) goto cleanup_backend; } - rc = transport_mbox_init(context, &mbox_ops); - /* TODO: Think about whether we could use a less branch-y strategy */ - have_transport_mbox = rc == 0; - if (!have_transport_mbox) { - /* Disable MBOX for poll()ing purposes */ - context->fds[MBOX_FD].fd = -1; - MSG_DBG("Failed to initialise MBOX transport: %d\n", rc); - MSG_INFO("MBOX transport unavailable\n"); - } - rc = lpc_dev_init(context); if (rc) { goto cleanup_mbox; @@ -450,10 +309,8 @@ int main(int argc, char **argv) goto cleanup_lpc; } - rc = dbus_init(context, &dbus_ops); - if (rc) { - goto cleanup_windows; - } + for (i = 0; i < ops_array_size; i++) + ops_array[i]->init(context, ops_array[i]); /* Set the LPC bus mapping */ __protocol_reset(context); @@ -462,19 +319,6 @@ int main(int argc, char **argv) context->bmc_events |= BMC_EVENT_DAEMON_READY; context->bmc_events |= BMC_EVENT_PROTOCOL_RESET; - /* Alert on all supported transports, as required */ - if (have_transport_mbox) { - rc = protocol_events_put(context, mbox_ops); - if (rc) { - goto cleanup; - } - } - - rc = protocol_events_put(context, dbus_ops); - if (rc) { - goto cleanup; - } - MSG_INFO("Entering Polling Loop\n"); rc = poll_loop(context); @@ -484,23 +328,14 @@ int main(int argc, char **argv) context->bmc_events &= ~BMC_EVENT_DAEMON_READY; context->bmc_events |= BMC_EVENT_PROTOCOL_RESET; - /* Alert on all supported transports, as required */ - if (have_transport_mbox) { - protocol_events_put(context, mbox_ops); - } - - protocol_events_put(context, dbus_ops); + /* I think we can skip all transport that are not the active + * transport */ -cleanup: - dbus_free(context); cleanup_windows: windows_free(context); cleanup_lpc: lpc_dev_free(context); cleanup_mbox: - if (have_transport_mbox) { - transport_mbox_free(context); - } protocol_free(context); cleanup_backend: backend_free(&context->backend); @@ -512,3 +347,109 @@ cleanup_context: return rc; } + + +/* Singal 'transport' */ +struct signal_context { + struct mbox_context *context; + struct ops_container w; + int signal_fd; +}; + +static inline struct signal_context* container_to_sctx(struct ops_container *container) +{ + return container_of(container, struct signal_context, w); +} + +static int init_signals(struct mbox_context *context, + struct transport_ops *ops) +{ + int rc; + sigset_t set; + + struct signal_context *sctx = calloc(1, sizeof(*sctx)); + + if (!sctx) { + MSG_ERR("Failed to allocate signal context\n"); + return -ENOMEM; + } + sctx->context = context; + sctx->w.ops = ops; + + /* Block SIGHUPs, SIGTERMs and SIGINTs */ + sigemptyset(&set); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + rc = sigprocmask(SIG_BLOCK, &set, NULL); + if (rc < 0) { + MSG_ERR("Failed to set SIG_BLOCK mask %s\n", strerror(errno)); + free(sctx); + return rc; + } + + /* Get Signal File Descriptor */ + rc = signalfd(-1, &set, SFD_NONBLOCK); + if (rc < 0) { + MSG_ERR("Failed to get signalfd %s\n", strerror(errno)); + free(sctx); + return rc; + } + sctx->signal_fd = rc; + + register_event_fd(sctx->signal_fd, context, &sctx->w); + return 0; +} + +static int signal_event(struct ops_container *container, + struct epoll_event *evt) +{ + struct signal_context *sctx = container_to_sctx(container); + struct mbox_context *context = sctx->context; + struct signalfd_siginfo info = { 0 }; + int rc; + + if (!(evt->events & EPOLLIN)) + { + MSG_ERR("Signal event, but no event ready\n"); + return -EINVAL; + } + + rc = read(sctx->signal_fd, (void *) &info, + sizeof(info)); + + if (rc != sizeof(info)) { + MSG_ERR("Error reading signal event: %s\n", + strerror(errno)); + return rc; + } + + MSG_DBG("Received signal: %d\n", info.ssi_signo); + switch (info.ssi_signo) { + case SIGINT: + case SIGTERM: + MSG_INFO("Caught Signal - Exiting...\n"); + context->terminate = true; + break; + case SIGHUP: + rc = protocol_reset(context); + if (rc < 0) { + MSG_ERR("Failed to reset on SIGHUP\n"); + } + break; + default: + MSG_ERR("Unhandled Signal: %d\n", + info.ssi_signo); + break; + } + return 0; +} + +DECLARE_TRANSPORT_OPS(signal) = { + .init = init_signals, + .event = signal_event, + .fini = 0, + .put_events = 0, + .set_events = 0, + .clear_events = 0, +}; diff --git a/mboxd.h b/mboxd.h index 6b14a24..5c786fc 100644 --- a/mboxd.h +++ b/mboxd.h @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -45,13 +44,6 @@ enum api_version { BMC_EVENT_FLASH_CTRL_LOST | \ BMC_EVENT_DAEMON_READY) -/* Put polled file descriptors first */ -#define DBUS_FD 0 -#define MBOX_FD 1 -#define SIG_FD 2 -#define POLL_FDS 3 /* Number of FDs we poll on */ -#define LPC_CTRL_FD 3 -#define TOTAL_FDS 4 #define MAPS_FLASH (1 << 0) #define MAPS_MEM (1 << 1) @@ -73,7 +65,8 @@ enum mbox_state { struct mbox_context { enum api_version version; const struct protocol_ops *protocol; - const struct transport_ops *transport; + //const struct transport_ops *transport; + struct ops_container *transport; struct backend backend; /* Commandline parameters */ @@ -81,8 +74,7 @@ struct mbox_context { /* System State */ enum mbox_state state; - struct pollfd fds[TOTAL_FDS]; - sd_bus *bus; + int epollfd; bool terminate; uint8_t bmc_events; uint8_t prev_seq; @@ -102,6 +94,10 @@ struct mbox_context { uint32_t mem_size; /* LPC Bus Base Address (bytes) */ uint32_t lpc_base; + /* In this implementation it's the context for + * the lpc.c file, the details of which are unneeded + * for the rest of the code */ + void *host_link_ctx; /* Tracing */ int blktracefd; diff --git a/protocol.c b/protocol.c index 0093236..92c0ec5 100644 --- a/protocol.c +++ b/protocol.c @@ -36,11 +36,11 @@ static inline uint8_t protocol_get_bmc_event_mask(struct mbox_context *context) * Return: 0 on success otherwise negative error code */ int protocol_events_put(struct mbox_context *context, - const struct transport_ops *ops) + struct ops_container *container) { const uint8_t mask = protocol_get_bmc_event_mask(context); - return ops->put_events(context, mask); + return container->ops->put_events(container, mask); } /* @@ -61,7 +61,7 @@ int protocol_events_set(struct mbox_context *context, uint8_t bmc_event) */ context->bmc_events |= bmc_event; - return context->transport->set_events(context, bmc_event, mask); + return context->transport->ops->set_events(context->transport, bmc_event, mask); } /* @@ -78,7 +78,7 @@ int protocol_events_clear(struct mbox_context *context, uint8_t bmc_event) context->bmc_events &= ~bmc_event; - return context->transport->clear_events(context, bmc_event, mask); + return context->transport->ops->clear_events(context->transport, bmc_event, mask); } static int protocol_negotiate_version(struct mbox_context *context, diff --git a/protocol.h b/protocol.h index f571fe1..7454245 100644 --- a/protocol.h +++ b/protocol.h @@ -6,6 +6,7 @@ struct mbox_context; struct transport_ops; +struct ops_container; /* * The GET_MBOX_INFO command is special as it can change the interface based on @@ -126,7 +127,7 @@ int __protocol_reset(struct mbox_context *context); int protocol_reset(struct mbox_context *context); int protocol_events_put(struct mbox_context *context, - const struct transport_ops *ops); + struct ops_container *container); int protocol_events_set(struct mbox_context *context, uint8_t bmc_event); int protocol_events_clear(struct mbox_context *context, uint8_t bmc_event); diff --git a/transport.h b/transport.h index bbc8444..06137c6 100644 --- a/transport.h +++ b/transport.h @@ -5,13 +5,48 @@ #define TRANSPORT_H struct mbox_context; +struct ops_container; +struct epoll_event; struct transport_ops { - int (*put_events)(struct mbox_context *context, uint8_t mask); - int (*set_events)(struct mbox_context *context, uint8_t events, + int (*init)(struct mbox_context *, struct transport_ops *); + int (*event)(struct ops_container *, struct epoll_event *); + int (*fini)(struct ops_container *); + + int (*put_events)(struct ops_container *context, uint8_t mask); + int (*set_events)(struct ops_container *context, uint8_t events, uint8_t mask); - int (*clear_events)(struct mbox_context *context, uint8_t events, + int (*clear_events)(struct ops_container *context, uint8_t events, uint8_t mask); }; +#define DECLARE_TRANSPORT_OPS(name) \ +static struct transport_ops name##_transport_ops; \ +static const __attribute((section("ops_array"),used)) \ +struct transport_ops *private_##name##_transport_ops_pointer = \ + & name##_transport_ops; \ +static struct transport_ops name##_transport_ops + +/* this is used to have a generic pointer, even + * if it's embedded in a type other code may have no knowledge of.*/ +struct ops_container { + struct transport_ops *ops; +}; + +#define container_of(ptr, type, member) ({ \ + /* Store ptr in a var so it's not expanded multiple times, \ + * if it's an expression*/ \ + void *__l_ptr = (void*)(ptr); \ + ((type *)(__l_ptr - __builtin_offsetof(type, member))); }) + +/* We add EPOLLOUT so that the transport has a chance + * to do some late init*/ +#define register_event_fd(fd, ctx, payload) \ +({ \ + struct epoll_event evt = { \ + .events = EPOLLIN | EPOLLOUT, \ + .data = { .ptr = payload, }, \ + }; \ + epoll_ctl(ctx->epollfd, EPOLL_CTL_ADD, fd, &evt); \ +}) #endif /* TRANSPORT_H */ diff --git a/transport_dbus.c b/transport_dbus.c index 18cd0d0..98ad31b 100644 --- a/transport_dbus.c +++ b/transport_dbus.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "common.h" #include "dbus.h" @@ -13,9 +14,13 @@ #include "protocol.h" #include "transport.h" -static int transport_dbus_property_update(struct mbox_context *context, +static int dbus_init(struct mbox_context *context, + const struct transport_ops *ops); + +static int transport_dbus_property_update(struct ops_container *container, uint8_t events) { + struct transport_dbus_context *dctx = container_to_dctx(container); /* Two properties plus a terminating NULL */ char *props[5] = { 0 }; int i = 0; @@ -37,7 +42,7 @@ static int transport_dbus_property_update(struct mbox_context *context, props[i++] = "ProtocolReset"; } - rc = sd_bus_emit_properties_changed_strv(context->bus, + rc = sd_bus_emit_properties_changed_strv(dctx->bus, MBOX_DBUS_OBJECT, /* FIXME: Hard-coding v2 */ MBOX_DBUS_PROTOCOL_IFACE_V2, @@ -47,24 +52,58 @@ static int transport_dbus_property_update(struct mbox_context *context, } -static int transport_dbus_put_events(struct mbox_context *context, uint8_t mask) +static int transport_dbus_put_events(struct ops_container *context, uint8_t mask) { return transport_dbus_property_update(context, mask); } -static int transport_dbus_set_events(struct mbox_context *context, +static int transport_dbus_set_events(struct ops_container *context, uint8_t events, uint8_t mask) { return transport_dbus_property_update(context, events & mask); } -static int transport_dbus_clear_events(struct mbox_context *context, +static int transport_dbus_clear_events(struct ops_container *context, uint8_t events, uint8_t mask) { return transport_dbus_property_update(context, events & mask); } -static const struct transport_ops transport_dbus_ops = { + +static int transport_dbus_event(struct ops_container *container, + struct epoll_event *evt) +{ + struct transport_dbus_context *dctx = container_to_dctx(container); + int rc; + + if (!(evt->events & EPOLLIN)) + return -EINVAL; + + while ((rc = sd_bus_process(dctx->bus, NULL)) > 0) { + MSG_DBG("DBUS Event\n"); + } + if (rc < 0) { + MSG_ERR("Error handling DBUS event: %s\n", + strerror(-rc)); + } + return rc; +} + +static void dbus_free(struct ops_container *container) +{ + struct transport_dbus_context *dctx = container_to_dctx(container); + struct mbox_context *context = dctx_to_mctx(dctx); + transport_dbus_free(context); + control_dbus_free(context); + control_legacy_free(context); + sd_bus_unref(dctx->bus); + free(dctx); +} + +DECLARE_TRANSPORT_OPS(dbus) = { + .init = dbus_init, + .event = transport_dbus_event, + .fini = dbus_free, .put_events = transport_dbus_put_events, .set_events = transport_dbus_set_events, .clear_events = transport_dbus_clear_events, @@ -73,7 +112,7 @@ static const struct transport_ops transport_dbus_ops = { static int transport_dbus_reset(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); sd_bus_message *n; int rc; @@ -101,7 +140,8 @@ static int transport_dbus_reset(sd_bus_message *m, void *userdata, static int transport_dbus_get_info(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct transport_dbus_context *ctx = userdata; + struct mbox_context *context = dctx_to_mctx(dctx); struct protocol_get_info io; sd_bus_message *n; int rc; @@ -123,7 +163,7 @@ static int transport_dbus_get_info(sd_bus_message *m, void *userdata, } /* Switch transport to DBus. This is fine as DBus signals are async */ - context->transport = &transport_dbus_ops; + context->transport = &dctx->w; /* A bit messy, but we need the correct event mask */ protocol_events_set(context, context->bmc_events); @@ -156,7 +196,7 @@ static int transport_dbus_get_info(sd_bus_message *m, void *userdata, static int transport_dbus_get_flash_info(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); struct protocol_get_flash_info io; sd_bus_message *n; int rc; @@ -239,7 +279,7 @@ static int transport_dbus_create_window(struct mbox_context *context, static int transport_dbus_create_read_window(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); return transport_dbus_create_window(context, true, m, ret_error); } @@ -247,7 +287,7 @@ static int transport_dbus_create_read_window(sd_bus_message *m, void *userdata, static int transport_dbus_create_write_window(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); return transport_dbus_create_window(context, false, m, ret_error); } @@ -255,7 +295,7 @@ static int transport_dbus_create_write_window(sd_bus_message *m, void *userdata, static int transport_dbus_close_window(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); struct protocol_close io; sd_bus_message *n; int rc; @@ -291,7 +331,7 @@ static int transport_dbus_close_window(sd_bus_message *m, void *userdata, static int transport_dbus_mark_dirty(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); struct protocol_mark_dirty io; sd_bus_message *n; int rc; @@ -326,7 +366,7 @@ static int transport_dbus_mark_dirty(sd_bus_message *m, void *userdata, static int transport_dbus_write_flush(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); sd_bus_message *n; int rc; @@ -354,7 +394,7 @@ static int transport_dbus_write_flush(sd_bus_message *m, void *userdata, static int transport_dbus_ack(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); struct protocol_ack io; sd_bus_message *n; int rc; @@ -389,7 +429,7 @@ static int transport_dbus_ack(sd_bus_message *m, void *userdata, static int transport_dbus_erase(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); struct protocol_erase io; sd_bus_message *n; int rc; @@ -429,7 +469,7 @@ static int transport_dbus_get_property(sd_bus *bus, void *userdata, sd_bus_error *ret_error) { - struct mbox_context *context = userdata; + struct mbox_context *context = dctx_to_mctx((struct transport_dbus_context*)userdata); bool value; assert(!strcmp(MBOX_DBUS_OBJECT, path)); @@ -504,33 +544,30 @@ static const sd_bus_vtable protocol_v2_vtable[] = { SD_BUS_VTABLE_END }; -int transport_dbus_init(struct mbox_context *context, - const struct transport_ops **ops) +int transport_dbus_init(struct transport_dbus_context* dctx, + const struct transport_ops *ops) { int rc; + struct mbox_context *context = dctx_to_mctx(dctx); - rc = sd_bus_add_object_vtable(context->bus, NULL, + rc = sd_bus_add_object_vtable(dctx->bus, NULL, MBOX_DBUS_OBJECT, MBOX_DBUS_PROTOCOL_IFACE, protocol_unversioned_vtable, - context); + dctx); if (rc < 0) { return rc; } - rc = sd_bus_add_object_vtable(context->bus, NULL, + rc = sd_bus_add_object_vtable(dctx->bus, NULL, MBOX_DBUS_OBJECT, MBOX_DBUS_PROTOCOL_IFACE_V2, - protocol_v2_vtable, context); + protocol_v2_vtable, dctx); if (rc < 0) { return rc; } - context->transport = &transport_dbus_ops; - - if (ops) { - *ops = &transport_dbus_ops; - } + context->transport = &dctx->w; return 0; } @@ -540,3 +577,67 @@ void transport_dbus_free(struct mbox_context *context __unused) { return; } + + +static int dbus_init(struct mbox_context *context, + const struct transport_ops *ops) +{ + int rc; + struct transport_dbus_context *dctx = + (struct transport_dbus_context *)calloc(1, sizeof(*dctx)); + + if (!dctx) { + rc = -ENOMEM; + MSG_ERR("Failed to allocate memory for dbus context\n"); + return rc; + } + dctx->context = context; + dctx->w.ops = ops; + + rc = sd_bus_default_system(&dctx->bus); + if (rc < 0) { + MSG_ERR("Failed to connect to the system bus: %s\n", + strerror(-rc)); + return rc; + } + + rc = control_legacy_init(dctx); + if (rc < 0) { + MSG_ERR("Failed to initialise legacy DBus interface: %s\n", + strerror(-rc)); + return rc; + } + + rc = control_dbus_init(dctx); + if (rc < 0) { + MSG_ERR("Failed to initialise DBus control interface: %s\n", + strerror(-rc)); + return rc; + } + + rc = transport_dbus_init(dctx, ops); + if (rc < 0) { + MSG_ERR("Failed to initialise DBus protocol interface: %s\n", + strerror(-rc)); + return rc; + } + + rc = sd_bus_request_name(dctx->bus, MBOX_DBUS_NAME, + SD_BUS_NAME_ALLOW_REPLACEMENT | + SD_BUS_NAME_REPLACE_EXISTING); + if (rc < 0) { + MSG_ERR("Failed to request DBus name: %s\n", strerror(-rc)); + return rc; + } + + rc = sd_bus_get_fd(dctx->bus); + if (rc < 0) { + MSG_ERR("Failed to get bus fd: %s\n", strerror(-rc)); + return rc; + } + + dctx->dbus_fd = rc; + register_event_fd(dctx->dbus_fd, context, &dctx->w); + + return 0; +} diff --git a/transport_mbox.c b/transport_mbox.c index 2759fa5..3249c37 100644 --- a/transport_mbox.c +++ b/transport_mbox.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "mboxd.h" #include "common.h" @@ -35,6 +36,18 @@ struct errno_map { int mbox_errno; }; +struct transport_mbox_context { + struct mbox_context *context; + struct ops_container w; + int mboxfd; +}; + +static inline struct transport_mbox_context* +container_to_mctx(struct ops_container *container) +{ + return container_of(container, struct transport_mbox_context, w); +} + static const struct errno_map errno_map_v1[] = { { 0, MBOX_R_SUCCESS }, { EACCES, MBOX_R_PARAM_ERROR }, @@ -90,12 +103,13 @@ static inline int mbox_xlate_errno(struct mbox_context *context, * * Return: 0 on success otherwise negative error code */ -static int transport_mbox_flush_events(struct mbox_context *context, uint8_t events) +static int transport_mbox_flush_events(struct transport_mbox_context *mctx, + uint8_t events) { int rc; /* Seek mbox registers */ - rc = lseek(context->fds[MBOX_FD].fd, MBOX_BMC_EVENT, SEEK_SET); + rc = lseek(mctx->mboxfd, MBOX_BMC_EVENT, SEEK_SET); if (rc != MBOX_BMC_EVENT) { MSG_ERR("Couldn't lseek mbox to byte %d: %s\n", MBOX_BMC_EVENT, strerror(errno)); @@ -103,7 +117,7 @@ static int transport_mbox_flush_events(struct mbox_context *context, uint8_t eve } /* Write to mbox status register */ - rc = write(context->fds[MBOX_FD].fd, &events, 1); + rc = write(mctx->mboxfd, &events, 1); if (rc != 1) { MSG_ERR("Couldn't write to BMC status reg: %s\n", strerror(errno)); @@ -111,7 +125,7 @@ static int transport_mbox_flush_events(struct mbox_context *context, uint8_t eve } /* Reset to start */ - rc = lseek(context->fds[MBOX_FD].fd, 0, SEEK_SET); + rc = lseek(mctx->mboxfd, 0, SEEK_SET); if (rc) { MSG_ERR("Couldn't reset MBOX offset to zero: %s\n", strerror(errno)); @@ -121,24 +135,22 @@ static int transport_mbox_flush_events(struct mbox_context *context, uint8_t eve return 0; } -static int transport_mbox_put_events(struct mbox_context *context, +static int transport_mbox_put_events(struct ops_container *container, uint8_t mask) { - return transport_mbox_flush_events(context, context->bmc_events & mask); + struct transport_mbox_context *mctx = container_to_mctx(container); + struct mbox_context *context = mctx->context; + return transport_mbox_flush_events(mctx, context->bmc_events & mask); } -static int transport_mbox_update_events(struct mbox_context *context, +static int transport_mbox_update_events(struct ops_container *container, uint8_t events, uint8_t mask) { - return transport_mbox_flush_events(context, context->bmc_events & mask); + struct transport_mbox_context *mctx = container_to_mctx(container); + struct mbox_context *context = mctx->context; + return transport_mbox_flush_events(mctx, context->bmc_events & mask); } -static const struct transport_ops transport_mbox_ops = { - .put_events = transport_mbox_put_events, - .set_events = transport_mbox_update_events, - .clear_events = transport_mbox_update_events, -}; - /* Command Handlers */ /* @@ -146,10 +158,10 @@ static const struct transport_ops transport_mbox_ops = { * Reset the LPC mapping to point back at the flash, or memory in case we're * using a virtual pnor. */ -static int mbox_handle_reset(struct mbox_context *context, +static int mbox_handle_reset(struct transport_mbox_context *mctx, union mbox_regs *req, struct mbox_msg *resp) { - return context->protocol->reset(context); + return mctx->context->protocol->reset(mctx->context); } /* @@ -174,9 +186,10 @@ static int mbox_handle_reset(struct mbox_context *context, * RESP[3:4]: Default write window size (number of blocks) * RESP[5]: Block size (as shift) */ -static int mbox_handle_mbox_info(struct mbox_context *context, +static int mbox_handle_mbox_info(struct transport_mbox_context *mctx, union mbox_regs *req, struct mbox_msg *resp) { + struct mbox_context *context = mctx->context; uint8_t mbox_api_version = req->msg.args[0]; struct protocol_get_info io = { .req = { .api_version = mbox_api_version } @@ -192,7 +205,7 @@ static int mbox_handle_mbox_info(struct mbox_context *context, * Switch transport to mbox, however we need to delay flushing the * event state until after the command is processed. */ - context->transport = &transport_mbox_ops; + context->transport = &mctx->w; resp->args[0] = io.resp.api_version; if (io.resp.api_version == API_VERSION_1) { @@ -217,9 +230,10 @@ static int mbox_handle_mbox_info(struct mbox_context *context, * RESP[0:1]: Flash Size (number of blocks) * RESP[2:3]: Erase Size (number of blocks) */ -static int mbox_handle_flash_info(struct mbox_context *context, +static int mbox_handle_flash_info(struct transport_mbox_context *mctx, union mbox_regs *req, struct mbox_msg *resp) { + struct mbox_context *context = mctx->context; struct protocol_get_flash_info io; int rc; @@ -309,10 +323,10 @@ static int mbox_handle_create_window(struct mbox_context *context, bool ro, * RESP[0:1]: LPC bus address for host to access this window (number of blocks) * RESP[2:3]: Actual window size that the host can access (number of blocks) */ -static int mbox_handle_read_window(struct mbox_context *context, +static int mbox_handle_read_window(struct transport_mbox_context *mctx, union mbox_regs *req, struct mbox_msg *resp) { - return mbox_handle_create_window(context, true, req, resp); + return mbox_handle_create_window(mctx->context, true, req, resp); } /* @@ -334,10 +348,10 @@ static int mbox_handle_read_window(struct mbox_context *context, * RESP[0:1]: LPC bus address for host to access this window (number of blocks) * RESP[2:3]: Actual window size that was mapped/host can access (n.o. blocks) */ -static int mbox_handle_write_window(struct mbox_context *context, +static int mbox_handle_write_window(struct transport_mbox_context *mctx, union mbox_regs *req, struct mbox_msg *resp) { - return mbox_handle_create_window(context, false, req, resp); + return mbox_handle_create_window(mctx->context, false, req, resp); } /* @@ -356,9 +370,10 @@ static int mbox_handle_write_window(struct mbox_context *context, * ARGS[0:1]: Where within window to start (number of blocks) * ARGS[2:3]: Number to mark dirty (number of blocks) */ -static int mbox_handle_dirty_window(struct mbox_context *context, +static int mbox_handle_dirty_window(struct transport_mbox_context *mctx, union mbox_regs *req, struct mbox_msg *resp) { + struct mbox_context *context = mctx->context; struct protocol_mark_dirty io; if (context->version == API_VERSION_1) { @@ -385,9 +400,10 @@ static int mbox_handle_dirty_window(struct mbox_context *context, * ARGS[0:1]: Where within window to start (number of blocks) * ARGS[2:3]: Number to erase (number of blocks) */ -static int mbox_handle_erase_window(struct mbox_context *context, +static int mbox_handle_erase_window(struct transport_mbox_context *mctx, union mbox_regs *req, struct mbox_msg *resp) { + struct mbox_context *context = mctx->context; struct protocol_erase io; io.req.offset = get_u16(&req->msg.args[0]); @@ -418,9 +434,10 @@ static int mbox_handle_erase_window(struct mbox_context *context, * V2: * NONE */ -static int mbox_handle_flush_window(struct mbox_context *context, +static int mbox_handle_flush_window(struct transport_mbox_context *mctx, union mbox_regs *req, struct mbox_msg *resp) { + struct mbox_context *context = mctx->context; struct protocol_flush io = { 0 }; if (context->version == API_VERSION_1) { @@ -442,9 +459,10 @@ static int mbox_handle_flush_window(struct mbox_context *context, * V2: * ARGS[0]: FLAGS */ -static int mbox_handle_close_window(struct mbox_context *context, +static int mbox_handle_close_window(struct transport_mbox_context *mctx, union mbox_regs *req, struct mbox_msg *resp) { + struct mbox_context *context = mctx->context; struct protocol_close io = { 0 }; if (context->version >= API_VERSION_2) { @@ -460,9 +478,10 @@ static int mbox_handle_close_window(struct mbox_context *context, * * ARGS[0]: Bitmap of bits to ack (by clearing) */ -static int mbox_handle_ack(struct mbox_context *context, union mbox_regs *req, - struct mbox_msg *resp) +static int mbox_handle_ack(struct transport_mbox_context *mctx, + union mbox_regs *req, struct mbox_msg *resp) { + struct mbox_context *context = mctx->context; struct protocol_ack io; io.req.flags = req->msg.args[0]; @@ -477,8 +496,9 @@ static int mbox_handle_ack(struct mbox_context *context, union mbox_regs *req, * * Return: 0 if request is valid otherwise negative error code */ -static int check_req_valid(struct mbox_context *context, union mbox_regs *req) +static int check_req_valid(struct transport_mbox_context *mctx, union mbox_regs *req) { + struct mbox_context *context = mctx->context; uint8_t cmd = req->msg.command; uint8_t seq = req->msg.seq; @@ -501,7 +521,7 @@ static int check_req_valid(struct mbox_context *context, union mbox_regs *req) } } - if (context->transport != &transport_mbox_ops) { + if (context->transport != &mctx->w) { if (cmd != MBOX_C_RESET_STATE && cmd != MBOX_C_GET_MBOX_INFO) { MSG_ERR("Cannot switch transport with command %d\n", cmd); @@ -520,8 +540,8 @@ static int check_req_valid(struct mbox_context *context, union mbox_regs *req) return 0; } -typedef int (*mboxd_mbox_handler)(struct mbox_context *, union mbox_regs *, - struct mbox_msg *); +typedef int (*mboxd_mbox_handler)(struct transport_mbox_context *, + union mbox_regs *, struct mbox_msg *); static const mboxd_mbox_handler transport_mbox_handlers[] = { mbox_handle_reset, @@ -543,9 +563,10 @@ static const mboxd_mbox_handler transport_mbox_handlers[] = { * * Return: 0 if handled successfully otherwise negative error code */ -static int handle_mbox_req(struct mbox_context *context, union mbox_regs *req) +static int handle_mbox_req(struct transport_mbox_context *mctx, union mbox_regs *req) { - const struct transport_ops *old_transport = context->transport; + struct mbox_context *context = mctx->context; + const struct ops_container *old_transport = context->transport; struct mbox_msg resp = { .command = req->msg.command, .seq = req->msg.seq, @@ -556,13 +577,13 @@ static int handle_mbox_req(struct mbox_context *context, union mbox_regs *req) MSG_INFO("Received MBOX command: %u\n", req->msg.command); - rc = check_req_valid(context, req); + rc = check_req_valid(mctx, req); if (!rc) { mboxd_mbox_handler handler; /* Commands start at 1 so we have to subtract 1 from the cmd */ handler = transport_mbox_handlers[req->msg.command - 1]; - rc = handler(context, req, &resp); + rc = handler(mctx, req, &resp); if (rc < 0) { MSG_ERR("Error handling mbox cmd: %d\n", req->msg.command); @@ -580,14 +601,14 @@ static int handle_mbox_req(struct mbox_context *context, union mbox_regs *req) MSG_DBG("MBOX arg[%d]: 0x%.2x\n", i, resp.args[i]); } MSG_INFO("Writing MBOX response: %u\n", resp.response); - len = write(context->fds[MBOX_FD].fd, &resp, sizeof(resp)); + len = write(mctx->mboxfd, &resp, sizeof(resp)); if (len < sizeof(resp)) { MSG_ERR("Didn't write the full response\n"); rc = -errno; } if (context->transport != old_transport && - context->transport == &transport_mbox_ops) { + context->transport == &mctx->w) { /* A bit messy, but we need the correct event mask */ protocol_events_set(context, context->bmc_events); } @@ -602,11 +623,12 @@ static int handle_mbox_req(struct mbox_context *context, union mbox_regs *req) * * Return: 0 if read successfully otherwise negative error code */ -static int get_message(struct mbox_context *context, union mbox_regs *msg) +static int get_message(struct transport_mbox_context *mctx, + union mbox_regs *msg) { int rc, i; - rc = read(context->fds[MBOX_FD].fd, msg, sizeof(msg->raw)); + rc = read(mctx->mboxfd, msg, sizeof(msg->raw)); if (rc < 0) { MSG_ERR("Couldn't read: %s\n", strerror(errno)); return -errno; @@ -631,57 +653,97 @@ static int get_message(struct mbox_context *context, union mbox_regs *msg) * * Return: 0 if handled successfully otherwise negative error code */ -int transport_mbox_dispatch(struct mbox_context *context) +static int transport_mbox_dispatch(struct ops_container *container, + struct epoll_event *evt) { + struct transport_mbox_context *mctx = container_to_mctx(container); + struct mbox_context *context = mctx->context; int rc = 0; union mbox_regs req = { 0 }; assert(context); - rc = get_message(context, &req); + /* First event should be an out event, that means we need to do + * some late setup. */ + if (evt->events & EPOLLOUT) + { + struct epoll_event evx = { + .events = EPOLLIN, + .data = { .ptr = evt->data.ptr, }, + }; + rc = protocol_events_put(context, container); + return rc; + } + + rc = get_message(mctx, &req); if (rc) { return rc; } - return handle_mbox_req(context, &req); + return handle_mbox_req(mctx, &req); } int __transport_mbox_init(struct mbox_context *context, const char *path, - const struct transport_ops **ops) + const struct transport_ops *ops) { int fd; + struct transport_mbox_context *mctx = calloc(1, sizeof(*mctx)); + + if (!mctx) { + MSG_INFO("Failed to allocate mbox transport context\n"); + return -ENOMEM; + } + + mctx->context = context; + /* Open MBOX Device */ fd = open(path, O_RDWR | O_NONBLOCK); if (fd < 0) { MSG_INFO("Couldn't open %s with flags O_RDWR: %s\n", path, strerror(errno)); + free(mctx); return -errno; } MSG_DBG("Opened mbox dev: %s\n", path); - context->fds[MBOX_FD].fd = fd; + mctx->mboxfd = fd; - if (ops) { - *ops = &transport_mbox_ops; - } + register_event_fd(mctx->mboxfd, context, &mctx->w); return 0; } -int transport_mbox_init(struct mbox_context *context, - const struct transport_ops **ops) +static int transport_mbox_init(struct mbox_context *context, + const struct transport_ops *ops) { int rc; rc = __transport_mbox_init(context, MBOX_HOST_PATH, ops); - if (rc) + if (rc) { + /* Disable MBOX for poll()ing purposes */ + MSG_DBG("Failed to initialise MBOX transport: %d\n", rc); + MSG_INFO("MBOX transport unavailable\n"); + return rc; + } return 0; } -void transport_mbox_free(struct mbox_context *context) +void transport_mbox_free(struct ops_container *container) { - close(context->fds[MBOX_FD].fd); + struct transport_mbox_context *mctx = container_to_mctx(container); + close(mctx->mboxfd); + free(mctx); } + +DECLARE_TRANSPORT_OPS(mbox) = { + .init = transport_mbox_init, + .event = transport_mbox_dispatch, + .fini = transport_mbox_free, + .put_events = transport_mbox_put_events, + .set_events = transport_mbox_update_events, + .clear_events = transport_mbox_update_events, +}; + diff --git a/transport_mbox.h b/transport_mbox.h index 8617f90..931950b 100644 --- a/transport_mbox.h +++ b/transport_mbox.h @@ -52,9 +52,4 @@ union mbox_regs { struct mbox_msg msg; }; -int transport_mbox_dispatch(struct mbox_context *context); -int transport_mbox_init(struct mbox_context *context, - const struct transport_ops **ops); -void transport_mbox_free(struct mbox_context *context); - #endif /* MBOXD_MSG_H */ -- 2.30.2