The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/bhnd/nvram/bhnd_nvram_iobuf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer,
   10  *    without modification.
   11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
   13  *    redistribution must be conditioned upon including a substantially
   14  *    similar Disclaimer requirement for further binary redistribution.
   15  *
   16  * NO WARRANTY
   17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
   20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
   21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
   22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   27  * THE POSSIBILITY OF SUCH DAMAGES.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #ifdef _KERNEL
   34 #include <sys/param.h>
   35 #include <sys/malloc.h>
   36 #include <sys/systm.h>
   37 #else /* !_KERNEL */
   38 #include <errno.h>
   39 #include <stdint.h>
   40 #include <stdlib.h>
   41 #include <string.h>
   42 #endif /* _KERNEL */
   43 
   44 #include "bhnd_nvram_private.h"
   45 
   46 #include "bhnd_nvram_io.h"
   47 #include "bhnd_nvram_iovar.h"
   48 
   49 /**
   50  * Buffer-backed NVRAM I/O context.
   51  * 
   52  * iobuf instances are gauranteed to provide persistent references to its
   53  * backing contigious buffer via bhnd_nvram_io_read_ptr() and
   54  * bhnd_nvram_io_write_ptr().
   55  */
   56 struct bhnd_nvram_iobuf {
   57         struct bhnd_nvram_io     io;            /**< common I/O instance state */
   58         void                    *buf;           /**< backing buffer. if inline-allocated, will
   59                                                      be a reference to data[]. */
   60         size_t                   size;          /**< size of @p buf */
   61         size_t                   capacity;      /**< capacity of @p buf */
   62         uint8_t                  data[];        /**< inline buffer allocation */
   63 };
   64 
   65 BHND_NVRAM_IOPS_DEFN(iobuf)
   66 
   67 /**
   68  * Allocate and return a new I/O context with an uninitialized
   69  * buffer of @p size and @p capacity.
   70  *
   71  * The caller is responsible for deallocating the returned I/O context via
   72  * bhnd_nvram_io_free().
   73  *
   74  * If @p capacity is less than @p size, a capacity of @p size will be used.
   75  * 
   76  * @param       size            The initial size of the I/O context.
   77  * @param       capacity        The total capacity of the I/O context buffer;
   78  *                              the returned I/O context may be resized up to
   79  *                              @p capacity via bhnd_nvram_io_setsize().
   80  *
   81  * @retval      bhnd_nvram_iobuf        success.
   82  * @retval      NULL                    allocation failed.
   83  * @retval      NULL                    the requested @p capacity is less than
   84  *                                      @p size.
   85  */
   86 struct bhnd_nvram_io *
   87 bhnd_nvram_iobuf_empty(size_t size, size_t capacity)
   88 {
   89         struct bhnd_nvram_iobuf *iobuf;
   90         size_t                   iosz;
   91         bool                     inline_alloc;
   92 
   93         /* Sanity check the capacity */
   94         if (size > capacity)
   95                 return (NULL);
   96 
   97         /* Would sizeof(iobuf)+capacity overflow? */
   98         if (SIZE_MAX - sizeof(*iobuf) < capacity) {
   99                 inline_alloc = false;
  100                 iosz = sizeof(*iobuf);
  101         } else {
  102                 inline_alloc = true;
  103                 iosz = sizeof(*iobuf) + capacity;
  104         }
  105 
  106         /* Allocate I/O context */
  107         iobuf = bhnd_nv_malloc(iosz);
  108         if (iobuf == NULL)
  109                 return (NULL);
  110 
  111         iobuf->io.iops = &bhnd_nvram_iobuf_ops;
  112         iobuf->buf = NULL;
  113         iobuf->size = size;
  114         iobuf->capacity = capacity;
  115 
  116         /* Either allocate our backing buffer, or initialize the
  117          * backing buffer with a reference to our inline allocation. */
  118         if (inline_alloc)
  119                 iobuf->buf = &iobuf->data;
  120         else
  121                 iobuf->buf = bhnd_nv_malloc(iobuf->capacity);
  122 
  123         if (iobuf->buf == NULL) {
  124                 bhnd_nv_free(iobuf);
  125                 return (NULL);
  126         }
  127 
  128         return (&iobuf->io);
  129 }
  130 
  131 /**
  132  * Allocate and return a new I/O context, copying @p size from @p buffer.
  133  *
  134  * The caller is responsible for deallocating the returned I/O context via
  135  * bhnd_nvram_io_free().
  136  * 
  137  * @param       buffer  The buffer data be copied by the returned I/O context.
  138  * @param       size    The size of @p buffer, in bytes.
  139  * 
  140  * @retval      bhnd_nvram_io   success.
  141  * @retval      NULL            allocation failed.
  142  */
  143 struct bhnd_nvram_io *
  144 bhnd_nvram_iobuf_new(const void *buffer, size_t size)
  145 {
  146         struct bhnd_nvram_io    *io;
  147         struct bhnd_nvram_iobuf *iobuf;
  148 
  149         /* Allocate the iobuf */
  150         if ((io = bhnd_nvram_iobuf_empty(size, size)) == NULL)
  151                 return (NULL);
  152 
  153         /* Copy the input to our new iobuf instance */
  154         iobuf = (struct bhnd_nvram_iobuf *)io;
  155         memcpy(iobuf->buf, buffer, iobuf->size);
  156 
  157         return (io);
  158 }
  159 
  160 /**
  161  * Allocate and return a new I/O context providing an in-memory copy
  162  * of the data mapped by @p src.
  163  *
  164  * The caller is responsible for deallocating the returned I/O context via
  165  * bhnd_nvram_io_free().
  166  * 
  167  * @param       src     The I/O context to be copied.
  168  * 
  169  * @retval      bhnd_nvram_io   success.
  170  * @retval      NULL            allocation failed.
  171  * @retval      NULL            copying @p src failed.
  172  */
  173 struct bhnd_nvram_io *
  174 bhnd_nvram_iobuf_copy(struct bhnd_nvram_io *src)
  175 {
  176         return (bhnd_nvram_iobuf_copy_range(src, 0x0,
  177             bhnd_nvram_io_getsize(src)));
  178 }
  179 
  180 /**
  181  * Allocate and return a new I/O context providing an in-memory copy
  182  * of @p size bytes mapped at @p offset by @p src.
  183  *
  184  * The caller is responsible for deallocating the returned I/O context via
  185  * bhnd_nvram_io_free().
  186  * 
  187  * @param       src     The I/O context to be copied.
  188  * @param       offset  The offset of the bytes to be copied from @p src.
  189  * @param       size    The number of bytes to copy at @p offset from @p src.
  190  * 
  191  * @retval      bhnd_nvram_io   success.
  192  * @retval      NULL            allocation failed.
  193  * @retval      NULL            copying @p src failed.
  194  */
  195 struct bhnd_nvram_io *
  196 bhnd_nvram_iobuf_copy_range(struct bhnd_nvram_io *src, size_t offset,
  197     size_t size)
  198 {
  199         struct bhnd_nvram_io    *io;
  200         struct bhnd_nvram_iobuf *iobuf;
  201         int                      error;
  202 
  203         /* Check if offset+size would overflow */
  204         if (SIZE_MAX - size < offset)
  205                 return (NULL);
  206 
  207         /* Allocate the iobuf instance */
  208         if ((io = bhnd_nvram_iobuf_empty(size, size)) == NULL)
  209                 return (NULL);
  210 
  211         /* Copy the input I/O context */
  212         iobuf = (struct bhnd_nvram_iobuf *)io;
  213         if ((error = bhnd_nvram_io_read(src, offset, iobuf->buf, size))) {
  214                 bhnd_nvram_io_free(&iobuf->io);
  215                 return (NULL);
  216         }
  217 
  218         return (io);
  219 }
  220 
  221 static void
  222 bhnd_nvram_iobuf_free(struct bhnd_nvram_io *io)
  223 {
  224         struct bhnd_nvram_iobuf *iobuf = (struct bhnd_nvram_iobuf *)io;
  225 
  226         /* Free the backing buffer if it wasn't allocated inline */
  227         if (iobuf->buf != &iobuf->data)
  228                 bhnd_nv_free(iobuf->buf);
  229 
  230         bhnd_nv_free(iobuf);
  231 }
  232 
  233 static size_t
  234 bhnd_nvram_iobuf_getsize(struct bhnd_nvram_io *io)
  235 {
  236         struct bhnd_nvram_iobuf *iobuf = (struct bhnd_nvram_iobuf *)io;
  237         return (iobuf->size);
  238 }
  239 
  240 static int
  241 bhnd_nvram_iobuf_setsize(struct bhnd_nvram_io *io, size_t size)
  242 {
  243         struct bhnd_nvram_iobuf *iobuf = (struct bhnd_nvram_iobuf *)io;
  244 
  245         /* Can't exceed the actual capacity */
  246         if (size > iobuf->capacity)
  247                 return (ENXIO);
  248 
  249         iobuf->size = size;
  250         return (0);
  251 }
  252 
  253 /* Common iobuf_(read|write)_ptr implementation */
  254 static int
  255 bhnd_nvram_iobuf_ptr(struct bhnd_nvram_iobuf *iobuf, size_t offset, void **ptr,
  256     size_t nbytes, size_t *navail)
  257 {
  258         size_t avail;
  259 
  260         /* Verify offset+nbytes fall within the buffer range */
  261         if (offset > iobuf->size)
  262                 return (ENXIO);
  263 
  264         avail = iobuf->size - offset;
  265         if (avail < nbytes)
  266                 return (ENXIO);
  267 
  268         /* Valid I/O range, provide a pointer to the buffer and the
  269          * total count of available bytes */
  270         *ptr = ((uint8_t *)iobuf->buf) + offset;
  271         if (navail != NULL)
  272                 *navail = avail;
  273 
  274         return (0);
  275 }
  276 
  277 static int
  278 bhnd_nvram_iobuf_read_ptr(struct bhnd_nvram_io *io, size_t offset,
  279     const void **ptr, size_t nbytes, size_t *navail)
  280 {
  281         struct bhnd_nvram_iobuf *iobuf;
  282         void                    *ioptr;
  283         int                      error;
  284 
  285         iobuf = (struct bhnd_nvram_iobuf *) io;
  286 
  287         /* Return a pointer into our backing buffer */
  288         error = bhnd_nvram_iobuf_ptr(iobuf, offset, &ioptr, nbytes, navail);
  289         if (error)
  290                 return (error);
  291 
  292         *ptr = ioptr;
  293 
  294         return (0);
  295 }
  296 
  297 static int
  298 bhnd_nvram_iobuf_write_ptr(struct bhnd_nvram_io *io, size_t offset,
  299     void **ptr, size_t nbytes, size_t *navail)
  300 {
  301         struct bhnd_nvram_iobuf *iobuf;
  302 
  303         iobuf = (struct bhnd_nvram_iobuf *) io;
  304 
  305         /* Return a pointer into our backing buffer */
  306         return (bhnd_nvram_iobuf_ptr(iobuf, offset, ptr, nbytes, navail));
  307 }
  308 
  309 static int
  310 bhnd_nvram_iobuf_read(struct bhnd_nvram_io *io, size_t offset, void *buffer,
  311     size_t nbytes)
  312 {
  313         const void      *ptr;
  314         int              error;
  315 
  316         /* Try to fetch a direct pointer for at least nbytes */
  317         if ((error = bhnd_nvram_io_read_ptr(io, offset, &ptr, nbytes, NULL)))
  318                 return (error);
  319 
  320         /* Copy out the requested data */
  321         memcpy(buffer, ptr, nbytes);
  322         return (0);
  323 }
  324 
  325 static int
  326 bhnd_nvram_iobuf_write(struct bhnd_nvram_io *io, size_t offset,
  327     void *buffer, size_t nbytes)
  328 {
  329         void    *ptr;
  330         int      error;
  331 
  332         /* Try to fetch a direct pointer for at least nbytes */
  333         if ((error = bhnd_nvram_io_write_ptr(io, offset, &ptr, nbytes, NULL)))
  334                 return (error);
  335 
  336         /* Copy in the provided data */
  337         memcpy(ptr, buffer, nbytes);
  338         return (0);
  339 }

Cache object: f93f115ce8f8790ccf974c9556c07f03


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.