summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Jeffery <andrew@aj.id.au>2019-03-15 12:40:41 +1030
committerAndrew Jeffery <andrew@aj.id.au>2019-03-19 16:40:59 +1030
commit5320f6e02453261e6c75d3bef101ad1bef6de82e (patch)
tree28d3df48b8fb56021a2bda3b3a7f460a3f5a46a4
parenta042978b03c91ca3a716e99f313ef5cda42820ba (diff)
downloadphosphor-mboxbridge-5320f6e02453261e6c75d3bef101ad1bef6de82e.tar.gz
phosphor-mboxbridge-5320f6e02453261e6c75d3bef101ad1bef6de82e.zip
mboxd: Add backend DBus interface and commandline options
Also implement a backend commandline option to mboxctl: `mboxctl --backend ...`, to allow easy run-time switching of the backend from the commandline. Switching between VPNOR and file backends via mboxctl was tested on Witherspoon, and MTD and file backends on Romulus. Change-Id: Iaf0e27ecf1d5cdd9e3a31729fb179096bbc37408 Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
-rw-r--r--backend.h29
-rw-r--r--control.c32
-rw-r--r--control_dbus.c88
-rw-r--r--control_dbus.h2
-rw-r--r--mboxctl.c97
-rw-r--r--mboxd.c52
-rw-r--r--mboxd.h2
-rw-r--r--test/Makefile.am.include2
-rw-r--r--test/backend.c11
-rw-r--r--vpnor/mboxd_pnor_partition_table.h10
10 files changed, 284 insertions, 41 deletions
diff --git a/backend.h b/backend.h
index 5b043ec..f7b56b4 100644
--- a/backend.h
+++ b/backend.h
@@ -6,6 +6,7 @@
#define BACKEND_H
#include <assert.h>
+#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <mtd/mtd-abi.h>
@@ -16,10 +17,6 @@
/* Estimate as to how long (milliseconds) it takes to access a MB from flash */
#define FLASH_ACCESS_MS_PER_MB 8000
-struct backend backend_get_mtd(void);
-struct backend backend_get_file(void);
-struct backend backend_get_vpnor(void);
-
enum backend_reset_mode { reset_lpc_flash, reset_lpc_memory };
struct backend_ops;
@@ -146,7 +143,8 @@ static inline int backend_init(struct backend *master, struct backend *with,
master->block_size_shift = 34;
#endif
- assert(master->ops->init);
+ if (!master->ops->init)
+ return -ENOTSUP;
rc = master->ops->init(master, data);
if (rc < 0)
@@ -224,11 +222,32 @@ static inline int backend_reset(struct backend *backend, void *buf,
return backend->ops->reset(backend, buf, count);
}
+struct backend backend_get_mtd(void);
int backend_probe_mtd(struct backend *master, const char *path);
+
+struct backend backend_get_file(void);
int backend_probe_file(struct backend *master, const char *path);
+
/* Avoid dependency on vpnor/mboxd_pnor_partition_table.h */
struct vpnor_partition_paths;
+#ifdef VIRTUAL_PNOR_ENABLED
+struct backend backend_get_vpnor(void);
+
int backend_probe_vpnor(struct backend *master,
const struct vpnor_partition_paths *paths);
+#else
+static inline struct backend backend_get_vpnor(void)
+{
+ struct backend be = { 0 };
+
+ return be;
+}
+
+static inline int backend_probe_vpnor(struct backend *master,
+ const struct vpnor_partition_paths *paths)
+{
+ return -ENOTSUP;
+}
+#endif
#endif /* BACKEND_H */
diff --git a/control.c b/control.c
index acca924..4b73efa 100644
--- a/control.c
+++ b/control.c
@@ -3,12 +3,12 @@
#include <errno.h>
#include <stdlib.h>
+#include "backend.h"
#include "common.h"
#include "dbus.h"
-#include "mboxd.h"
-#include "backend.h"
#include "lpc.h"
-#include "transport_mbox.h"
+#include "mboxd.h"
+#include "protocol.h"
#include "windows.h"
int control_ping(struct mbox_context *context)
@@ -116,3 +116,29 @@ int control_resume(struct mbox_context *context, bool modified)
return rc;
}
+
+int control_set_backend(struct mbox_context *context, struct backend *backend,
+ void *data)
+{
+ int rc;
+
+ if (context->state & STATE_SUSPENDED)
+ return -EINVAL;
+
+ rc = protocol_events_clear(context, BMC_EVENT_DAEMON_READY);
+ if (rc < 0)
+ return rc;
+
+ backend_free(&context->backend);
+
+ rc = backend_init(&context->backend, backend, data);
+ if (rc < 0)
+ return rc;
+
+ rc = __protocol_reset(context);
+ if (rc < 0)
+ return rc;
+
+ return protocol_events_set(context,
+ BMC_EVENT_DAEMON_READY | BMC_EVENT_PROTOCOL_RESET);
+}
diff --git a/control_dbus.c b/control_dbus.c
index c8c6463..e22d736 100644
--- a/control_dbus.c
+++ b/control_dbus.c
@@ -2,12 +2,14 @@
// Copyright (C) 2018 IBM Corp.
#include <assert.h>
#include <errno.h>
+#include <stdlib.h>
#include <systemd/sd-bus.h>
#include "common.h"
#include "dbus.h"
#include "control_dbus.h"
#include "mboxd.h"
+#include "vpnor/mboxd_pnor_partition_table.h"
typedef int (*control_action)(struct mbox_context *context);
@@ -108,6 +110,90 @@ static int control_dbus_resume(sd_bus_message *m, void *userdata,
return sd_bus_send(NULL, n, NULL);
}
+static int control_dbus_set_backend(sd_bus_message *m, void *userdata,
+ sd_bus_error *ret_error)
+{
+ struct mbox_context *context;
+ struct backend backend;
+ sd_bus_message *n;
+ const char *name;
+ int rc;
+
+ context = (struct mbox_context *) userdata;
+ if (!context) {
+ MSG_ERR("DBUS Internal Error\n");
+ return -EINVAL;
+ }
+
+ rc = sd_bus_message_read_basic(m, 's', &name);
+ if (rc < 0) {
+ MSG_ERR("DBUS error reading message: %s\n", strerror(-rc));
+ return rc;
+ }
+
+ if (!strcmp(name, "vpnor")) {
+ struct vpnor_partition_paths paths;
+
+ vpnor_default_paths(&paths);
+ backend = backend_get_vpnor();
+ rc = control_set_backend(context, &backend, &paths);
+ if (rc < 0)
+ return rc;
+ } else if (!strcmp(name, "mtd")) {
+ char **paths = NULL;
+ char *path = NULL;
+
+ rc = sd_bus_message_read_strv(m, &paths);
+ if (rc < 0)
+ return rc;
+
+ if (paths && *paths)
+ path = *paths;
+ else
+ path = get_dev_mtd();
+
+ backend = backend_get_mtd();
+
+ rc = control_set_backend(context, &backend, path);
+ if (rc < 0)
+ return rc;
+
+ free(path);
+ free(paths);
+ } else if (!strcmp(name, "file")) {
+ char **paths = NULL;
+ char *path = NULL;
+
+ rc = sd_bus_message_read_strv(m, &paths);
+ if (rc < 0)
+ return rc;
+
+ if (!(paths && *paths))
+ return -EINVAL;
+
+ path = *paths;
+
+ backend = backend_get_file();
+
+ rc = control_set_backend(context, &backend, path);
+ if (rc < 0)
+ return rc;
+
+ free(path);
+ free(paths);
+ } else {
+ return -EINVAL;
+ }
+
+ rc = sd_bus_message_new_method_return(m, &n);
+ if (rc < 0) {
+ MSG_ERR("sd_bus_message_new_method_return failed: %d\n", rc);
+ return rc;
+ }
+
+ return sd_bus_send(NULL, n, NULL);
+}
+
static int control_dbus_get_u8(sd_bus *bus, const char *path,
const char *interface, const char *property,
sd_bus_message *reply, void *userdata,
@@ -144,6 +230,8 @@ static const sd_bus_vtable mboxd_vtable[] = {
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Resume", "b", NULL, &control_dbus_resume,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetBackend", "sas", NULL, &control_dbus_set_backend,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_PROPERTY("DaemonState", "y", &control_dbus_get_u8, 0,
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("LpcState", "y", &control_dbus_get_u8, 0,
diff --git a/control_dbus.h b/control_dbus.h
index 17e4dec..16661c9 100644
--- a/control_dbus.h
+++ b/control_dbus.h
@@ -2,6 +2,7 @@
#define DBUS_CONTROL_H
struct mbox_context;
+struct backend;
int control_dbus_init(struct mbox_context *context);
void control_dbus_free(struct mbox_context *context);
@@ -18,5 +19,6 @@ int control_kill(struct mbox_context *context);
int control_modified(struct mbox_context *context);
int control_suspend(struct mbox_context *context);
int control_resume(struct mbox_context *context, bool modified);
+int control_set_backend(struct mbox_context *context, struct backend *backend, void *data);
#endif
diff --git a/mboxctl.c b/mboxctl.c
index 9dbc149..b001fb9 100644
--- a/mboxctl.c
+++ b/mboxctl.c
@@ -4,6 +4,7 @@
#include <errno.h>
#include <getopt.h>
+#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -25,7 +26,8 @@
"\t\t--suspend\t\t- suspend the daemon to inhibit flash accesses (0)\n" \
"\t\t--resume\t\t- resume the daemon (1)\n" \
"\t\t\targ[0]: < \"clean\" | \"modified\" >\n" \
-"\t\t--clear-cache\t- tell the daemon to discard any caches (0)\n"
+"\t\t--clear-cache\t- tell the daemon to discard any caches (0)\n" \
+"\t\t--backend <vpnor|mtd[:PATH]|file:PATH>\n"
#define NAME "Mailbox Control"
@@ -269,6 +271,95 @@ static int handle_cmd_modified(struct mboxctl_context *context)
return rc;
}
+static int handle_cmd_backend(struct mboxctl_context *context, char *sarg)
+{
+ sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus_message *m = NULL, *n = NULL;
+ char *delim = NULL;
+ char *strv[2];
+ int rc;
+
+ if (!sarg) {
+ MSG_ERR("Backend command takes an argument\n");
+ return -EINVAL;
+ }
+
+ rc = sd_bus_message_new_method_call(context->bus, &m,
+ MBOX_DBUS_NAME,
+ MBOX_DBUS_OBJECT,
+ MBOX_DBUS_CONTROL_IFACE,
+ "SetBackend");
+ if (rc < 0) {
+ MSG_ERR("Failed to init method call: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+
+ if (!strncmp(sarg, "vpnor", strlen("vpnor"))) {
+ if (strchr(sarg, ':')) {
+ MSG_ERR("Path parameter not supported for vpnor\n");
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = sd_bus_message_append(m, "s", "vpnor");
+ if (rc < 0)
+ goto out;
+ } else if (!strncmp(sarg, "mtd", strlen("mtd"))) {
+ rc = sd_bus_message_append(m, "s", "mtd");
+ if (rc < 0)
+ goto out;
+ } else if (!strncmp(sarg, "file", strlen("file"))) {
+ rc = sd_bus_message_append(m, "s", "file");
+ if (rc < 0)
+ goto out;
+ } else {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ delim = strchr(sarg, ':');
+ if (delim) {
+ char *path;
+
+ path = realpath(delim + 1, NULL);
+ if (!path) {
+ MSG_ERR("Failed to resolve path: %s\n",
+ strerror(errno));
+ rc = -errno;
+ goto out;
+ }
+
+ strv[0] = path;
+ strv[1] = NULL;
+
+ rc = sd_bus_message_append_strv(m, &strv[0]);
+ free(path);
+ if (rc < 0)
+ goto out;
+ } else {
+ strv[0] = NULL;
+ strv[1] = NULL;
+ rc = sd_bus_message_append_strv(m, &strv[0]);
+ if (rc < 0)
+ goto out;
+ }
+
+ rc = sd_bus_call(context->bus, m, 0, &error, &n);
+ if (rc < 0) {
+ MSG_ERR("Failed to post message: %s\n", strerror(-rc));
+ goto out;
+ }
+
+ MSG_OUT("SetBackend: %s\n", rc < 0 ? strerror(-rc) : "Success");
+
+out:
+ sd_bus_error_free(&error);
+ sd_bus_message_unref(m);
+
+ return rc < 0 ? rc : 0;
+}
+
static int parse_cmdline(struct mboxctl_context *context, int argc, char **argv)
{
int opt, rc = -1;
@@ -284,6 +375,7 @@ static int parse_cmdline(struct mboxctl_context *context, int argc, char **argv)
{ "suspend", no_argument, 0, 'u' },
{ "resume", required_argument, 0, 'e' },
{ "clear-cache", no_argument, 0, 'c' },
+ { "backend", required_argument, 0, 'b' },
{ "version", no_argument, 0, 'v' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
@@ -325,6 +417,9 @@ static int parse_cmdline(struct mboxctl_context *context, int argc, char **argv)
case 'c':
rc = handle_cmd_modified(context);
break;
+ case 'b':
+ rc = handle_cmd_backend(context, optarg);
+ break;
case 'v':
MSG_OUT("%s V%s\n", NAME, PACKAGE_VERSION);
rc = 0;
diff --git a/mboxd.c b/mboxd.c
index 85e1d3f..48624c8 100644
--- a/mboxd.c
+++ b/mboxd.c
@@ -44,9 +44,9 @@ const char* USAGE =
"\t\t[-w | --window-size <size>M]\n"
"\t\t-f | --flash <size>[K|M]\n"
#ifdef VIRTUAL_PNOR_ENABLED
- "\t\t-s | --source <vpnor|path>\n\n"
+ "\t\t-b | --backend <vpnor|mtd[:PATH]|file:PATH>\n"
#else
- "\t\t-s | --source <path>\n\n"
+ "\t\t-b | --backend <mtd[:PATH]|file:PATH>\n"
#endif
"\t-v | --verbose\t\tBe [more] verbose\n"
"\t-s | --syslog\t\tLog output to syslog (pointless without -v)\n"
@@ -272,7 +272,7 @@ static bool parse_cmdline(int argc, char **argv,
}
break;
case 'b':
- context->path = optarg;
+ context->source = optarg;
break;
case 'n':
context->windows.num = strtol(argv[optind], &endptr,
@@ -316,9 +316,6 @@ static bool parse_cmdline(int argc, char **argv,
}
}
- if (!context->path) {
- context->path = get_dev_mtd();
- }
if (!context->backend.flash_size) {
fprintf(stderr, "Must specify a non-zero flash size\n");
return false;
@@ -336,23 +333,44 @@ static bool parse_cmdline(int argc, char **argv,
static int mboxd_backend_init(struct mbox_context *context)
{
+ const char *delim;
+ const char *path;
int rc;
-#ifdef VIRTUAL_PNOR_ENABLED
- struct vpnor_partition_paths paths;
- vpnor_default_paths(&paths);
+ if (!context->source) {
+ struct vpnor_partition_paths paths;
+ vpnor_default_paths(&paths);
- rc = backend_probe_vpnor(&context->backend, &paths);
- if(rc)
-#endif
- {
- rc = backend_probe_mtd(&context->backend, context->path);
- if (rc) {
- rc = backend_probe_file(&context->backend,
- context->path);
+ rc = backend_probe_vpnor(&context->backend, &paths);
+ if(rc < 0)
+ rc = backend_probe_mtd(&context->backend, NULL);
+
+ return rc;
+ }
+
+ delim = strchr(context->source, ':');
+ path = delim ? delim + 1 : NULL;
+
+ if (!strncmp(context->source, "vpnor", strlen("vpnor"))) {
+ struct vpnor_partition_paths paths;
+
+ if (path) {
+ rc = -EINVAL;
+ } else {
+ vpnor_default_paths(&paths);
+ rc = backend_probe_vpnor(&context->backend, &paths);
}
+ } else if (!strncmp(context->source, "mtd", strlen("mtd"))) {
+ rc = backend_probe_mtd(&context->backend, path);
+ } else if (!strncmp(context->source, "file", strlen("file"))) {
+ rc = backend_probe_file(&context->backend, path);
+ } else {
+ rc = -EINVAL;
}
+ if (rc < 0)
+ MSG_ERR("Invalid backend argument: %s\n", context->source);
+
return rc;
}
diff --git a/mboxd.h b/mboxd.h
index 7930242..ef4f5be 100644
--- a/mboxd.h
+++ b/mboxd.h
@@ -76,7 +76,7 @@ struct mbox_context {
struct backend backend;
/* Commandline parameters */
- const char *path;
+ const char *source;
/* System State */
enum mbox_state state;
diff --git a/test/Makefile.am.include b/test/Makefile.am.include
index 2b7ba75..addf2f9 100644
--- a/test/Makefile.am.include
+++ b/test/Makefile.am.include
@@ -35,7 +35,7 @@ TEST_MOCK_CORE = \
%reldir%/mbox.c \
%reldir%/system.c
-TEST_MOCK_SRCS = %reldir%/backend.c $(TEST_MOCK_CORE)
+TEST_MOCK_SRCS = $(TEST_MOCK_CORE)
test_get_mbox_info_v2_SOURCES = %reldir%/get_mbox_info_v2.c \
$(TEST_MBOX_SRCS) $(TEST_MOCK_SRCS)
diff --git a/test/backend.c b/test/backend.c
deleted file mode 100644
index 7b9fec8..0000000
--- a/test/backend.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "backend.h"
-#include "mboxd.h"
-
-#include <errno.h>
-
-struct backend backend_get_vpnor(void)
-{
- struct backend be = {0};
-
- return be;
-}
diff --git a/vpnor/mboxd_pnor_partition_table.h b/vpnor/mboxd_pnor_partition_table.h
index e325775..b76aa98 100644
--- a/vpnor/mboxd_pnor_partition_table.h
+++ b/vpnor/mboxd_pnor_partition_table.h
@@ -2,8 +2,6 @@
/* Copyright (C) 2018 IBM Corp. */
#pragma once
-#ifdef VIRTUAL_PNOR_ENABLED
-
#include <limits.h>
#include "pnor_partition_defs.h"
#include "backend.h"
@@ -34,8 +32,16 @@ extern "C" {
*
* Returns 0 if the call succeeds, else a negative error code.
*/
+#ifdef VIRTUAL_PNOR_ENABLED
void vpnor_default_paths(struct vpnor_partition_paths *paths);
+#else
+static inline void vpnor_default_paths(struct vpnor_partition_paths *paths)
+{
+ memset(paths, 0, sizeof(*paths));
+}
+#endif
+#ifdef VIRTUAL_PNOR_ENABLED
/** @brief Create a virtual PNOR partition table.
*
* @param[in] backend - The backend context pointer
OpenPOWER on IntegriCloud