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_plist.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) 2015-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 #include <sys/param.h>
   34 #include <sys/hash.h>
   35 
   36 #ifdef _KERNEL
   37 
   38 #include <sys/systm.h>
   39 
   40 #else /* !_KERNEL */
   41 
   42 #include <errno.h>
   43 #include <stdint.h>
   44 #include <stdlib.h>
   45 #include <string.h>
   46 
   47 #endif /* _KERNEL */
   48 
   49 #include "bhnd_nvram_plistvar.h"
   50 #include "bhnd_nvram_private.h"
   51 
   52 static bhnd_nvram_plist_entry   *bhnd_nvram_plist_get_entry(
   53                                      bhnd_nvram_plist *plist, const char *name);
   54 
   55 /**
   56  * Allocate and initialize a new, empty property list.
   57  * 
   58  * The caller is responsible for releasing the returned property value
   59  * via bhnd_nvram_plist_release().
   60  * 
   61  * @retval non-NULL     success
   62  * @retval NULL         if allocation fails.
   63  */
   64 bhnd_nvram_plist *
   65 bhnd_nvram_plist_new(void)
   66 {
   67         bhnd_nvram_plist *plist;
   68 
   69         plist = bhnd_nv_calloc(1, sizeof(*plist));
   70         if (plist == NULL)
   71                 return NULL;
   72 
   73         /* Implicit caller-owned reference */
   74         plist->refs = 1;
   75 
   76         /* Initialize entry list */
   77         plist->num_entries = 0;
   78         TAILQ_INIT(&plist->entries);
   79 
   80         /* Initialize entry hash table */
   81         for (size_t i = 0; i < nitems(plist->names); i++)
   82                 LIST_INIT(&plist->names[i]);
   83 
   84         return (plist);
   85 }
   86 
   87 /**
   88  * Retain a reference and return @p plist to the caller.
   89  * 
   90  * The caller is responsible for releasing their reference ownership via
   91  * bhnd_nvram_plist_release().
   92  * 
   93  * @param       plist   The property list to be retained.
   94  */
   95 bhnd_nvram_plist *
   96 bhnd_nvram_plist_retain(bhnd_nvram_plist *plist)
   97 {
   98         BHND_NV_ASSERT(plist->refs >= 1, ("plist over-released"));
   99 
  100         refcount_acquire(&plist->refs);
  101         return (plist);
  102 }
  103 
  104 /**
  105  * Release a reference to @p plist.
  106  *
  107  * If this is the last reference, all associated resources will be freed.
  108  * 
  109  * @param       plist   The property list to be released.
  110  */
  111 void
  112 bhnd_nvram_plist_release(bhnd_nvram_plist *plist)
  113 {
  114         bhnd_nvram_plist_entry *ple, *ple_next;
  115 
  116         BHND_NV_ASSERT(plist->refs >= 1, ("plist over-released"));
  117 
  118         /* Drop reference */
  119         if (!refcount_release(&plist->refs))
  120                 return;
  121 
  122         /* Free all property entries */
  123         TAILQ_FOREACH_SAFE(ple, &plist->entries, pl_link, ple_next) {
  124                 bhnd_nvram_prop_release(ple->prop);
  125                 bhnd_nv_free(ple);
  126         }
  127 
  128         /* Free plist instance */
  129         bhnd_nv_free(plist);
  130 }
  131 
  132 /**
  133  * Return a shallow copy of @p plist.
  134  * 
  135  * The caller is responsible for releasing the returned property value
  136  * via bhnd_nvram_plist_release().
  137  * 
  138  * @retval non-NULL     success
  139  * @retval NULL         if allocation fails.
  140  */
  141 bhnd_nvram_plist *
  142 bhnd_nvram_plist_copy(bhnd_nvram_plist *plist)
  143 {
  144         bhnd_nvram_plist        *copy;
  145         bhnd_nvram_prop         *prop;
  146         int                      error;
  147 
  148         /* Allocate new, empty plist */
  149         if ((copy = bhnd_nvram_plist_new()) == NULL)
  150                 return (NULL);
  151 
  152         /* Append all properties */
  153         prop = NULL;
  154         while ((prop = bhnd_nvram_plist_next(plist, prop)) != NULL) {
  155                 error = bhnd_nvram_plist_append(copy, prop);
  156                 if (error) {
  157                         if (error != ENOMEM) {
  158                                 BHND_NV_LOG("error copying property: %d\n",
  159                                     error);
  160                         }
  161 
  162                         bhnd_nvram_plist_release(copy);
  163                         return (NULL);
  164                 }
  165         }
  166 
  167         /* Return ownership of the copy to our caller */
  168         return (copy);
  169 }
  170 
  171 /**
  172  * Return the number of properties in @p plist.
  173  */
  174 size_t
  175 bhnd_nvram_plist_count(bhnd_nvram_plist *plist)
  176 {
  177         return (plist->num_entries);
  178 }
  179 
  180 /**
  181  * Return true if @p plist contains a property name @p name, false otherwise.
  182  * 
  183  * @param       plist   The property list to be queried.
  184  * @param       name    The property name to be queried.
  185  */
  186 bool
  187 bhnd_nvram_plist_contains(bhnd_nvram_plist *plist, const char *name)
  188 {
  189         if (bhnd_nvram_plist_get_entry(plist, name) != NULL)
  190                 return (true);
  191 
  192         return (false);
  193 }
  194 
  195 /**
  196  * Replace the current property value for a property matching the name
  197  * of @p prop, maintaining the property's current order in @p plist.
  198  * 
  199  * If a matching property is not found in @p plist, @p prop will instead be
  200  * appended.
  201  * 
  202  * @param       plist   The property list to be modified.
  203  * @param       prop    The replacement property.
  204  * 
  205  * @retval 0            success
  206  * @retval ENOMEM       if allocation fails.
  207  * @retval non-zero     if modifying @p plist otherwise fails, a regular unix
  208  *                      error code will be returned.
  209  */
  210 int
  211 bhnd_nvram_plist_replace(bhnd_nvram_plist *plist, bhnd_nvram_prop *prop)
  212 {
  213         bhnd_nvram_plist_entry  *entry;
  214 
  215         /* Fetch current entry */
  216         entry = bhnd_nvram_plist_get_entry(plist, prop->name);
  217         if (entry == NULL) {
  218                 /* Not found -- append property instead */
  219                 return (bhnd_nvram_plist_append(plist, prop));
  220         }
  221 
  222         /* Replace the current entry's property reference */
  223         bhnd_nvram_prop_release(entry->prop);
  224         entry->prop = bhnd_nvram_prop_retain(prop);
  225 
  226         return (0);
  227 }
  228 
  229 /**
  230  * Replace the current property value for a property matching @p name,
  231  * maintaining the property's order in @p plist.
  232  * 
  233  * If @p name is not found in @p plist, a new property will be appended.
  234  * 
  235  * @param       plist   The property list to be modified.
  236  * @param       name    The name of the property to be replaced.
  237  * @param       val     The replacement value for @p name.
  238  * 
  239  * @retval 0            success
  240  * @retval ENOMEM       if allocation fails.
  241  * @retval non-zero     if modifying @p plist otherwise fails, a regular unix
  242  *                      error code will be returned.
  243  */
  244 int
  245 bhnd_nvram_plist_replace_val(bhnd_nvram_plist *plist, const char *name,
  246     bhnd_nvram_val *val)
  247 {
  248         bhnd_nvram_prop         *prop;
  249         int                      error;
  250 
  251         /* Construct a new property instance for the name and value */
  252         if ((prop = bhnd_nvram_prop_new(name, val)) == NULL)
  253                 return (ENOMEM);
  254 
  255         /* Attempt replace */
  256         error = bhnd_nvram_plist_replace(plist, prop);
  257         bhnd_nvram_prop_release(prop);
  258 
  259         return (error);
  260 }
  261 
  262 /**
  263  * Replace the current property value for a property matching @p name, copying
  264  * the new property value from the given @p inp buffer of @p itype and @p ilen. 
  265  * 
  266  * The current property order of @p name in @p plist will be maintained.
  267  * 
  268  * If @p name is not found in @p plist, a new property will be appended.
  269  * 
  270  * @param       plist   The property list to be modified.
  271  * @param       name    The name of the property to be replaced.
  272  * @param       inp     Input buffer.
  273  * @param       ilen    Input buffer length.
  274  * @param       itype   Input buffer type.
  275  * 
  276  * @retval 0            success
  277  * @retval ENOMEM       if allocation fails.
  278  * @retval non-zero     if modifying @p plist otherwise fails, a regular unix
  279  *                      error code will be returned.
  280  */
  281 int
  282 bhnd_nvram_plist_replace_bytes(bhnd_nvram_plist *plist, const char *name,
  283     const void *inp, size_t ilen, bhnd_nvram_type itype)
  284 {
  285         bhnd_nvram_prop *prop;
  286         int              error;
  287 
  288         if ((prop = bhnd_nvram_prop_bytes_new(name, inp, ilen, itype)) == NULL)
  289                 return (ENOMEM);
  290 
  291         error = bhnd_nvram_plist_replace(plist, prop);
  292         bhnd_nvram_prop_release(prop);
  293 
  294         return (error);
  295 }
  296 
  297 /**
  298  * Replace the current property value for a property matching @p name, copying
  299  * the new property value from @p val.
  300  * 
  301  * The current property order of @p name in @p plist will be maintained.
  302  * 
  303  * If @p name is not found in @p plist, a new property will be appended.
  304  * 
  305  * @param       plist   The property list to be modified.
  306  * @param       name    The name of the property to be replaced.
  307  * @param       val     The property's replacement string value.
  308  * 
  309  * @retval 0            success
  310  * @retval ENOMEM       if allocation fails.
  311  * @retval non-zero     if modifying @p plist otherwise fails, a regular unix
  312  *                      error code will be returned.
  313  */
  314 int
  315 bhnd_nvram_plist_replace_string(bhnd_nvram_plist *plist, const char *name,
  316     const char *val)
  317 {
  318         return (bhnd_nvram_plist_replace_bytes(plist, name, val, strlen(val)+1,
  319             BHND_NVRAM_TYPE_STRING));
  320 }
  321 
  322 /**
  323  * Remove the property entry for the property @p name, if any.
  324  * 
  325  * @param       plist   The property list to be modified.
  326  * @param       name    The name of the property to be removed.
  327  */
  328 void
  329 bhnd_nvram_plist_remove(bhnd_nvram_plist *plist, const char *name)
  330 {
  331         bhnd_nvram_plist_entry *entry;
  332 
  333         /* Fetch entry */
  334         entry = bhnd_nvram_plist_get_entry(plist, name);
  335         if (entry == NULL)
  336                 return;
  337 
  338         /* Remove from entry list and hash table */
  339         TAILQ_REMOVE(&plist->entries, entry, pl_link);
  340         LIST_REMOVE(entry, pl_hash_link);
  341 
  342         /* Free plist entry */
  343         bhnd_nvram_prop_release(entry->prop);
  344         bhnd_nv_free(entry);
  345 
  346         /* Decrement entry count */
  347         BHND_NV_ASSERT(plist->num_entries > 0, ("entry count over-release"));
  348         plist->num_entries--;
  349 }
  350 
  351 /**
  352  * Fetch the property list entry for @p name, if any.
  353  * 
  354  * @param       plist   The property list to be queried.
  355  * @param       name    The property name to be queried.
  356  * 
  357  * @retval non-NULL     if @p name is found.
  358  * @retval NULL         if @p name is not found.
  359  */
  360 static bhnd_nvram_plist_entry *
  361 bhnd_nvram_plist_get_entry(bhnd_nvram_plist *plist, const char *name)
  362 {
  363         bhnd_nvram_plist_entry_list     *hash_list;
  364         bhnd_nvram_plist_entry          *entry;
  365         uint32_t                         h;
  366 
  367         h = hash32_str(name, HASHINIT);
  368         hash_list = &plist->names[h % nitems(plist->names)];
  369 
  370         LIST_FOREACH(entry, hash_list, pl_hash_link) {
  371                 if (strcmp(entry->prop->name, name) == 0)
  372                         return (entry);
  373         };
  374 
  375         /* Not found */
  376         return (NULL);
  377 }
  378 
  379 /**
  380  * Append all properties from @p tail to @p plist.
  381   * 
  382  * @param       plist   The property list to be modified.
  383  * @param       tail    The property list to append.
  384  * 
  385  * @retval 0            success
  386  * @retval ENOMEM       if allocation fails.
  387  * @retval EEXIST       an existing property from @p tail was found in @p plist.
  388  */
  389 int
  390 bhnd_nvram_plist_append_list(bhnd_nvram_plist *plist, bhnd_nvram_plist *tail)
  391 {
  392         bhnd_nvram_prop *p;
  393         int              error;
  394 
  395         p = NULL;
  396         while ((p = bhnd_nvram_plist_next(tail, p)) != NULL) {
  397                 if ((error = bhnd_nvram_plist_append(plist, p)))
  398                         return (error);
  399         }
  400 
  401         return (0);
  402 }
  403 
  404 /**
  405  * Append @p prop to @p plist.
  406  * 
  407  * @param       plist   The property list to be modified.
  408  * @param       prop    The property to append.
  409  * 
  410  * @retval 0            success
  411  * @retval ENOMEM       if allocation fails.
  412  * @retval EEXIST       an existing property with @p name was found in @p plist.
  413  */
  414 int
  415 bhnd_nvram_plist_append(bhnd_nvram_plist *plist, bhnd_nvram_prop *prop)
  416 {
  417         bhnd_nvram_plist_entry_list     *hash_list;
  418         bhnd_nvram_plist_entry          *entry;
  419         uint32_t                         h;
  420 
  421         if (bhnd_nvram_plist_contains(plist, prop->name))
  422                 return (EEXIST);
  423 
  424         /* Have we hit the maximum representable entry count? */
  425         if (plist->num_entries == SIZE_MAX)
  426                 return (ENOMEM);
  427 
  428         /* Allocate new entry */
  429         entry = bhnd_nv_malloc(sizeof(*entry));
  430         if (entry == NULL)
  431                 return (ENOMEM);
  432 
  433         entry->prop = bhnd_nvram_prop_retain(prop);
  434 
  435         /* Append to entry list */
  436         TAILQ_INSERT_TAIL(&plist->entries, entry, pl_link);
  437 
  438         /* Add to name-based hash table */
  439         h = hash32_str(prop->name, HASHINIT);
  440         hash_list = &plist->names[h % nitems(plist->names)];
  441         LIST_INSERT_HEAD(hash_list, entry, pl_hash_link);
  442 
  443         /* Increment entry count */
  444         plist->num_entries++;
  445 
  446         return (0);
  447 }
  448 
  449 /**
  450  * Append a new property to @p plist with @p name and @p val.
  451  * 
  452  * @param       plist   The property list to be modified.
  453  * @param       name    The name of the property to be appended.
  454  * @param       val     The value of the property to be appended.
  455  * 
  456  * @retval 0            success
  457  * @retval ENOMEM       if allocation fails.
  458  * @retval EEXIST       an existing property with @p name was found in @p plist.
  459  */
  460 int
  461 bhnd_nvram_plist_append_val(bhnd_nvram_plist *plist, const char *name,
  462     bhnd_nvram_val *val)
  463 {
  464         bhnd_nvram_prop *prop;
  465         int              error;
  466 
  467         if ((prop = bhnd_nvram_prop_new(name, val)) == NULL)
  468                 return (ENOMEM);
  469 
  470         error = bhnd_nvram_plist_append(plist, prop);
  471         bhnd_nvram_prop_release(prop);
  472 
  473         return (error);
  474 }
  475 
  476 /**
  477  * Append a new property to @p plist, copying the property value from the
  478  * given @p inp buffer of @p itype and @p ilen.
  479  * 
  480  * @param       plist   The property list to be modified.
  481  * @param       name    The name of the property to be appended.
  482  * @param       inp     Input buffer.
  483  * @param       ilen    Input buffer length.
  484  * @param       itype   Input buffer type.
  485  * 
  486  * @retval 0            success
  487  * @retval ENOMEM       if allocation fails.
  488  * @retval EEXIST       an existing property with @p name was found in @p plist.
  489  */
  490 int
  491 bhnd_nvram_plist_append_bytes(bhnd_nvram_plist *plist, const char *name,
  492     const void *inp, size_t ilen, bhnd_nvram_type itype)
  493 {
  494         bhnd_nvram_prop *prop;
  495         int              error;
  496 
  497         if ((prop = bhnd_nvram_prop_bytes_new(name, inp, ilen, itype)) == NULL)
  498                 return (ENOMEM);
  499 
  500         error = bhnd_nvram_plist_append(plist, prop);
  501         bhnd_nvram_prop_release(prop);
  502 
  503         return (error);
  504 }
  505 
  506 /**
  507  * Append a new string property to @p plist, copying the property value from
  508  * @p val.
  509  * 
  510  * @param       plist   The property list to be modified.
  511  * @param       name    The name of the property to be appended.
  512  * @param       val     The new property's string value.
  513  *
  514  * @retval 0            success
  515  * @retval ENOMEM       if allocation fails.
  516  * @retval EEXIST       an existing property with @p name was found in @p plist.
  517  */
  518 int
  519 bhnd_nvram_plist_append_string(bhnd_nvram_plist *plist, const char *name,
  520     const char *val)
  521 {
  522         return (bhnd_nvram_plist_append_bytes(plist, name, val, strlen(val)+1,
  523             BHND_NVRAM_TYPE_STRING));
  524 }
  525 
  526 /**
  527  * Iterate over all properties in @p plist.
  528  * 
  529  * @param       plist   The property list to be iterated.
  530  * @param       prop    A property in @p plist, or NULL to return the first
  531  *                      property in @p plist.
  532  * 
  533  * @retval non-NULL     A borrowed reference to the next property in @p plist.
  534  * @retval NULL         If the end of the property list is reached or @p prop
  535  *                      is not found in @p plist.
  536  */
  537 bhnd_nvram_prop *
  538 bhnd_nvram_plist_next(bhnd_nvram_plist *plist, bhnd_nvram_prop *prop)
  539 {
  540         bhnd_nvram_plist_entry *entry;
  541 
  542         if (prop == NULL) {
  543                 if ((entry = TAILQ_FIRST(&plist->entries)) == NULL)
  544                         return (NULL);
  545 
  546                 return (entry->prop);
  547         }
  548 
  549         /* Look up previous property entry by name */
  550         if ((entry = bhnd_nvram_plist_get_entry(plist, prop->name)) == NULL)
  551                 return (NULL);
  552 
  553         /* The property instance must be identical */
  554         if (entry->prop != prop)
  555                 return (NULL);
  556 
  557         /* Fetch next entry */
  558         if ((entry = TAILQ_NEXT(entry, pl_link)) == NULL)
  559                 return (NULL);
  560 
  561         return (entry->prop);
  562 }
  563 
  564 /**
  565  * Return a borrowed reference to a named property, or NULL if @p name is
  566  * not found in @p plist.
  567  * 
  568  * @param       plist   The property list to be queried.
  569  * @param       name    The name of the property to be returned.
  570  *
  571  * @retval non-NULL     if @p name is found.
  572  * @retval NULL         if @p name is not found.
  573  */
  574 bhnd_nvram_prop *
  575 bhnd_nvram_plist_get_prop(bhnd_nvram_plist *plist, const char *name)
  576 {
  577         bhnd_nvram_plist_entry *entry;
  578 
  579         if ((entry = bhnd_nvram_plist_get_entry(plist, name)) == NULL)
  580                 return (NULL);
  581 
  582         return (entry->prop);
  583 }
  584 
  585 /**
  586  * Return a borrowed reference to the named property's value, or NULL if
  587  * @p name is not found in @p plist.
  588  * 
  589  * @param       plist   The property list to be queried.
  590  * @param       name    The name of the property to be returned.
  591  *
  592  * @retval non-NULL     if @p name is found.
  593  * @retval NULL         if @p name is not found.
  594  */
  595 bhnd_nvram_val *
  596 bhnd_nvram_plist_get_val(bhnd_nvram_plist *plist, const char *name)
  597 {
  598         bhnd_nvram_prop *prop;
  599 
  600         if ((prop = bhnd_nvram_plist_get_prop(plist, name)) == NULL)
  601                 return (NULL);
  602 
  603         return (bhnd_nvram_prop_val(prop));
  604 }
  605 
  606 /**
  607  * Attempt to encode a named property's value as @p otype, writing the result
  608  * to @p outp.
  609  *
  610  * @param               plist   The property list to be queried.
  611  * @param               name    The name of the property value to be returned.
  612  * @param[out]          outp    On success, the value will be written to this 
  613  *                              buffer. This argment may be NULL if the value is
  614  *                              not desired.
  615  * @param[in,out]       olen    The capacity of @p outp. On success, will be set
  616  *                              to the actual size of the requested value.
  617  * @param               otype   The data type to be written to @p outp.
  618  *
  619  * @retval 0            success
  620  * @retval ENOENT       If @p name is not found in @p plist.
  621  * @retval ENOMEM       If the @p outp is non-NULL, and the provided @p olen
  622  *                      is too small to hold the encoded value.
  623  * @retval EFTYPE       If value coercion from @p prop to @p otype is
  624  *                      impossible.
  625  * @retval ERANGE       If value coercion would overflow (or underflow) the
  626  *                      a @p otype representation.
  627  */
  628 int
  629 bhnd_nvram_plist_get_encoded(bhnd_nvram_plist *plist, const char *name,
  630     void *outp, size_t olen, bhnd_nvram_type otype)
  631 {
  632         bhnd_nvram_prop *prop;
  633 
  634         if ((prop = bhnd_nvram_plist_get_prop(plist, name)) == NULL)
  635                 return (ENOENT);
  636 
  637         return (bhnd_nvram_prop_encode(prop, outp, &olen, otype));
  638 }
  639 
  640 /**
  641  * Return the character representation of a named property's value.
  642  * 
  643  * @param       plist   The property list to be queried.
  644  * @param       name    The name of the property value to be returned.
  645  * @param[out]  val     On success, the character value of @p name.
  646  *
  647  * @retval 0            success
  648  * @retval ENOENT       If @p name is not found in @p plist.
  649  * @retval EFTYPE       If coercion of the property's value to @p val.
  650  * @retval ERANGE       If coercion of the property's value would overflow
  651  *                      (or underflow) @p val.
  652  */
  653 int
  654 bhnd_nvram_plist_get_char(bhnd_nvram_plist *plist, const char *name,
  655     u_char *val)
  656 {
  657         return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
  658             BHND_NVRAM_TYPE_CHAR));
  659 }
  660 
  661 /**
  662  * Return the uint8 representation of a named property's value.
  663  * 
  664  * @param       plist   The property list to be queried.
  665  * @param       name    The name of the property value to be returned.
  666  * @param[out]  val     On success, the uint8 value of @p name.
  667  *
  668  * @retval 0            success
  669  * @retval ENOENT       If @p name is not found in @p plist.
  670  * @retval EFTYPE       If coercion of the property's value to @p val.
  671  * @retval ERANGE       If coercion of the property's value would overflow
  672  *                      (or underflow) @p val.
  673  */
  674 int
  675 bhnd_nvram_plist_get_uint8(bhnd_nvram_plist *plist, const char *name,
  676     uint8_t *val)
  677 {
  678         return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
  679             BHND_NVRAM_TYPE_UINT8));
  680 }
  681 
  682 /**
  683  * Return the uint16 representation of a named property's value.
  684  * 
  685  * @param       plist   The property list to be queried.
  686  * @param       name    The name of the property value to be returned.
  687  * @param[out]  val     On success, the uint16 value of @p name.
  688  *
  689  * @retval 0            success
  690  * @retval ENOENT       If @p name is not found in @p plist.
  691  * @retval EFTYPE       If coercion of the property's value to @p val.
  692  * @retval ERANGE       If coercion of the property's value would overflow
  693  *                      (or underflow) @p val.
  694  */
  695 int
  696 bhnd_nvram_plist_get_uint16(bhnd_nvram_plist *plist, const char *name,
  697     uint16_t *val)
  698 {
  699         return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
  700             BHND_NVRAM_TYPE_UINT16));
  701 }
  702 
  703 /**
  704  * Return the uint32 representation of a named property's value.
  705  * 
  706  * @param       plist   The property list to be queried.
  707  * @param       name    The name of the property value to be returned.
  708  * @param[out]  val     On success, the uint32 value of @p name.
  709  *
  710  * @retval 0            success
  711  * @retval ENOENT       If @p name is not found in @p plist.
  712  * @retval EFTYPE       If coercion of the property's value to @p val.
  713  * @retval ERANGE       If coercion of the property's value would overflow
  714  *                      (or underflow) @p val.
  715  */
  716 int
  717 bhnd_nvram_plist_get_uint32(bhnd_nvram_plist *plist, const char *name,
  718     uint32_t *val)
  719 {
  720         return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
  721             BHND_NVRAM_TYPE_UINT32));
  722 }
  723 
  724 /**
  725  * Return the uint64 representation of a named property's value.
  726  * 
  727  * @param       plist   The property list to be queried.
  728  * @param       name    The name of the property value to be returned.
  729  * @param[out]  val     On success, the uint64 value of @p name.
  730  *
  731  * @retval 0            success
  732  * @retval ENOENT       If @p name is not found in @p plist.
  733  * @retval EFTYPE       If coercion of the property's value to @p val.
  734  * @retval ERANGE       If coercion of the property's value would overflow
  735  *                      (or underflow) @p val.
  736  */
  737 int
  738 bhnd_nvram_plist_get_uint64(bhnd_nvram_plist *plist, const char *name,
  739     uint64_t *val)
  740 {
  741         return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
  742             BHND_NVRAM_TYPE_UINT64));
  743 }
  744 
  745 /**
  746  * Return the boolean representation of a named property's value.
  747  * 
  748  * @param       plist   The property list to be queried.
  749  * @param       name    The name of the property value to be returned.
  750  * @param[out]  val     On success, the boolean value of @p name.
  751  *
  752  * @retval 0            success
  753  * @retval ENOENT       If @p name is not found in @p plist.
  754  * @retval EFTYPE       If coercion of the property's value to @p val.
  755  * @retval ERANGE       If coercion of the property's value would overflow
  756  *                      (or underflow) @p val.
  757  */
  758 int
  759 bhnd_nvram_plist_get_bool(bhnd_nvram_plist *plist, const char *name,
  760     bool *val)
  761 {
  762         return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
  763             BHND_NVRAM_TYPE_BOOL));
  764 }
  765 
  766 /**
  767  * Allocate and initialize a new property value.
  768  * 
  769  * The caller is responsible for releasing the returned property value
  770  * via bhnd_nvram_prop_release().
  771  * 
  772  * @param       name    Property name.
  773  * @param       val     Property value.
  774  * 
  775  * @retval non-NULL     success
  776  * @retval NULL         if allocation fails.
  777  */
  778 struct bhnd_nvram_prop *
  779 bhnd_nvram_prop_new(const char *name, bhnd_nvram_val *val)
  780 {
  781         struct bhnd_nvram_prop *prop;
  782 
  783         prop = bhnd_nv_calloc(1, sizeof(*prop));
  784         if (prop == NULL)
  785                 return NULL;
  786 
  787         /* Implicit caller-owned reference */
  788         prop->refs = 1;
  789 
  790         if ((prop->name = bhnd_nv_strdup(name)) == NULL)
  791                 goto failed;
  792 
  793         if ((prop->val = bhnd_nvram_val_copy(val)) == NULL)
  794                 goto failed;
  795 
  796         return (prop);
  797 
  798 failed:
  799         if (prop->name != NULL)
  800                 bhnd_nv_free(prop->name);
  801 
  802         if (prop->val != NULL)
  803                 bhnd_nvram_val_release(prop->val);
  804 
  805         bhnd_nv_free(prop);
  806         return (NULL);
  807 }
  808 
  809 /**
  810  * Allocate a new property value and attempt to initialize its value from
  811  * the given @p inp buffer of @p itype and @p ilen.
  812  *
  813  * The caller is responsible for releasing the returned property value
  814  * via bhnd_nvram_prop_release().
  815  *
  816  * @param       name    Property name.
  817  * @param       inp     Input buffer.
  818  * @param       ilen    Input buffer length.
  819  * @param       itype   Input buffer type.
  820  * 
  821  * @retval non-NULL     success
  822  * @retval NULL         if allocation or initialization fails.
  823  */
  824 bhnd_nvram_prop *
  825 bhnd_nvram_prop_bytes_new(const char *name, const void *inp, size_t ilen,
  826     bhnd_nvram_type itype)
  827 {
  828         bhnd_nvram_prop *prop;
  829         bhnd_nvram_val  *val;
  830         int              error;
  831 
  832         /* Construct new value instance */
  833         error = bhnd_nvram_val_new(&val, NULL, inp, ilen, itype,
  834             BHND_NVRAM_VAL_DYNAMIC);
  835         if (error) {
  836                 if (error != ENOMEM) {
  837                         BHND_NV_LOG("invalid input data; initialization "
  838                             "failed: %d\n", error);
  839                 }
  840 
  841                 return (NULL);
  842         }
  843 
  844         /* Delegate to default implementation */
  845         prop = bhnd_nvram_prop_new(name, val);
  846 
  847         /* Clean up */
  848         bhnd_nvram_val_release(val);
  849         return (prop);
  850 }
  851 
  852 /**
  853  * Retain a reference and return @p prop to the caller.
  854  * 
  855  * The caller is responsible for releasing their reference ownership via
  856  * bhnd_nvram_prop_release().
  857  * 
  858  * @param       prop    The property to be retained.
  859  */
  860 bhnd_nvram_prop *
  861 bhnd_nvram_prop_retain(bhnd_nvram_prop *prop)
  862 {
  863         BHND_NV_ASSERT(prop->refs >= 1, ("prop over-released"));
  864 
  865         refcount_acquire(&prop->refs);
  866         return (prop);
  867 }
  868 
  869 /**
  870  * Release a reference to @p prop.
  871  *
  872  * If this is the last reference, all associated resources will be freed.
  873  * 
  874  * @param       prop    The property to be released.
  875  */
  876 void
  877 bhnd_nvram_prop_release(bhnd_nvram_prop *prop)
  878 {
  879         BHND_NV_ASSERT(prop->refs >= 1, ("prop over-released"));
  880 
  881         /* Drop reference */
  882         if (!refcount_release(&prop->refs))
  883                 return;
  884 
  885         /* Free property data */
  886         bhnd_nvram_val_release(prop->val);
  887         bhnd_nv_free(prop->name);
  888         bhnd_nv_free(prop);
  889 }
  890 
  891 /**
  892  * Return a borrowed reference to the property's name.
  893  * 
  894  * @param       prop    The property to query.
  895  */
  896 const char *
  897 bhnd_nvram_prop_name(bhnd_nvram_prop *prop)
  898 {
  899         return (prop->name);
  900 }
  901 
  902 /**
  903  * Return a borrowed reference to the property's value.
  904  * 
  905  * @param       prop    The property to query.
  906  */
  907 bhnd_nvram_val *
  908 bhnd_nvram_prop_val(bhnd_nvram_prop *prop)
  909 {
  910         return (prop->val);
  911 }
  912 
  913 /**
  914  * Return the property's value type.
  915  * 
  916  * @param       prop    The property to query.
  917  */
  918 bhnd_nvram_type
  919 bhnd_nvram_prop_type(bhnd_nvram_prop *prop)
  920 {
  921         return (bhnd_nvram_val_type(prop->val));
  922 }
  923 
  924 /**
  925  * Return true if @p prop has a NULL value type (BHND_NVRAM_TYPE_NULL), false
  926  * otherwise.
  927  * 
  928  * @param      prop    The property to query.
  929  */
  930 bool
  931 bhnd_nvram_prop_is_null(bhnd_nvram_prop *prop)
  932 {
  933         return (bhnd_nvram_prop_type(prop) == BHND_NVRAM_TYPE_NULL);
  934 }
  935 
  936 /**
  937  * Return a borrowed reference to the property's internal value representation.
  938  *
  939  * @param       prop    The property to query.
  940  * @param[out]  olen    The returned data's size, in bytes.
  941  * @param[out]  otype   The returned data's type.
  942  */
  943 const void *
  944 bhnd_nvram_prop_bytes(bhnd_nvram_prop *prop, size_t *olen,
  945     bhnd_nvram_type *otype)
  946 {
  947         const void *bytes;
  948 
  949         bytes = bhnd_nvram_val_bytes(prop->val, olen, otype);
  950         BHND_NV_ASSERT(*otype == bhnd_nvram_prop_type(prop), ("type mismatch"));
  951 
  952         return (bytes);
  953 }
  954 
  955 /**
  956  * Attempt to encode the property's value as @p otype, writing the result
  957  * to @p outp.
  958  *
  959  * @param               prop    The property to be encoded.
  960  * @param[out]          outp    On success, the value will be written to this 
  961  *                              buffer. This argment may be NULL if the value is
  962  *                              not desired.
  963  * @param[in,out]       olen    The capacity of @p outp. On success, will be set
  964  *                              to the actual size of the requested value.
  965  * @param               otype   The data type to be written to @p outp.
  966  *
  967  * @retval 0            success
  968  * @retval ENOMEM       If the @p outp is non-NULL, and the provided @p olen
  969  *                      is too small to hold the encoded value.
  970  * @retval EFTYPE       If value coercion from @p prop to @p otype is
  971  *                      impossible.
  972  * @retval ERANGE       If value coercion would overflow (or underflow) the
  973  *                      a @p otype representation.
  974  */
  975 int
  976 bhnd_nvram_prop_encode(bhnd_nvram_prop *prop, void *outp, size_t *olen,
  977     bhnd_nvram_type otype)
  978 {
  979         return (bhnd_nvram_val_encode(prop->val, outp, olen, otype));
  980 }

Cache object: 9d837ce7f53c31f7f16048ac089dda95


[ 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.