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_store.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 #include <sys/limits.h>
   36 #include <sys/queue.h>
   37 
   38 #ifdef _KERNEL
   39 
   40 #include <sys/ctype.h>
   41 #include <sys/systm.h>
   42 
   43 #include <machine/_inttypes.h>
   44 
   45 #else /* !_KERNEL */
   46 
   47 #include <ctype.h>
   48 #include <errno.h>
   49 #include <inttypes.h>
   50 #include <stdbool.h>
   51 #include <stdio.h>
   52 #include <stdint.h>
   53 #include <stdlib.h>
   54 #include <string.h>
   55 
   56 #endif /* _KERNEL */
   57 
   58 #include "bhnd_nvram_private.h"
   59 #include "bhnd_nvram_datavar.h"
   60 
   61 #include "bhnd_nvram_storevar.h"
   62 
   63 /*
   64  * BHND NVRAM Store
   65  *
   66  * Manages in-memory and persistent representations of NVRAM data.
   67  */
   68 
   69 static int                       bhnd_nvstore_parse_data(
   70                                      struct bhnd_nvram_store *sc);
   71 
   72 static int                       bhnd_nvstore_parse_path_entries(
   73                                      struct bhnd_nvram_store *sc);
   74 
   75 static int                       bhnd_nvram_store_export_child(
   76                                      struct bhnd_nvram_store *sc,
   77                                      bhnd_nvstore_path *top,
   78                                      bhnd_nvstore_path *child,
   79                                      bhnd_nvram_plist *plist,
   80                                      uint32_t flags);
   81 
   82 static int                       bhnd_nvstore_export_merge(
   83                                      struct bhnd_nvram_store *sc,
   84                                      bhnd_nvstore_path *path,
   85                                      bhnd_nvram_plist *merged,
   86                                      uint32_t flags);
   87 
   88 static int                       bhnd_nvstore_export_devpath_alias(
   89                                      struct bhnd_nvram_store *sc,
   90                                      bhnd_nvstore_path *path,
   91                                      const char *devpath,
   92                                      bhnd_nvram_plist *plist,
   93                                      u_long *alias_val);
   94 
   95 /**
   96  * Allocate and initialize a new NVRAM data store instance.
   97  *
   98  * The caller is responsible for deallocating the instance via
   99  * bhnd_nvram_store_free().
  100  * 
  101  * @param[out] store On success, a pointer to the newly allocated NVRAM data
  102  * instance.
  103  * @param data The NVRAM data to be managed by the returned NVRAM data store
  104  * instance.
  105  *
  106  * @retval 0 success
  107  * @retval non-zero if an error occurs during allocation or initialization, a
  108  * regular unix error code will be returned.
  109  */
  110 int
  111 bhnd_nvram_store_new(struct bhnd_nvram_store **store,
  112     struct bhnd_nvram_data *data)
  113 {
  114         struct bhnd_nvram_store *sc;
  115         int                      error;
  116 
  117         /* Allocate new instance */
  118         sc = bhnd_nv_calloc(1, sizeof(*sc));
  119         if (sc == NULL)
  120                 return (ENOMEM);
  121 
  122         BHND_NVSTORE_LOCK_INIT(sc);
  123         BHND_NVSTORE_LOCK(sc);
  124 
  125         /* Initialize path hash table */
  126         sc->num_paths = 0;
  127         for (size_t i = 0; i < nitems(sc->paths); i++)
  128                 LIST_INIT(&sc->paths[i]);
  129 
  130         /* Initialize alias hash table */
  131         sc->num_aliases = 0;
  132         for (size_t i = 0; i < nitems(sc->aliases); i++)
  133                 LIST_INIT(&sc->aliases[i]);
  134 
  135         /* Retain the NVRAM data */
  136         sc->data = bhnd_nvram_data_retain(data);
  137         sc->data_caps = bhnd_nvram_data_caps(data);
  138         sc->data_opts = bhnd_nvram_data_options(data);
  139         if (sc->data_opts != NULL) {
  140                 bhnd_nvram_plist_retain(sc->data_opts);
  141         } else {
  142                 sc->data_opts = bhnd_nvram_plist_new();
  143                 if (sc->data_opts == NULL) {
  144                         error = ENOMEM;
  145                         goto cleanup;
  146                 }
  147         }
  148 
  149         /* Register required root path */
  150         error = bhnd_nvstore_register_path(sc, BHND_NVSTORE_ROOT_PATH,
  151             BHND_NVSTORE_ROOT_PATH_LEN);
  152         if (error)
  153                 goto cleanup;
  154 
  155         sc->root_path = bhnd_nvstore_get_path(sc, BHND_NVSTORE_ROOT_PATH,
  156             BHND_NVSTORE_ROOT_PATH_LEN);
  157         BHND_NV_ASSERT(sc->root_path, ("missing root path"));
  158 
  159         /* Parse all variables vended by our backing NVRAM data instance,
  160          * generating all path entries, alias entries, and variable indexes */
  161         if ((error = bhnd_nvstore_parse_data(sc)))
  162                 goto cleanup;
  163 
  164         *store = sc;
  165 
  166         BHND_NVSTORE_UNLOCK(sc);
  167         return (0);
  168 
  169 cleanup:
  170         BHND_NVSTORE_UNLOCK(sc);
  171         bhnd_nvram_store_free(sc);
  172         return (error);
  173 }
  174 
  175 /**
  176  * Allocate and initialize a new NVRAM data store instance, parsing the
  177  * NVRAM data from @p io.
  178  *
  179  * The caller is responsible for deallocating the instance via
  180  * bhnd_nvram_store_free().
  181  * 
  182  * The NVRAM data mapped by @p io will be copied, and @p io may be safely
  183  * deallocated after bhnd_nvram_store_new() returns.
  184  * 
  185  * @param[out] store On success, a pointer to the newly allocated NVRAM data
  186  * instance.
  187  * @param io An I/O context mapping the NVRAM data to be copied and parsed.
  188  * @param cls The NVRAM data class to be used when parsing @p io, or NULL
  189  * to perform runtime identification of the appropriate data class.
  190  *
  191  * @retval 0 success
  192  * @retval non-zero if an error occurs during allocation or initialization, a
  193  * regular unix error code will be returned.
  194  */
  195 int
  196 bhnd_nvram_store_parse_new(struct bhnd_nvram_store **store,
  197     struct bhnd_nvram_io *io, bhnd_nvram_data_class *cls)
  198 {
  199         struct bhnd_nvram_data  *data;
  200         int                      error;
  201 
  202         /* Try to parse the data */
  203         if ((error = bhnd_nvram_data_new(cls, &data, io)))
  204                 return (error);
  205 
  206         /* Try to create our new store instance */
  207         error = bhnd_nvram_store_new(store, data);
  208         bhnd_nvram_data_release(data);
  209 
  210         return (error);
  211 }
  212 
  213 /**
  214  * Free an NVRAM store instance, releasing all associated resources.
  215  * 
  216  * @param sc A store instance previously allocated via
  217  * bhnd_nvram_store_new().
  218  */
  219 void
  220 bhnd_nvram_store_free(struct bhnd_nvram_store *sc)
  221 {
  222 
  223         /* Clean up alias hash table */
  224         for (size_t i = 0; i < nitems(sc->aliases); i++) {
  225                 bhnd_nvstore_alias *alias, *anext;
  226                 LIST_FOREACH_SAFE(alias, &sc->aliases[i], na_link, anext)
  227                         bhnd_nv_free(alias);
  228         }
  229 
  230         /* Clean up path hash table */
  231         for (size_t i = 0; i < nitems(sc->paths); i++) {
  232                 bhnd_nvstore_path *path, *pnext;
  233                 LIST_FOREACH_SAFE(path, &sc->paths[i], np_link, pnext)
  234                         bhnd_nvstore_path_free(path);
  235         }
  236 
  237         if (sc->data != NULL)
  238                 bhnd_nvram_data_release(sc->data);
  239 
  240         if (sc->data_opts != NULL)
  241                 bhnd_nvram_plist_release(sc->data_opts);
  242 
  243         BHND_NVSTORE_LOCK_DESTROY(sc);
  244         bhnd_nv_free(sc);
  245 }
  246 
  247 /**
  248  * Parse all variables vended by our backing NVRAM data instance,
  249  * generating all path entries, alias entries, and variable indexes.
  250  * 
  251  * @param       sc      The NVRAM store instance to be initialized with
  252  *                      paths, aliases, and data parsed from its backing
  253  *                      data.
  254  *
  255  * @retval 0            success
  256  * @retval non-zero     if an error occurs during parsing, a regular unix error
  257  *                      code will be returned.
  258  */
  259 static int
  260 bhnd_nvstore_parse_data(struct bhnd_nvram_store *sc)
  261 {
  262         const char      *name;
  263         void            *cookiep;
  264         int              error;
  265 
  266         /* Parse and register all device paths and path aliases. This enables
  267          * resolution of _forward_ references to device paths aliases when
  268          * scanning variable entries below */
  269         if ((error = bhnd_nvstore_parse_path_entries(sc)))
  270                 return (error);
  271 
  272         /* Calculate the per-path variable counts, and report dangling alias
  273          * references as an error. */
  274         cookiep = NULL;
  275         while ((name = bhnd_nvram_data_next(sc->data, &cookiep))) {
  276                 bhnd_nvstore_path       *path;
  277                 bhnd_nvstore_name_info   info;
  278 
  279                 /* Parse the name info */
  280                 error = bhnd_nvstore_parse_name_info(name,
  281                     BHND_NVSTORE_NAME_INTERNAL, sc->data_caps, &info);
  282                 if (error)
  283                         return (error);
  284 
  285                 switch (info.type) {
  286                 case BHND_NVSTORE_VAR:
  287                         /* Fetch referenced path */
  288                         path = bhnd_nvstore_var_get_path(sc, &info);
  289                         if (path == NULL) {
  290                                 BHND_NV_LOG("variable '%s' has dangling "
  291                                             "path reference\n", name);
  292                                 return (EFTYPE);
  293                         }
  294 
  295                         /* Increment path variable count */
  296                         if (path->num_vars == SIZE_MAX) {
  297                                 BHND_NV_LOG("more than SIZE_MAX variables in "
  298                                     "path %s\n", path->path_str);
  299                                 return (EFTYPE);
  300                         }
  301                         path->num_vars++;
  302                         break;
  303 
  304                 case BHND_NVSTORE_ALIAS_DECL:
  305                         /* Skip -- path alias already parsed and recorded */
  306                         break;
  307                 }
  308         }
  309 
  310         /* If the backing NVRAM data instance vends only a single root ("/")
  311          * path, we may be able to skip generating an index for the root
  312          * path */
  313         if (sc->num_paths == 1) {
  314                 bhnd_nvstore_path *path;
  315 
  316                 /* If the backing instance provides its own name-based lookup
  317                  * indexing, we can skip generating a duplicate here */
  318                 if (sc->data_caps & BHND_NVRAM_DATA_CAP_INDEXED)
  319                         return (0);
  320 
  321                 /* If the sole root path contains fewer variables than the
  322                  * minimum indexing threshhold, we do not need to generate an
  323                  * index */
  324                 path = bhnd_nvstore_get_root_path(sc);
  325                 if (path->num_vars < BHND_NV_IDX_VAR_THRESHOLD)
  326                         return (0);
  327         }
  328 
  329         /* Allocate per-path index instances */
  330         for (size_t i = 0; i < nitems(sc->paths); i++) {
  331                 bhnd_nvstore_path       *path;
  332 
  333                 LIST_FOREACH(path, &sc->paths[i], np_link) {
  334                         path->index = bhnd_nvstore_index_new(path->num_vars);
  335                         if (path->index == NULL)
  336                                 return (ENOMEM);
  337                 }
  338         }
  339 
  340         /* Populate per-path indexes */
  341         cookiep = NULL;
  342         while ((name = bhnd_nvram_data_next(sc->data, &cookiep))) {
  343                 bhnd_nvstore_name_info   info;
  344                 bhnd_nvstore_path       *path;
  345 
  346                 /* Parse the name info */
  347                 error = bhnd_nvstore_parse_name_info(name,
  348                     BHND_NVSTORE_NAME_INTERNAL, sc->data_caps, &info);
  349                 if (error)
  350                         return (error);
  351 
  352                 switch (info.type) {
  353                 case BHND_NVSTORE_VAR:
  354                         /* Fetch referenced path */
  355                         path = bhnd_nvstore_var_get_path(sc, &info);
  356                         BHND_NV_ASSERT(path != NULL,
  357                             ("dangling path reference"));
  358 
  359                         /* Append to index */
  360                         error = bhnd_nvstore_index_append(sc, path->index,
  361                             cookiep);
  362                         if (error)
  363                                 return (error);
  364                         break;
  365 
  366                 case BHND_NVSTORE_ALIAS_DECL:
  367                         /* Skip */
  368                         break;
  369                 }
  370         }
  371 
  372         /* Prepare indexes for querying */
  373         for (size_t i = 0; i < nitems(sc->paths); i++) {
  374                 bhnd_nvstore_path       *path;
  375 
  376                 LIST_FOREACH(path, &sc->paths[i], np_link) {
  377                         error = bhnd_nvstore_index_prepare(sc, path->index);
  378                         if (error)
  379                                 return (error);
  380                 }
  381         }
  382 
  383         return (0);
  384 }
  385 
  386 /**
  387  * Parse and register path and path alias entries for all declarations found in
  388  * the NVRAM data backing @p nvram.
  389  * 
  390  * @param sc            The NVRAM store instance.
  391  *
  392  * @retval 0            success
  393  * @retval non-zero     If parsing fails, a regular unix error code will be
  394  *                      returned.
  395  */
  396 static int
  397 bhnd_nvstore_parse_path_entries(struct bhnd_nvram_store *sc)
  398 {
  399         const char      *name;
  400         void            *cookiep;
  401         int              error;
  402 
  403         BHND_NVSTORE_LOCK_ASSERT(sc, MA_OWNED);
  404 
  405         /* Skip path registration if the data source does not support device
  406          * paths. */
  407         if (!(sc->data_caps & BHND_NVRAM_DATA_CAP_DEVPATHS)) {
  408                 BHND_NV_ASSERT(sc->root_path != NULL, ("missing root path"));
  409                 return (0);
  410         }
  411 
  412         /* Otherwise, parse and register all paths and path aliases */
  413         cookiep = NULL;
  414         while ((name = bhnd_nvram_data_next(sc->data, &cookiep))) {
  415                 bhnd_nvstore_name_info info;
  416 
  417                 /* Parse the name info */
  418                 error = bhnd_nvstore_parse_name_info(name,
  419                     BHND_NVSTORE_NAME_INTERNAL, sc->data_caps, &info);
  420                 if (error)
  421                         return (error);
  422 
  423                 /* Register the path */
  424                 error = bhnd_nvstore_var_register_path(sc, &info, cookiep);
  425                 if (error) {
  426                         BHND_NV_LOG("failed to register path for %s: %d\n",
  427                             name, error);
  428                         return (error);
  429                 }
  430         }
  431 
  432         return (0);
  433 }
  434 
  435 /**
  436  * Merge exported per-path variables (uncommitted, committed, or both) into 
  437  * the empty @p merged property list.
  438  * 
  439  * @param       sc      The NVRAM store instance.
  440  * @param       path    The NVRAM path to be exported.
  441  * @param       merged  The property list to populate with the merged results.
  442  * @param       flags   Export flags. See BHND_NVSTORE_EXPORT_*.
  443  * 
  444  * @retval 0            success
  445  * @retval ENOMEM       If allocation fails.
  446  * @retval non-zero     If merging the variables defined in @p path otherwise
  447  *                      fails, a regular unix error code will be returned.
  448  */
  449 static int
  450 bhnd_nvstore_export_merge(struct bhnd_nvram_store *sc,
  451     bhnd_nvstore_path *path, bhnd_nvram_plist *merged, uint32_t flags)
  452 {
  453         void    *cookiep, *idxp;
  454         int      error;
  455 
  456         /* Populate merged list with all pending variables */
  457         if (BHND_NVSTORE_GET_FLAG(flags, EXPORT_UNCOMMITTED)) {
  458                 bhnd_nvram_prop *prop;
  459 
  460                 prop = NULL;
  461                 while ((prop = bhnd_nvram_plist_next(path->pending, prop))) {
  462                         /* Skip variables marked for deletion */
  463                         if (!BHND_NVSTORE_GET_FLAG(flags, EXPORT_DELETED)) {
  464                                 if (bhnd_nvram_prop_is_null(prop))
  465                                         continue;
  466                         }
  467 
  468                         /* Append to merged list */
  469                         error = bhnd_nvram_plist_append(merged, prop);
  470                         if (error)
  471                                 return (error);
  472                 }
  473         }
  474 
  475         /* Skip merging committed variables? */
  476         if (!BHND_NVSTORE_GET_FLAG(flags, EXPORT_COMMITTED))
  477                 return (0);
  478 
  479         /* Merge in the committed NVRAM variables */
  480         idxp = NULL;
  481         while ((cookiep = bhnd_nvstore_path_data_next(sc, path, &idxp))) {
  482                 const char      *name;
  483                 bhnd_nvram_val  *val;
  484 
  485                 /* Fetch the variable name */
  486                 name = bhnd_nvram_data_getvar_name(sc->data, cookiep);
  487 
  488                 /* Trim device path prefix */
  489                 if (sc->data_caps & BHND_NVRAM_DATA_CAP_DEVPATHS)
  490                         name = bhnd_nvram_trim_path_name(name);
  491 
  492                 /* Skip if already defined in pending updates */
  493                 if (BHND_NVSTORE_GET_FLAG(flags, EXPORT_UNCOMMITTED)) {
  494                         if (bhnd_nvram_plist_contains(path->pending, name))
  495                                 continue;
  496                 }
  497 
  498                 /* Skip if higher precedence value was already defined. This
  499                  * may occur if the underlying data store contains duplicate
  500                  * keys; iteration will always return the definition with
  501                  * the highest precedence first */
  502                 if (bhnd_nvram_plist_contains(merged, name))
  503                         continue;
  504 
  505                 /* Fetch the variable's value representation */
  506                 if ((error = bhnd_nvram_data_copy_val(sc->data, cookiep, &val)))
  507                         return (error);
  508 
  509                 /* Add to path variable list */
  510                 error = bhnd_nvram_plist_append_val(merged, name, val);
  511                 bhnd_nvram_val_release(val);
  512                 if (error)
  513                         return (error);
  514         }
  515 
  516         return (0);
  517 }
  518 
  519 /**
  520  * Find a free alias value for @p path, and append the devpathXX alias
  521  * declaration to @p plist.
  522  * 
  523  * @param       sc              The NVRAM store instance.
  524  * @param       path            The NVRAM path for which a devpath alias
  525  *                              variable should be produced.
  526  * @param       devpath         The devpathXX path value for @p path.
  527  * @param       plist           The property list to which @p path's devpath
  528  *                              variable will be appended.
  529  * @param[out]  alias_val       On success, will be set to the alias value
  530  *                              allocated for @p path.
  531  * 
  532  * @retval 0            success
  533  * @retval ENOMEM       If allocation fails.
  534  * @retval non-zero     If merging the variables defined in @p path otherwise
  535  *                      fails, a regular unix error code will be returned.
  536  */
  537 static int
  538 bhnd_nvstore_export_devpath_alias(struct bhnd_nvram_store *sc,
  539     bhnd_nvstore_path *path, const char *devpath, bhnd_nvram_plist *plist,
  540     u_long *alias_val)
  541 {
  542         bhnd_nvstore_alias      *alias;
  543         char                    *pathvar;
  544         int                      error;
  545 
  546         *alias_val = 0;
  547 
  548         /* Prefer alias value already reserved for this path. */
  549         alias = bhnd_nvstore_find_alias(sc, path->path_str);
  550         if (alias != NULL) {
  551                 *alias_val = alias->alias;
  552 
  553                 /* Allocate devpathXX variable name */
  554                 bhnd_nv_asprintf(&pathvar, "devpath%lu", *alias_val);
  555                 if (pathvar == NULL)
  556                         return (ENOMEM);
  557 
  558                 /* Append alias variable to property list */
  559                 error = bhnd_nvram_plist_append_string(plist, pathvar, devpath);
  560 
  561                 BHND_NV_ASSERT(error != EEXIST, ("reserved alias %lu:%s in use",
  562                    * alias_val, path->path_str));
  563 
  564                 bhnd_nv_free(pathvar);
  565                 return (error);
  566         }
  567 
  568         /* Find the next free devpathXX alias entry */
  569         while (1) {
  570                 /* Skip existing reserved alias values */
  571                 while (bhnd_nvstore_get_alias(sc, *alias_val) != NULL) {
  572                         if (*alias_val == ULONG_MAX)
  573                                 return (ENOMEM);
  574 
  575                         (*alias_val)++;
  576                 }
  577 
  578                 /* Allocate devpathXX variable name */
  579                 bhnd_nv_asprintf(&pathvar, "devpath%lu", *alias_val);
  580                 if (pathvar == NULL)
  581                         return (ENOMEM);
  582 
  583                 /* If not in-use, we can terminate the search */
  584                 if (!bhnd_nvram_plist_contains(plist, pathvar))
  585                         break;
  586 
  587                 /* Keep searching */
  588                 bhnd_nv_free(pathvar);
  589 
  590                 if (*alias_val == ULONG_MAX)
  591                         return (ENOMEM);
  592 
  593                 (*alias_val)++;
  594         }
  595 
  596         /* Append alias variable to property list */
  597         error = bhnd_nvram_plist_append_string(plist, pathvar, devpath);
  598 
  599         bhnd_nv_free(pathvar);
  600         return (error);
  601 }
  602 
  603 /**
  604  * Export a single @p child path's properties, appending the result to @p plist.
  605  * 
  606  * @param       sc              The NVRAM store instance.
  607  * @param       top             The root NVRAM path being exported.
  608  * @param       child           The NVRAM path to be exported.
  609  * @param       plist           The property list to which @p child's exported
  610  *                              properties should be appended.
  611  * @param       flags           Export flags. See BHND_NVSTORE_EXPORT_*.
  612  * 
  613  * @retval 0            success
  614  * @retval ENOMEM       If allocation fails.
  615  * @retval non-zero     If merging the variables defined in @p path otherwise
  616  *                      fails, a regular unix error code will be returned.
  617  */
  618 static int
  619 bhnd_nvram_store_export_child(struct bhnd_nvram_store *sc,
  620     bhnd_nvstore_path *top, bhnd_nvstore_path *child, bhnd_nvram_plist *plist,
  621     uint32_t flags)
  622 {
  623         bhnd_nvram_plist        *path_vars;
  624         bhnd_nvram_prop         *prop;
  625         const char              *relpath;
  626         char                    *prefix, *namebuf;
  627         size_t                   prefix_len, relpath_len;
  628         size_t                   namebuf_size;
  629         bool                     emit_compact_devpath;
  630         int                      error;
  631 
  632         BHND_NVSTORE_LOCK_ASSERT(sc, MA_OWNED);
  633 
  634         prefix = NULL;
  635         path_vars = NULL;
  636         namebuf = NULL;
  637 
  638         /* Determine the path relative to the top-level path */
  639         relpath = bhnd_nvstore_parse_relpath(top->path_str, child->path_str);
  640         if (relpath == NULL) {
  641                 /* Skip -- not a child of the root path */
  642                 return (0);
  643         }
  644         relpath_len = strlen(relpath);
  645 
  646         /* Skip sub-path if export of children was not requested,  */
  647         if (!BHND_NVSTORE_GET_FLAG(flags, EXPORT_CHILDREN) && relpath_len > 0)
  648                 return (0);
  649 
  650         /* Collect all variables to be included in the export */
  651         if ((path_vars = bhnd_nvram_plist_new()) == NULL)
  652                 return (ENOMEM);
  653 
  654         if ((error = bhnd_nvstore_export_merge(sc, child, path_vars, flags))) {
  655                 bhnd_nvram_plist_release(path_vars);
  656                 return (error);
  657         }
  658 
  659         /* Skip if no children are to be exported */
  660         if (bhnd_nvram_plist_count(path_vars) == 0) {
  661                 bhnd_nvram_plist_release(path_vars);
  662                 return (0);
  663         }
  664 
  665         /* Determine appropriate device path encoding */
  666         emit_compact_devpath = false;
  667         if (BHND_NVSTORE_GET_FLAG(flags, EXPORT_COMPACT_DEVPATHS)) {
  668                 /* Re-encode as compact (if non-empty path) */
  669                 if (relpath_len > 0)
  670                         emit_compact_devpath = true;
  671         } else if (BHND_NVSTORE_GET_FLAG(flags, EXPORT_EXPAND_DEVPATHS)) {
  672                 /* Re-encode with fully expanded device path */
  673                 emit_compact_devpath = false;
  674         } else if (BHND_NVSTORE_GET_FLAG(flags, EXPORT_PRESERVE_DEVPATHS)) {
  675                 /* Preserve existing encoding of this path */
  676                 if (bhnd_nvstore_find_alias(sc, child->path_str) != NULL)
  677                         emit_compact_devpath = true;
  678         } else {
  679                 BHND_NV_LOG("invalid device path flag: %#" PRIx32, flags);
  680                 error = EINVAL;
  681                 goto finished;
  682         }
  683 
  684         /* Allocate variable device path prefix to use for all property names,
  685          * and if using compact encoding, emit the devpathXX= variable */
  686         prefix = NULL;
  687         prefix_len = 0;
  688         if (emit_compact_devpath) {
  689                 u_long  alias_val;
  690                 int     len;
  691 
  692                 /* Reserve an alias value and append the devpathXX= variable to
  693                  * the property list */
  694                 error = bhnd_nvstore_export_devpath_alias(sc, child, relpath,
  695                     plist, &alias_val);
  696                 if (error)
  697                         goto finished;
  698 
  699                 /* Allocate variable name prefix */
  700                 len = bhnd_nv_asprintf(&prefix, "%lu:", alias_val);
  701                 if (prefix == NULL) {
  702                         error = ENOMEM;
  703                         goto finished;
  704                 }
  705 
  706                 prefix_len = len;
  707         } else if (relpath_len > 0) {
  708                 int len;
  709 
  710                 /* Allocate the variable name prefix, appending '/' to the
  711                  * relative path */
  712                 len = bhnd_nv_asprintf(&prefix, "%s/", relpath);
  713                 if (prefix == NULL) {
  714                         error = ENOMEM;
  715                         goto finished;
  716                 }
  717 
  718                 prefix_len = len;
  719         }
  720 
  721         /* If prefixing of variable names is required, allocate a name
  722          * formatting buffer */
  723         namebuf_size = 0;
  724         if (prefix != NULL) {
  725                 size_t  maxlen;
  726 
  727                 /* Find the maximum name length */
  728                 maxlen = 0;
  729                 prop = NULL;
  730                 while ((prop = bhnd_nvram_plist_next(path_vars, prop))) {
  731                         const char *name;
  732 
  733                         name = bhnd_nvram_prop_name(prop);
  734                         maxlen = bhnd_nv_ummax(strlen(name), maxlen);
  735                 }
  736 
  737                 /* Allocate name buffer (path-prefix + name + '\0') */
  738                 namebuf_size = prefix_len + maxlen + 1;
  739                 namebuf = bhnd_nv_malloc(namebuf_size);
  740                 if (namebuf == NULL) {
  741                         error = ENOMEM;
  742                         goto finished;
  743                 }
  744         }
  745 
  746         /* Append all path variables to the export plist, prepending the
  747          * device-path prefix to the variable names, if required */
  748         prop = NULL;
  749         while ((prop = bhnd_nvram_plist_next(path_vars, prop)) != NULL) {
  750                 const char *name;
  751 
  752                 /* Prepend device prefix to the variable name */
  753                 name = bhnd_nvram_prop_name(prop);
  754                 if (prefix != NULL) {
  755                         int len;
  756 
  757                         /*
  758                          * Write prefixed variable name to our name buffer.
  759                          * 
  760                          * We precalcuate the size when scanning all names 
  761                          * above, so this should always succeed.
  762                          */
  763                         len = snprintf(namebuf, namebuf_size, "%s%s", prefix,
  764                             name);
  765                         if (len < 0 || (size_t)len >= namebuf_size)
  766                                 BHND_NV_PANIC("invalid max_name_len");
  767 
  768                         name = namebuf;
  769                 }
  770 
  771                 /* Add property to export plist */
  772                 error = bhnd_nvram_plist_append_val(plist, name,
  773                     bhnd_nvram_prop_val(prop));
  774                 if (error)
  775                         goto finished;
  776         }
  777 
  778         /* Success */
  779         error = 0;
  780 
  781 finished:
  782         if (prefix != NULL)
  783                 bhnd_nv_free(prefix);
  784 
  785         if (namebuf != NULL)
  786                 bhnd_nv_free(namebuf);
  787 
  788         if (path_vars != NULL)
  789                 bhnd_nvram_plist_release(path_vars);
  790 
  791         return (error);
  792 }
  793 
  794 /**
  795  * Export a flat, ordered NVRAM property list representation of all NVRAM
  796  * properties at @p path.
  797  * 
  798  * @param       sc      The NVRAM store instance.
  799  * @param       path    The NVRAM path to export, or NULL to select the root
  800  *                      path.
  801  * @param[out]  cls     On success, will be set to the backing data class
  802  *                      of @p sc. If the data class is are not desired,
  803  *                      a NULL pointer may be provided.
  804  * @param[out]  props   On success, will be set to a caller-owned property
  805  *                      list containing the exported properties. The caller is
  806  *                      responsible for releasing this value via
  807  *                      bhnd_nvram_plist_release().
  808  * @param[out]  options On success, will be set to a caller-owned property
  809  *                      list containing the current NVRAM serialization options
  810  *                      for @p sc. The caller is responsible for releasing this
  811  *                      value via bhnd_nvram_plist_release().
  812  * @param       flags   Export flags. See BHND_NVSTORE_EXPORT_*.
  813  * 
  814  * @retval 0            success
  815  * @retval EINVAL       If @p flags is invalid.
  816  * @retval ENOENT       The requested path was not found.
  817  * @retval ENOMEM       If allocation fails.
  818  * @retval non-zero     If export of  @p path otherwise fails, a regular unix
  819  *                      error code will be returned.
  820  */
  821 int
  822 bhnd_nvram_store_export(struct bhnd_nvram_store *sc, const char *path,
  823     bhnd_nvram_data_class **cls, bhnd_nvram_plist **props,
  824     bhnd_nvram_plist **options, uint32_t flags)
  825 {
  826         bhnd_nvram_plist        *unordered;
  827         bhnd_nvstore_path       *top;
  828         bhnd_nvram_prop         *prop;
  829         const char              *name;
  830         void                    *cookiep;
  831         size_t                   num_dpath_flags;
  832         int                      error;
  833 
  834         *props = NULL;
  835         unordered = NULL;
  836         num_dpath_flags = 0;
  837         if (options != NULL)
  838                 *options = NULL;
  839 
  840         /* Default to exporting root path */
  841         if (path == NULL)
  842                 path = BHND_NVSTORE_ROOT_PATH;
  843 
  844         /* Default to exporting all properties */
  845         if (!BHND_NVSTORE_GET_FLAG(flags, EXPORT_COMMITTED) &&
  846             !BHND_NVSTORE_GET_FLAG(flags, EXPORT_UNCOMMITTED))
  847         {
  848                 flags |= BHND_NVSTORE_EXPORT_ALL_VARS;
  849         }
  850 
  851         /* Default to preserving the current device path encoding */
  852         if (!BHND_NVSTORE_GET_FLAG(flags, EXPORT_COMPACT_DEVPATHS) &&
  853             !BHND_NVSTORE_GET_FLAG(flags, EXPORT_EXPAND_DEVPATHS))
  854         {
  855                 flags |= BHND_NVSTORE_EXPORT_PRESERVE_DEVPATHS;
  856         }
  857 
  858         /* Exactly one device path encoding flag must be set */
  859         if (BHND_NVSTORE_GET_FLAG(flags, EXPORT_COMPACT_DEVPATHS))
  860                 num_dpath_flags++;
  861 
  862         if (BHND_NVSTORE_GET_FLAG(flags, EXPORT_EXPAND_DEVPATHS))
  863                 num_dpath_flags++;
  864 
  865         if (BHND_NVSTORE_GET_FLAG(flags, EXPORT_PRESERVE_DEVPATHS))
  866                 num_dpath_flags++;
  867 
  868         if (num_dpath_flags != 1)
  869                 return (EINVAL);
  870 
  871         /* If EXPORT_DELETED is set, EXPORT_UNCOMMITTED must be set too */
  872         if (BHND_NVSTORE_GET_FLAG(flags, EXPORT_DELETED) &&
  873             !BHND_NVSTORE_GET_FLAG(flags, EXPORT_DELETED))
  874         {
  875                 return (EINVAL);
  876         }
  877 
  878         /* Lock internal state before querying paths/properties */
  879         BHND_NVSTORE_LOCK(sc);
  880 
  881         /* Fetch referenced path */
  882         top = bhnd_nvstore_get_path(sc, path, strlen(path));
  883         if (top == NULL) {
  884                 error = ENOENT;
  885                 goto failed;
  886         }
  887 
  888         /* Allocate new, empty property list */
  889         if ((unordered = bhnd_nvram_plist_new()) == NULL) {
  890                 error = ENOMEM;
  891                 goto failed;
  892         }
  893 
  894         /* Export the top-level path first */
  895         error = bhnd_nvram_store_export_child(sc, top, top, unordered, flags);
  896         if (error)
  897                 goto failed;
  898 
  899         /* Attempt to export any children of the root path */
  900         for (size_t i = 0; i < nitems(sc->paths); i++) {
  901                 bhnd_nvstore_path *child;
  902 
  903                 LIST_FOREACH(child, &sc->paths[i], np_link) {
  904                         /* Top-level path was already exported */
  905                         if (child == top)
  906                                 continue;
  907 
  908                         error = bhnd_nvram_store_export_child(sc, top,
  909                             child, unordered, flags);
  910                         if (error)
  911                                 goto failed;
  912                 }
  913         }
  914 
  915         /* If requested, provide the current class and serialization options */
  916         if (cls != NULL)
  917                 *cls = bhnd_nvram_data_get_class(sc->data);
  918 
  919         if (options != NULL)
  920                 *options = bhnd_nvram_plist_retain(sc->data_opts);
  921 
  922         /*
  923          * If we're re-encoding device paths, don't bother preserving the
  924          * existing NVRAM variable order; our variable names will not match
  925          * the existing backing NVRAM data.
  926          */
  927         if (!BHND_NVSTORE_GET_FLAG(flags, EXPORT_PRESERVE_DEVPATHS)) {
  928                 *props = unordered;
  929                 unordered = NULL;
  930 
  931                 goto finished;
  932         }
  933 
  934         /* 
  935          * Re-order the flattened output to match the existing NVRAM variable
  936          * ordering.
  937          * 
  938          * We append all new variables at the end of the input; this should
  939          * reduce the delta that needs to be written (e.g. to flash) when
  940          * committing NVRAM updates, and should result in a serialization
  941          * identical to the input serialization if uncommitted updates are
  942          * excluded from the export.
  943          */
  944         if ((*props = bhnd_nvram_plist_new()) == NULL) {
  945                 error = ENOMEM;
  946                 goto failed;
  947         }
  948 
  949         /* Using the backing NVRAM data ordering to order all variables
  950          * currently defined in the backing store */ 
  951         cookiep = NULL;
  952         while ((name = bhnd_nvram_data_next(sc->data, &cookiep))) {
  953                 prop = bhnd_nvram_plist_get_prop(unordered, name);
  954                 if (prop == NULL)
  955                         continue;
  956 
  957                 /* Append to ordered result */
  958                 if ((error = bhnd_nvram_plist_append(*props, prop)))
  959                         goto failed;
  960 
  961                 /* Remove from unordered list */
  962                 bhnd_nvram_plist_remove(unordered, name);
  963         }
  964 
  965         /* Any remaining variables are new, and should be appended to the
  966          * end of the export list */
  967         prop = NULL;
  968         while ((prop = bhnd_nvram_plist_next(unordered, prop)) != NULL) {
  969                 if ((error = bhnd_nvram_plist_append(*props, prop)))
  970                         goto failed;
  971         }
  972 
  973         /* Export complete */
  974 finished:
  975         BHND_NVSTORE_UNLOCK(sc);
  976 
  977         if (unordered != NULL)
  978                 bhnd_nvram_plist_release(unordered);
  979 
  980         return (0);
  981 
  982 failed:
  983         BHND_NVSTORE_UNLOCK(sc);
  984 
  985         if (unordered != NULL)
  986                 bhnd_nvram_plist_release(unordered);
  987 
  988         if (options != NULL && *options != NULL)
  989                 bhnd_nvram_plist_release(*options);
  990 
  991         if (*props != NULL)
  992                 bhnd_nvram_plist_release(*props);
  993 
  994         return (error);
  995 }
  996 
  997 /**
  998  * Encode all NVRAM properties at @p path, using the @p store's current NVRAM
  999  * data format.
 1000  * 
 1001  * @param       sc      The NVRAM store instance.
 1002  * @param       path    The NVRAM path to export, or NULL to select the root
 1003  *                      path.
 1004  * @param[out]  data    On success, will be set to the newly serialized value.
 1005  *                      The caller is responsible for freeing this value
 1006  *                      via bhnd_nvram_io_free().
 1007  * @param       flags   Export flags. See BHND_NVSTORE_EXPORT_*.
 1008  *
 1009  * @retval 0            success
 1010  * @retval EINVAL       If @p flags is invalid.
 1011  * @retval ENOENT       The requested path was not found.
 1012  * @retval ENOMEM       If allocation fails.
 1013  * @retval non-zero     If serialization of  @p path otherwise fails, a regular
 1014  *                      unix error code will be returned.
 1015  */
 1016 int
 1017 bhnd_nvram_store_serialize(struct bhnd_nvram_store *sc, const char *path,
 1018    struct bhnd_nvram_io **data,  uint32_t flags)
 1019 {
 1020         bhnd_nvram_plist        *props;
 1021         bhnd_nvram_plist        *options;
 1022         bhnd_nvram_data_class   *cls;
 1023         struct bhnd_nvram_io    *io;
 1024         void                    *outp;
 1025         size_t                   olen;
 1026         int                      error;
 1027 
 1028         props = NULL;
 1029         options = NULL;
 1030         io = NULL;
 1031 
 1032         /* Perform requested export */
 1033         error = bhnd_nvram_store_export(sc, path, &cls, &props, &options,
 1034             flags);
 1035         if (error)
 1036                 return (error);
 1037 
 1038         /* Determine serialized size */
 1039         error = bhnd_nvram_data_serialize(cls, props, options, NULL, &olen);
 1040         if (error)
 1041                 goto failed;
 1042 
 1043         /* Allocate output buffer */
 1044         if ((io = bhnd_nvram_iobuf_empty(olen, olen)) == NULL) {
 1045                 error = ENOMEM;
 1046                 goto failed;
 1047         }
 1048 
 1049         /* Fetch write pointer */
 1050         if ((error = bhnd_nvram_io_write_ptr(io, 0, &outp, olen, NULL)))
 1051                 goto failed;
 1052 
 1053         /* Perform serialization */
 1054         error = bhnd_nvram_data_serialize(cls, props, options, outp, &olen);
 1055         if (error)
 1056                 goto failed;
 1057 
 1058         if ((error = bhnd_nvram_io_setsize(io, olen)))
 1059                 goto failed;
 1060 
 1061         /* Success */
 1062         bhnd_nvram_plist_release(props);
 1063         bhnd_nvram_plist_release(options);
 1064 
 1065         *data = io;
 1066         return (0);
 1067 
 1068 failed:
 1069         if (props != NULL)
 1070                 bhnd_nvram_plist_release(props);
 1071 
 1072         if (options != NULL)
 1073                 bhnd_nvram_plist_release(options);
 1074 
 1075         if (io != NULL)
 1076                 bhnd_nvram_io_free(io);
 1077 
 1078         return (error);
 1079 }
 1080 
 1081 /**
 1082  * Read an NVRAM variable.
 1083  *
 1084  * @param               sc      The NVRAM parser state.
 1085  * @param               name    The NVRAM variable name.
 1086  * @param[out]          outp    On success, the requested value will be written
 1087  *                              to this buffer. This argment may be NULL if
 1088  *                              the value is not desired.
 1089  * @param[in,out]       olen    The capacity of @p outp. On success, will be set
 1090  *                              to the actual size of the requested value.
 1091  * @param               otype   The requested data type to be written to
 1092  *                              @p outp.
 1093  *
 1094  * @retval 0            success
 1095  * @retval ENOENT       The requested variable was not found.
 1096  * @retval ENOMEM       If @p outp is non-NULL and a buffer of @p olen is too
 1097  *                      small to hold the requested value.
 1098  * @retval non-zero     If reading @p name otherwise fails, a regular unix
 1099  *                      error code will be returned.
 1100   */
 1101 int
 1102 bhnd_nvram_store_getvar(struct bhnd_nvram_store *sc, const char *name,
 1103     void *outp, size_t *olen, bhnd_nvram_type otype)
 1104 {
 1105         bhnd_nvstore_name_info   info;
 1106         bhnd_nvstore_path       *path;
 1107         bhnd_nvram_prop         *prop;
 1108         void                    *cookiep;
 1109         int                      error;
 1110 
 1111         BHND_NVSTORE_LOCK(sc);
 1112 
 1113         /* Parse the variable name */
 1114         error = bhnd_nvstore_parse_name_info(name, BHND_NVSTORE_NAME_EXTERNAL,
 1115             sc->data_caps, &info);
 1116         if (error)
 1117                 goto finished;
 1118 
 1119         /* Fetch the variable's enclosing path entry */
 1120         if ((path = bhnd_nvstore_var_get_path(sc, &info)) == NULL) {
 1121                 error = ENOENT;
 1122                 goto finished;
 1123         }
 1124 
 1125         /* Search uncommitted updates first */
 1126         prop = bhnd_nvstore_path_get_update(sc, path, info.name);
 1127         if (prop != NULL) {
 1128                 if (bhnd_nvram_prop_is_null(prop)) {
 1129                         /* NULL denotes a pending deletion */
 1130                         error = ENOENT;
 1131                 } else {
 1132                         error = bhnd_nvram_prop_encode(prop, outp, olen, otype);
 1133                 }
 1134                 goto finished;
 1135         }
 1136 
 1137         /* Search the backing NVRAM data */
 1138         cookiep = bhnd_nvstore_path_data_lookup(sc, path, info.name);
 1139         if (cookiep != NULL) {
 1140                 /* Found in backing store */
 1141                 error = bhnd_nvram_data_getvar(sc->data, cookiep, outp, olen,
 1142                      otype);
 1143                 goto finished;
 1144         }
 1145 
 1146         /* Not found */
 1147         error = ENOENT;
 1148 
 1149 finished:
 1150         BHND_NVSTORE_UNLOCK(sc);
 1151         return (error);
 1152 }
 1153 
 1154 /**
 1155  * Common bhnd_nvram_store_set*() and bhnd_nvram_store_unsetvar()
 1156  * implementation.
 1157  * 
 1158  * If @p value is NULL, the variable will be marked for deletion.
 1159  */
 1160 static int
 1161 bhnd_nvram_store_setval_common(struct bhnd_nvram_store *sc, const char *name,
 1162     bhnd_nvram_val *value)
 1163 {
 1164         bhnd_nvstore_path       *path;
 1165         bhnd_nvstore_name_info   info;
 1166         int                      error;
 1167 
 1168         BHND_NVSTORE_LOCK_ASSERT(sc, MA_OWNED);
 1169 
 1170         /* Parse the variable name */
 1171         error = bhnd_nvstore_parse_name_info(name, BHND_NVSTORE_NAME_EXTERNAL,
 1172             sc->data_caps, &info);
 1173         if (error)
 1174                 return (error);
 1175 
 1176         /* Fetch the variable's enclosing path entry */
 1177         if ((path = bhnd_nvstore_var_get_path(sc, &info)) == NULL)
 1178                 return (error);
 1179 
 1180         /* Register the update entry */
 1181         return (bhnd_nvstore_path_register_update(sc, path, info.name, value));
 1182 }
 1183 
 1184 /**
 1185  * Set an NVRAM variable.
 1186  * 
 1187  * @param       sc      The NVRAM parser state.
 1188  * @param       name    The NVRAM variable name.
 1189  * @param       value   The new value.
 1190  *
 1191  * @retval 0            success
 1192  * @retval ENOENT       The requested variable @p name was not found.
 1193  * @retval EINVAL       If @p value is invalid.
 1194  */
 1195 int
 1196 bhnd_nvram_store_setval(struct bhnd_nvram_store *sc, const char *name,
 1197     bhnd_nvram_val *value)
 1198 {
 1199         int error;
 1200 
 1201         BHND_NVSTORE_LOCK(sc);
 1202         error = bhnd_nvram_store_setval_common(sc, name, value);
 1203         BHND_NVSTORE_UNLOCK(sc);
 1204 
 1205         return (error);
 1206 }
 1207 
 1208 /**
 1209  * Set an NVRAM variable.
 1210  * 
 1211  * @param               sc      The NVRAM parser state.
 1212  * @param               name    The NVRAM variable name.
 1213  * @param[out]          inp     The new value.
 1214  * @param[in,out]       ilen    The size of @p inp.
 1215  * @param               itype   The data type of @p inp.
 1216  *
 1217  * @retval 0            success
 1218  * @retval ENOENT       The requested variable @p name was not found.
 1219  * @retval EINVAL       If the new value is invalid.
 1220  * @retval EINVAL       If @p name is read-only.
 1221  */
 1222 int
 1223 bhnd_nvram_store_setvar(struct bhnd_nvram_store *sc, const char *name,
 1224     const void *inp, size_t ilen, bhnd_nvram_type itype)
 1225 {
 1226         bhnd_nvram_val  val;
 1227         int             error;
 1228 
 1229         error = bhnd_nvram_val_init(&val, NULL, inp, ilen, itype,
 1230             BHND_NVRAM_VAL_FIXED|BHND_NVRAM_VAL_BORROW_DATA);
 1231         if (error) {
 1232                 BHND_NV_LOG("error initializing value: %d\n", error);
 1233                 return (EINVAL);
 1234         }
 1235 
 1236         BHND_NVSTORE_LOCK(sc);
 1237         error = bhnd_nvram_store_setval_common(sc, name, &val);
 1238         BHND_NVSTORE_UNLOCK(sc);
 1239 
 1240         bhnd_nvram_val_release(&val);
 1241 
 1242         return (error);
 1243 }
 1244 
 1245 /**
 1246  * Unset an NVRAM variable.
 1247  * 
 1248  * @param               sc      The NVRAM parser state.
 1249  * @param               name    The NVRAM variable name.
 1250  *
 1251  * @retval 0            success
 1252  * @retval ENOENT       The requested variable @p name was not found.
 1253  * @retval EINVAL       If @p name is read-only.
 1254  */
 1255 int
 1256 bhnd_nvram_store_unsetvar(struct bhnd_nvram_store *sc, const char *name)
 1257 {
 1258         int error;
 1259 
 1260         BHND_NVSTORE_LOCK(sc);
 1261         error = bhnd_nvram_store_setval_common(sc, name, BHND_NVRAM_VAL_NULL);
 1262         BHND_NVSTORE_UNLOCK(sc);
 1263 
 1264         return (error);
 1265 }

Cache object: 7a546221aac801dc220950a65b031e68


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