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