Author: landonf Date: Mon Dec 19 20:11:48 2016 New Revision: 310291 URL: https://svnweb.freebsd.org/changeset/base/310291
Log: bhnd(4): Implement a new bhnd_nvram_plist and bhnd_nvram_prop API for representing arbitrary Broadcom NVRAM key/value pairs. This will be used to track pending changes in bhnd_nvram_store, and provide support for exporting all or a device subpath for NVRAM (as required by some fullmac wifi chipsets). Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8756 Added: head/sys/dev/bhnd/nvram/bhnd_nvram_plist.c (contents, props changed) head/sys/dev/bhnd/nvram/bhnd_nvram_plist.h (contents, props changed) head/sys/dev/bhnd/nvram/bhnd_nvram_plistvar.h (contents, props changed) Modified: head/sys/conf/files head/sys/dev/bhnd/nvram/bhnd_nvram_private.h head/sys/dev/bhnd/nvram/bhnd_nvram_value.c head/sys/dev/bhnd/nvram/bhnd_nvram_value.h head/sys/modules/bhnd/Makefile Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Mon Dec 19 20:07:58 2016 (r310290) +++ head/sys/conf/files Mon Dec 19 20:11:48 2016 (r310291) @@ -1241,6 +1241,7 @@ dev/bhnd/nvram/bhnd_nvram_if.m optional dev/bhnd/nvram/bhnd_nvram_io.c optional bhnd dev/bhnd/nvram/bhnd_nvram_iobuf.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 dev/bhnd/nvram/bhnd_nvram_subr.c optional bhnd dev/bhnd/nvram/bhnd_nvram_value.c optional bhnd Added: head/sys/dev/bhnd/nvram/bhnd_nvram_plist.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/bhnd/nvram/bhnd_nvram_plist.c Mon Dec 19 20:11:48 2016 (r310291) @@ -0,0 +1,947 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller <land...@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$"); + +#include <sys/param.h> +#include <sys/hash.h> + +#ifdef _KERNEL + +#include <sys/systm.h> + +#else /* !_KERNEL */ + +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#endif /* _KERNEL */ + +#include "bhnd_nvram_plistvar.h" +#include "bhnd_nvram_private.h" + +static bhnd_nvram_plist_entry *bhnd_nvram_plist_get_entry( + bhnd_nvram_plist *plist, const char *name); + +/** + * Allocate and initialize a new, empty property list. + * + * The caller is responsible for releasing the returned property value + * via bhnd_nvram_plist_release(). + * + * @retval non-NULL success + * @retval NULL if allocation fails. + */ +bhnd_nvram_plist * +bhnd_nvram_plist_new(void) +{ + bhnd_nvram_plist *plist; + + plist = bhnd_nv_calloc(1, sizeof(*plist)); + if (plist == NULL) + return NULL; + + /* Implicit caller-owned reference */ + plist->refs = 1; + + /* Initialize entry list */ + plist->num_entries = 0; + TAILQ_INIT(&plist->entries); + + /* Initialize entry hash table */ + for (size_t i = 0; i < nitems(plist->names); i++) + LIST_INIT(&plist->names[i]); + + return (plist); +} + +/** + * Retain a reference and return @p plist to the caller. + * + * The caller is responsible for releasing their reference ownership via + * bhnd_nvram_plist_release(). + * + * @param plist The property list to be retained. + */ +bhnd_nvram_plist * +bhnd_nvram_plist_retain(bhnd_nvram_plist *plist) +{ + BHND_NV_ASSERT(plist->refs >= 1, ("plist over-released")); + + refcount_acquire(&plist->refs); + return (plist); +} + +/** + * Release a reference to @p plist. + * + * If this is the last reference, all associated resources will be freed. + * + * @param plist The property list to be released. + */ +void +bhnd_nvram_plist_release(bhnd_nvram_plist *plist) +{ + bhnd_nvram_plist_entry *ple, *ple_next; + + BHND_NV_ASSERT(plist->refs >= 1, ("plist over-released")); + + /* Drop reference */ + if (!refcount_release(&plist->refs)) + return; + + /* Free all property entries */ + TAILQ_FOREACH_SAFE(ple, &plist->entries, pl_link, ple_next) { + bhnd_nvram_prop_release(ple->prop); + bhnd_nv_free(ple); + } + + /* Free plist instance */ + bhnd_nv_free(plist); +} + +/** + * Return a shallow copy of @p plist. + * + * The caller is responsible for releasing the returned property value + * via bhnd_nvram_plist_release(). + * + * @retval non-NULL success + * @retval NULL if allocation fails. + */ +bhnd_nvram_plist * +bhnd_nvram_plist_copy(bhnd_nvram_plist *plist) +{ + bhnd_nvram_plist *copy; + bhnd_nvram_prop *prop; + int error; + + /* Allocate new, empty plist */ + if ((copy = bhnd_nvram_plist_new()) == NULL) + return (NULL); + + /* Append all properties */ + prop = NULL; + while ((prop = bhnd_nvram_plist_next(plist, prop)) != NULL) { + error = bhnd_nvram_plist_append(copy, prop); + if (error) { + if (error != ENOMEM) { + BHND_NV_LOG("error copying property: %d\n", + error); + } + + bhnd_nvram_plist_release(copy); + return (NULL); + } + } + + /* Return ownership of the copy to our caller */ + return (copy); +} + +/** + * Return the number of properties in @p plist. + */ +size_t +bhnd_nvram_plist_count(bhnd_nvram_plist *plist) +{ + return (plist->num_entries); +} + +/** + * Return true if @p plist contains a property name @p name, false otherwise. + * + * @param plist The property list to be queried. + * @param name The property name to be queried. + */ +bool +bhnd_nvram_plist_contains(bhnd_nvram_plist *plist, const char *name) +{ + if (bhnd_nvram_plist_get_entry(plist, name) != NULL) + return (true); + + return (false); +} + +/** + * Replace the current property value for a property matching the name + * of @p prop, maintaining the property's current order in @p plist. + * + * If a matching property is not found in @p plist, @p prop will instead be + * appended. + * + * @param plist The property list to be modified. + * @param prop The replacement property. + * + * @retval 0 success + * @retval ENOMEM if allocation fails. + * @retval non-zero if modifying @p plist otherwise fails, a regular unix + * error code will be returned. + */ +int +bhnd_nvram_plist_replace(bhnd_nvram_plist *plist, bhnd_nvram_prop *prop) +{ + bhnd_nvram_plist_entry *entry; + + /* Fetch current entry */ + entry = bhnd_nvram_plist_get_entry(plist, prop->name); + if (entry == NULL) { + /* Not found -- append property instead */ + return (bhnd_nvram_plist_append(plist, prop)); + } + + /* Replace the current entry's property reference */ + bhnd_nvram_prop_release(entry->prop); + entry->prop = bhnd_nvram_prop_retain(prop); + + return (0); +} + +/** + * Replace the current property value for a property matching @p name, + * maintaining the property's order in @p plist. + * + * If @p name is not found in @p plist, a new property will be appended. + * + * @param plist The property list to be modified. + * @param name The name of the property to be replaced. + * @param val The replacement value for @p name. + * + * @retval 0 success + * @retval ENOMEM if allocation fails. + * @retval non-zero if modifying @p plist otherwise fails, a regular unix + * error code will be returned. + */ +int +bhnd_nvram_plist_replace_val(bhnd_nvram_plist *plist, const char *name, + bhnd_nvram_val *val) +{ + bhnd_nvram_prop *prop; + int error; + + /* Construct a new property instance for the name and value */ + if ((prop = bhnd_nvram_prop_new(name, val)) == NULL) + return (ENOMEM); + + /* Attempt replace */ + error = bhnd_nvram_plist_replace(plist, prop); + bhnd_nvram_prop_release(prop); + + return (error); +} + +/** + * Replace the current property value for a property matching @p name, copying + * the new property value from the given @p inp buffer of @p itype and @p ilen. + * + * The current property order of @p name in @p plist will be maintained. + * + * If @p name is not found in @p plist, a new property will be appended. + * + * @param plist The property list to be modified. + * @param name The name of the property to be replaced. + * @param inp Input buffer. + * @param ilen Input buffer length. + * @param itype Input buffer type. + * + * @retval 0 success + * @retval ENOMEM if allocation fails. + * @retval non-zero if modifying @p plist otherwise fails, a regular unix + * error code will be returned. + */ +int +bhnd_nvram_plist_replace_bytes(bhnd_nvram_plist *plist, const char *name, + const void *inp, size_t ilen, bhnd_nvram_type itype) +{ + bhnd_nvram_prop *prop; + int error; + + if ((prop = bhnd_nvram_prop_bytes_new(name, inp, ilen, itype)) == NULL) + return (ENOMEM); + + error = bhnd_nvram_plist_replace(plist, prop); + bhnd_nvram_prop_release(prop); + + return (error); +} + +/** + * Replace the current property value for a property matching @p name, copying + * the new property value from @p val. + * + * The current property order of @p name in @p plist will be maintained. + * + * If @p name is not found in @p plist, a new property will be appended. + * + * @param plist The property list to be modified. + * @param name The name of the property to be replaced. + * @param val The property's replacement string value. + * + * @retval 0 success + * @retval ENOMEM if allocation fails. + * @retval non-zero if modifying @p plist otherwise fails, a regular unix + * error code will be returned. + */ +int +bhnd_nvram_plist_replace_string(bhnd_nvram_plist *plist, const char *name, + const char *val) +{ + return (bhnd_nvram_plist_replace_bytes(plist, name, val, strlen(val)+1, + BHND_NVRAM_TYPE_STRING)); +} + +/** + * Remove the property entry for the property @p name, if any. + * + * @param plist The property list to be modified. + * @param name The name of the property to be removed. + */ +void +bhnd_nvram_plist_remove(bhnd_nvram_plist *plist, const char *name) +{ + bhnd_nvram_plist_entry *entry; + + /* Fetch entry */ + entry = bhnd_nvram_plist_get_entry(plist, name); + if (entry == NULL) + return; + + /* Remove from entry list and hash table */ + TAILQ_REMOVE(&plist->entries, entry, pl_link); + LIST_REMOVE(entry, pl_hash_link); + + /* Free plist entry */ + bhnd_nvram_prop_release(entry->prop); + bhnd_nv_free(entry); + + /* Decrement entry count */ + BHND_NV_ASSERT(plist->num_entries > 0, ("entry count over-release")); + plist->num_entries--; +} + +/** + * Fetch the property list entry for @p name, if any. + * + * @param plist The property list to be queried. + * @param name The property name to be queried. + * + * @retval non-NULL if @p name is found. + * @retval NULL if @p name is not found. + */ +static bhnd_nvram_plist_entry * +bhnd_nvram_plist_get_entry(bhnd_nvram_plist *plist, const char *name) +{ + bhnd_nvram_plist_entry_list *hash_list; + bhnd_nvram_plist_entry *entry; + uint32_t h; + + h = hash32_str(name, HASHINIT); + hash_list = &plist->names[h % nitems(plist->names)]; + + LIST_FOREACH(entry, hash_list, pl_hash_link) { + if (strcmp(entry->prop->name, name) == 0) + return (entry); + }; + + /* Not found */ + return (NULL); +} + +/** + * Append all properties from @p tail to @p plist. + * + * @param plist The property list to be modified. + * @param tail The property list to append. + * + * @retval 0 success + * @retval ENOMEM if allocation fails. + * @retval EEXIST an existing property from @p tail was found in @p plist. + */ +int +bhnd_nvram_plist_append_list(bhnd_nvram_plist *plist, bhnd_nvram_plist *tail) +{ + bhnd_nvram_prop *p; + int error; + + p = NULL; + while ((p = bhnd_nvram_plist_next(tail, p)) != NULL) { + if ((error = bhnd_nvram_plist_append(plist, p))) + return (error); + } + + return (0); +} + +/** + * Append @p prop to @p plist. + * + * @param plist The property list to be modified. + * @param prop The property to append. + * + * @retval 0 success + * @retval ENOMEM if allocation fails. + * @retval EEXIST an existing property with @p name was found in @p plist. + */ +int +bhnd_nvram_plist_append(bhnd_nvram_plist *plist, bhnd_nvram_prop *prop) +{ + bhnd_nvram_plist_entry_list *hash_list; + bhnd_nvram_plist_entry *entry; + uint32_t h; + + if (bhnd_nvram_plist_contains(plist, prop->name)) + return (EEXIST); + + /* Have we hit the maximum representable entry count? */ + if (plist->num_entries == SIZE_MAX) + return (ENOMEM); + + /* Allocate new entry */ + entry = bhnd_nv_malloc(sizeof(*entry)); + if (entry == NULL) + return (ENOMEM); + + entry->prop = bhnd_nvram_prop_retain(prop); + + /* Append to entry list */ + TAILQ_INSERT_TAIL(&plist->entries, entry, pl_link); + + /* Add to name-based hash table */ + h = hash32_str(prop->name, HASHINIT); + hash_list = &plist->names[h % nitems(plist->names)]; + LIST_INSERT_HEAD(hash_list, entry, pl_hash_link); + + /* Increment entry count */ + plist->num_entries++; + + return (0); +} + +/** + * Append a new property to @p plist with @p name and @p val. + * + * @param plist The property list to be modified. + * @param name The name of the property to be appended. + * @param val The value of the property to be appended. + * + * @retval 0 success + * @retval ENOMEM if allocation fails. + * @retval EEXIST an existing property with @p name was found in @p plist. + */ +int +bhnd_nvram_plist_append_val(bhnd_nvram_plist *plist, const char *name, + bhnd_nvram_val *val) +{ + bhnd_nvram_prop *prop; + int error; + + if ((prop = bhnd_nvram_prop_new(name, val)) == NULL) + return (ENOMEM); + + error = bhnd_nvram_plist_append(plist, prop); + bhnd_nvram_prop_release(prop); + + return (error); +} + +/** + * Append a new property to @p plist, copying the property value from the + * given @p inp buffer of @p itype and @p ilen. + * + * @param plist The property list to be modified. + * @param name The name of the property to be appended. + * @param inp Input buffer. + * @param ilen Input buffer length. + * @param itype Input buffer type. + * + * @retval 0 success + * @retval ENOMEM if allocation fails. + * @retval EEXIST an existing property with @p name was found in @p plist. + */ +int +bhnd_nvram_plist_append_bytes(bhnd_nvram_plist *plist, const char *name, + const void *inp, size_t ilen, bhnd_nvram_type itype) +{ + bhnd_nvram_prop *prop; + int error; + + if ((prop = bhnd_nvram_prop_bytes_new(name, inp, ilen, itype)) == NULL) + return (ENOMEM); + + error = bhnd_nvram_plist_append(plist, prop); + bhnd_nvram_prop_release(prop); + + return (error); +} + +/** + * Append a new string property to @p plist, copying the property value from + * @p val. + * + * @param plist The property list to be modified. + * @param name The name of the property to be appended. + * @param val The new property's string value. + * + * @retval 0 success + * @retval ENOMEM if allocation fails. + * @retval EEXIST an existing property with @p name was found in @p plist. + */ +int +bhnd_nvram_plist_append_string(bhnd_nvram_plist *plist, const char *name, + const char *val) +{ + return (bhnd_nvram_plist_append_bytes(plist, name, val, strlen(val)+1, + BHND_NVRAM_TYPE_STRING)); +} + +/** + * Iterate over all properties in @p plist. + * + * @param plist The property list to be iterated. + * @param prop A property in @p plist, or NULL to return the first + * property in @p plist. + * + * @retval non-NULL A borrowed reference to the next property in @p plist. + * @retval NULL If the end of the property list is reached or @p prop + * is not found in @p plist. + */ +bhnd_nvram_prop * +bhnd_nvram_plist_next(bhnd_nvram_plist *plist, bhnd_nvram_prop *prop) +{ + bhnd_nvram_plist_entry *entry; + + if (prop == NULL) { + if ((entry = TAILQ_FIRST(&plist->entries)) == NULL) + return (NULL); + + return (entry->prop); + } + + /* Look up previous property entry by name */ + if ((entry = bhnd_nvram_plist_get_entry(plist, prop->name)) == NULL) + return (NULL); + + /* The property instance must be identical */ + if (entry->prop != prop) + return (NULL); + + /* Fetch next entry */ + if ((entry = TAILQ_NEXT(entry, pl_link)) == NULL) + return (NULL); + + return (entry->prop); +} + +/** + * Return a borrowed reference to a named property, or NULL if @p name is + * not found in @p plist. + * + * @param plist The property list to be queried. + * @param name The name of the property to be returned. + * + * @retval non-NULL if @p name is found. + * @retval NULL if @p name is not found. + */ +bhnd_nvram_prop * +bhnd_nvram_plist_get_prop(bhnd_nvram_plist *plist, const char *name) +{ + bhnd_nvram_plist_entry *entry; + + if ((entry = bhnd_nvram_plist_get_entry(plist, name)) == NULL) + return (NULL); + + return (entry->prop); +} + +/** + * Return a borrowed reference to the named property's value, or NULL if + * @p name is not found in @p plist. + * + * @param plist The property list to be queried. + * @param name The name of the property to be returned. + * + * @retval non-NULL if @p name is found. + * @retval NULL if @p name is not found. + */ +bhnd_nvram_val * +bhnd_nvram_plist_get_val(bhnd_nvram_plist *plist, const char *name) +{ + bhnd_nvram_prop *prop; + + if ((prop = bhnd_nvram_plist_get_prop(plist, name)) == NULL) + return (NULL); + + return (bhnd_nvram_prop_val(prop)); +} + +/** + * Attempt to encode a named property's value as @p otype, writing the result + * to @p outp. + * + * @param plist The property list to be queried. + * @param name The name of the property value to be returned. + * @param[out] outp On success, the value will be written to this + * buffer. This argment may be NULL if the value is + * not desired. + * @param[in,out] olen The capacity of @p outp. On success, will be set + * to the actual size of the requested value. + * @param otype The data type to be written to @p outp. + * + * @retval 0 success + * @retval ENOENT If @p name is not found in @p plist. + * @retval ENOMEM If the @p outp is non-NULL, and the provided @p olen + * is too small to hold the encoded value. + * @retval EFTYPE If value coercion from @p prop to @p otype is + * impossible. + * @retval ERANGE If value coercion would overflow (or underflow) the + * a @p otype representation. + */ +int +bhnd_nvram_plist_get_encoded(bhnd_nvram_plist *plist, const char *name, + void *outp, size_t olen, bhnd_nvram_type otype) +{ + bhnd_nvram_prop *prop; + + if ((prop = bhnd_nvram_plist_get_prop(plist, name)) == NULL) + return (ENOENT); + + return (bhnd_nvram_prop_encode(prop, outp, &olen, otype)); +} + +/** + * Return the character representation of a named property's value. + * + * @param plist The property list to be queried. + * @param name The name of the property value to be returned. + * @param[out] val On success, the character value of @p name. + * + * @retval 0 success + * @retval ENOENT If @p name is not found in @p plist. + * @retval EFTYPE If coercion of the property's value to @p val. + * @retval ERANGE If coercion of the property's value would overflow + * (or underflow) @p val. + */ +int +bhnd_nvram_plist_get_char(bhnd_nvram_plist *plist, const char *name, + u_char *val) +{ + return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val), + BHND_NVRAM_TYPE_CHAR)); +} + +/** + * Return the uint8 representation of a named property's value. + * + * @param plist The property list to be queried. + * @param name The name of the property value to be returned. + * @param[out] val On success, the uint8 value of @p name. + * + * @retval 0 success + * @retval ENOENT If @p name is not found in @p plist. + * @retval EFTYPE If coercion of the property's value to @p val. + * @retval ERANGE If coercion of the property's value would overflow + * (or underflow) @p val. + */ +int +bhnd_nvram_plist_get_uint8(bhnd_nvram_plist *plist, const char *name, + uint8_t *val) +{ + return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val), + BHND_NVRAM_TYPE_UINT8)); +} + +/** + * Return the uint16 representation of a named property's value. + * + * @param plist The property list to be queried. + * @param name The name of the property value to be returned. + * @param[out] val On success, the uint16 value of @p name. + * + * @retval 0 success + * @retval ENOENT If @p name is not found in @p plist. + * @retval EFTYPE If coercion of the property's value to @p val. + * @retval ERANGE If coercion of the property's value would overflow + * (or underflow) @p val. + */ +int +bhnd_nvram_plist_get_uint16(bhnd_nvram_plist *plist, const char *name, + uint16_t *val) +{ + return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val), + BHND_NVRAM_TYPE_UINT16)); +} + +/** + * Return the uint32 representation of a named property's value. + * + * @param plist The property list to be queried. + * @param name The name of the property value to be returned. + * @param[out] val On success, the uint32 value of @p name. + * + * @retval 0 success + * @retval ENOENT If @p name is not found in @p plist. + * @retval EFTYPE If coercion of the property's value to @p val. + * @retval ERANGE If coercion of the property's value would overflow + * (or underflow) @p val. + */ +int +bhnd_nvram_plist_get_uint32(bhnd_nvram_plist *plist, const char *name, + uint32_t *val) +{ + return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val), + BHND_NVRAM_TYPE_UINT32)); +} + +/** + * Return the uint64 representation of a named property's value. + * + * @param plist The property list to be queried. + * @param name The name of the property value to be returned. + * @param[out] val On success, the uint64 value of @p name. + * + * @retval 0 success + * @retval ENOENT If @p name is not found in @p plist. + * @retval EFTYPE If coercion of the property's value to @p val. + * @retval ERANGE If coercion of the property's value would overflow + * (or underflow) @p val. + */ +int +bhnd_nvram_plist_get_uint64(bhnd_nvram_plist *plist, const char *name, + uint64_t *val) +{ + return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val), + BHND_NVRAM_TYPE_UINT64)); +} + +/** + * Allocate and initialize a new property value. + * + * The caller is responsible for releasing the returned property value + * via bhnd_nvram_prop_release(). + * + * @param name Property name. + * @param val Property value. + * + * @retval non-NULL success + * @retval NULL if allocation fails. + */ +struct bhnd_nvram_prop * +bhnd_nvram_prop_new(const char *name, bhnd_nvram_val *val) +{ + struct bhnd_nvram_prop *prop; + + prop = bhnd_nv_calloc(1, sizeof(*prop)); + if (prop == NULL) + return NULL; + + /* Implicit caller-owned reference */ + prop->refs = 1; + + if ((prop->name = bhnd_nv_strdup(name)) == NULL) + goto failed; + + if ((prop->val = bhnd_nvram_val_copy(val)) == NULL) + goto failed; + + return (prop); + +failed: + if (prop->name != NULL) + bhnd_nv_free(prop->name); + + if (prop->val != NULL) + bhnd_nvram_val_release(prop->val); + + bhnd_nv_free(prop); + return (NULL); +} + +/** + * Allocate a new property value and attempt to initialize its value from + * the given @p inp buffer of @p itype and @p ilen. + * + * The caller is responsible for releasing the returned property value + * via bhnd_nvram_prop_release(). + * + * @param name Property name. + * @param inp Input buffer. + * @param ilen Input buffer length. + * @param itype Input buffer type. + * + * @retval non-NULL success + * @retval NULL if allocation or initialization fails. + */ +bhnd_nvram_prop * +bhnd_nvram_prop_bytes_new(const char *name, const void *inp, size_t ilen, + bhnd_nvram_type itype) +{ + bhnd_nvram_prop *prop; + bhnd_nvram_val *val; + int error; + + /* Construct new value instance */ + error = bhnd_nvram_val_new(&val, NULL, inp, ilen, itype, + BHND_NVRAM_VAL_DYNAMIC); + if (error) { + if (error != ENOMEM) { + BHND_NV_LOG("invalid input data; initialization " + "failed: %d\n", error); + } + + return (NULL); + } + + /* Delegate to default implementation */ + prop = bhnd_nvram_prop_new(name, val); + + /* Clean up */ + bhnd_nvram_val_release(val); + return (prop); +} + +/** + * Retain a reference and return @p prop to the caller. + * + * The caller is responsible for releasing their reference ownership via + * bhnd_nvram_prop_release(). + * + * @param prop The property to be retained. + */ +bhnd_nvram_prop * +bhnd_nvram_prop_retain(bhnd_nvram_prop *prop) +{ + BHND_NV_ASSERT(prop->refs >= 1, ("prop over-released")); + + refcount_acquire(&prop->refs); + return (prop); +} + +/** + * Release a reference to @p prop. + * + * If this is the last reference, all associated resources will be freed. + * + * @param prop The property to be released. + */ +void +bhnd_nvram_prop_release(bhnd_nvram_prop *prop) +{ + BHND_NV_ASSERT(prop->refs >= 1, ("prop over-released")); + + /* Drop reference */ + if (!refcount_release(&prop->refs)) + return; + + /* Free property data */ + bhnd_nvram_val_release(prop->val); + bhnd_nv_free(prop->name); + bhnd_nv_free(prop); +} + +/** + * Return a borrowed reference to the property's name. + * + * @param prop The property to query. + */ +const char * +bhnd_nvram_prop_name(bhnd_nvram_prop *prop) +{ + return (prop->name); +} + +/** + * Return a borrowed reference to the property's value. + * + * @param prop The property to query. + */ +bhnd_nvram_val * +bhnd_nvram_prop_val(bhnd_nvram_prop *prop) +{ + return (prop->val); +} + +/** + * Return the property's value type. + * + * @param prop The property to query. + */ +bhnd_nvram_type +bhnd_nvram_prop_type(bhnd_nvram_prop *prop) +{ + return (bhnd_nvram_val_type(prop->val)); +} + +/** + * Return a borrowed reference to the property's internal value representation. + * + * @param prop The property to query. + * @param[out] olen The returned data's size, in bytes. + * @param[out] otype The returned data's type. + */ +const void * +bhnd_nvram_prop_bytes(bhnd_nvram_prop *prop, size_t *olen, + bhnd_nvram_type *otype) +{ + const void *bytes; + + bytes = bhnd_nvram_val_bytes(prop->val, olen, otype); + BHND_NV_ASSERT(*otype == bhnd_nvram_prop_type(prop), ("type mismatch")); + + return (bytes); +} + +/** + * Attempt to encode the property's value as @p otype, writing the result + * to @p outp. + * + * @param prop The property to be encoded. + * @param[out] outp On success, the value will be written to this + * buffer. This argment may be NULL if the value is + * not desired. + * @param[in,out] olen The capacity of @p outp. On success, will be set + * to the actual size of the requested value. + * @param otype The data type to be written to @p outp. + * + * @retval 0 success + * @retval ENOMEM If the @p outp is non-NULL, and the provided @p olen + * is too small to hold the encoded value. + * @retval EFTYPE If value coercion from @p prop to @p otype is + * impossible. + * @retval ERANGE If value coercion would overflow (or underflow) the + * a @p otype representation. + */ +int +bhnd_nvram_prop_encode(bhnd_nvram_prop *prop, void *outp, size_t *olen, + bhnd_nvram_type otype) +{ + return (bhnd_nvram_val_encode(prop->val, outp, olen, otype)); +} Added: head/sys/dev/bhnd/nvram/bhnd_nvram_plist.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/bhnd/nvram/bhnd_nvram_plist.h Mon Dec 19 20:11:48 2016 (r310291) @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller <lan...@landonf.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. + * + * $FreeBSD$ + */ + +#ifndef _BHND_NVRAM_BHND_NVRAM_PLIST_H_ +#define _BHND_NVRAM_BHND_NVRAM_PLIST_H_ + +#ifdef _KERNEL +#include <sys/types.h> +#else /* !_KERNEL */ *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"