Path: blob/main/sys/dev/bhnd/nvram/bhnd_nvram_ioptr.c
39536 views
/*-1* Copyright (c) 2016 Landon Fuller <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer,9* without modification.10* 2. Redistributions in binary form must reproduce at minimum a disclaimer11* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any12* redistribution must be conditioned upon including a substantially13* similar Disclaimer requirement for further binary redistribution.14*15* NO WARRANTY16* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS17* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT18* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY19* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL20* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,21* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF22* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS23* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER24* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)25* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF26* THE POSSIBILITY OF SUCH DAMAGES.27*/2829#include <sys/cdefs.h>30#ifdef _KERNEL31#include <sys/param.h>32#include <sys/malloc.h>33#include <sys/systm.h>34#else /* !_KERNEL */35#include <errno.h>36#include <stdint.h>37#include <stdlib.h>38#include <string.h>39#endif /* _KERNEL */4041#include "bhnd_nvram_private.h"4243#include "bhnd_nvram_io.h"44#include "bhnd_nvram_iovar.h"4546/**47* Memory-backed NVRAM I/O context.48*49* ioptr instances are gauranteed to provide persistent references to its50* backing contigious memory via bhnd_nvram_io_read_ptr() and51* bhnd_nvram_io_write_ptr().52*/53struct bhnd_nvram_ioptr {54struct bhnd_nvram_io io; /**< common I/O instance state */55void *ptr; /**< backing memory */56size_t size; /**< size at @p ptr */57size_t capacity; /**< capacity at @p ptr */58uint32_t flags; /**< flags (see BHND_NVRAM_IOPTR_*) */59};6061BHND_NVRAM_IOPS_DEFN(ioptr)6263/**64* Allocate and return a new I/O context, mapping @p size bytes at @p ptr.6566* The caller is responsible for deallocating the returned I/O context via67* bhnd_nvram_io_free().68*69* @param ptr The pointer to be mapped by the returned I/O70* context. Must remain valid for the lifetime of71* the returned I/O context.72* @param size The total number of bytes mapped at @p ptr.73* @param capacity The maximum number of bytes that may be mapped74* at @p ptr via bhnd_nvram_ioptr_setsize().75* @param flags Access flags (see BHND_NVRAM_IOPTR_*).76*77* @retval bhnd_nvram_io success.78* @retval NULL allocation failed.79* @retval NULL the requested @p capacity is less than @p size.80*/81struct bhnd_nvram_io *82bhnd_nvram_ioptr_new(const void *ptr, size_t size, size_t capacity,83uint32_t flags)84{85struct bhnd_nvram_ioptr *ioptr;8687/* Sanity check the capacity */88if (size > capacity)89return (NULL);9091/* Allocate I/O context */92ioptr = bhnd_nv_malloc(sizeof(*ioptr));93if (ioptr == NULL)94return (NULL);9596ioptr->io.iops = &bhnd_nvram_ioptr_ops;97ioptr->ptr = __DECONST(void *, ptr);98ioptr->size = size;99ioptr->capacity = capacity;100ioptr->flags = flags;101102return (&ioptr->io);103}104105static void106bhnd_nvram_ioptr_free(struct bhnd_nvram_io *io)107{108bhnd_nv_free(io);109}110111static size_t112bhnd_nvram_ioptr_getsize(struct bhnd_nvram_io *io)113{114struct bhnd_nvram_ioptr *ioptr = (struct bhnd_nvram_ioptr *)io;115return (ioptr->size);116}117118static int119bhnd_nvram_ioptr_setsize(struct bhnd_nvram_io *io, size_t size)120{121struct bhnd_nvram_ioptr *ioptr = (struct bhnd_nvram_ioptr *)io;122123/* Must be writable */124if (!(ioptr->flags & BHND_NVRAM_IOPTR_RDWR))125return (ENODEV);126127/* Can't exceed the actual capacity */128if (size > ioptr->capacity)129return (ENXIO);130131ioptr->size = size;132return (0);133}134135/* Common ioptr_(read|write)_ptr implementation */136static int137bhnd_nvram_ioptr_ptr(struct bhnd_nvram_ioptr *ioptr, size_t offset, void **ptr,138size_t nbytes, size_t *navail)139{140size_t avail;141142/* Verify offset+nbytes fall within the buffer range */143if (offset > ioptr->size)144return (ENXIO);145146avail = ioptr->size - offset;147if (avail < nbytes)148return (ENXIO);149150/* Valid I/O range, provide a pointer to the buffer and the151* total count of available bytes */152*ptr = ((uint8_t *)ioptr->ptr) + offset;153if (navail != NULL)154*navail = avail;155156return (0);157}158159static int160bhnd_nvram_ioptr_read_ptr(struct bhnd_nvram_io *io, size_t offset,161const void **ptr, size_t nbytes, size_t *navail)162{163struct bhnd_nvram_ioptr *ioptr;164void *writep;165int error;166167ioptr = (struct bhnd_nvram_ioptr *) io;168169/* Return a pointer into our backing buffer */170error = bhnd_nvram_ioptr_ptr(ioptr, offset, &writep, nbytes, navail);171if (error)172return (error);173174*ptr = writep;175176return (0);177}178179static int180bhnd_nvram_ioptr_write_ptr(struct bhnd_nvram_io *io, size_t offset,181void **ptr, size_t nbytes, size_t *navail)182{183struct bhnd_nvram_ioptr *ioptr;184185ioptr = (struct bhnd_nvram_ioptr *) io;186187/* Must be writable */188if (!(ioptr->flags & BHND_NVRAM_IOPTR_RDWR))189return (ENODEV);190191/* Return a pointer into our backing buffer */192return (bhnd_nvram_ioptr_ptr(ioptr, offset, ptr, nbytes, navail));193}194195static int196bhnd_nvram_ioptr_read(struct bhnd_nvram_io *io, size_t offset, void *buffer,197size_t nbytes)198{199const void *ptr;200int error;201202/* Try to fetch a direct pointer for at least nbytes */203if ((error = bhnd_nvram_io_read_ptr(io, offset, &ptr, nbytes, NULL)))204return (error);205206/* Copy out the requested data */207memcpy(buffer, ptr, nbytes);208return (0);209}210211static int212bhnd_nvram_ioptr_write(struct bhnd_nvram_io *io, size_t offset,213void *buffer, size_t nbytes)214{215void *ptr;216int error;217218/* Try to fetch a direct pointer for at least nbytes */219if ((error = bhnd_nvram_io_write_ptr(io, offset, &ptr, nbytes, NULL)))220return (error);221222/* Copy in the provided data */223memcpy(ptr, buffer, nbytes);224return (0);225}226227228