aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorLandon J. Fuller <landonf@FreeBSD.org>2016-12-19 20:26:10 +0000
committerLandon J. Fuller <landonf@FreeBSD.org>2016-12-19 20:26:10 +0000
commitf76db8de03b8979bcdd782a2d2237db732160811 (patch)
treee84564d496756bb0299d6de60089788f858b8e32 /sys
parent6cffadf0f0719b1e05d710fa78bed272d81a6f2a (diff)
downloadsrc-f76db8de03b8979bcdd782a2d2237db732160811.tar.gz
src-f76db8de03b8979bcdd782a2d2237db732160811.zip
bhnd(4): add support for wrapping arbitrary pointers in an NVRAM I/O
context. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8759
Notes
Notes: svn path=/head/; revision=310294
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files1
-rw-r--r--sys/dev/bhnd/nvram/bhnd_nvram_io.h11
-rw-r--r--sys/dev/bhnd/nvram/bhnd_nvram_ioptr.c228
-rw-r--r--sys/modules/bhnd/Makefile1
4 files changed, 241 insertions, 0 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 8073ae163ae2..25641c2ccd56 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1240,6 +1240,7 @@ dev/bhnd/nvram/bhnd_nvram_data_tlv.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_if.m optional bhnd
dev/bhnd/nvram/bhnd_nvram_io.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_iobuf.c optional bhnd
+dev/bhnd/nvram/bhnd_nvram_ioptr.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_iores.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_plist.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_store.c optional bhnd
diff --git a/sys/dev/bhnd/nvram/bhnd_nvram_io.h b/sys/dev/bhnd/nvram/bhnd_nvram_io.h
index fcec2d7b1dd6..cf86ca8ff023 100644
--- a/sys/dev/bhnd/nvram/bhnd_nvram_io.h
+++ b/sys/dev/bhnd/nvram/bhnd_nvram_io.h
@@ -52,6 +52,9 @@ struct bhnd_nvram_io *bhnd_nvram_iobuf_copy(struct bhnd_nvram_io *src);
struct bhnd_nvram_io *bhnd_nvram_iobuf_copy_range(struct bhnd_nvram_io *src,
size_t offset, size_t size);
+struct bhnd_nvram_io *bhnd_nvram_ioptr_new(const void *ptr, size_t size,
+ size_t capacity, uint32_t flags);
+
#ifdef _KERNEL
struct bhnd_nvram_io *bhnd_nvram_iores_new(struct bhnd_resource *r,
bus_size_t offset, bus_size_t size,
@@ -76,4 +79,12 @@ int bhnd_nvram_io_write_ptr(struct bhnd_nvram_io *io,
void bhnd_nvram_io_free(struct bhnd_nvram_io *io);
+/**
+ * bhnd_nvram_ioptr flags
+ */
+enum {
+ BHND_NVRAM_IOPTR_RDONLY = (1<<0), /**< read-only */
+ BHND_NVRAM_IOPTR_RDWR = (1<<1), /**< read/write */
+};
+
#endif /* _BHND_NVRAM_BHND_NVRAM_IO_H_ */
diff --git a/sys/dev/bhnd/nvram/bhnd_nvram_ioptr.c b/sys/dev/bhnd/nvram/bhnd_nvram_ioptr.c
new file mode 100644
index 000000000000..50fb164c3ec3
--- /dev/null
+++ b/sys/dev/bhnd/nvram/bhnd_nvram_ioptr.c
@@ -0,0 +1,228 @@
+/*-
+ * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef _KERNEL
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#else /* !_KERNEL */
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#endif /* _KERNEL */
+
+#include "bhnd_nvram_private.h"
+
+#include "bhnd_nvram_io.h"
+#include "bhnd_nvram_iovar.h"
+
+/**
+ * Memory-backed NVRAM I/O context.
+ *
+ * ioptr instances are gauranteed to provide persistent references to its
+ * backing contigious memory via bhnd_nvram_io_read_ptr() and
+ * bhnd_nvram_io_write_ptr().
+ */
+struct bhnd_nvram_ioptr {
+ struct bhnd_nvram_io io; /**< common I/O instance state */
+ void *ptr; /**< backing memory */
+ size_t size; /**< size at @p ptr */
+ size_t capacity; /**< capacity at @p ptr */
+ uint32_t flags; /**< flags (see BHND_NVRAM_IOPTR_*) */
+};
+
+BHND_NVRAM_IOPS_DEFN(ioptr)
+
+/**
+ * Allocate and return a new I/O context, mapping @p size bytes at @p ptr.
+
+ * The caller is responsible for deallocating the returned I/O context via
+ * bhnd_nvram_io_free().
+ *
+ * @param ptr The pointer to be mapped by the returned I/O
+ * context. Must remain valid for the lifetime of
+ * the returned I/O context.
+ * @param size The total number of bytes mapped at @p ptr.
+ * @param capacity The maximum number of bytes that may be mapped
+ * at @p ptr via bhnd_nvram_ioptr_setsize().
+ * @param flags Access flags (see BHND_NVRAM_IOPTR_*).
+ *
+ * @retval bhnd_nvram_io success.
+ * @retval NULL allocation failed.
+ * @retval NULL the requested @p capacity is less than @p size.
+ */
+struct bhnd_nvram_io *
+bhnd_nvram_ioptr_new(const void *ptr, size_t size, size_t capacity,
+ uint32_t flags)
+{
+ struct bhnd_nvram_ioptr *ioptr;
+
+ /* Sanity check the capacity */
+ if (size > capacity)
+ return (NULL);
+
+ /* Allocate I/O context */
+ ioptr = bhnd_nv_malloc(sizeof(*ioptr));
+ if (ioptr == NULL)
+ return (NULL);
+
+ ioptr->io.iops = &bhnd_nvram_ioptr_ops;
+ ioptr->ptr = __DECONST(void *, ptr);
+ ioptr->size = size;
+ ioptr->capacity = capacity;
+ ioptr->flags = flags;
+
+ return (&ioptr->io);
+}
+
+static void
+bhnd_nvram_ioptr_free(struct bhnd_nvram_io *io)
+{
+ bhnd_nv_free(io);
+}
+
+static size_t
+bhnd_nvram_ioptr_getsize(struct bhnd_nvram_io *io)
+{
+ struct bhnd_nvram_ioptr *ioptr = (struct bhnd_nvram_ioptr *)io;
+ return (ioptr->size);
+}
+
+static int
+bhnd_nvram_ioptr_setsize(struct bhnd_nvram_io *io, size_t size)
+{
+ struct bhnd_nvram_ioptr *ioptr = (struct bhnd_nvram_ioptr *)io;
+
+ /* Must be writable */
+ if (!(ioptr->flags & BHND_NVRAM_IOPTR_RDWR))
+ return (ENODEV);
+
+ /* Can't exceed the actual capacity */
+ if (size > ioptr->capacity)
+ return (ENXIO);
+
+ ioptr->size = size;
+ return (0);
+}
+
+/* Common ioptr_(read|write)_ptr implementation */
+static int
+bhnd_nvram_ioptr_ptr(struct bhnd_nvram_ioptr *ioptr, size_t offset, void **ptr,
+ size_t nbytes, size_t *navail)
+{
+ size_t avail;
+
+ /* Verify offset+nbytes fall within the buffer range */
+ if (offset > ioptr->size)
+ return (ENXIO);
+
+ avail = ioptr->size - offset;
+ if (avail < nbytes)
+ return (ENXIO);
+
+ /* Valid I/O range, provide a pointer to the buffer and the
+ * total count of available bytes */
+ *ptr = ((uint8_t *)ioptr->ptr) + offset;
+ if (navail != NULL)
+ *navail = avail;
+
+ return (0);
+}
+
+static int
+bhnd_nvram_ioptr_read_ptr(struct bhnd_nvram_io *io, size_t offset,
+ const void **ptr, size_t nbytes, size_t *navail)
+{
+ struct bhnd_nvram_ioptr *ioptr;
+ void *writep;
+ int error;
+
+ ioptr = (struct bhnd_nvram_ioptr *) io;
+
+ /* Return a pointer into our backing buffer */
+ error = bhnd_nvram_ioptr_ptr(ioptr, offset, &writep, nbytes, navail);
+ if (error)
+ return (error);
+
+ *ptr = writep;
+
+ return (0);
+}
+
+static int
+bhnd_nvram_ioptr_write_ptr(struct bhnd_nvram_io *io, size_t offset,
+ void **ptr, size_t nbytes, size_t *navail)
+{
+ struct bhnd_nvram_ioptr *ioptr;
+
+ ioptr = (struct bhnd_nvram_ioptr *) io;
+
+ /* Must be writable */
+ if (!(ioptr->flags & BHND_NVRAM_IOPTR_RDWR))
+ return (ENODEV);
+
+ /* Return a pointer into our backing buffer */
+ return (bhnd_nvram_ioptr_ptr(ioptr, offset, ptr, nbytes, navail));
+}
+
+static int
+bhnd_nvram_ioptr_read(struct bhnd_nvram_io *io, size_t offset, void *buffer,
+ size_t nbytes)
+{
+ const void *ptr;
+ int error;
+
+ /* Try to fetch a direct pointer for at least nbytes */
+ if ((error = bhnd_nvram_io_read_ptr(io, offset, &ptr, nbytes, NULL)))
+ return (error);
+
+ /* Copy out the requested data */
+ memcpy(buffer, ptr, nbytes);
+ return (0);
+}
+
+static int
+bhnd_nvram_ioptr_write(struct bhnd_nvram_io *io, size_t offset,
+ void *buffer, size_t nbytes)
+{
+ void *ptr;
+ int error;
+
+ /* Try to fetch a direct pointer for at least nbytes */
+ if ((error = bhnd_nvram_io_write_ptr(io, offset, &ptr, nbytes, NULL)))
+ return (error);
+
+ /* Copy in the provided data */
+ memcpy(ptr, buffer, nbytes);
+ return (0);
+}
diff --git a/sys/modules/bhnd/Makefile b/sys/modules/bhnd/Makefile
index dfc877841019..82f9ddbe98a4 100644
--- a/sys/modules/bhnd/Makefile
+++ b/sys/modules/bhnd/Makefile
@@ -35,6 +35,7 @@ SRCS+= bhnd_nvram_data.c \
bhnd_nvram_data_tlv.c \
bhnd_nvram_io.c \
bhnd_nvram_iobuf.c \
+ bhnd_nvram_ioptr.c \
bhnd_nvram_iores.c \
bhnd_nvram_plist.c \
bhnd_nvram_store.c \