mboxd: Add a backend abstraction layer to mboxd.
Introduce a backend abstraction, enabling multiple implementations to be
compiled in at once. This change formally abstracts the two existing
backends, mtd and vpnor.
With the backend abstraction in place, subsequent backends are easier to
implement.
This change is based of Evan's work and he retains authorship credit. I
(AJ) have reworked the patch to pass the vpnor tests, refactored some
parts to enable broader use of const structures and others to clarify
the initialisation sequences.
Due to the existing lack of abstraction the patch has unfortunately
wide-ranging impacts. I've whittled it down as much as I consider
reasonable.
Change-Id: I29984a36dae4ea86ec00b853d2a756f0b9afb3ec
Signed-off-by: Evan Lojewski <github@meklort.com>
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/Makefile.am b/Makefile.am
index fb21633..0ce5242 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,11 +16,12 @@
mboxd_LDFLAGS = $(LIBSYSTEMD_LIBS)
mboxd_CFLAGS = $(LIBSYSTEMD_CFLAGS)
+# MTD Backing storage
+include mtd/Makefile.am.include
+
if VIRTUAL_PNOR_ENABLED
+# VPNOR Backing storage
include vpnor/Makefile.am.include
-else
-mboxd_SOURCES += flash.c \
- lpc_reset.c
endif
mboxctl_SOURCES = mboxctl.c
diff --git a/backend.h b/backend.h
new file mode 100644
index 0000000..05c5498
--- /dev/null
+++ b/backend.h
@@ -0,0 +1,232 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/* Copyright (C) 2018 IBM Corp. */
+/* Copyright (C) 2018 Evan Lojewski. */
+
+#ifndef BACKEND_H
+#define BACKEND_H
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <mtd/mtd-abi.h>
+
+#define FLASH_DIRTY 0x00
+#define FLASH_ERASED 0x01
+
+/* 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_vpnor(void);
+
+enum backend_reset_mode { reset_lpc_flash, reset_lpc_memory };
+
+struct backend_ops;
+
+struct backend {
+ const struct backend_ops *ops;
+
+ /* Backend private data */
+ void *priv;
+
+ /* Flash size from command line (bytes) */
+ uint32_t flash_size;
+
+ /* Erase size (as a shift) */
+ uint32_t erase_size_shift;
+ /* Block size (as a shift) */
+ uint32_t block_size_shift;
+};
+
+struct backend_ops {
+ /*
+ * init() - Main initialization function for backing device
+ * @context: The backend context pointer
+ * @data: Additional backend-implementation-specifc data
+ * Return: Zero on success, otherwise negative error
+ */
+ int (*init)(struct backend *backend, void *data);
+
+ /*
+ * free() - Main teardown function for backing device
+ * @context: The backend context pointer
+ */
+ void (*free)(struct backend *backend);
+
+ /*
+ * copy() - Copy data from the flash device into a provided buffer
+ * @context: The mbox context pointer
+ * @offset: The flash offset to copy from (bytes)
+ * @mem: The buffer to copy into (must be of atleast 'size' bytes)
+ * @size: The number of bytes to copy
+ * Return: Number of bytes copied on success, otherwise negative error
+ * code. flash_copy will copy at most 'size' bytes, but it may
+ * copy less.
+ */
+ int64_t (*copy)(struct backend *backend, uint32_t offset, void *mem,
+ uint32_t size);
+
+ /*
+ * set_bytemap() - Set the flash erased bytemap
+ * @context: The mbox context pointer
+ * @offset: The flash offset to set (bytes)
+ * @count: Number of bytes to set
+ * @val: Value to set the bytemap to
+ *
+ * The flash bytemap only tracks the erased status at the erase block level so
+ * this will update the erased state for an (or many) erase blocks
+ *
+ * Return: 0 if success otherwise negative error code
+ */
+ int (*set_bytemap)(struct backend *backend, uint32_t offset,
+ uint32_t count, uint8_t val);
+
+ /*
+ * erase() - Erase the flash
+ * @context: The backend context pointer
+ * @offset: The flash offset to erase (bytes)
+ * @size: The number of bytes to erase
+ *
+ * Return: 0 on success otherwise negative error code
+ */
+ int (*erase)(struct backend *backend, uint32_t offset,
+ uint32_t count);
+ /*
+ * write() - Write the flash from a provided buffer
+ * @context: The backend context pointer
+ * @offset: The flash offset to write to (bytes)
+ * @buf: The buffer to write from (must be of atleast size)
+ * @size: The number of bytes to write
+ *
+ * Return: 0 on success otherwise negative error code
+ */
+ int (*write)(struct backend *backend, uint32_t offset, void *buf,
+ uint32_t count);
+
+ /*
+ * validate() - Validates a requested window
+ * @context: The backend context pointer
+ * @offset: The requested flash offset
+ * @size: The requested region size
+ * @ro: The requested access type: True for read-only, false
+ * for read-write
+ *
+ * Return: 0 on valid otherwise negative error code
+ */
+ int (*validate)(struct backend *backend,
+ uint32_t offset, uint32_t size, bool ro);
+
+ /*
+ * reset() - Ready the reserved memory for host startup
+ * @context: The backend context pointer
+ * @buf: The LPC reserved memory pointer
+ * @count The size of the LPC reserved memory region
+ *
+ * Return: 0 on success otherwise negative error code
+ */
+ int (*reset)(struct backend *backend, void *buf, uint32_t count);
+};
+
+/* Make this better */
+static inline int backend_init(struct backend *master, struct backend *with,
+ void *data)
+{
+ int rc;
+
+ assert(master);
+
+ /* FIXME: A bit hacky? */
+ with->flash_size = master->flash_size;
+ *master = *with;
+
+#ifndef NDEBUG
+ /* Set some poison values to ensure backends init properly */
+ master->erase_size_shift = 33;
+ master->block_size_shift = 34;
+#endif
+
+ assert(master->ops->init);
+
+ rc = master->ops->init(master, data);
+ if (rc < 0)
+ return rc;
+
+ assert(master->erase_size_shift < 32);
+ assert(master->block_size_shift < 32);
+
+ return 0;
+}
+
+static inline void backend_free(struct backend *backend)
+{
+ assert(backend);
+
+ if (backend->ops->free)
+ backend->ops->free(backend);
+}
+
+static inline int64_t backend_copy(struct backend *backend,
+ uint32_t offset, void *mem, uint32_t size)
+{
+ assert(backend);
+ assert(backend->ops->copy);
+ return backend->ops->copy(backend, offset, mem, size);
+
+}
+
+static inline int backend_set_bytemap(struct backend *backend,
+ uint32_t offset, uint32_t count,
+ uint8_t val)
+{
+ assert(backend);
+
+ if (backend->ops->set_bytemap)
+ return backend->ops->set_bytemap(backend, offset, count, val);
+
+ return 0;
+}
+
+static inline int backend_erase(struct backend *backend, uint32_t offset,
+ uint32_t count)
+{
+ assert(backend);
+ if (backend->ops->erase)
+ return backend->ops->erase(backend, offset, count);
+
+ return 0;
+}
+
+static inline int backend_write(struct backend *backend, uint32_t offset,
+ void *buf, uint32_t count)
+{
+ assert(backend);
+ assert(backend->ops->write);
+ return backend->ops->write(backend, offset, buf, count);
+}
+
+static inline int backend_validate(struct backend *backend,
+ uint32_t offset, uint32_t size, bool ro)
+{
+ assert(backend);
+
+ if (backend->ops->validate)
+ return backend->ops->validate(backend, offset, size, ro);
+
+ return 0;
+}
+
+static inline int backend_reset(struct backend *backend, void *buf,
+ uint32_t count)
+{
+ assert(backend);
+ assert(backend->ops->reset);
+ return backend->ops->reset(backend, buf, count);
+}
+
+int backend_probe_mtd(struct backend *master, const char *path);
+/* Avoid dependency on vpnor/mboxd_pnor_partition_table.h */
+struct vpnor_partition_paths;
+int backend_probe_vpnor(struct backend *master,
+ const struct vpnor_partition_paths *paths);
+
+#endif /* BACKEND_H */
diff --git a/control.c b/control.c
index 648e1c5..a02b119 100644
--- a/control.c
+++ b/control.c
@@ -6,7 +6,7 @@
#include "common.h"
#include "dbus.h"
#include "mboxd.h"
-#include "flash.h"
+#include "backend.h"
#include "lpc.h"
#include "transport_mbox.h"
#include "windows.h"
@@ -62,7 +62,8 @@
int control_modified(struct mbox_context *context)
{
/* Flash has been modified - can no longer trust our erased bytemap */
- flash_set_bytemap(context, 0, context->flash_size, FLASH_DIRTY);
+ flash_set_bytemap(context, 0, context->backend.flash_size,
+ FLASH_DIRTY);
/* Force daemon to reload all windows -> Set BMC event to notify host */
if (windows_reset_all(context)) {
diff --git a/flash.c b/flash.c
deleted file mode 100644
index 6bd5c84..0000000
--- a/flash.c
+++ /dev/null
@@ -1,306 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-// Copyright (C) 2018 IBM Corp.
-
-#define _GNU_SOURCE
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <limits.h>
-#include <poll.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/timerfd.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <errno.h>
-#include <mtd/mtd-abi.h>
-
-#include "mboxd.h"
-#include "common.h"
-#include "flash.h"
-
-int flash_dev_init(struct mbox_context *context)
-{
- char *filename = get_dev_mtd();
- int fd, rc = 0;
-
- if (!filename) {
- MSG_ERR("Couldn't find the PNOR /dev/mtd partition\n");
- return -1;
- }
-
- MSG_DBG("Opening %s\n", filename);
-
- /* Open Flash Device */
- fd = open(filename, O_RDWR);
- if (fd < 0) {
- MSG_ERR("Couldn't open %s with flags O_RDWR: %s\n",
- filename, strerror(errno));
- rc = -errno;
- goto out;
- }
- context->fds[MTD_FD].fd = fd;
-
- /* Read the Flash Info */
- if (ioctl(fd, MEMGETINFO, &context->mtd_info) == -1) {
- MSG_ERR("Couldn't get information about MTD: %s\n",
- strerror(errno));
- rc = -1;
- goto out;
- }
-
- if (context->flash_size == 0) {
- /*
- * PNOR images for current OpenPOWER systems are at most 64MB
- * despite the PNOR itself sometimes being as big as 128MB. To
- * ensure the image read from the PNOR is exposed in the LPC
- * address space at the location expected by the host firmware,
- * it is required that the image size be used for
- * context->flash_size, and not the size of the flash device.
- *
- * However, the test cases specify the flash size via special
- * test APIs (controlling flash behaviour) which don't have
- * access to the mbox context. Rather than requiring
- * error-prone assignments in every test case, we instead rely
- * on context->flash_size being set to the size reported by the
- * MEMINFO ioctl().
- *
- * As this case should never be hit in production (i.e. outside
- * the test environment), log an error. As a consequence, this
- * error is expected in the test case output.
- */
- MSG_ERR("Flash size MUST be supplied on the commandline. However, continuing by assuming flash is %u bytes\n",
- context->mtd_info.size);
- context->flash_size = context->mtd_info.size;
- }
-
- /* We know the erase size so we can allocate the flash_erased bytemap */
- context->erase_size_shift = log_2(context->mtd_info.erasesize);
- context->flash_bmap = calloc(context->flash_size >>
- context->erase_size_shift,
- sizeof(*context->flash_bmap));
- MSG_DBG("Flash erase size: 0x%.8x\n", context->mtd_info.erasesize);
-
-out:
- free(filename);
- return rc;
-}
-
-void flash_dev_free(struct mbox_context *context)
-{
- free(context->flash_bmap);
- close(context->fds[MTD_FD].fd);
-}
-
-/* Flash Functions */
-
-int flash_validate(struct mbox_context *context, uint32_t offset,
- uint32_t size, bool ro)
-{
- /* Default behaviour is all accesses are valid */
- return 0;
-}
-
-/*
- * flash_is_erased() - Check if an offset into flash is erased
- * @context: The mbox context pointer
- * @offset: The flash offset to check (bytes)
- *
- * Return: true if erased otherwise false
- */
-static inline bool flash_is_erased(struct mbox_context *context,
- uint32_t offset)
-{
- return context->flash_bmap[offset >> context->erase_size_shift]
- == FLASH_ERASED;
-}
-
-/*
- * flash_set_bytemap() - Set the flash erased bytemap
- * @context: The mbox context pointer
- * @offset: The flash offset to set (bytes)
- * @count: Number of bytes to set
- * @val: Value to set the bytemap to
- *
- * The flash bytemap only tracks the erased status at the erase block level so
- * this will update the erased state for an (or many) erase blocks
- *
- * Return: 0 if success otherwise negative error code
- */
-int flash_set_bytemap(struct mbox_context *context, uint32_t offset,
- uint32_t count, uint8_t val)
-{
- if ((offset + count) > context->flash_size) {
- return -EINVAL;
- }
-
- MSG_DBG("Set flash bytemap @ 0x%.8x for 0x%.8x to %s\n",
- offset, count, val ? "ERASED" : "DIRTY");
- memset(context->flash_bmap + (offset >> context->erase_size_shift),
- val,
- align_up(count, 1 << context->erase_size_shift) >>
- context->erase_size_shift);
-
- return 0;
-}
-
-/*
- * flash_erase() - Erase the flash
- * @context: The mbox context pointer
- * @offset: The flash offset to erase (bytes)
- * @size: The number of bytes to erase
- *
- * Return: 0 on success otherwise negative error code
- */
-int flash_erase(struct mbox_context *context, uint32_t offset, uint32_t count)
-{
- const uint32_t erase_size = 1 << context->erase_size_shift;
- struct erase_info_user erase_info = { 0 };
- int rc;
-
- MSG_DBG("Erase flash @ 0x%.8x for 0x%.8x\n", offset, count);
-
- /*
- * We have an erased_bytemap for the flash so we want to avoid erasing
- * blocks which we already know to be erased. Look for runs of blocks
- * which aren't erased and erase the entire run at once to avoid how
- * often we have to call the erase ioctl. If the block is already
- * erased then there's nothing we need to do.
- */
- while (count) {
- if (!flash_is_erased(context, offset)) { /* Need to erase */
- if (!erase_info.length) { /* Start of not-erased run */
- erase_info.start = offset;
- }
- erase_info.length += erase_size;
- } else if (erase_info.length) { /* Already erased|end of run? */
- /* Erase the previous run which just ended */
- MSG_DBG("Erase flash @ 0x%.8x for 0x%.8x\n",
- erase_info.start, erase_info.length);
- rc = ioctl(context->fds[MTD_FD].fd, MEMERASE,
- &erase_info);
- if (rc < 0) {
- MSG_ERR("Couldn't erase flash at 0x%.8x\n",
- erase_info.start);
- return -errno;
- }
- /* Mark ERASED where we just erased */
- flash_set_bytemap(context, erase_info.start,
- erase_info.length, FLASH_ERASED);
- erase_info.start = 0;
- erase_info.length = 0;
- }
-
- offset += erase_size;
- count -= erase_size;
- }
-
- if (erase_info.length) {
- MSG_DBG("Erase flash @ 0x%.8x for 0x%.8x\n",
- erase_info.start, erase_info.length);
- rc = ioctl(context->fds[MTD_FD].fd, MEMERASE, &erase_info);
- if (rc < 0) {
- MSG_ERR("Couldn't erase flash at 0x%.8x\n",
- erase_info.start);
- return -errno;
- }
- /* Mark ERASED where we just erased */
- flash_set_bytemap(context, erase_info.start, erase_info.length,
- FLASH_ERASED);
- }
-
- return 0;
-}
-
-#define CHUNKSIZE (64 * 1024)
-
-/*
- * flash_copy() - Copy data from the flash device into a provided buffer
- * @context: The mbox context pointer
- * @offset: The flash offset to copy from (bytes)
- * @mem: The buffer to copy into (must be of atleast 'size' bytes)
- * @size: The number of bytes to copy
- * Return: Number of bytes copied on success, otherwise negative error
- * code. flash_copy will copy at most 'size' bytes, but it may
- * copy less.
- */
-int64_t flash_copy(struct mbox_context *context, uint32_t offset, void *mem,
- uint32_t size)
-{
- int32_t size_read;
- void *start = mem;
-
- MSG_DBG("Copy flash to %p for size 0x%.8x from offset 0x%.8x\n",
- mem, size, offset);
- if (lseek(context->fds[MTD_FD].fd, offset, SEEK_SET) != offset) {
- MSG_ERR("Couldn't seek flash at pos: %u %s\n", offset,
- strerror(errno));
- return -errno;
- }
-
- do {
- size_read = read(context->fds[MTD_FD].fd, mem,
- min_u32(CHUNKSIZE, size));
- if (size_read < 0) {
- MSG_ERR("Couldn't copy mtd into ram: %s\n",
- strerror(errno));
- return -errno;
- }
-
- size -= size_read;
- mem += size_read;
- } while (size && size_read);
-
- return size_read ? mem - start : -EIO;
-}
-
-/*
- * flash_write() - Write the flash from a provided buffer
- * @context: The mbox context pointer
- * @offset: The flash offset to write to (bytes)
- * @buf: The buffer to write from (must be of atleast size)
- * @size: The number of bytes to write
- *
- * Return: 0 on success otherwise negative error code
- */
-int flash_write(struct mbox_context *context, uint32_t offset, void *buf,
- uint32_t count)
-{
- uint32_t buf_offset = 0;
- int rc;
-
- MSG_DBG("Write flash @ 0x%.8x for 0x%.8x from %p\n", offset, count, buf);
-
- if (lseek(context->fds[MTD_FD].fd, offset, SEEK_SET) != offset) {
- MSG_ERR("Couldn't seek flash at pos: %u %s\n", offset,
- strerror(errno));
- return -errno;
- }
-
- while (count) {
- rc = write(context->fds[MTD_FD].fd, buf + buf_offset, count);
- if (rc < 0) {
- MSG_ERR("Couldn't write to flash, write lost: %s\n",
- strerror(errno));
- return -errno;
- }
- /* Mark *NOT* erased where we just wrote */
- flash_set_bytemap(context, offset + buf_offset, rc,
- FLASH_DIRTY);
- count -= rc;
- buf_offset += rc;
- }
-
- return 0;
-}
diff --git a/flash.h b/flash.h
deleted file mode 100644
index 2760563..0000000
--- a/flash.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: Apache-2.0 */
-/* Copyright (C) 2018 IBM Corp. */
-
-#ifndef FLASH_H
-#define FLASH_H
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#define FLASH_DIRTY 0x00
-#define FLASH_ERASED 0x01
-
-/* Estimate as to how long (milliseconds) it takes to access a MB from flash */
-#define FLASH_ACCESS_MS_PER_MB 8000
-
-struct mbox_context;
-
-int flash_dev_init(struct mbox_context *context);
-void flash_dev_free(struct mbox_context *context);
-int flash_validate(struct mbox_context *context, uint32_t offset,
- uint32_t size, bool ro);
-int64_t flash_copy(struct mbox_context *context, uint32_t offset, void *mem,
- uint32_t size);
-int flash_set_bytemap(struct mbox_context *context, uint32_t offset,
- uint32_t count, uint8_t val);
-int flash_erase(struct mbox_context *context, uint32_t offset, uint32_t count);
-int flash_write(struct mbox_context *context, uint32_t offset, void *buf,
- uint32_t count);
-
-#endif /* FLASH_H */
diff --git a/lpc.c b/lpc.c
index 9435246..3dc761a 100644
--- a/lpc.c
+++ b/lpc.c
@@ -27,7 +27,7 @@
#include "mboxd.h"
#include "common.h"
#include "lpc.h"
-#include "flash.h"
+#include "backend.h"
#include <linux/aspeed-lpc-ctrl.h>
#define LPC_CTRL_PATH "/dev/aspeed-lpc-ctrl"
@@ -108,9 +108,9 @@
* The mask is because the top nibble is the host LPC FW space,
* we want space 0.
*/
- .addr = 0x0FFFFFFF & -context->flash_size,
+ .addr = 0x0FFFFFFF & -context->backend.flash_size,
.offset = 0,
- .size = context->flash_size
+ .size = context->backend.flash_size
};
if (context->state & MAPS_FLASH) {
@@ -124,7 +124,7 @@
MSG_INFO("Pointing HOST LPC bus at the flash\n");
MSG_INFO("Assuming %dMB of flash: HOST LPC 0x%08x\n",
- context->flash_size >> 20, map.addr);
+ context->backend.flash_size >> 20, map.addr);
if (ioctl(context->fds[LPC_CTRL_FD].fd, ASPEED_LPC_CTRL_IOCTL_MAP, &map)
== -1) {
@@ -138,7 +138,8 @@
* Since the host now has access to the flash it can change it out from
* under us
*/
- return flash_set_bytemap(context, 0, context->flash_size, FLASH_DIRTY);
+ return flash_set_bytemap(context, 0, context->backend.flash_size,
+ FLASH_DIRTY);
}
/*
diff --git a/lpc.h b/lpc.h
index eca78b2..1e90668 100644
--- a/lpc.h
+++ b/lpc.h
@@ -10,6 +10,5 @@
void lpc_dev_free(struct mbox_context *context);
int lpc_map_flash(struct mbox_context *context);
int lpc_map_memory(struct mbox_context *context);
-int lpc_reset(struct mbox_context *context);
#endif /* LPC_H */
diff --git a/lpc_reset.c b/lpc_reset.c
deleted file mode 100644
index 9b64aa7..0000000
--- a/lpc_reset.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-// Copyright (C) 2018 IBM Corp.
-
-#define _GNU_SOURCE
-
-#include "lpc.h"
-
-struct mbox_context;
-
-/*
- * lpc_reset() - Reset the lpc bus mapping
- * @context: The mbox context pointer
- *
- * Return: 0 on success otherwise negative error code
- */
-int lpc_reset(struct mbox_context *context)
-{
- return lpc_map_flash(context);
-}
diff --git a/mboxd.c b/mboxd.c
index c2f2623..d0c4490 100644
--- a/mboxd.c
+++ b/mboxd.c
@@ -31,7 +31,7 @@
#include "common.h"
#include "dbus.h"
#include "control_dbus.h"
-#include "flash.h"
+#include "backend.h"
#include "lpc.h"
#include "transport_mbox.h"
#include "transport_dbus.h"
@@ -246,7 +246,7 @@
case 0:
break;
case 'f':
- context->flash_size = strtol(optarg, &endptr, 10);
+ context->backend.flash_size = strtol(optarg, &endptr, 10);
if (optarg == endptr) {
fprintf(stderr, "Unparseable flash size\n");
return false;
@@ -255,9 +255,9 @@
case '\0':
break;
case 'M':
- context->flash_size <<= 10;
+ context->backend.flash_size <<= 10;
case 'K':
- context->flash_size <<= 10;
+ context->backend.flash_size <<= 10;
break;
default:
fprintf(stderr, "Unknown units '%c'\n",
@@ -307,12 +307,15 @@
}
}
- if (!context->flash_size) {
+ 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;
}
- MSG_INFO("Flash size: 0x%.8x\n", context->flash_size);
+ MSG_INFO("Flash size: 0x%.8x\n", context->backend.flash_size);
if (verbosity) {
MSG_INFO("%s logging\n", verbosity == MBOX_LOG_DEBUG ? "Debug" :
@@ -322,6 +325,24 @@
return true;
}
+static int mboxd_backend_init(struct mbox_context *context)
+{
+ int rc;
+
+#ifdef VIRTUAL_PNOR_ENABLED
+ 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);
+ }
+
+ return rc;
+}
+
int main(int argc, char **argv)
{
const struct transport_ops *mbox_ops, *dbus_ops;
@@ -353,6 +374,11 @@
goto finish;
}
+ rc = mboxd_backend_init(context);
+ if (rc) {
+ goto finish;
+ }
+
rc = protocol_init(context);
if (rc) {
goto finish;
@@ -374,20 +400,11 @@
goto finish;
}
- rc = flash_dev_init(context);
- if (rc) {
- goto finish;
- }
-
rc = dbus_init(context, &dbus_ops);
if (rc) {
goto finish;
}
-#ifdef VIRTUAL_PNOR_ENABLED
- init_vpnor(context);
-#endif
-
/* Set the LPC bus mapping */
__protocol_reset(context);
@@ -421,10 +438,10 @@
protocol_events_put(context, dbus_ops);
#ifdef VIRTUAL_PNOR_ENABLED
- destroy_vpnor(context);
+ vpnor_destroy(&context->backend);
#endif
dbus_free(context);
- flash_dev_free(context);
+ backend_free(&context->backend);
lpc_dev_free(context);
transport_mbox_free(context);
windows_free(context);
diff --git a/mboxd.h b/mboxd.h
index 1047e46..e046785 100644
--- a/mboxd.h
+++ b/mboxd.h
@@ -4,11 +4,13 @@
#ifndef MBOX_H
#define MBOX_H
+#include <assert.h>
#include <mtd/mtd-abi.h>
#include <systemd/sd-bus.h>
#include <poll.h>
#include <stdbool.h>
+#include "backend.h"
#include "protocol.h"
#include "transport.h"
#include "vpnor/mboxd_pnor_partition_table.h"
@@ -48,8 +50,7 @@
#define SIG_FD 2
#define POLL_FDS 3 /* Number of FDs we poll on */
#define LPC_CTRL_FD 3
-#define MTD_FD 4
-#define TOTAL_FDS 5
+#define TOTAL_FDS 4
#define MAPS_FLASH (1 << 0)
#define MAPS_MEM (1 << 1)
@@ -72,6 +73,10 @@
enum api_version version;
const struct protocol_ops *protocol;
const struct transport_ops *transport;
+ struct backend backend;
+
+ /* Commandline parameters */
+ const char *path;
/* System State */
enum mbox_state state;
@@ -96,21 +101,32 @@
uint32_t mem_size;
/* LPC Bus Base Address (bytes) */
uint32_t lpc_base;
- /* Flash size from command line (bytes) */
- uint32_t flash_size;
- /* Bytemap of the erased state of the entire flash */
- uint8_t *flash_bmap;
- /* Erase size (as a shift) */
- uint32_t erase_size_shift;
- /* Block size (as a shift) */
- uint32_t block_size_shift;
- /* Actual Flash Info */
- struct mtd_info_user mtd_info;
-#ifdef VIRTUAL_PNOR_ENABLED
- /* Virtual PNOR partition table */
- struct vpnor_partition_table *vpnor;
- struct vpnor_partition_paths paths;
-#endif
};
+/* Temporary flash API compatibility */
+static inline int64_t flash_copy(struct mbox_context *context, uint32_t offset,
+ void *mem, uint32_t size)
+{
+ return backend_copy(&context->backend, offset, mem, size);
+}
+
+static inline int flash_set_bytemap(struct mbox_context *context,
+ uint32_t offset, uint32_t count,
+ uint8_t val)
+{
+ return backend_set_bytemap(&context->backend, offset, count, val);
+}
+
+static inline int flash_erase(struct mbox_context *context, uint32_t offset,
+ uint32_t count)
+{
+ return backend_erase(&context->backend, offset, count);
+}
+
+static inline int flash_write(struct mbox_context *context, uint32_t offset,
+ void *buf, uint32_t count)
+{
+ return backend_write(&context->backend, offset, buf, count);
+}
+
#endif /* MBOX_H */
diff --git a/mtd/Makefile.am.include b/mtd/Makefile.am.include
new file mode 100644
index 0000000..155db50
--- /dev/null
+++ b/mtd/Makefile.am.include
@@ -0,0 +1 @@
+mboxd_SOURCES += %reldir%/backend.c
diff --git a/mtd/backend.c b/mtd/backend.c
new file mode 100644
index 0000000..be8f2b2
--- /dev/null
+++ b/mtd/backend.c
@@ -0,0 +1,371 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (C) 2018 IBM Corp.
+
+#define _GNU_SOURCE
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <mtd/mtd-abi.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/timerfd.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "backend.h"
+#include "lpc.h"
+#include "mboxd.h"
+#include "mtd/backend.h"
+
+static int mtd_dev_init(struct backend *backend, void *data)
+{
+ const char *path = data;
+ struct mtd_data *priv;
+ int rc = 0;
+
+ if (!path) {
+ MSG_INFO("Discovering PNOR MTD\n");
+ path = get_dev_mtd();
+ }
+
+ priv = malloc(sizeof(*priv));
+ if (!priv) {
+ rc = -errno;
+ goto out;
+ }
+
+ MSG_DBG("Opening %s\n", path);
+
+ priv->fd = open(path, O_RDWR);
+ if (priv->fd < 0) {
+ MSG_ERR("Couldn't open %s with flags O_RDWR: %s\n", path,
+ strerror(errno));
+ rc = -errno;
+ goto cleanup_priv;
+ }
+
+ /* If the file does not support MEMGETINFO it's not an mtd device */
+ if (ioctl(priv->fd, MEMGETINFO, &priv->mtd_info) == -1) {
+ rc = -errno;
+ close(priv->fd);
+ goto cleanup_priv;
+ }
+
+ if (backend->flash_size == 0) {
+ /*
+ * PNOR images for current OpenPOWER systems are at most 64MB
+ * despite the PNOR itself sometimes being as big as 128MB. To
+ * ensure the image read from the PNOR is exposed in the LPC
+ * address space at the location expected by the host firmware,
+ * it is required that the image size be used for
+ * context->flash_size, and not the size of the flash device.
+ *
+ * However, the test cases specify the flash size via special
+ * test APIs (controlling flash behaviour) which don't have
+ * access to the mbox context. Rather than requiring
+ * error-prone assignments in every test case, we instead rely
+ * on context->flash_size being set to the size reported by the
+ * MEMINFO ioctl().
+ *
+ * As this case should never be hit in production (i.e. outside
+ * the test environment), log an error. As a consequence, this
+ * error is expected in the test case output.
+ */
+ MSG_ERR(
+ "Flash size MUST be supplied on the commandline. However, "
+ "continuing by assuming flash is %u bytes\n",
+ priv->mtd_info.size);
+ backend->flash_size = priv->mtd_info.size;
+ }
+
+ /* We know the erase size so we can allocate the flash_erased bytemap */
+ backend->erase_size_shift = log_2(priv->mtd_info.erasesize);
+ backend->block_size_shift = backend->erase_size_shift;
+ priv->flash_bmap = calloc(backend->flash_size
+ >> backend->erase_size_shift,
+ sizeof(*priv->flash_bmap));
+ MSG_DBG("Flash erase size: 0x%.8x\n", priv->mtd_info.erasesize);
+
+ backend->priv = priv;
+
+out:
+ return rc;
+
+cleanup_priv:
+ free(priv);
+ return rc;
+}
+
+static void mtd_dev_free(struct backend *backend)
+{
+ struct mtd_data *priv = backend->priv;
+
+ free(priv->flash_bmap);
+ close(priv->fd);
+ free(priv);
+}
+
+/* Flash Functions */
+
+int flash_validate(struct mbox_context *context, uint32_t offset,
+ uint32_t size, bool ro)
+{
+ /* Default behaviour is all accesses are valid */
+ return 0;
+}
+
+/*
+ * mtd_is_erased() - Check if an offset into flash is erased
+ * @context: The mbox context pointer
+ * @offset: The flash offset to check (bytes)
+ *
+ * Return: true if erased otherwise false
+ */
+static inline bool mtd_is_erased(struct backend *backend, uint32_t offset)
+{
+ const off_t index = offset >> backend->erase_size_shift;
+ struct mtd_data *priv = backend->priv;
+
+ return priv->flash_bmap[index] == FLASH_ERASED;
+}
+
+/*
+ * mtd_set_bytemap() - Set the flash erased bytemap
+ * @context: The backend context pointer
+ * @offset: The flash offset to set (bytes)
+ * @count: Number of bytes to set
+ * @val: Value to set the bytemap to
+ *
+ * The flash bytemap only tracks the erased status at the erase block level so
+ * this will update the erased state for an (or many) erase blocks
+ *
+ * Return: 0 if success otherwise negative error code
+ */
+static int mtd_set_bytemap(struct backend *backend, uint32_t offset,
+ uint32_t count, uint8_t val)
+{
+ struct mtd_data *priv = backend->priv;
+
+ if ((offset + count) > backend->flash_size) {
+ return -EINVAL;
+ }
+
+ MSG_DBG("Set flash bytemap @ 0x%.8x for 0x%.8x to %s\n", offset, count,
+ val ? "ERASED" : "DIRTY");
+ memset(priv->flash_bmap + (offset >> backend->erase_size_shift),
+ val,
+ align_up(count, 1 << backend->erase_size_shift) >>
+ backend->erase_size_shift);
+
+ return 0;
+}
+
+/*
+ * mtd_erase() - Erase the flash
+ * @context: The mbox context pointer
+ * @offset: The flash offset to erase (bytes)
+ * @size: The number of bytes to erase
+ *
+ * Return: 0 on success otherwise negative error code
+ */
+static int mtd_erase(struct backend *backend, uint32_t offset, uint32_t count)
+{
+ const uint32_t erase_size = 1 << backend->erase_size_shift;
+ struct mtd_data *priv = backend->priv;
+ struct erase_info_user erase_info = {0};
+ int rc;
+
+ MSG_DBG("Erase flash @ 0x%.8x for 0x%.8x\n", offset, count);
+
+ /*
+ * We have an erased_bytemap for the flash so we want to avoid erasing
+ * blocks which we already know to be erased. Look for runs of blocks
+ * which aren't erased and erase the entire run at once to avoid how
+ * often we have to call the erase ioctl. If the block is already
+ * erased then there's nothing we need to do.
+ */
+ while (count) {
+ if (!mtd_is_erased(backend, offset)) { /* Need to erase */
+ if (!erase_info.length) { /* Start of not-erased run */
+ erase_info.start = offset;
+ }
+ erase_info.length += erase_size;
+ } else if (erase_info.length) { /* Already erased|end of run? */
+ /* Erase the previous run which just ended */
+ MSG_DBG("Erase flash @ 0x%.8x for 0x%.8x\n",
+ erase_info.start, erase_info.length);
+ rc = ioctl(priv->fd, MEMERASE, &erase_info);
+ if (rc < 0) {
+ MSG_ERR("Couldn't erase flash at 0x%.8x\n",
+ erase_info.start);
+ return -errno;
+ }
+ /* Mark ERASED where we just erased */
+ mtd_set_bytemap(backend, erase_info.start,
+ erase_info.length, FLASH_ERASED);
+ erase_info.start = 0;
+ erase_info.length = 0;
+ }
+
+ offset += erase_size;
+ count -= erase_size;
+ }
+
+ if (erase_info.length) {
+ MSG_DBG("Erase flash @ 0x%.8x for 0x%.8x\n", erase_info.start,
+ erase_info.length);
+ rc = ioctl(priv->fd, MEMERASE, &erase_info);
+ if (rc < 0) {
+ MSG_ERR("Couldn't erase flash at 0x%.8x\n",
+ erase_info.start);
+ return -errno;
+ }
+ /* Mark ERASED where we just erased */
+ mtd_set_bytemap(backend, erase_info.start, erase_info.length,
+ FLASH_ERASED);
+ }
+
+ return 0;
+}
+
+#define CHUNKSIZE (64 * 1024)
+
+/*
+ * mtd_copy() - Copy data from the flash device into a provided buffer
+ * @context: The backend context pointer
+ * @offset: The flash offset to copy from (bytes)
+ * @mem: The buffer to copy into (must be of atleast 'size' bytes)
+ * @size: The number of bytes to copy
+ * Return: Number of bytes copied on success, otherwise negative error
+ * code. mtd_copy will copy at most 'size' bytes, but it may
+ * copy less.
+ */
+static int64_t mtd_copy(struct backend *backend, uint32_t offset,
+ void *mem, uint32_t size)
+{
+ struct mtd_data *priv = backend->priv;
+ int32_t size_read;
+ void *start = mem;
+
+ MSG_DBG("Copy flash to %p for size 0x%.8x from offset 0x%.8x\n", mem,
+ size, offset);
+ if (lseek(priv->fd, offset, SEEK_SET) != offset) {
+ MSG_ERR("Couldn't seek flash at pos: %u %s\n", offset,
+ strerror(errno));
+ return -errno;
+ }
+
+ do {
+ size_read = read(priv->fd, mem,
+ min_u32(CHUNKSIZE, size));
+ if (size_read < 0) {
+ MSG_ERR("Couldn't copy mtd into ram: %s\n",
+ strerror(errno));
+ return -errno;
+ }
+
+ size -= size_read;
+ mem += size_read;
+ } while (size && size_read);
+
+ return size_read ? mem - start : -EIO;
+}
+
+/*
+ * mtd_write() - Write the flash from a provided buffer
+ * @context: The mbox context pointer
+ * @offset: The flash offset to write to (bytes)
+ * @buf: The buffer to write from (must be of atleast size)
+ * @size: The number of bytes to write
+ *
+ * Return: 0 on success otherwise negative error code
+ */
+static int mtd_write(struct backend *backend, uint32_t offset, void *buf,
+ uint32_t count)
+{
+ struct mtd_data *priv = backend->priv;
+ uint32_t buf_offset = 0;
+ int rc;
+
+ MSG_DBG("Write flash @ 0x%.8x for 0x%.8x from %p\n", offset, count,
+ buf);
+
+ if (lseek(priv->fd, offset, SEEK_SET) != offset) {
+ MSG_ERR("Couldn't seek flash at pos: %u %s\n", offset,
+ strerror(errno));
+ return -errno;
+ }
+
+ while (count) {
+ rc = write(priv->fd, buf + buf_offset, count);
+ if (rc < 0) {
+ MSG_ERR("Couldn't write to flash, write lost: %s\n",
+ strerror(errno));
+ return -errno;
+ }
+ /* Mark *NOT* erased where we just wrote */
+ mtd_set_bytemap(backend, offset + buf_offset, rc, FLASH_DIRTY);
+ count -= rc;
+ buf_offset += rc;
+ }
+
+ return 0;
+}
+
+/*
+ * mtd_reset() - Reset the lpc bus mapping
+ * @context: The mbox context pointer
+ *
+ * Return: A value from enum backend_reset_mode, otherwise a negative
+ * error code
+ */
+static int mtd_reset(struct backend *backend,
+ void *buf __attribute__((unused)),
+ uint32_t count __attribute__((unused)))
+{
+ return reset_lpc_flash;
+}
+
+static const struct backend_ops mtd_ops = {
+ .init = mtd_dev_init,
+ .free = mtd_dev_free,
+ .copy = mtd_copy,
+ .set_bytemap = mtd_set_bytemap,
+ .erase = mtd_erase,
+ .write = mtd_write,
+ .validate = NULL,
+ .reset = mtd_reset,
+};
+
+struct backend backend_get_mtd(void)
+{
+ struct backend be = {0};
+
+ be.ops = &mtd_ops;
+
+ return be;
+}
+
+int backend_probe_mtd(struct backend *master, const char *path)
+{
+ struct backend with;
+
+ assert(master);
+ with = backend_get_mtd();
+
+ return backend_init(master, &with, (void *)path);
+}
diff --git a/mtd/backend.h b/mtd/backend.h
new file mode 100644
index 0000000..0f64215
--- /dev/null
+++ b/mtd/backend.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/* Copyright (C) 2019 IBM Corp. */
+
+#ifndef MTD_BACKEND_H
+#define MTD_BACKEND_H
+
+struct mtd_data {
+ int fd;
+ uint8_t *flash_bmap;
+ struct mtd_info_user mtd_info;
+};
+
+#endif
diff --git a/protocol.c b/protocol.c
index 76bc6ea..7158bfc 100644
--- a/protocol.c
+++ b/protocol.c
@@ -4,9 +4,10 @@
#include <errno.h>
#include <stdint.h>
+#include <stdio.h>
+#include "backend.h"
#include "common.h"
-#include "flash.h"
#include "lpc.h"
#include "mboxd.h"
#include "protocol.h"
@@ -77,11 +78,12 @@
return context->transport->clear_events(context, bmc_event, mask);
}
+static int protocol_negotiate_version(struct mbox_context *context,
+ uint8_t requested);
+
static int protocol_v1_reset(struct mbox_context *context)
{
- /* Host requested it -> No BMC Event */
- windows_reset_all(context);
- return lpc_reset(context);
+ return __protocol_reset(context);
}
static int protocol_negotiate_version(struct mbox_context *context,
@@ -109,26 +111,26 @@
io->resp.api_version = rc;
/* Now do all required intialisation for v1 */
- context->block_size_shift = BLOCK_SIZE_SHIFT_V1;
+ context->backend.block_size_shift = BLOCK_SIZE_SHIFT_V1;
MSG_INFO("Block Size: 0x%.8x (shift: %u)\n",
- 1 << context->block_size_shift, context->block_size_shift);
+ 1 << context->backend.block_size_shift, context->backend.block_size_shift);
/* Knowing blocksize we can allocate the window dirty_bytemap */
windows_alloc_dirty_bytemap(context);
io->resp.v1.read_window_size =
- context->windows.default_size >> context->block_size_shift;
+ context->windows.default_size >> context->backend.block_size_shift;
io->resp.v1.write_window_size =
- context->windows.default_size >> context->block_size_shift;
+ context->windows.default_size >> context->backend.block_size_shift;
return lpc_map_memory(context);
}
static int protocol_v1_get_flash_info(struct mbox_context *context,
- struct protocol_get_flash_info *io)
+ struct protocol_get_flash_info *io)
{
- io->resp.v1.flash_size = context->flash_size;
- io->resp.v1.erase_size = context->mtd_info.erasesize;
+ io->resp.v1.flash_size = context->backend.flash_size;
+ io->resp.v1.erase_size = 1 << context->backend.erase_size_shift;
return 0;
}
@@ -150,17 +152,20 @@
MSG_DBG("LPC address of current window: 0x%.8x\n", lpc_addr);
- return lpc_addr >> context->block_size_shift;
+ return lpc_addr >> context->backend.block_size_shift;
}
static int protocol_v1_create_window(struct mbox_context *context,
struct protocol_create_window *io)
{
- uint32_t offset = io->req.offset << context->block_size_shift;
- uint32_t size = io->req.size << context->block_size_shift;
+ struct backend *backend = &context->backend;
+ uint32_t offset;
+ uint32_t size;
int rc;
- rc = flash_validate(context, offset, size, io->req.ro);
+ offset = io->req.offset << backend->block_size_shift;
+ size = io->req.size << backend->block_size_shift;
+ rc = backend_validate(backend, offset, size, io->req.ro);
if (rc < 0) {
/* Backend does not allow window to be created. */
return rc;
@@ -227,11 +232,11 @@
/* For V1 offset given relative to flash - we want the window */
off = offset - ((context->current->flash_offset) >>
- context->block_size_shift);
+ context->backend.block_size_shift);
if (off > offset) { /* Underflow - before current window */
MSG_ERR("Tried to mark dirty before start of window\n");
MSG_ERR("requested offset: 0x%x window start: 0x%x\n",
- offset << context->block_size_shift,
+ offset << context->backend.block_size_shift,
context->current->flash_offset);
return -EINVAL;
}
@@ -241,12 +246,12 @@
* For protocol V1 we can get away with just marking the whole
* block dirty.
*/
- size = align_up(size, 1 << context->block_size_shift);
- size >>= context->block_size_shift;
+ size = align_up(size, 1 << context->backend.block_size_shift);
+ size >>= context->backend.block_size_shift;
MSG_INFO("Dirty window @ 0x%.8x for 0x%.8x\n",
- offset << context->block_size_shift,
- size << context->block_size_shift);
+ offset << context->backend.block_size_shift,
+ size << context->backend.block_size_shift);
return window_set_bytemap(context, context->current, offset, size,
WINDOW_DIRTY);
@@ -270,7 +275,7 @@
* (dirty/erased) changes we perform the required action on the backing
* store and update the current streak-type
*/
- for (i = 0; i < (context->current->size >> context->block_size_shift);
+ for (i = 0; i < (context->current->size >> context->backend.block_size_shift);
i++) {
uint8_t cur = context->current->dirty_bmap[i];
if (cur != WINDOW_CLEAN) {
@@ -312,7 +317,7 @@
/* Clear the dirty bytemap since we have written back all changes */
return window_set_bytemap(context, context->current, 0,
context->current->size >>
- context->block_size_shift,
+ context->backend.block_size_shift,
WINDOW_CLEAN);
}
@@ -416,14 +421,14 @@
io->resp.api_version = rc;
/* Now do all required intialisation for v2 */
- context->block_size_shift = log_2(context->mtd_info.erasesize);
- MSG_INFO("Block Size: 0x%.8x (shift: %u)\n",
- 1 << context->block_size_shift, context->block_size_shift);
/* Knowing blocksize we can allocate the window dirty_bytemap */
windows_alloc_dirty_bytemap(context);
- io->resp.v2.block_size_shift = context->block_size_shift;
+ io->resp.v2.block_size_shift = context->backend.block_size_shift;
+ MSG_INFO("Block Size: 0x%.8x (shift: %u)\n",
+ 1 << context->backend.block_size_shift, context->backend.block_size_shift);
+
io->resp.v2.timeout = get_suggested_timeout(context);
return lpc_map_memory(context);
@@ -432,10 +437,12 @@
static int protocol_v2_get_flash_info(struct mbox_context *context,
struct protocol_get_flash_info *io)
{
+ struct backend *backend = &context->backend;
+
io->resp.v2.flash_size =
- context->flash_size >> context->block_size_shift;
+ backend->flash_size >> backend->block_size_shift;
io->resp.v2.erase_size =
- context->mtd_info.erasesize >> context->block_size_shift;
+ ((1 << backend->erase_size_shift) >> backend->block_size_shift);
return 0;
}
@@ -449,9 +456,9 @@
if (rc < 0)
return rc;
- io->resp.size = context->current->size >> context->block_size_shift;
+ io->resp.size = context->current->size >> context->backend.block_size_shift;
io->resp.offset = context->current->flash_offset >>
- context->block_size_shift;
+ context->backend.block_size_shift;
return 0;
}
@@ -465,8 +472,8 @@
}
MSG_INFO("Dirty window @ 0x%.8x for 0x%.8x\n",
- io->req.v2.offset << context->block_size_shift,
- io->req.v2.size << context->block_size_shift);
+ io->req.v2.offset << context->backend.block_size_shift,
+ io->req.v2.size << context->backend.block_size_shift);
return window_set_bytemap(context, context->current, io->req.v2.offset,
io->req.v2.size, WINDOW_DIRTY);
@@ -484,8 +491,8 @@
}
MSG_INFO("Erase window @ 0x%.8x for 0x%.8x\n",
- io->req.offset << context->block_size_shift,
- io->req.size << context->block_size_shift);
+ io->req.offset << context->backend.block_size_shift,
+ io->req.size << context->backend.block_size_shift);
rc = window_set_bytemap(context, context->current, io->req.offset,
io->req.size, WINDOW_ERASED);
@@ -494,8 +501,8 @@
}
/* Write 0xFF to mem -> This ensures consistency between flash & ram */
- start = io->req.offset << context->block_size_shift;
- len = io->req.size << context->block_size_shift;
+ start = io->req.offset << context->backend.block_size_shift;
+ len = io->req.size << context->backend.block_size_shift;
memset(context->current->mem + start, 0xFF, len);
return 0;
@@ -597,9 +604,24 @@
/* Don't do any state manipulation, just perform the reset */
int __protocol_reset(struct mbox_context *context)
{
+ enum backend_reset_mode mode;
+ int rc;
+
windows_reset_all(context);
- return lpc_reset(context);
+ rc = backend_reset(&context->backend, context->mem, context->mem_size);
+ if (rc < 0)
+ return rc;
+
+ mode = rc;
+ if (!(mode == reset_lpc_flash || mode == reset_lpc_memory))
+ return -EINVAL;
+
+ if (mode == reset_lpc_flash)
+ return lpc_map_flash(context);
+
+ assert(mode == reset_lpc_memory);
+ return lpc_map_memory(context);
}
/* Prevent the host from performing actions whilst reset takes place */
diff --git a/test/Makefile.am.include b/test/Makefile.am.include
index 195e451..2b7ba75 100644
--- a/test/Makefile.am.include
+++ b/test/Makefile.am.include
@@ -2,20 +2,23 @@
test_flash_copy_SOURCES = \
%reldir%/flash_copy.c \
- flash.c \
+ mtd/backend.c \
+ lpc.c \
common.c mtd.c \
%reldir%/tmpf.c \
%reldir%/system.c
test_flash_erase_SOURCES = \
%reldir%/flash_erase.c \
- flash.c \
+ mtd/backend.c \
+ lpc.c \
common.c \
%reldir%/tmpf.c
test_flash_write_SOURCES = \
%reldir%/flash_write.c \
- flash.c \
+ mtd/backend.c \
+ lpc.c \
common.c \
%reldir%/tmpf.c
@@ -23,12 +26,16 @@
transport_mbox.c \
windows.c \
lpc.c \
- lpc_reset.c \
common.c \
- flash.c \
protocol.c
-TEST_MOCK_SRCS = %reldir%/tmpf.c %reldir%/mbox.c %reldir%/system.c
+TEST_MOCK_CORE = \
+ %reldir%/tmpf.c \
+ mtd/backend.c \
+ %reldir%/mbox.c \
+ %reldir%/system.c
+
+TEST_MOCK_SRCS = %reldir%/backend.c $(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
new file mode 100644
index 0000000..7b9fec8
--- /dev/null
+++ b/test/backend.c
@@ -0,0 +1,11 @@
+#include "backend.h"
+#include "mboxd.h"
+
+#include <errno.h>
+
+struct backend backend_get_vpnor(void)
+{
+ struct backend be = {0};
+
+ return be;
+}
diff --git a/test/flash_copy.c b/test/flash_copy.c
index 3b88b76..472315b 100644
--- a/test/flash_copy.c
+++ b/test/flash_copy.c
@@ -11,7 +11,7 @@
#include "common.h"
#include "mboxd.h"
-#include "flash.h"
+#include "backend.h"
#include "test/system.h"
#include "test/tmpf.h"
@@ -69,12 +69,15 @@
goto free;
}
- context.fds[MTD_FD].fd = tmp.fd;
+ assert(!backend_probe_mtd(&context.backend, tmp.path));
flash_copy(&context, 0, dst, TEST_SIZE);
assert(0 == memcmp(src, dst, TEST_SIZE));
+ backend_free(&context.backend);
+
free:
+
free(src);
free(dst);
diff --git a/test/flash_erase.c b/test/flash_erase.c
index 3d299dd..ad4e535 100644
--- a/test/flash_erase.c
+++ b/test/flash_erase.c
@@ -13,7 +13,7 @@
#include "common.h"
#include "mboxd.h"
-#include "flash.h"
+#include "backend.h"
#include "test/tmpf.h"
@@ -32,7 +32,7 @@
if (rc < 0)
return NULL;
- return strdup(mtd.path);
+ return mtd.path;
}
struct erase_info_user *recorded;
@@ -98,10 +98,13 @@
int main(void)
{
- struct mbox_context context;
+ struct mbox_context context = {0};
+ struct backend *backend;
char data[MEM_SIZE];
int rc;
+ backend = &context.backend;
+
rc = atexit(cleanup_mtd);
if (rc)
return rc;
@@ -111,7 +114,7 @@
n_ioctls = 0;
recorded = NULL;
- flash_dev_init(&context);
+ assert(!backend_probe_mtd(backend, get_dev_mtd()));
/* Erase from an unknown state */
rc = flash_erase(&context, 0, sizeof(data));
@@ -206,7 +209,7 @@
recorded = NULL;
n_ioctls = 0;
- flash_dev_free(&context);
+ backend_free(backend);
return rc;
}
diff --git a/test/flash_write.c b/test/flash_write.c
index 1b55dbe..168b2aa 100644
--- a/test/flash_write.c
+++ b/test/flash_write.c
@@ -12,7 +12,7 @@
#include "common.h"
#include "mboxd.h"
-#include "flash.h"
+#include "backend.h"
#include "test/tmpf.h"
@@ -31,7 +31,7 @@
if (rc < 0)
return NULL;
- return strdup(tmp->path);
+ return tmp->path;
}
#define MEM_SIZE 3
@@ -58,6 +58,7 @@
int main(void)
{
struct mbox_context _context, *context = &_context;
+ struct backend *backend = &context->backend;
char src[MEM_SIZE];
uint8_t *map;
int rc;
@@ -66,7 +67,7 @@
mbox_vlog = &mbox_log_console;
- rc = flash_dev_init(context);
+ rc = backend_probe_mtd(backend, get_dev_mtd());
assert(rc == 0);
map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE, tmp->fd, 0);
@@ -102,7 +103,7 @@
rc = memcmp(src, map, sizeof(src));
assert(rc == 0);
- flash_dev_free(context);
+ backend_free(backend);
return rc;
}
diff --git a/test/implicit_flush.c b/test/implicit_flush.c
index 74275e4..f186d19 100644
--- a/test/implicit_flush.c
+++ b/test/implicit_flush.c
@@ -5,6 +5,7 @@
#include <sys/mman.h>
#include "mboxd.h"
+#include "mtd/backend.h"
#include "transport_mbox.h"
#include "test/mbox.h"
@@ -92,7 +93,7 @@
assert(rc == 0);
map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE,
- ctx->fds[MTD_FD].fd, 0);
+ ((struct mtd_data *)ctx->backend.priv)->fd, 0);
assert(map != MAP_FAILED);
rc = memcmp(finish_data, map, sizeof(finish_data));
@@ -124,7 +125,7 @@
assert(rc == 0);
map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE,
- ctx->fds[MTD_FD].fd, 0);
+ ((struct mtd_data *)ctx->backend.priv)->fd, 0);
assert(map != MAP_FAILED);
rc = memcmp(finish_data, map, sizeof(finish_data));
diff --git a/test/mark_write_erased_v2.c b/test/mark_write_erased_v2.c
index 9c0f172..95cff4b 100644
--- a/test/mark_write_erased_v2.c
+++ b/test/mark_write_erased_v2.c
@@ -5,6 +5,7 @@
#include <sys/mman.h>
#include "mboxd.h"
+#include "mtd/backend.h"
#include "transport_mbox.h"
#include "test/mbox.h"
@@ -74,7 +75,7 @@
assert(rc == 0);
map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE,
- ctx->fds[MTD_FD].fd, 0);
+ ((struct mtd_data *)ctx->backend.priv)->fd, 0);
assert(map != MAP_FAILED);
rc = memcmp(start_data, map, sizeof(start_data));
diff --git a/test/mbox.c b/test/mbox.c
index a351250..55af00c 100644
--- a/test/mbox.c
+++ b/test/mbox.c
@@ -8,13 +8,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include "config.h"
#include "mboxd.h"
-#include "flash.h"
+#include "backend.h"
#include "lpc.h"
#include "transport_mbox.h"
#include "windows.h"
@@ -212,8 +214,9 @@
int __transport_mbox_init(struct mbox_context *context, const char *path);
int __lpc_dev_init(struct mbox_context *context, const char *path);
-struct mbox_context *mbox_create_test_context(int n_windows, size_t len)
+struct mbox_context *mbox_create_frontend_context(int n_windows, size_t len)
{
+ struct mtd_info_user mtd_info;
int rc;
mbox_vlog = &mbox_log_console;
@@ -224,9 +227,6 @@
rc = tmpf_init(&test.mbox, "mbox-store.XXXXXX");
assert(rc == 0);
- rc = tmpf_init(&test.flash, "flash-store.XXXXXX");
- assert(rc == 0);
-
rc = tmpf_init(&test.lpc, "lpc-store.XXXXXX");
assert(rc == 0);
@@ -247,12 +247,18 @@
assert(rc == 0);
test.context.fds[MBOX_FD].fd = test.mbox.fd;
- rc = flash_dev_init(&test.context);
+ /* Instantiate the mtd backend */
+ rc = tmpf_init(&test.flash, "flash-store.XXXXXX");
assert(rc == 0);
- rc = fallocate(test.flash.fd, 0, 0, test.context.mtd_info.size);
+ rc = ioctl(test.flash.fd, MEMGETINFO, &mtd_info);
assert(rc == 0);
+ rc = fallocate(test.flash.fd, 0, 0, mtd_info.size);
+ assert(rc == 0);
+
+ test.context.backend.flash_size = mtd_info.size;
+
rc = __lpc_dev_init(&test.context, test.lpc.path);
assert(rc == 0);
@@ -265,6 +271,20 @@
return rc ? NULL : &test.context;
}
+struct mbox_context *mbox_create_test_context(int n_windows, size_t len)
+{
+ struct mbox_context *ctx;
+ int rc;
+
+ ctx = mbox_create_frontend_context(n_windows, len);
+ assert(ctx);
+
+ rc = backend_probe_mtd(&ctx->backend, test.flash.path);
+ assert(rc == 0);
+
+ return ctx;
+}
+
/* From ccan's container_of module, CC0 license */
#define container_of(member_ptr, containing_type, member) \
((containing_type *) \
@@ -295,13 +315,13 @@
/* Sanity check */
arg = container_of(context, struct mbox_test_context, context);
assert(&test == arg);
- assert(len <= test.context.flash_size);
+ assert(len <= test.context.backend.flash_size);
- map = mmap(NULL, test.context.mtd_info.size, PROT_WRITE, MAP_SHARED,
- test.flash.fd, 0);
+ map = mmap(NULL, test.context.backend.flash_size,
+ PROT_WRITE, MAP_SHARED, test.flash.fd, 0);
assert(map != MAP_FAILED);
memcpy(map, data, len);
- munmap(map, test.context.mtd_info.size);
+ munmap(map, test.context.backend.flash_size);
return 0;
}
diff --git a/test/mbox.h b/test/mbox.h
index 8c1bff9..a030b7d 100644
--- a/test/mbox.h
+++ b/test/mbox.h
@@ -14,6 +14,7 @@
#include "tmpf.h"
struct mbox_context *mbox_create_test_context(int n_windows, size_t len);
+struct mbox_context *mbox_create_frontend_context(int n_windows, size_t len);
int mbox_set_mtd_data(struct mbox_context *context, const void *data,
size_t len);
diff --git a/test/write_flush_v2.c b/test/write_flush_v2.c
index fafa7d0..b53550d 100644
--- a/test/write_flush_v2.c
+++ b/test/write_flush_v2.c
@@ -5,6 +5,7 @@
#include <sys/mman.h>
#include "mboxd.h"
+#include "mtd/backend.h"
#include "transport_mbox.h"
#include "test/mbox.h"
@@ -95,7 +96,7 @@
assert(rc == 0);
map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE,
- ctx->fds[MTD_FD].fd, 0);
+ ((struct mtd_data *)ctx->backend.priv)->fd, 0);
assert(map != MAP_FAILED);
rc = memcmp(flush_middle_data, map, sizeof(flush_middle_data));
diff --git a/test/write_window_dirty_erase.c b/test/write_window_dirty_erase.c
index e839890..15f0bc3 100644
--- a/test/write_window_dirty_erase.c
+++ b/test/write_window_dirty_erase.c
@@ -5,6 +5,7 @@
#include <sys/mman.h>
#include "mboxd.h"
+#include "mtd/backend.h"
#include "transport_mbox.h"
#include "test/mbox.h"
@@ -114,7 +115,7 @@
assert(rc == 0);
map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE,
- ctx->fds[MTD_FD].fd, 0);
+ ((struct mtd_data *)ctx->backend.priv)->fd, 0);
assert(map != MAP_FAILED);
rc = memcmp(flush_dirty_erased_dirty_data, map,
diff --git a/transport_mbox.c b/transport_mbox.c
index 852c0a4..3d71820 100644
--- a/transport_mbox.c
+++ b/transport_mbox.c
@@ -264,7 +264,7 @@
MSG_DBG("LPC address of current window: 0x%.8x\n", lpc_addr);
- return lpc_addr >> context->block_size_shift;
+ return lpc_addr >> context->backend.block_size_shift;
}
static int mbox_handle_create_window(struct mbox_context *context, bool ro,
diff --git a/vpnor/Makefile.am.include b/vpnor/Makefile.am.include
index 36e3c50..d69a94b 100644
--- a/vpnor/Makefile.am.include
+++ b/vpnor/Makefile.am.include
@@ -1,8 +1,7 @@
mboxd_SOURCES += %reldir%/pnor_partition_table.cpp \
%reldir%/mboxd_pnor_partition_table.cpp \
- %reldir%/flash.cpp \
- %reldir%/pnor_partition.cpp \
- %reldir%/lpc_reset.cpp
+ %reldir%/backend.cpp \
+ %reldir%/pnor_partition.cpp
mboxd_LDFLAGS += -lstdc++fs \
$(SDBUSPLUS_LIBS) \
diff --git a/vpnor/backend.cpp b/vpnor/backend.cpp
new file mode 100644
index 0000000..ccda4ec
--- /dev/null
+++ b/vpnor/backend.cpp
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (C) 2018 IBM Corp.
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+extern "C" {
+#include "common.h"
+#include "lpc.h"
+#include "mboxd.h"
+#include "protocol.h"
+}
+
+#include "config.h"
+
+#include "pnor_partition.hpp"
+#include "pnor_partition_table.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+
+#include <exception>
+#include <memory>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
+#include <stdexcept>
+#include <string>
+
+#include "mboxd_pnor_partition_table.h"
+
+namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
+namespace fs = std::experimental::filesystem;
+namespace vpnor = openpower::virtual_pnor;
+
+static constexpr uint32_t VPNOR_ERASE_SIZE = 4 * 1024;
+
+int vpnor_dev_init(struct backend* backend, void* data)
+{
+ vpnor_partition_paths* paths = (vpnor_partition_paths*)data;
+ struct mtd_info_user mtd_info;
+ const char* filename = NULL;
+ int fd;
+ int rc = 0;
+
+ if (!(fs::is_directory(fs::status(paths->ro_loc)) &&
+ fs::is_directory(fs::status(paths->rw_loc)) &&
+ fs::is_directory(fs::status(paths->prsv_loc))))
+ {
+ return -EINVAL;
+ }
+
+ if (backend->flash_size == 0)
+ {
+ filename = get_dev_mtd();
+
+ MSG_INFO("No flash size provided, using PNOR MTD size\n");
+
+ if (!filename)
+ {
+ MSG_ERR("Couldn't find the flash /dev/mtd partition\n");
+ return -errno;
+ }
+
+ MSG_DBG("Opening %s\n", filename);
+
+ fd = open(filename, O_RDWR);
+ if (fd < 0)
+ {
+ MSG_ERR("Couldn't open %s with flags O_RDWR: %s\n", filename,
+ strerror(errno));
+ rc = -errno;
+ goto cleanup_filename;
+ }
+
+ // Read the Flash Info
+ if (ioctl(fd, MEMGETINFO, &mtd_info) == -1)
+ {
+ MSG_ERR("Couldn't get information about MTD: %s\n",
+ strerror(errno));
+ rc = -errno;
+ goto cleanup_fd;
+ }
+
+ close(fd);
+ free((void*)filename);
+
+ // See comment in flash.c on why
+ // this is needed.
+ backend->flash_size = mtd_info.size;
+ }
+
+ // Hostboot requires a 4K block-size to be used in the FFS flash structure
+ backend->erase_size_shift = log_2(VPNOR_ERASE_SIZE);
+ backend->block_size_shift = backend->erase_size_shift;
+
+ return vpnor_init(backend, paths);
+
+cleanup_fd:
+ close(fd);
+
+cleanup_filename:
+ free((void*)filename);
+
+ return rc;
+}
+
+static void vpnor_free(struct backend* backend)
+{
+ vpnor_destroy(backend);
+}
+
+/*
+ * vpnor_copy() - Copy data from the virtual pnor into a provided buffer
+ * @context: The backend context pointer
+ * @offset: The pnor offset to copy from (bytes)
+ * @mem: The buffer to copy into (must be of atleast 'size' bytes)
+ * @size: The number of bytes to copy
+ * Return: Number of bytes copied on success, otherwise negative error
+ * code. vpnor_copy will copy at most 'size' bytes, but it may
+ * copy less.
+ */
+static int64_t vpnor_copy(struct backend* backend, uint32_t offset, void* mem,
+ uint32_t size)
+{
+ struct vpnor_data* priv = (struct vpnor_data*)backend->priv;
+ vpnor::partition::Table* table;
+ int rc = size;
+
+ if (!(priv->vpnor && priv->vpnor->table))
+ {
+ MSG_ERR("Trying to copy data with uninitialised context!\n");
+ return -EINVAL;
+ }
+
+ table = priv->vpnor->table;
+
+ MSG_DBG("Copy virtual pnor to %p for size 0x%.8x from offset 0x%.8x\n", mem,
+ size, offset);
+
+ /* The virtual PNOR partition table starts at offset 0 in the virtual
+ * pnor image. Check if host asked for an offset that lies within the
+ * partition table.
+ */
+ size_t sz = table->size();
+ if (offset < sz)
+ {
+ const pnor_partition_table& toc = table->getHostTable();
+ rc = std::min(sz - offset, static_cast<size_t>(size));
+ memcpy(mem, ((uint8_t*)&toc) + offset, rc);
+ return rc;
+ }
+
+ try
+ {
+ vpnor::Request req(backend, offset);
+ rc = req.read(mem, size);
+ }
+ catch (vpnor::UnmappedOffset& e)
+ {
+ /*
+ * Hooo boy. Pretend that this is valid flash so we don't have
+ * discontiguous regions presented to the host. Instead, fill a window
+ * with 0xff so the 'flash' looks erased. Writes to such regions are
+ * dropped on the floor, see the implementation of vpnor_write() below.
+ */
+ MSG_INFO("Host requested unmapped region of %" PRId32
+ " bytes at offset 0x%" PRIx32 "\n",
+ size, offset);
+ uint32_t span = e.next - e.base;
+ rc = std::min(size, span);
+ memset(mem, 0xff, rc);
+ }
+ catch (std::exception& e)
+ {
+ MSG_ERR("%s\n", e.what());
+ phosphor::logging::commit<err::InternalFailure>();
+ rc = -EIO;
+ }
+ return rc;
+}
+
+/*
+ * vpnor_write() - Write to the virtual pnor from a provided buffer
+ * @context: The backend context pointer
+ * @offset: The flash offset to write to (bytes)
+ * @buf: The buffer to write from (must be of atleast size)
+ * @size: The number of bytes to write
+ *
+ * Return: 0 on success otherwise negative error code
+ */
+
+static int vpnor_write(struct backend* backend, uint32_t offset, void* buf,
+ uint32_t count)
+{
+ assert(backend);
+
+ struct vpnor_data* priv = (struct vpnor_data*)backend->priv;
+
+ if (!(priv && priv->vpnor && priv->vpnor->table))
+ {
+ MSG_ERR("Trying to write data with uninitialised context!\n");
+ return -EINVAL;
+ }
+
+ vpnor::partition::Table* table = priv->vpnor->table;
+
+ try
+ {
+ const struct pnor_partition& part = table->partition(offset);
+ if (part.data.user.data[1] & PARTITION_READONLY)
+ {
+ MSG_ERR("Unreachable: Host attempted to write to read-only "
+ "partition %s\n",
+ part.data.name);
+ return -EPERM;
+ }
+
+ MSG_DBG("Write flash @ 0x%.8x for 0x%.8x from %p\n", offset, count,
+ buf);
+ vpnor::Request req(backend, offset);
+ req.write(buf, count);
+ }
+ catch (vpnor::UnmappedOffset& e)
+ {
+ MSG_ERR("Unreachable: Host attempted to write %" PRIu32
+ " bytes to unmapped offset 0x%" PRIx32 "\n",
+ count, offset);
+ return -EACCES;
+ }
+ catch (const vpnor::OutOfBoundsOffset& e)
+ {
+ MSG_ERR("%s\n", e.what());
+ return -EINVAL;
+ }
+ catch (const std::exception& e)
+ {
+ MSG_ERR("%s\n", e.what());
+ phosphor::logging::commit<err::InternalFailure>();
+ return -EIO;
+ }
+ return 0;
+}
+
+static bool vpnor_partition_is_readonly(const pnor_partition& part)
+{
+ return part.data.user.data[1] & PARTITION_READONLY;
+}
+
+static int vpnor_validate(struct backend* backend, uint32_t offset,
+ uint32_t size __attribute__((unused)), bool ro)
+{
+ struct vpnor_data* priv = (struct vpnor_data*)backend->priv;
+
+ /* All reads are allowed */
+ if (ro)
+ {
+ return 0;
+ }
+
+ /* Only allow write windows on regions mapped by the ToC as writeable */
+ try
+ {
+ const pnor_partition& part = priv->vpnor->table->partition(offset);
+ if (vpnor_partition_is_readonly(part))
+ {
+ return -EPERM;
+ }
+ }
+ catch (const openpower::virtual_pnor::UnmappedOffset& e)
+ {
+ /*
+ * Writes to unmapped areas are not meaningful, so deny the request.
+ * This removes the ability for a compromised host to abuse unused
+ * space if any data was to be persisted (which it isn't).
+ */
+ return -EACCES;
+ }
+
+ // Allowed.
+ return 0;
+}
+
+/*
+ * vpnor_reset() - Reset the lpc bus mapping
+ * @context: The mbox context pointer
+ *
+ * Return 0 on success otherwise negative error code
+ */
+static int vpnor_reset(struct backend* backend, void* buf, uint32_t count)
+{
+ const struct vpnor_data* priv = (const struct vpnor_data*)backend->priv;
+ int rc;
+
+ vpnor_partition_paths paths = priv->paths;
+
+ vpnor_destroy(backend);
+
+ rc = vpnor_init(backend, &paths);
+ if (rc < 0)
+ return rc;
+
+ rc = vpnor_copy_bootloader_partition(backend, buf, count);
+ if (rc < 0)
+ return rc;
+
+ return reset_lpc_memory;
+}
+
+static const struct backend_ops vpnor_ops = {
+ .init = vpnor_dev_init,
+ .free = vpnor_free,
+ .copy = vpnor_copy,
+ .set_bytemap = NULL,
+ .erase = NULL,
+ .write = vpnor_write,
+ .validate = vpnor_validate,
+ .reset = vpnor_reset,
+};
+
+struct backend backend_get_vpnor(void)
+{
+ struct backend be = {0};
+
+ be.ops = &vpnor_ops;
+
+ return be;
+}
+
+int backend_probe_vpnor(struct backend* master,
+ const struct vpnor_partition_paths* paths)
+{
+ struct backend with;
+
+ assert(master);
+ with = backend_get_vpnor();
+
+ return backend_init(master, &with, (void*)paths);
+}
diff --git a/vpnor/flash.cpp b/vpnor/flash.cpp
deleted file mode 100644
index 847e6a5..0000000
--- a/vpnor/flash.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-// Copyright (C) 2018 IBM Corp.
-
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <algorithm>
-
-extern "C" {
-#include "common.h"
-#include "flash.h"
-}
-
-#include "config.h"
-
-#include "pnor_partition.hpp"
-#include "pnor_partition_table.hpp"
-#include "xyz/openbmc_project/Common/error.hpp"
-
-#include <exception>
-#include <memory>
-#include <phosphor-logging/elog-errors.hpp>
-#include <phosphor-logging/log.hpp>
-#include <stdexcept>
-#include <string>
-
-#include "mboxd_pnor_partition_table.h"
-
-namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
-namespace fs = std::experimental::filesystem;
-namespace vpnor = openpower::virtual_pnor;
-
-/** @brief unique_ptr functor to release a char* reference. */
-struct StringDeleter
-{
- void operator()(char* ptr) const
- {
- free(ptr);
- }
-};
-using StringPtr = std::unique_ptr<char, StringDeleter>;
-
-int flash_dev_init(struct mbox_context* context)
-{
- StringPtr filename(get_dev_mtd());
- int fd = 0;
- int rc = 0;
-
- if (!filename)
- {
- MSG_ERR("Couldn't find the flash /dev/mtd partition\n");
- return -1;
- }
-
- MSG_DBG("Opening %s\n", filename.get());
-
- fd = open(filename.get(), O_RDWR);
- if (fd < 0)
- {
- MSG_ERR("Couldn't open %s with flags O_RDWR: %s\n", filename.get(),
- strerror(errno));
- return -errno;
- }
-
- // Read the Flash Info
- if (ioctl(fd, MEMGETINFO, &context->mtd_info) == -1)
- {
- MSG_ERR("Couldn't get information about MTD: %s\n", strerror(errno));
- close(fd);
- return -errno;
- }
-
- if (context->flash_size == 0)
- {
- // See comment in mboxd_flash_physical.c on why
- // this is needed.
- context->flash_size = context->mtd_info.size;
- }
-
- // Hostboot requires a 4K block-size to be used in the FFS flash structure
- context->mtd_info.erasesize = 4096;
- context->erase_size_shift = log_2(context->mtd_info.erasesize);
- context->flash_bmap = NULL;
- context->fds[MTD_FD].fd = -1;
-
- close(fd);
- return rc;
-}
-
-void flash_dev_free(struct mbox_context* context)
-{
- // No-op
-}
-
-int flash_set_bytemap(struct mbox_context* context, uint32_t offset,
- uint32_t count, uint8_t val)
-{
- // No-op
- return 0;
-}
-
-int flash_erase(struct mbox_context* context, uint32_t offset, uint32_t count)
-{
- // No-op
- return 0;
-}
-
-/*
- * flash_copy() - Copy data from the virtual pnor into a provided buffer
- * @context: The mbox context pointer
- * @offset: The pnor offset to copy from (bytes)
- * @mem: The buffer to copy into (must be of atleast 'size' bytes)
- * @size: The number of bytes to copy
- * Return: Number of bytes copied on success, otherwise negative error
- * code. flash_copy will copy at most 'size' bytes, but it may
- * copy less.
- */
-int64_t flash_copy(struct mbox_context* context, uint32_t offset, void* mem,
- uint32_t size)
-{
- vpnor::partition::Table* table;
- int rc = size;
-
- if (!(context && context->vpnor && context->vpnor->table))
- {
- MSG_ERR("Trying to copy data with uninitialised context!\n");
- return -EINVAL;
- }
-
- table = context->vpnor->table;
-
- MSG_DBG("Copy virtual pnor to %p for size 0x%.8x from offset 0x%.8x\n", mem,
- size, offset);
-
- /* The virtual PNOR partition table starts at offset 0 in the virtual
- * pnor image. Check if host asked for an offset that lies within the
- * partition table.
- */
- size_t sz = table->size();
- if (offset < sz)
- {
- const pnor_partition_table& toc = table->getHostTable();
- rc = std::min(sz - offset, static_cast<size_t>(size));
- memcpy(mem, ((uint8_t*)&toc) + offset, rc);
- return rc;
- }
-
- try
- {
- vpnor::Request req(context, offset);
- rc = req.read(mem, size);
- }
- catch (vpnor::UnmappedOffset& e)
- {
- /*
- * Hooo boy. Pretend that this is valid flash so we don't have
- * discontiguous regions presented to the host. Instead, fill a window
- * with 0xff so the 'flash' looks erased. Writes to such regions are
- * dropped on the floor, see the implementation of flash_write() below.
- */
- MSG_INFO("Host requested unmapped region of %" PRId32
- " bytes at offset 0x%" PRIx32 "\n",
- size, offset);
- uint32_t span = e.next - e.base;
- rc = std::min(size, span);
- memset(mem, 0xff, rc);
- }
- catch (std::exception& e)
- {
- MSG_ERR("%s\n", e.what());
- phosphor::logging::commit<err::InternalFailure>();
- rc = -EIO;
- }
- return rc;
-}
-
-/*
- * flash_write() - Write to the virtual pnor from a provided buffer
- * @context: The mbox context pointer
- * @offset: The flash offset to write to (bytes)
- * @buf: The buffer to write from (must be of atleast size)
- * @size: The number of bytes to write
- *
- * Return: 0 on success otherwise negative error code
- */
-
-int flash_write(struct mbox_context* context, uint32_t offset, void* buf,
- uint32_t count)
-{
-
- if (!(context && context->vpnor && context->vpnor->table))
- {
- MSG_ERR("Trying to write data with uninitialised context!\n");
- return -EINVAL;
- }
-
- vpnor::partition::Table* table = context->vpnor->table;
-
- try
- {
- const struct pnor_partition& part = table->partition(offset);
- if (part.data.user.data[1] & PARTITION_READONLY)
- {
- MSG_ERR("Unreachable: Host attempted to write to read-only "
- "partition %s\n",
- part.data.name);
- return -EPERM;
- }
-
- MSG_DBG("Write flash @ 0x%.8x for 0x%.8x from %p\n", offset, count,
- buf);
- vpnor::Request req(context, offset);
- req.write(buf, count);
- }
- catch (vpnor::UnmappedOffset& e)
- {
- MSG_ERR("Unreachable: Host attempted to write %" PRIu32
- " bytes to unmapped offset 0x%" PRIx32 "\n",
- count, offset);
- return -EACCES;
- }
- catch (const vpnor::OutOfBoundsOffset& e)
- {
- MSG_ERR("%s\n", e.what());
- return -EINVAL;
- }
- catch (const std::exception& e)
- {
- MSG_ERR("%s\n", e.what());
- phosphor::logging::commit<err::InternalFailure>();
- return -EIO;
- }
- return 0;
-}
-
-static bool vpnor_partition_is_readonly(const pnor_partition& part)
-{
- return part.data.user.data[1] & PARTITION_READONLY;
-}
-
-int flash_validate(struct mbox_context* context, uint32_t offset,
- uint32_t size __attribute__((unused)), bool ro)
-{
- /* All reads are allowed */
- if (ro)
- {
- return 0;
- }
-
- /* Only allow write windows on regions mapped by the ToC as writeable */
- try
- {
- const pnor_partition& part = context->vpnor->table->partition(offset);
- if (vpnor_partition_is_readonly(part))
- {
- return -EPERM;
- }
- }
- catch (const openpower::virtual_pnor::UnmappedOffset& e)
- {
- /*
- * Writes to unmapped areas are not meaningful, so deny the request.
- * This removes the ability for a compromised host to abuse unused
- * space if any data was to be persisted (which it isn't).
- */
- return -EACCES;
- }
-
- return 0;
-}
diff --git a/vpnor/lpc_reset.cpp b/vpnor/lpc_reset.cpp
deleted file mode 100644
index 80ec6ac..0000000
--- a/vpnor/lpc_reset.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Mailbox Daemon LPC Helpers
- *
- * Copyright 2017 IBM
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-extern "C" {
-#include "lpc.h"
-#include "mboxd.h"
-}
-
-#include "mboxd_pnor_partition_table.h"
-
-/*
- * lpc_reset() - Reset the lpc bus mapping
- * @context: The mbox context pointer
- *
- * Return 0 on success otherwise negative error code
- */
-int lpc_reset(struct mbox_context* context)
-{
- int rc;
-
- destroy_vpnor(context);
-
- rc = init_vpnor(context);
- if (rc < 0)
- return rc;
-
- rc = vpnor_copy_bootloader_partition(context);
- if (rc < 0)
- return rc;
-
- return lpc_map_memory(context);
-}
diff --git a/vpnor/mboxd_pnor_partition_table.cpp b/vpnor/mboxd_pnor_partition_table.cpp
index a6ebd4e..394cc18 100644
--- a/vpnor/mboxd_pnor_partition_table.cpp
+++ b/vpnor/mboxd_pnor_partition_table.cpp
@@ -1,11 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2018 IBM Corp.
-extern "C" {
-#include "flash.h"
-}
-
#include "config.h"
+#include <assert.h>
+
+extern "C" {
+#include "backend.h"
+}
+
#include "pnor_partition_table.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
@@ -16,57 +18,58 @@
#include "mboxd.h"
#include "mboxd_pnor_partition_table.h"
-int init_vpnor(struct mbox_context* context)
+void vpnor_default_paths(vpnor_partition_paths* paths)
{
- if (context && !context->vpnor)
- {
- int rc;
-
- strncpy(context->paths.ro_loc, PARTITION_FILES_RO_LOC, PATH_MAX);
- context->paths.ro_loc[PATH_MAX - 1] = '\0';
- strncpy(context->paths.rw_loc, PARTITION_FILES_RW_LOC, PATH_MAX);
- context->paths.rw_loc[PATH_MAX - 1] = '\0';
- strncpy(context->paths.prsv_loc, PARTITION_FILES_PRSV_LOC, PATH_MAX);
- context->paths.prsv_loc[PATH_MAX - 1] = '\0';
- strncpy(context->paths.patch_loc, PARTITION_FILES_PATCH_LOC, PATH_MAX);
- context->paths.prsv_loc[PATH_MAX - 1] = '\0';
-
- rc = init_vpnor_from_paths(context);
- if (rc < 0)
- {
- return rc;
- }
- }
-
- return 0;
+ strncpy(paths->ro_loc, PARTITION_FILES_RO_LOC, PATH_MAX);
+ paths->ro_loc[PATH_MAX - 1] = '\0';
+ strncpy(paths->rw_loc, PARTITION_FILES_RW_LOC, PATH_MAX);
+ paths->rw_loc[PATH_MAX - 1] = '\0';
+ strncpy(paths->prsv_loc, PARTITION_FILES_PRSV_LOC, PATH_MAX);
+ paths->prsv_loc[PATH_MAX - 1] = '\0';
+ strncpy(paths->patch_loc, PARTITION_FILES_PATCH_LOC, PATH_MAX);
+ paths->prsv_loc[PATH_MAX - 1] = '\0';
}
-int init_vpnor_from_paths(struct mbox_context* context)
+int vpnor_init(struct backend* backend, const vpnor_partition_paths* paths)
{
namespace err = sdbusplus::xyz::openbmc_project::Common::Error;
namespace fs = std::experimental::filesystem;
namespace vpnor = openpower::virtual_pnor;
- if (context && !context->vpnor)
+ if (!(backend && paths))
+ return -EINVAL;
+
+ vpnor_data* priv = new vpnor_data;
+ assert(priv);
+
+ priv->paths = *paths;
+ backend->priv = priv;
+
+ try
{
+ priv->vpnor = new vpnor_partition_table;
+ priv->vpnor->table =
+ new openpower::virtual_pnor::partition::Table(backend);
+ }
+ catch (vpnor::TocEntryError& e)
+ {
+ MSG_ERR("%s\n", e.what());
try
{
- context->vpnor = new vpnor_partition_table;
- context->vpnor->table =
- new openpower::virtual_pnor::partition::Table(context);
- }
- catch (vpnor::TocEntryError& e)
- {
- MSG_ERR("%s\n", e.what());
phosphor::logging::commit<err::InternalFailure>();
- return -EINVAL;
}
+ catch (const std::exception& e)
+ {
+ MSG_ERR("Failed to commit InternalFailure: %s\n", e.what());
+ }
+ return -EINVAL;
}
return 0;
}
-int vpnor_copy_bootloader_partition(const struct mbox_context* context)
+int vpnor_copy_bootloader_partition(const struct backend* backend, void* buf,
+ uint32_t count)
{
// The hostboot bootloader has certain size/offset assumptions, so
// we need a special partition table here.
@@ -90,8 +93,12 @@
try
{
vpnor_partition_table vtbl{};
- struct mbox_context local = *context;
- local.vpnor = &vtbl;
+ struct vpnor_data priv;
+ struct backend local = *backend;
+
+ priv.vpnor = &vtbl;
+ priv.paths = ((struct vpnor_data*)backend->priv)->paths;
+ local.priv = &priv;
local.block_size_shift = log_2(eraseSize);
openpower::virtual_pnor::partition::Table blTable(&local);
@@ -104,16 +111,16 @@
size_t hbbOffset = partition.data.base * eraseSize;
uint32_t hbbSize = partition.data.actual;
- if (context->mem_size < tocStart + blTable.capacity() ||
- context->mem_size < hbbOffset + hbbSize)
+ if (count < tocStart + blTable.capacity() ||
+ count < hbbOffset + hbbSize)
{
MSG_ERR("Reserved memory too small for dumb bootstrap\n");
return -EINVAL;
}
- uint8_t* buf8 = static_cast<uint8_t*>(context->mem);
- flash_copy(&local, tocOffset, buf8 + tocStart, blTable.capacity());
- flash_copy(&local, hbbOffset, buf8 + hbbOffset, hbbSize);
+ uint8_t* buf8 = static_cast<uint8_t*>(buf);
+ backend_copy(&local, tocOffset, buf8 + tocStart, blTable.capacity());
+ backend_copy(&local, hbbOffset, buf8 + hbbOffset, hbbSize);
}
catch (err::InternalFailure& e)
{
@@ -130,12 +137,17 @@
return 0;
}
-void destroy_vpnor(struct mbox_context* context)
+void vpnor_destroy(struct backend* backend)
{
- if (context && context->vpnor)
+ struct vpnor_data* priv = (struct vpnor_data*)backend->priv;
+
+ if (priv)
{
- delete context->vpnor->table;
- delete context->vpnor;
- context->vpnor = nullptr;
+ if (priv->vpnor)
+ {
+ delete priv->vpnor->table;
+ }
+ delete priv->vpnor;
}
+ delete priv;
}
diff --git a/vpnor/mboxd_pnor_partition_table.h b/vpnor/mboxd_pnor_partition_table.h
index d13a2d2..e325775 100644
--- a/vpnor/mboxd_pnor_partition_table.h
+++ b/vpnor/mboxd_pnor_partition_table.h
@@ -6,6 +6,7 @@
#include <limits.h>
#include "pnor_partition_defs.h"
+#include "backend.h"
struct mbox_context;
struct vpnor_partition_table;
@@ -18,47 +19,55 @@
char patch_loc[PATH_MAX];
};
+struct vpnor_data {
+ struct vpnor_partition_table *vpnor;
+ struct vpnor_partition_paths paths;
+};
+
#ifdef __cplusplus
extern "C" {
#endif
+/** @brief Populate the path object with the default partition paths
+ *
+ * @param[in/out] paths - A paths object in which to store the defaults
+ *
+ * Returns 0 if the call succeeds, else a negative error code.
+ */
+void vpnor_default_paths(struct vpnor_partition_paths *paths);
+
/** @brief Create a virtual PNOR partition table.
*
- * @param[in] context - mbox context pointer
+ * @param[in] backend - The backend context pointer
+ * @param[in] paths - A paths object pointer to initialise vpnor
*
* This API should be called before calling any other APIs below. If a table
* already exists, this function will not do anything further. This function
* will not do anything if the context is NULL.
*
- * Returns 0 if the call succeeds, else a negative error code.
- */
-int init_vpnor(struct mbox_context *context);
-
-/** @brief Create a virtual PNOR partition table.
- *
- * @param[in] context - mbox context pointer
- *
- * This API is same as above one but requires context->path is initialised
- * with all the necessary paths.
+ * The content of the paths object is copied out, ownership is retained by the
+ * caller.
*
* Returns 0 if the call succeeds, else a negative error code.
*/
-int init_vpnor_from_paths(struct mbox_context *context);
+int vpnor_init(struct backend *backend,
+ const struct vpnor_partition_paths *paths);
/** @brief Copy bootloader partition (alongwith TOC) to LPC memory
*
- * @param[in] context - mbox context pointer
+ * @param[in] backend - The backend context pointer
*
* @returns 0 on success, negative error code on failure
*/
-int vpnor_copy_bootloader_partition(const struct mbox_context *context);
+int vpnor_copy_bootloader_partition(const struct backend *backend, void *buf,
+ uint32_t count);
/** @brief Destroy partition table, if it exists.
*
- * @param[in] context - mbox context pointer
+ * @param[in] backend - The backend context pointer
*/
-void destroy_vpnor(struct mbox_context *context);
+void vpnor_destroy(struct backend *backend);
#ifdef __cplusplus
}
diff --git a/vpnor/pnor_partition.cpp b/vpnor/pnor_partition.cpp
index 613ee26..9854159 100644
--- a/vpnor/pnor_partition.cpp
+++ b/vpnor/pnor_partition.cpp
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2018 IBM Corp.
extern "C" {
-#include "flash.h"
+#include "mboxd.h"
}
#include "config.h"
@@ -39,8 +39,10 @@
fs::path Request::getPartitionFilePath(int flags)
{
+ struct vpnor_data* priv = (struct vpnor_data*)backend->priv;
+
// Check if partition exists in patch location
- auto dst = fs::path(ctx->paths.patch_loc) / partition.data.name;
+ auto dst = fs::path(priv->paths.patch_loc) / partition.data.name;
if (fs::is_regular_file(dst))
{
return dst;
@@ -50,15 +52,15 @@
(PARTITION_PRESERVED | PARTITION_READONLY))
{
case PARTITION_PRESERVED:
- dst = ctx->paths.prsv_loc;
+ dst = priv->paths.prsv_loc;
break;
case PARTITION_READONLY:
- dst = ctx->paths.ro_loc;
+ dst = priv->paths.ro_loc;
break;
default:
- dst = ctx->paths.rw_loc;
+ dst = priv->paths.rw_loc;
}
dst /= partition.data.name;
@@ -69,22 +71,22 @@
if (flags == O_RDONLY)
{
- dst = fs::path(ctx->paths.ro_loc) / partition.data.name;
+ dst = fs::path(priv->paths.ro_loc) / partition.data.name;
assert(fs::exists(dst));
return dst;
}
assert(flags == O_RDWR);
- auto src = fs::path(ctx->paths.ro_loc) / partition.data.name;
+ auto src = fs::path(priv->paths.ro_loc) / partition.data.name;
assert(fs::exists(src));
MSG_DBG("RWRequest: Didn't find '%s' under '%s', copying from '%s'\n",
partition.data.name, dst.c_str(), src.c_str());
- dst = ctx->paths.rw_loc;
+ dst = priv->paths.rw_loc;
if (partition.data.user.data[1] & PARTITION_PRESERVED)
{
- dst = ctx->paths.prsv_loc;
+ dst = priv->paths.prsv_loc;
}
dst /= partition.data.name;
@@ -96,7 +98,7 @@
size_t Request::clamp(size_t len)
{
size_t maxAccess = offset + len;
- size_t partSize = partition.data.size << ctx->block_size_shift;
+ size_t partSize = partition.data.size << backend->block_size_shift;
return std::min(maxAccess, partSize) - offset;
}
@@ -168,7 +170,7 @@
else
{
memcpy((char*)map + offset, buf, len);
- flash_set_bytemap(ctx, base + offset, len, FLASH_DIRTY);
+ backend_set_bytemap(backend, base + offset, len, FLASH_DIRTY);
}
munmap(map, fileSize);
close(fd);
diff --git a/vpnor/pnor_partition.hpp b/vpnor/pnor_partition.hpp
index 95d4309..c91f22e 100644
--- a/vpnor/pnor_partition.hpp
+++ b/vpnor/pnor_partition.hpp
@@ -3,7 +3,8 @@
#pragma once
extern "C" {
-#include "mboxd.h"
+#include "backend.h"
+#include "mboxd_pnor_partition_table.h"
};
#include "pnor_partition_table.hpp"
@@ -14,8 +15,6 @@
#include <experimental/filesystem>
#include <string>
-#include "mboxd_pnor_partition_table.h"
-
namespace openpower
{
namespace virtual_pnor
@@ -28,7 +27,7 @@
public:
/** @brief Construct a flash access request
*
- * @param[in] ctx - The mbox context used to process the request
+ * @param[in] backend - The backend context used to process the request
* @param[in] offset - The absolute offset into the flash device as
* provided by the mbox message associated with the
* request
@@ -37,9 +36,10 @@
* the ctx pointer must strictly exceed the lifetime of the class
* instance.
*/
- Request(struct mbox_context* ctx, size_t offset) :
- ctx(ctx), partition(ctx->vpnor->table->partition(offset)),
- base(partition.data.base << ctx->block_size_shift),
+ Request(struct backend* backend, size_t offset) :
+ backend(backend), partition(((struct vpnor_data*)backend->priv)
+ ->vpnor->table->partition(offset)),
+ base(partition.data.base << backend->block_size_shift),
offset(offset - base)
{
}
@@ -64,7 +64,8 @@
std::stringstream err;
err << "Request size 0x" << std::hex << len << " from offset 0x"
<< std::hex << offset << " exceeds the partition size 0x"
- << std::hex << (partition.data.size << ctx->block_size_shift);
+ << std::hex
+ << (partition.data.size << backend->block_size_shift);
throw OutOfBoundsOffset(err.str());
}
constexpr auto flags = O_RDWR;
@@ -132,7 +133,7 @@
size_t fulfil(const std::experimental::filesystem::path& path, int flags,
void* dst, size_t len);
- struct mbox_context* ctx;
+ struct backend* backend;
const pnor_partition& partition;
size_t base;
size_t offset;
diff --git a/vpnor/pnor_partition_table.cpp b/vpnor/pnor_partition_table.cpp
index 7e99ae2..2a9442b 100644
--- a/vpnor/pnor_partition_table.cpp
+++ b/vpnor/pnor_partition_table.cpp
@@ -14,8 +14,11 @@
#include <phosphor-logging/elog-errors.hpp>
#include <regex>
+extern "C" {
+#include "backend.h"
#include "common.h"
#include "mboxd.h"
+}
namespace openpower
{
@@ -28,11 +31,11 @@
namespace partition
{
-Table::Table(const struct mbox_context* ctx) :
+Table::Table(const struct backend* be) :
szBytes(sizeof(pnor_partition_table)), numParts(0),
- blockSize(1 << ctx->erase_size_shift), pnorSize(ctx->flash_size)
+ blockSize(1 << be->erase_size_shift), pnorSize(be->flash_size)
{
- preparePartitions(ctx);
+ preparePartitions((const struct vpnor_data*)be->priv);
prepareHeader();
hostTbl = endianFixup(tbl);
}
@@ -74,10 +77,10 @@
tbl.resize(capacity());
}
-void Table::preparePartitions(const struct mbox_context* ctx)
+void Table::preparePartitions(const struct vpnor_data* priv)
{
- const fs::path roDir = ctx->paths.ro_loc;
- const fs::path patchDir = ctx->paths.patch_loc;
+ const fs::path roDir(priv->paths.ro_loc);
+ const fs::path patchDir(priv->paths.patch_loc);
fs::path tocFile = roDir / PARTITION_TOC_FILE;
allocateMemory(tocFile);
diff --git a/vpnor/pnor_partition_table.hpp b/vpnor/pnor_partition_table.hpp
index 8ba432a..90f014c 100644
--- a/vpnor/pnor_partition_table.hpp
+++ b/vpnor/pnor_partition_table.hpp
@@ -7,8 +7,12 @@
#include <numeric>
#include <vector>
+extern "C" {
+#include "backend.h"
#include "common.h"
+#include "mboxd_pnor_partition_table.h"
#include "pnor_partition_defs.h"
+}
struct mbox_context;
@@ -97,7 +101,7 @@
*
* Throws MalformedTocEntry, InvalidTocEntry
*/
- Table(const struct mbox_context* ctx);
+ Table(const struct backend* be);
Table(const Table&) = delete;
Table& operator=(const Table&) = delete;
@@ -186,7 +190,7 @@
*
* Throws: MalformedTocEntry, InvalidTocEntry
*/
- void preparePartitions(const struct mbox_context* ctx);
+ void preparePartitions(const struct vpnor_data* ctx);
/** @brief Prepares the PNOR header.
*/
diff --git a/vpnor/protocol.h b/vpnor/protocol.h
deleted file mode 100644
index 8cebda6..0000000
--- a/vpnor/protocol.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: Apache-2.0 */
-/* Copyright (C) 2018 IBM Corp. */
-#ifndef VPNOR_PROTOCOL_H
-#define VPNOR_PROTOCOL_H
-
-#include "protocol.h"
-
-/* Protocol v1 */
-int protocol_v1_vpnor_create_window(struct mbox_context *context,
- struct protocol_create_window *io);
-
-/* Protocol v2 */
-int protocol_v2_vpnor_create_window(struct mbox_context *context,
- struct protocol_create_window *io);
-
-#endif /* VPNOR_PROTOCOL_H */
diff --git a/vpnor/test/Makefile.am.include b/vpnor/test/Makefile.am.include
index 5ff4dcc..0600969 100644
--- a/vpnor/test/Makefile.am.include
+++ b/vpnor/test/Makefile.am.include
@@ -1,7 +1,4 @@
-TEST_MBOX_VPNOR_SRCS = \
- common.c \
- vpnor/pnor_partition_table.cpp \
- %reldir%/tmpd.cpp
+TEST_MOCK_VPNOR_SRCS = $(TEST_MOCK_CORE)
TEST_MBOX_VPNOR_INTEG_SRCS = \
common.c \
@@ -9,9 +6,8 @@
transport_mbox.c \
windows.c \
lpc.c \
- vpnor/lpc_reset.cpp \
+ vpnor/backend.cpp \
vpnor/mboxd_pnor_partition_table.cpp \
- vpnor/flash.cpp \
vpnor/pnor_partition.cpp \
vpnor/pnor_partition_table.cpp \
%reldir%/tmpd.cpp
@@ -22,14 +18,14 @@
$(PHOSPHOR_DBUS_INTERFACES_LIBS)
vpnor_test_create_pnor_partition_table_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_pnor_partition_table.cpp
vpnor_test_create_pnor_partition_table_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_create_pnor_partition_table_LDADD = $(VPNOR_LDADD)
vpnor_test_create_read_window_partition_exists_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_read_window_partition_exists.cpp
vpnor_test_create_read_window_partition_exists_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
@@ -106,63 +102,63 @@
vpnor_test_toc_flags_LDADD = $(VPNOR_LDADD)
vpnor_test_toc_overlap_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/toc_overlap.cpp
vpnor_test_toc_overlap_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_toc_overlap_LDADD = $(VPNOR_LDADD)
vpnor_test_toc_lookup_found_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/toc_lookup_found.cpp
vpnor_test_toc_lookup_found_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_toc_lookup_found_LDADD = $(VPNOR_LDADD)
vpnor_test_toc_lookup_failed_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/toc_lookup_failed.cpp
vpnor_test_toc_lookup_failed_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_toc_lookup_failed_LDADD = $(VPNOR_LDADD)
vpnor_test_toc_missing_file_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/toc_missing_file.cpp
vpnor_test_toc_missing_file_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_toc_missing_file_LDADD = $(VPNOR_LDADD)
vpnor_test_create_read_window_oob_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_read_window_oob.cpp
vpnor_test_create_read_window_oob_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_create_read_window_oob_LDADD = $(VPNOR_LDADD)
vpnor_test_create_read_window_toc_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_read_window_toc.cpp
vpnor_test_create_read_window_toc_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_create_read_window_toc_LDADD = $(VPNOR_LDADD)
vpnor_test_create_read_window_straddle_partitions_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_read_window_straddle_partitions.cpp
vpnor_test_create_read_window_straddle_partitions_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_create_read_window_straddle_partitions_LDADD = $(VPNOR_LDADD)
vpnor_test_create_read_window_partition_invalid_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_read_window_partition_invalid.cpp
vpnor_test_create_read_window_partition_invalid_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_create_read_window_partition_invalid_LDADD = $(VPNOR_LDADD)
vpnor_test_read_patch_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/read_patch.cpp
vpnor_test_read_patch_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
@@ -176,56 +172,56 @@
vpnor_test_write_patch_resize_LDADD = $(VPNOR_LDADD)
vpnor_test_dump_flash_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/dump_flash.cpp
vpnor_test_dump_flash_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_dump_flash_LDADD = $(VPNOR_LDADD)
vpnor_test_create_read_window_size_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_read_window_size.cpp
vpnor_test_create_read_window_size_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_create_read_window_size_LDADD = $(VPNOR_LDADD)
vpnor_test_create_read_window_remap_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_read_window_remap.cpp
vpnor_test_create_read_window_remap_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_create_read_window_remap_LDADD = $(VPNOR_LDADD)
vpnor_test_create_write_window_ro_partition_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_write_window_ro_partition.cpp
vpnor_test_create_write_window_ro_partition_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_create_write_window_ro_partition_LDADD = $(VPNOR_LDADD)
vpnor_test_create_write_window_rw_partition_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_write_window_rw_partition.cpp
vpnor_test_create_write_window_rw_partition_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_create_write_window_rw_partition_LDADD = $(VPNOR_LDADD)
vpnor_test_create_write_window_unmapped_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/create_write_window_unmapped.cpp
vpnor_test_create_write_window_unmapped_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_create_write_window_unmapped_LDADD = $(VPNOR_LDADD)
vpnor_test_write_toc_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/write_toc.cpp
vpnor_test_write_toc_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
vpnor_test_write_toc_LDADD = $(VPNOR_LDADD)
vpnor_test_force_readonly_toc_SOURCES = \
- $(TEST_MOCK_SRCS) \
+ $(TEST_MOCK_VPNOR_SRCS) \
$(TEST_MBOX_VPNOR_INTEG_SRCS) \
%reldir%/force_readonly_toc.cpp
vpnor_test_force_readonly_toc_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
diff --git a/vpnor/test/create_pnor_partition_table.cpp b/vpnor/test/create_pnor_partition_table.cpp
index cdbe8b6..f198f29 100644
--- a/vpnor/test/create_pnor_partition_table.cpp
+++ b/vpnor/test/create_pnor_partition_table.cpp
@@ -34,9 +34,9 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- const openpower::virtual_pnor::partition::Table table(ctx);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+ const openpower::virtual_pnor::partition::Table table(&ctx->backend);
pnor_partition_table expectedTable{};
expectedTable.data.magic = PARTITION_HEADER_MAGIC;
diff --git a/vpnor/test/create_read_window_oob.cpp b/vpnor/test/create_read_window_oob.cpp
index 240c10e..d1e7e64 100644
--- a/vpnor/test/create_read_window_oob.cpp
+++ b/vpnor/test/create_read_window_oob.cpp
@@ -48,9 +48,8 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- init_vpnor_from_paths(ctx);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == 1);
diff --git a/vpnor/test/create_read_window_partition_exists.cpp b/vpnor/test/create_read_window_partition_exists.cpp
index d3532ec..7ff3018 100644
--- a/vpnor/test/create_read_window_partition_exists.cpp
+++ b/vpnor/test/create_read_window_partition_exists.cpp
@@ -53,13 +53,11 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
root.write("HBB", data, sizeof(data));
- init_vpnor_from_paths(ctx);
-
int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == 1);
diff --git a/vpnor/test/create_read_window_partition_invalid.cpp b/vpnor/test/create_read_window_partition_invalid.cpp
index 36431d3..4d28b2c 100644
--- a/vpnor/test/create_read_window_partition_invalid.cpp
+++ b/vpnor/test/create_read_window_partition_invalid.cpp
@@ -44,14 +44,14 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- init_vpnor_from_paths(ctx);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == 1);
rc = mbox_command_dispatch(ctx, create_read_window,
sizeof(create_read_window));
+
return !(rc == 1);
}
diff --git a/vpnor/test/create_read_window_remap.cpp b/vpnor/test/create_read_window_remap.cpp
index 7a11053..f81d1bc 100644
--- a/vpnor/test/create_read_window_remap.cpp
+++ b/vpnor/test/create_read_window_remap.cpp
@@ -47,9 +47,8 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- init_vpnor_from_paths(ctx);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == 1);
diff --git a/vpnor/test/create_read_window_size.cpp b/vpnor/test/create_read_window_size.cpp
index 6ea11f1..4e8cb5d 100644
--- a/vpnor/test/create_read_window_size.cpp
+++ b/vpnor/test/create_read_window_size.cpp
@@ -56,9 +56,8 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- init_vpnor_from_paths(ctx);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == 1);
diff --git a/vpnor/test/create_read_window_straddle_partitions.cpp b/vpnor/test/create_read_window_straddle_partitions.cpp
index bc963dd..bdc3fa5 100644
--- a/vpnor/test/create_read_window_straddle_partitions.cpp
+++ b/vpnor/test/create_read_window_straddle_partitions.cpp
@@ -52,9 +52,8 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- init_vpnor_from_paths(ctx);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == 1);
diff --git a/vpnor/test/create_read_window_toc.cpp b/vpnor/test/create_read_window_toc.cpp
index fee61ca..7571f37 100644
--- a/vpnor/test/create_read_window_toc.cpp
+++ b/vpnor/test/create_read_window_toc.cpp
@@ -55,15 +55,13 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- vpnor::partition::Table table(ctx);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+ vpnor::partition::Table table(&ctx->backend);
/* Make sure the ToC exactly fits in the space allocated for it */
assert(table.capacity() == TOC_PART_SIZE);
- init_vpnor_from_paths(ctx);
-
rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == 1);
diff --git a/vpnor/test/create_write_window_ro_partition.cpp b/vpnor/test/create_write_window_ro_partition.cpp
index 5cc19ca..59d4a0d 100644
--- a/vpnor/test/create_write_window_ro_partition.cpp
+++ b/vpnor/test/create_write_window_ro_partition.cpp
@@ -45,11 +45,9 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-
- init_vpnor_from_paths(ctx);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == 1);
diff --git a/vpnor/test/create_write_window_rw_partition.cpp b/vpnor/test/create_write_window_rw_partition.cpp
index 879fd85..ed6f3dd 100644
--- a/vpnor/test/create_write_window_rw_partition.cpp
+++ b/vpnor/test/create_write_window_rw_partition.cpp
@@ -45,11 +45,9 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-
- init_vpnor_from_paths(ctx);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == 1);
diff --git a/vpnor/test/create_write_window_unmapped.cpp b/vpnor/test/create_write_window_unmapped.cpp
index 76694fc..d7f76fd 100644
--- a/vpnor/test/create_write_window_unmapped.cpp
+++ b/vpnor/test/create_write_window_unmapped.cpp
@@ -46,11 +46,9 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-
- init_vpnor_from_paths(ctx);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == MBOX_R_SUCCESS);
diff --git a/vpnor/test/dump_flash.cpp b/vpnor/test/dump_flash.cpp
index 5179b7c..f285a61 100644
--- a/vpnor/test/dump_flash.cpp
+++ b/vpnor/test/dump_flash.cpp
@@ -68,9 +68,8 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
- tctx->ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(tctx->ctx, toc, BLOCK_SIZE);
- init_vpnor_from_paths(tctx->ctx);
+ tctx->ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&tctx->ctx->backend, toc, BLOCK_SIZE);
rc = mbox_command_dispatch(tctx->ctx, get_info, sizeof(get_info));
assert(rc == 1);
diff --git a/vpnor/test/force_readonly_toc.cpp b/vpnor/test/force_readonly_toc.cpp
index 8d3bec1..465adad 100644
--- a/vpnor/test/force_readonly_toc.cpp
+++ b/vpnor/test/force_readonly_toc.cpp
@@ -52,14 +52,12 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- vpnor::partition::Table table(ctx);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+ vpnor::partition::Table table(&ctx->backend);
assert(table.capacity() == TOC_PART_SIZE);
- init_vpnor_from_paths(ctx);
-
rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == MBOX_R_SUCCESS);
diff --git a/vpnor/test/read_patch.cpp b/vpnor/test/read_patch.cpp
index 631a23c..4d541f6 100644
--- a/vpnor/test/read_patch.cpp
+++ b/vpnor/test/read_patch.cpp
@@ -47,8 +47,8 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
// PATCH_SIZE is smaller than the size of the partition we defined. This
// test ensures that mboxd will behave correctly when we request an offset
@@ -57,8 +57,6 @@
std::vector<uint8_t> patch(PATCH_SIZE, 0xff);
root.patch("ONE", patch.data(), patch.size());
- init_vpnor_from_paths(ctx);
-
int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == 1);
diff --git a/vpnor/test/tmpd.hpp b/vpnor/test/tmpd.hpp
index 7386f2f..f6ea7c9 100644
--- a/vpnor/test/tmpd.hpp
+++ b/vpnor/test/tmpd.hpp
@@ -4,6 +4,7 @@
#include "config.h"
extern "C" {
+#include "backend.h"
#include "mboxd.h"
}
@@ -28,8 +29,9 @@
{
public:
template <std::size_t N>
- VpnorRoot(struct mbox_context* ctx, const std::string (&toc)[N],
- size_t blockSize)
+ VpnorRoot(struct backend* backend, const std::string (&toc)[N],
+ size_t blockSize) :
+ backend(backend)
{
char tmplt[] = "/tmp/vpnor_root.XXXXXX";
char* tmpdir = mkdtemp(tmplt);
@@ -58,14 +60,21 @@
std::ofstream(tocFilePath, std::ofstream::app) << line << "\n";
}
- strncpy(ctx->paths.ro_loc, ro().c_str(), PATH_MAX - 1);
- ctx->paths.ro_loc[PATH_MAX - 1] = '\0';
- strncpy(ctx->paths.rw_loc, rw().c_str(), PATH_MAX - 1);
- ctx->paths.rw_loc[PATH_MAX - 1] = '\0';
- strncpy(ctx->paths.prsv_loc, prsv().c_str(), PATH_MAX - 1);
- ctx->paths.prsv_loc[PATH_MAX - 1] = '\0';
- strncpy(ctx->paths.patch_loc, patch().c_str(), PATH_MAX - 1);
- ctx->paths.patch_loc[PATH_MAX - 1] = '\0';
+ vpnor_partition_paths paths{};
+
+ snprintf(paths.ro_loc, PATH_MAX - 1, "%s/ro", root.c_str());
+ paths.ro_loc[PATH_MAX - 1] = '\0';
+ snprintf(paths.rw_loc, PATH_MAX - 1, "%s/rw", root.c_str());
+ paths.rw_loc[PATH_MAX - 1] = '\0';
+ snprintf(paths.prsv_loc, PATH_MAX - 1, "%s/prsv", root.c_str());
+ paths.prsv_loc[PATH_MAX - 1] = '\0';
+ snprintf(paths.patch_loc, PATH_MAX - 1, "%s/patch", root.c_str());
+ paths.patch_loc[PATH_MAX - 1] = '\0';
+
+ if (backend_probe_vpnor(backend, &paths))
+ {
+ throw std::system_error(errno, std::system_category());
+ }
}
VpnorRoot(const VpnorRoot&) = delete;
@@ -75,6 +84,7 @@
~VpnorRoot()
{
+ backend_free(backend);
fs::remove_all(root);
}
fs::path ro()
@@ -97,6 +107,7 @@
size_t patch(const std::string& name, const void* data, size_t len);
private:
+ struct backend* backend;
fs::path root;
const std::string attributes[4] = {"ro", "rw", "prsv", "patch"};
};
diff --git a/vpnor/test/toc_lookup_failed.cpp b/vpnor/test/toc_lookup_failed.cpp
index bb07725..cb56e51 100644
--- a/vpnor/test/toc_lookup_failed.cpp
+++ b/vpnor/test/toc_lookup_failed.cpp
@@ -37,10 +37,10 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- vpnor::partition::Table table(ctx);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+ vpnor::partition::Table table(&ctx->backend);
try
{
diff --git a/vpnor/test/toc_lookup_found.cpp b/vpnor/test/toc_lookup_found.cpp
index fccee0c..b8c879c 100644
--- a/vpnor/test/toc_lookup_found.cpp
+++ b/vpnor/test/toc_lookup_found.cpp
@@ -37,10 +37,10 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- vpnor::partition::Table table(ctx);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+ vpnor::partition::Table table(&ctx->backend);
const struct pnor_partition& part = table.partition("TWO");
assert(part.data.id == 2);
diff --git a/vpnor/test/toc_missing_file.cpp b/vpnor/test/toc_missing_file.cpp
index 6b7e068..95147c0 100644
--- a/vpnor/test/toc_missing_file.cpp
+++ b/vpnor/test/toc_missing_file.cpp
@@ -37,15 +37,15 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
fs::remove(root.ro() / "TWO");
try
{
- vpnor::partition::Table table(ctx);
+ vpnor::partition::Table table(&ctx->backend);
}
catch (vpnor::InvalidTocEntry& e)
{
diff --git a/vpnor/test/toc_overlap.cpp b/vpnor/test/toc_overlap.cpp
index a7ac20d..18b7151 100644
--- a/vpnor/test/toc_overlap.cpp
+++ b/vpnor/test/toc_overlap.cpp
@@ -36,15 +36,13 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
try
{
- vpnor::partition::Table table(ctx);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
}
- catch (vpnor::InvalidTocEntry& e)
+ catch (std::system_error& e)
{
return 0;
}
diff --git a/vpnor/test/write_patch.cpp b/vpnor/test/write_patch.cpp
index 1bf6ba9..4f59db5 100644
--- a/vpnor/test/write_patch.cpp
+++ b/vpnor/test/write_patch.cpp
@@ -4,8 +4,8 @@
#include "config.h"
extern "C" {
+#include "backend.h"
#include "common.h"
-#include "flash.h"
#include "mboxd.h"
}
@@ -47,15 +47,14 @@
mbox_vlog = &mbox_log_console;
verbosity = (verbose)2;
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+ ctx->backend.flash_size = 0x2000;
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
root.write("TEST1", data, sizeof(data));
/* flash_write doesn't copy the file for us */
assert(fs::copy_file(root.ro() / "TEST1", root.rw() / "TEST1"));
fs::path patch = root.patch() / "TEST1";
assert(fs::copy_file(root.ro() / "TEST1", patch));
- init_vpnor_from_paths(ctx);
-
/* Test */
memset(src, 0x33, sizeof(src));
rc = flash_write(ctx, 0x1000, src, sizeof(src));
@@ -79,8 +78,5 @@
munmap(map, sizeof(src));
close(fd);
- destroy_vpnor(ctx);
- free(ctx->flash_bmap);
-
return rc;
}
diff --git a/vpnor/test/write_patch_resize.cpp b/vpnor/test/write_patch_resize.cpp
index 9a6979f..ce128c8 100644
--- a/vpnor/test/write_patch_resize.cpp
+++ b/vpnor/test/write_patch_resize.cpp
@@ -4,8 +4,8 @@
#include "config.h"
extern "C" {
+#include "backend.h"
#include "common.h"
-#include "flash.h"
#include "mboxd.h"
}
@@ -46,15 +46,14 @@
mbox_vlog = &mbox_log_console;
verbosity = (verbose)2;
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+ ctx->backend.flash_size = 0x2000;
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
std::vector<uint8_t> roContent(PART_SIZE, 0xff);
root.write("TEST1", roContent.data(), roContent.size());
/* flash_write doesn't copy the file for us */
std::vector<uint8_t> patchContent(PATCH_SIZE, 0xaa);
root.patch("TEST1", patchContent.data(), patchContent.size());
- init_vpnor_from_paths(ctx);
-
/* Test */
std::vector<uint8_t> update(UPDATE_SIZE, 0x55);
rc = flash_write(ctx, 0x1000, update.data(), update.size());
@@ -71,8 +70,5 @@
munmap(map, update.size());
close(fd);
- destroy_vpnor(ctx);
- free(ctx->flash_bmap);
-
return rc;
}
diff --git a/vpnor/test/write_prsv.cpp b/vpnor/test/write_prsv.cpp
index 53f3cfe..9ee1fb3 100644
--- a/vpnor/test/write_prsv.cpp
+++ b/vpnor/test/write_prsv.cpp
@@ -2,8 +2,8 @@
// Copyright (C) 2018 IBM Corp.
extern "C" {
+#include "backend.h"
#include "common.h"
-#include "flash.h"
#include "mboxd.h"
}
@@ -41,8 +41,8 @@
mbox_vlog = &mbox_log_console;
verbosity = (verbose)2;
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- init_vpnor_from_paths(ctx);
+ ctx->backend.flash_size = 0x2000;
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
/* Test */
memset(src, 0xaa, sizeof(src));
@@ -60,8 +60,5 @@
munmap(map, sizeof(src));
close(fd);
- /* Cleanup */
- destroy_vpnor(ctx);
-
return 0;
}
diff --git a/vpnor/test/write_ro.cpp b/vpnor/test/write_ro.cpp
index e5671b1..e6bedd3 100644
--- a/vpnor/test/write_ro.cpp
+++ b/vpnor/test/write_ro.cpp
@@ -3,8 +3,8 @@
#include "config.h"
extern "C" {
+#include "backend.h"
#include "common.h"
-#include "flash.h"
#include "mboxd.h"
}
@@ -39,8 +39,8 @@
mbox_vlog = &mbox_log_console;
verbosity = (verbose)2;
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- init_vpnor_from_paths(ctx);
+ ctx->backend.flash_size = 0x2000;
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
/* Test */
rc = flash_write(ctx, 0x1000, src, sizeof(src));
@@ -48,7 +48,5 @@
/* Verify we can't write to RO partitions */
assert(rc != 0);
- destroy_vpnor(ctx);
-
return 0;
}
diff --git a/vpnor/test/write_rw.cpp b/vpnor/test/write_rw.cpp
index e64f01e..3b742a1 100644
--- a/vpnor/test/write_rw.cpp
+++ b/vpnor/test/write_rw.cpp
@@ -3,8 +3,8 @@
#include "config.h"
extern "C" {
+#include "backend.h"
#include "common.h"
-#include "flash.h"
#include "mboxd.h"
}
@@ -41,10 +41,10 @@
mbox_vlog = &mbox_log_console;
verbosity = (verbose)2;
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+ ctx->backend.flash_size = 0x2000;
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
/* flash_write() doesn't copy the file for us */
assert(fs::copy_file(root.ro() / "TEST1", root.rw() / "TEST1"));
- init_vpnor_from_paths(ctx);
/* Test */
memset(src, 0xbb, sizeof(src));
@@ -95,7 +95,5 @@
munmap(map, sizeof(src));
close(fd);
- destroy_vpnor(ctx);
-
return 0;
}
diff --git a/vpnor/test/write_toc.cpp b/vpnor/test/write_toc.cpp
index 6f6b101..8b690a1 100644
--- a/vpnor/test/write_toc.cpp
+++ b/vpnor/test/write_toc.cpp
@@ -67,14 +67,12 @@
system_set_reserved_size(MEM_SIZE);
system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
- ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
- test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
- vpnor::partition::Table table(ctx);
+ ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+ test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+ vpnor::partition::Table table(&ctx->backend);
assert(table.capacity() == TOC_PART_SIZE);
- init_vpnor_from_paths(ctx);
-
rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
assert(rc == MBOX_R_SUCCESS);
diff --git a/windows.c b/windows.c
index 0b852c5..8f9fb02 100644
--- a/windows.c
+++ b/windows.c
@@ -29,7 +29,7 @@
#include "common.h"
#include "transport_mbox.h"
#include "windows.h"
-#include "flash.h"
+#include "backend.h"
/* Initialisation Functions */
@@ -173,11 +173,11 @@
* boundary
*/
low_mem.flash_offset = align_down(flash_offset,
- context->mtd_info.erasesize);
+ 1 << context->backend.erase_size_shift);
low_mem.size = flash_offset - low_mem.flash_offset;
high_mem.flash_offset = flash_offset + count_bytes;
high_mem.size = align_up(high_mem.flash_offset,
- context->mtd_info.erasesize) -
+ 1 << context->backend.erase_size_shift) -
high_mem.flash_offset;
/*
@@ -279,8 +279,8 @@
uint32_t count, uint8_t type)
{
int rc;
- uint32_t flash_offset, count_bytes = count << context->block_size_shift;
- uint32_t offset_bytes = offset << context->block_size_shift;
+ uint32_t flash_offset, count_bytes = count << context->backend.block_size_shift;
+ uint32_t offset_bytes = offset << context->backend.block_size_shift;
switch (type) {
case WINDOW_ERASED: /* >= V2 ONLY -> block_size == erasesize */
@@ -297,8 +297,8 @@
* so we have a special function to make sure that we do this
* correctly without losing data.
*/
- if (log_2(context->mtd_info.erasesize) !=
- context->block_size_shift) {
+ if (context->backend.erase_size_shift !=
+ context->backend.block_size_shift) {
return window_flush_v1(context, offset_bytes,
count_bytes);
}
@@ -345,7 +345,7 @@
free(cur->dirty_bmap);
/* Allocate the new one */
cur->dirty_bmap = calloc((context->windows.default_size >>
- context->block_size_shift),
+ context->backend.block_size_shift),
sizeof(*cur->dirty_bmap));
}
}
@@ -363,12 +363,12 @@
int window_set_bytemap(struct mbox_context *context, struct window_context *cur,
uint32_t offset, uint32_t size, uint8_t val)
{
- if (offset + size > (cur->size >> context->block_size_shift)) {
+ if (offset + size > (cur->size >> context->backend.block_size_shift)) {
MSG_ERR("Tried to set window bytemap past end of window\n");
MSG_ERR("Requested offset: 0x%x size: 0x%x window size: 0x%x\n",
- offset << context->block_size_shift,
- size << context->block_size_shift,
- cur->size << context->block_size_shift);
+ offset << context->backend.block_size_shift,
+ size << context->backend.block_size_shift,
+ cur->size << context->backend.block_size_shift);
return -EACCES;
}
@@ -410,7 +410,7 @@
window->size = context->windows.default_size;
if (window->dirty_bmap) { /* Might not have been allocated */
window_set_bytemap(context, window, 0,
- window->size >> context->block_size_shift,
+ window->size >> context->backend.block_size_shift,
WINDOW_CLEAN);
}
window->age = 0;
@@ -593,10 +593,10 @@
}
#endif
- if (offset > context->flash_size) {
+ if (offset > context->backend.flash_size) {
MSG_ERR("Tried to open read window past flash limit\n");
return -EINVAL;
- } else if ((offset + cur->size) > context->flash_size) {
+ } else if ((offset + cur->size) > context->backend.flash_size) {
/*
* There is V1 skiboot implementations out there which don't
* mask offset with window size, meaning when we have
@@ -608,14 +608,14 @@
* this.
*/
if (context->version == API_VERSION_1) {
- cur->size = align_down(context->flash_size - offset,
- 1 << context->block_size_shift);
+ cur->size = align_down(context->backend.flash_size - offset,
+ 1 << context->backend.block_size_shift);
} else {
/*
* Allow requests to exceed the flash size, but limit
* the response to the size of the flash.
*/
- cur->size = context->flash_size - offset;
+ cur->size = context->backend.flash_size - offset;
}
}
@@ -632,7 +632,7 @@
* FIXME: This should only be the case for the vpnor ToC now, so handle
* it there
*/
- cur->size = align_up(rc, (1ULL << context->block_size_shift));
+ cur->size = align_up(rc, (1ULL << context->backend.block_size_shift));
/* Would like a known value, pick 0xFF to it looks like erased flash */
memset(cur->mem + rc, 0xFF, cur->size - rc);
@@ -662,7 +662,7 @@
/* Clear the bytemap of the window just loaded -> we know it's clean */
window_set_bytemap(context, cur, 0,
- cur->size >> context->block_size_shift,
+ cur->size >> context->backend.block_size_shift,
WINDOW_CLEAN);
/* Update so we know what's in the window */