Author: landonf
Date: Sat Nov 26 23:22:32 2016
New Revision: 309202
URL: https://svnweb.freebsd.org/changeset/base/309202

Log:
  bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding.
  
  
  - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM
    parsing from the actual underlying NVRAM data provider (e.g. CFE firmware
    devices).
  - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling
    higher-level NVRAM operations (indexed lookup, data conversion, etc) from
    the underlying NVRAM file format parsing/serialization.
  - Implemented a new high-level bhnd_nvram_store API, providing indexed
    variable lookup, pending write tracking, etc on top of an arbitrary
    bhnd_nvram_data instance.
  - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store
    API.
  - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM
    variable values, including applying format-specific behavior when
    converting to/from the NVRAM string representations.
  - Dropped the now unnecessary bhnd_nvram driver, and moved the
    broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom.
  - Implemented a new nvram_map file format:
          - Variable definitions are now defined separately from the SPROM
            layout. This will also allow us to define CIS tuple NVRAM
            mappings referencing the common NVRAM variable definitions.
          - Variables can now be defined within arbitrary named groups.
          - Textual descriptions and help information can be defined inline
            for both variables and variable groups.
          - Implemented a new, compact encoding of SPROM image layout
            offsets.
  - Source-level (but not build system) support for building the NVRAM file
    format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a
    userspace library.
  
  The new compact SPROM image layout encoding is loosely modeled on Apple
  dyld compressed LINKEDIT symbol binding opcodes; it provides a compact
  state-machine encoding of the mapping between NVRAM variables and the SPROM
  image offset, mask, and shift instructions necessary to decode or encode
  the SPROM variable data.
  
  The compact encoding reduces the size of the generated SPROM layout data
  from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables
  also simplify iteration of the SPROM variables, as it's no longer
  neccessary to iterate the full NVRAM variable definition table, but
  instead simply scan the SPROM revision's layout opcode table.
  
  Approved by:    adrian (mentor)
  Differential Revision:  https://reviews.freebsd.org/D8645

Added:
  head/sys/dev/bhnd/nvram/bhnd_nvram_data.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_data.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmraw.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmreg.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmvar.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_data_btxt.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_data_spromvar.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_data_tlv.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_data_tlvreg.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_datavar.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_io.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_io.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_iobuf.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_iores.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_iovar.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_private.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_store.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_store.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_storevar.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_value.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_value.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_value_fmts.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_value_prf.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_valuevar.h   (contents, props changed)
  head/sys/mips/broadcom/bcm_nvram_cfe.c   (contents, props changed)
  head/sys/mips/broadcom/bcm_nvram_cfevar.h   (contents, props changed)
Deleted:
  head/sys/dev/bhnd/nvram/bhnd_nvram.c
  head/sys/dev/bhnd/nvram/bhnd_nvram_cfe.c
  head/sys/dev/bhnd/nvram/bhnd_nvram_common.c
  head/sys/dev/bhnd/nvram/bhnd_nvram_common.h
  head/sys/dev/bhnd/nvram/bhnd_nvram_parser.c
  head/sys/dev/bhnd/nvram/bhnd_nvram_parser.h
  head/sys/dev/bhnd/nvram/bhnd_nvram_parserreg.h
  head/sys/dev/bhnd/nvram/bhnd_nvram_parservar.h
  head/sys/dev/bhnd/nvram/bhnd_nvramvar.h
  head/sys/dev/bhnd/nvram/bhnd_sprom_parser.c
  head/sys/dev/bhnd/nvram/bhnd_sprom_parser.h
  head/sys/dev/bhnd/nvram/bhnd_sprom_parservar.h
Modified:
  head/sys/conf/files
  head/sys/dev/bhnd/bhnd_subr.c
  head/sys/dev/bhnd/nvram/bhnd_nvram.h
  head/sys/dev/bhnd/nvram/bhnd_sprom.c
  head/sys/dev/bhnd/nvram/bhnd_spromvar.h
  head/sys/dev/bhnd/nvram/nvram_map
  head/sys/dev/bhnd/tools/nvram_map_gen.awk
  head/sys/dev/bwn/bwn_mac.c
  head/sys/mips/broadcom/files.broadcom
  head/sys/modules/bhnd/Makefile

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files Sat Nov 26 23:15:11 2016        (r309201)
+++ head/sys/conf/files Sat Nov 26 23:22:32 2016        (r309202)
@@ -1220,14 +1220,22 @@ dev/bhnd/cores/pmu/bhnd_pmu.c           optional 
 dev/bhnd/cores/pmu/bhnd_pmu_core.c     optional bhnd
 dev/bhnd/cores/pmu/bhnd_pmu_if.m       optional bhnd
 dev/bhnd/cores/pmu/bhnd_pmu_subr.c     optional bhnd
-dev/bhnd/nvram/bhnd_nvram.c            optional bhnd
-dev/bhnd/nvram/bhnd_nvram_common.c     optional bhnd
-dev/bhnd/nvram/bhnd_nvram_cfe.c                optional bhnd siba_nexus cfe | \
-                                                bhnd bcma_nexus cfe
+dev/bhnd/nvram/bhnd_nvram_data.c       optional bhnd
+dev/bhnd/nvram/bhnd_nvram_data_bcm.c   optional bhnd
+dev/bhnd/nvram/bhnd_nvram_data_bcmraw.c        optional bhnd
+dev/bhnd/nvram/bhnd_nvram_data_btxt.c  optional bhnd
+dev/bhnd/nvram/bhnd_nvram_data_sprom.c optional bhnd
+dev/bhnd/nvram/bhnd_nvram_data_tlv.c   optional bhnd
 dev/bhnd/nvram/bhnd_nvram_if.m         optional bhnd
-dev/bhnd/nvram/bhnd_nvram_parser.c     optional bhnd
+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_store.c      optional bhnd
+dev/bhnd/nvram/bhnd_nvram_subr.c       optional bhnd
+dev/bhnd/nvram/bhnd_nvram_value.c      optional bhnd
+dev/bhnd/nvram/bhnd_nvram_value_fmts.c optional bhnd
+dev/bhnd/nvram/bhnd_nvram_value_prf.c  optional bhnd
 dev/bhnd/nvram/bhnd_sprom.c            optional bhnd
-dev/bhnd/nvram/bhnd_sprom_parser.c     optional bhnd
 dev/bhnd/siba/siba.c                   optional siba bhnd
 dev/bhnd/siba/siba_bhndb.c             optional siba bhnd bhndb
 dev/bhnd/siba/siba_erom.c              optional siba bhnd

Modified: head/sys/dev/bhnd/bhnd_subr.c
==============================================================================
--- head/sys/dev/bhnd/bhnd_subr.c       Sat Nov 26 23:15:11 2016        
(r309201)
+++ head/sys/dev/bhnd/bhnd_subr.c       Sat Nov 26 23:22:32 2016        
(r309202)
@@ -1057,7 +1057,8 @@ bhnd_nvram_getvar_str(device_t dev, cons
        int     error;
 
        larg = len;
-       error = bhnd_nvram_getvar(dev, name, buf, &larg, BHND_NVRAM_TYPE_CSTR);
+       error = bhnd_nvram_getvar(dev, name, buf, &larg,
+           BHND_NVRAM_TYPE_STRING);
        if (rlen != NULL)
                *rlen = larg;
 

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram.h
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram.h        Sat Nov 26 23:15:11 2016        
(r309201)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram.h        Sat Nov 26 23:22:32 2016        
(r309202)
@@ -32,11 +32,17 @@
 #ifndef _BHND_NVRAM_BHND_NVRAM_H_
 #define _BHND_NVRAM_BHND_NVRAM_H_
 
+#ifdef _KERNEL
+#include <sys/types.h>
+#else /* !_KERNEL */
+#include <stdbool.h>
+#include <stdint.h>
+#endif /* _KERNEL */
+
 /**
  * NVRAM data sources supported by bhnd(4) devices.
  */
 typedef enum {
-       
        BHND_NVRAM_SRC_OTP,     /**< On-chip one-time-programmable
                                  *  memory. */
 
@@ -67,50 +73,52 @@ typedef enum {
                                  */
 } bhnd_nvram_src;
 
-/** Supported NVRAM formats. */
-typedef enum {
-       BHND_NVRAM_FMT_BCM      = 0,    /**< Broadcom NUL-delimited key=value 
pairs */
-       BHND_NVRAM_FMT_TLV      = 1,    /**< CFE TLV encoding, as used on 
WGT634U */
-       BHND_NVRAM_FMT_BTXT     = 2,    /**< Broadcom board text file. This is 
used
-                                            to provide external NVRAM data for 
some
-                                            fullmac WiFi devices. */
-       BHND_NVRAM_FMT_SPROM    = 3,    /**< SPROM/OTP-specific encoding used by
-                                            Broadcom network adapters */
-       BHND_NVRAM_FMT_CIS      = 4,    /**< A mostly CIS-compatible encoding 
used
-                                            on some Broadcom network adapters 
*/ 
-       BHND_NVRAM_FMT_UNKNOWN  = 5     /**< Unknown or unrecognized format */
-} bhnd_nvram_format;
-
-
-/** bhnd_nvram_type bit flags */
-enum {
-       BHND_NVRAM_TF_SIGNED    = (1<<7),
-};
-
-#define        BHND_NVRAM_TYPE_ID_MASK         0xF
-#define        BHND_NVRAM_TYPE_FLAGS_MASK      0x70
-
-#define        BHND_NVRAM_TYPE_ID(_id, _flags)         \
-       (((_id) & BHND_NVRAM_TYPE_ID_MASK) |    \
-           ((_flags) & BHND_NVRAM_TYPE_FLAGS_MASK))
-
-/** Supported NVRAM data types */
+/**
+ * NVRAM data types.
+ * 
+ * @internal
+ * 
+ * All primitive (non-array) constants should be representable as a 4-bit
+ * integer (e.g. 0-15) to support SPROM_OPCODE_TYPE_IMM encoding as used by
+ * nvram_map_gen.awk.
+ */
 typedef enum {
-       BHND_NVRAM_TYPE_UINT8   = BHND_NVRAM_TYPE_ID(0, 0),                     
/**< unsigned 8-bit integer */
-       BHND_NVRAM_TYPE_UINT16  = BHND_NVRAM_TYPE_ID(1, 0),                     
/**< unsigned 16-bit integer */
-       BHND_NVRAM_TYPE_UINT32  = BHND_NVRAM_TYPE_ID(2, 0),                     
/**< unsigned 32-bit integer */
-       BHND_NVRAM_TYPE_INT8    = BHND_NVRAM_TYPE_ID(4, BHND_NVRAM_TF_SIGNED),  
/**< signed 8-bit integer */
-       BHND_NVRAM_TYPE_INT16   = BHND_NVRAM_TYPE_ID(5, BHND_NVRAM_TF_SIGNED),  
/**< signed 16-bit integer */
-       BHND_NVRAM_TYPE_INT32   = BHND_NVRAM_TYPE_ID(6, BHND_NVRAM_TF_SIGNED),  
/**< signed 32-bit integer */
-       BHND_NVRAM_TYPE_CHAR    = BHND_NVRAM_TYPE_ID(7, BHND_NVRAM_TF_SIGNED),  
/**< ASCII character */
-       BHND_NVRAM_TYPE_CSTR    = BHND_NVRAM_TYPE_ID(8, 0),                     
/**< NUL-terminated C string */
+       BHND_NVRAM_TYPE_UINT8           = 0,    /**< unsigned 8-bit integer */
+       BHND_NVRAM_TYPE_UINT16          = 1,    /**< unsigned 16-bit integer */
+       BHND_NVRAM_TYPE_UINT32          = 2,    /**< unsigned 32-bit integer */
+       BHND_NVRAM_TYPE_UINT64          = 3,    /**< signed 64-bit integer */
+       BHND_NVRAM_TYPE_INT8            = 4,    /**< signed 8-bit integer */
+       BHND_NVRAM_TYPE_INT16           = 5,    /**< signed 16-bit integer */
+       BHND_NVRAM_TYPE_INT32           = 6,    /**< signed 32-bit integer */
+       BHND_NVRAM_TYPE_INT64           = 7,    /**< signed 64-bit integer */
+       BHND_NVRAM_TYPE_CHAR            = 8,    /**< ASCII/UTF-8 character */
+       BHND_NVRAM_TYPE_STRING          = 9,    /**< ASCII/UTF-8 NUL-terminated
+                                                    string */
+
+       /* 10-15 reserved for primitive (non-array) types */
+
+       BHND_NVRAM_TYPE_UINT8_ARRAY     = 16,   /**< array of uint8 integers */
+       BHND_NVRAM_TYPE_UINT16_ARRAY    = 17,   /**< array of uint16 integers */
+       BHND_NVRAM_TYPE_UINT32_ARRAY    = 18,   /**< array of uint32 integers */
+       BHND_NVRAM_TYPE_UINT64_ARRAY    = 19,   /**< array of uint64 integers */
+       BHND_NVRAM_TYPE_INT8_ARRAY      = 20,   /**< array of int8 integers */
+       BHND_NVRAM_TYPE_INT16_ARRAY     = 21,   /**< array of int16 integers */
+       BHND_NVRAM_TYPE_INT32_ARRAY     = 22,   /**< array of int32 integers */
+       BHND_NVRAM_TYPE_INT64_ARRAY     = 23,   /**< array of int64 integers */
+       BHND_NVRAM_TYPE_CHAR_ARRAY      = 24,   /**< array of ASCII/UTF-8
+                                                    characters */
+       BHND_NVRAM_TYPE_STRING_ARRAY    = 25,   /**< array of ASCII/UTF-8
+                                                    NUL-terminated strings */
 } bhnd_nvram_type;
 
-#undef BHND_NVRAM_TYPE_ID_MASK
-#undef BHND_NVRAM_TYPE_FLAGS_MASK
-#undef BHND_NVRAM_TYPE_ID
+const char     *bhnd_nvram_string_array_next(const char *inp, size_t ilen,
+                    const char *prev); 
 
-#define        BHND_NVRAM_SIGNED_TYPE(_type)   \
-       (((_type) & BHND_NVRAM_TF_SIGNED) == BHND_NVRAM_TF_SIGNED)
+bool            bhnd_nvram_is_signed_type(bhnd_nvram_type type);
+bool            bhnd_nvram_is_unsigned_type(bhnd_nvram_type type);
+bool            bhnd_nvram_is_int_type(bhnd_nvram_type type);
+bool            bhnd_nvram_is_array_type(bhnd_nvram_type type);
+bhnd_nvram_type         bhnd_nvram_base_type(bhnd_nvram_type type);
+const char     *bhnd_nvram_type_name(bhnd_nvram_type type);
 
 #endif /* _BHND_NVRAM_BHND_NVRAM_H_ */

Added: head/sys/dev/bhnd/nvram/bhnd_nvram_data.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data.c   Sat Nov 26 23:22:32 2016        
(r309202)
@@ -0,0 +1,527 @@
+/*-
+ * 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$");
+
+
+#ifdef _KERNEL
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/_inttypes.h>
+
+#else /* !_KERNEL */
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#endif /* _KERNEL */
+
+#include "bhnd_nvram_private.h"
+#include "bhnd_nvram_io.h"
+
+#include "bhnd_nvram_datavar.h"
+#include "bhnd_nvram_data.h"
+
+/**
+ * Return a human-readable description for the given NVRAM data class.
+ * 
+ * @param cls The NVRAM class.
+ */
+const char *
+bhnd_nvram_data_class_desc(bhnd_nvram_data_class_t *cls)
+{
+       return (cls->desc);
+}
+
+/**
+ * Probe to see if this NVRAM data class class supports the data mapped by the
+ * given I/O context, returning a BHND_NVRAM_DATA_PROBE probe result.
+ *
+ * @param cls The NVRAM class.
+ * @param io An I/O context mapping the NVRAM data.
+ *
+ * @retval 0 if this is the only possible NVRAM data class for @p io.
+ * @retval negative if the probe succeeds, a negative value should be returned;
+ * the class returning the highest negative value should be selected to handle
+ * NVRAM parsing.
+ * @retval ENXIO If the NVRAM format is not handled by @p cls.
+ * @retval positive if an error occurs during probing, a regular unix error
+ * code should be returned.
+ */
+int
+bhnd_nvram_data_probe(bhnd_nvram_data_class_t *cls, struct bhnd_nvram_io *io)
+{
+       return (cls->op_probe(io));
+}
+
+/**
+ * Probe to see if an NVRAM data class in @p classes supports parsing
+ * of the data mapped by @p io, returning the parsed data in @p data.
+ * 
+ * The caller is responsible for deallocating the returned instance via
+ * bhnd_nvram_data_release().
+ * 
+ * @param[out] data On success, the parsed NVRAM data instance.
+ * @param io An I/O context mapping the NVRAM data to be copied and parsed.
+ * @param classes An array of NVRAM data classes to be probed, or NULL to
+ * probe the default supported set.
+ * @param num_classes The number of NVRAM data classes in @p classes.
+ * 
+ * @retval 0 success
+ * @retval ENXIO if no class is found capable of parsing @p io.
+ * @retval non-zero if an error otherwise occurs during allocation,
+ * initialization, or parsing of the NVRAM data, a regular unix error code
+ * will be returned.
+ */
+int
+bhnd_nvram_data_probe_classes(struct bhnd_nvram_data **data,
+    struct bhnd_nvram_io *io, bhnd_nvram_data_class_t *classes[],
+    size_t num_classes)
+{
+       bhnd_nvram_data_class_t *cls;
+       int                      error, prio, result;
+
+       cls = NULL;
+       prio = 0;
+       *data = NULL;
+
+       /* If class array is NULL, default to our linker set */
+       if (classes == NULL) {
+               classes = SET_BEGIN(bhnd_nvram_data_class_set);
+               num_classes = SET_COUNT(bhnd_nvram_data_class_set);
+       }
+
+       /* Try to find the best data class capable of parsing io */
+       for (size_t i = 0; i < num_classes; i++) {
+               bhnd_nvram_data_class_t *next_cls;
+
+               next_cls = classes[i];
+
+               /* Try to probe */
+               result = bhnd_nvram_data_probe(next_cls, io);
+
+               /* The parser did not match if an error was returned */
+               if (result > 0)
+                       continue;
+
+               /* Lower priority than previous match; keep
+                * searching */
+               if (cls != NULL && result <= prio)
+                       continue;
+
+               /* Drop any previously parsed data */
+               if (*data != NULL) {
+                       bhnd_nvram_data_release(*data);
+                       *data = NULL;
+               }
+
+               /* If this is a 'maybe' match, attempt actual parsing to
+                * verify that this does in fact match */
+               if (result <= BHND_NVRAM_DATA_PROBE_MAYBE) {
+                       /* If parsing fails, keep searching */
+                       error = bhnd_nvram_data_new(next_cls, data, io);
+                       if (error)
+                               continue;
+               }
+
+               /* Record best new match */
+               prio = result;
+               cls = next_cls;
+
+
+               /* Terminate search immediately on
+                * BHND_NVRAM_DATA_PROBE_SPECIFIC */
+               if (result == BHND_NVRAM_DATA_PROBE_SPECIFIC)
+                       break;
+       }
+
+       /* If no match, return error */
+       if (cls == NULL)
+               return (ENXIO);
+
+       /* If the NVRAM data was not parsed above, do so now */
+       if (*data == NULL) {
+               if ((error = bhnd_nvram_data_new(cls, data, io)))
+                       return (error);
+       }
+
+       return (0);
+}
+
+/**
+ * Allocate and initialize a new instance of data class @p cls, copying and
+ * parsing NVRAM data from @p io.
+ *
+ * The caller is responsible for releasing the returned parser instance
+ * reference via bhnd_nvram_data_release().
+ * 
+ * @param cls If non-NULL, the data class to be allocated. If NULL,
+ * bhnd_nvram_data_probe_classes() will be used to determine the data format.
+ * @param[out] nv On success, a pointer to the newly allocated NVRAM data 
instance.
+ * @param io An I/O context mapping the NVRAM data to be copied and parsed.
+ * 
+ * @retval 0 success
+ * @retval non-zero if an error occurs during allocation or initialization, a
+ * regular unix error code will be returned.
+ */
+int
+bhnd_nvram_data_new(bhnd_nvram_data_class_t *cls,
+    struct bhnd_nvram_data **nv, struct bhnd_nvram_io *io)
+{
+       struct bhnd_nvram_data  *data;
+       int                      error;
+
+       /* If NULL, try to identify the appropriate class */
+       if (cls == NULL)
+               return (bhnd_nvram_data_probe_classes(nv, io, NULL, 0));
+
+       /* Allocate new instance */
+       BHND_NV_ASSERT(sizeof(struct bhnd_nvram_data) <= cls->size,
+           ("instance size %zu less than minimum %zu", cls->size,
+            sizeof(struct bhnd_nvram_data)));
+
+       data = bhnd_nv_calloc(1, cls->size);
+       data->cls = cls;
+       refcount_init(&data->refs, 1);
+
+       /* Let the class handle initialization */
+       if ((error = cls->op_new(data, io))) {
+               bhnd_nv_free(data);
+               return (error);
+       }
+
+       *nv = data;
+       return (0);
+}
+
+/**
+ * Retain and return a reference to the given data instance.
+ * 
+ * @param nv The reference to be retained.
+ */
+struct bhnd_nvram_data *
+bhnd_nvram_data_retain(struct bhnd_nvram_data *nv)
+{
+       refcount_acquire(&nv->refs);
+       return (nv);
+}
+
+/**
+ * Release a reference to the given data instance.
+ *
+ * If this is the last reference, the data instance and its associated
+ * resources will be freed.
+ * 
+ * @param nv The reference to be released.
+ */
+void
+bhnd_nvram_data_release(struct bhnd_nvram_data *nv)
+{
+       if (!refcount_release(&nv->refs))
+               return;
+
+       /* Free any internal resources */
+       nv->cls->op_free(nv);
+
+       /* Free the instance allocation */
+       bhnd_nv_free(nv);
+}
+
+/**
+ * Return a pointer to @p nv's data class.
+ * 
+ * @param nv The NVRAM data instance to be queried.
+ */
+bhnd_nvram_data_class_t *
+bhnd_nvram_data_class(struct bhnd_nvram_data *nv)
+{
+       return (nv->cls);
+}
+
+/**
+ * Return the number of variables in @p nv.
+ * 
+ * @param nv The NVRAM data to be queried.
+ */
+size_t
+bhnd_nvram_data_count(struct bhnd_nvram_data *nv)
+{
+       return (nv->cls->op_count(nv));
+}
+
+/**
+ * Compute the size of the serialized form of @p nv.
+ *
+ * Serialization may be performed via bhnd_nvram_data_serialize().
+ *
+ * @param      nv      The NVRAM data to be queried.
+ * @param[out] len     On success, will be set to the computed size.
+ * 
+ * @retval 0           success
+ * @retval non-zero    if computing the serialized size otherwise fails, a
+ *                     regular unix error code will be returned.
+ */
+int
+bhnd_nvram_data_size(struct bhnd_nvram_data *nv, size_t *len)
+{
+       return (nv->cls->op_size(nv, len));
+}
+
+/**
+ * Serialize the NVRAM data to @p buf, using the NVRAM data class' native
+ * format.
+ * 
+ * The resulting serialization may be reparsed with @p nv's BHND NVRAM data
+ * class.
+ * 
+ * @param              nv      The NVRAM data to be serialized.
+ * @param[out]         buf     On success, the serialed NVRAM data will be
+ *                             written to this buffer. This argment may be
+ *                             NULL if the value is not desired.
+ * @param[in,out]      len     The capacity of @p buf. On success, will be set
+ *                             to the actual length of the serialized data.
+ *
+ * @retval 0           success
+ * @retval ENOMEM      If @p buf is non-NULL and a buffer of @p len is too
+ *                     small to hold the serialized data.
+ * @retval non-zero    If serialization otherwise fails, a regular unix error
+ *                     code will be returned.
+ */
+int
+bhnd_nvram_data_serialize(struct bhnd_nvram_data *nv,
+    void *buf, size_t *len)
+{
+       return (nv->cls->op_serialize(nv, buf, len));
+}
+
+/**
+ * Return the capability flags (@see BHND_NVRAM_DATA_CAP_*) for @p nv.
+ *
+ * @param      nv      The NVRAM data to be queried.
+ */
+uint32_t
+bhnd_nvram_data_caps(struct bhnd_nvram_data *nv)
+{
+       return (nv->cls->op_caps(nv));
+}
+
+/**
+ * Iterate over @p nv, returning the names of subsequent variables.
+ * 
+ * @param              nv      The NVRAM data to be iterated.
+ * @param[in,out]      cookiep A pointer to a cookiep value previously returned
+ *                             by bhnd_nvram_data_next(), or a NULL value to
+ *                             begin iteration.
+ * 
+ * @return Returns the next variable name, or NULL if there are no more
+ * variables defined in @p nv.
+ */
+const char *
+bhnd_nvram_data_next(struct bhnd_nvram_data *nv, void **cookiep)
+{
+       return (nv->cls->op_next(nv, cookiep));
+}
+
+/**
+ * Search @p nv for a named variable, returning the variable's opaque reference
+ * if found, or NULL if unavailable.
+ *
+ * The BHND_NVRAM_DATA_CAP_INDEXED capability flag will be returned by
+ * bhnd_nvram_data_caps() if @p nv supports effecient name-based
+ * lookups.
+ *
+ * @param      nv      The NVRAM data to search.
+ * @param      name    The name to search for.
+ *
+ * @retval non-NULL    If @p name is found, the opaque cookie value will be
+ *                     returned.
+ * @retval NULL                If @p name is not found.
+ */
+void *
+bhnd_nvram_data_find(struct bhnd_nvram_data *nv, const char *name)
+{
+       return (nv->cls->op_find(nv, name));
+}
+
+/**
+ * A generic implementation of bhnd_nvram_data_find().
+ *
+ * This implementation will use bhnd_nvram_data_next() to perform a
+ * simple O(n) case-insensitve search for @p name.
+ */
+void *
+bhnd_nvram_data_generic_find(struct bhnd_nvram_data *nv, const char *name)
+{
+       const char      *next;
+       void            *cookiep;
+
+       cookiep = NULL;
+       while ((next = bhnd_nvram_data_next(nv, &cookiep))) {
+               if (strcasecmp(name, next) == 0)
+                       return (cookiep);
+       }
+
+       /* Not found */
+       return (NULL);
+}
+
+/**
+ * Read a variable and decode as @p type.
+ *
+ * @param              nv      The NVRAM data.
+ * @param              cookiep An NVRAM variable cookie previously returned
+ *                             via bhnd_nvram_data_next() or
+ *                             bhnd_nvram_data_find().
+ * @param[out]         buf     On success, the requested value will be written
+ *                             to this buffer. This argment may be NULL if
+ *                             the value is not desired.
+ * @param[in,out]      len     The capacity of @p buf. On success, will be set
+ *                             to the actual size of the requested value.
+ * @param              type    The data type to be written to @p buf.
+ *
+ * @retval 0           success
+ * @retval ENOMEM      If @p buf is non-NULL and a buffer of @p len is too
+ *                     small to hold the requested value.
+ * @retval EFTYPE      If the variable data cannot be coerced to @p type.
+ * @retval ERANGE      If value coercion would overflow @p type.
+ */
+int
+bhnd_nvram_data_getvar(struct bhnd_nvram_data *nv, void *cookiep, void *buf,
+    size_t *len, bhnd_nvram_type type)
+{
+       return (nv->cls->op_getvar(nv, cookiep, buf, len, type));
+}
+
+/**
+ * A generic implementation of bhnd_nvram_data_getvar().
+ * 
+ * This implementation will call bhnd_nvram_data_getvar_ptr() to fetch
+ * a pointer to the variable data and perform data coercion on behalf
+ * of the caller.
+ *
+ * If a variable definition for the requested variable is available via
+ * bhnd_nvram_find_vardefn(), the definition will be used to provide
+ * formatting hints to bhnd_nvram_coerce_value().
+ */
+int
+bhnd_nvram_data_generic_rp_getvar(struct bhnd_nvram_data *nv, void *cookiep,
+    void *outp, size_t *olen, bhnd_nvram_type otype)
+{
+       bhnd_nvram_val_t                 val;
+       const struct bhnd_nvram_vardefn *vdefn;
+       const bhnd_nvram_val_fmt_t      *fmt;
+       const char                      *name;
+       const void                      *vptr;
+       bhnd_nvram_type                  vtype;
+       size_t                           vlen;
+       int                              error;
+
+       BHND_NV_ASSERT(bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_READ_PTR,
+           ("instance does not advertise READ_PTR support"));
+
+       /* Fetch pointer to our variable data */
+       vptr = bhnd_nvram_data_getvar_ptr(nv, cookiep, &vlen, &vtype);
+       if (vptr == NULL)
+               return (EINVAL);
+
+       /* Use the NVRAM string support */
+       switch (vtype) {
+       case BHND_NVRAM_TYPE_STRING:
+       case BHND_NVRAM_TYPE_STRING_ARRAY:
+               fmt = &bhnd_nvram_val_bcm_string_fmt;
+               break;
+       default:
+               fmt = NULL;
+       }
+
+       /* Check the variable definition table for a matching entry; if
+        * it exists, use it to populate the value format. */
+       name = bhnd_nvram_data_getvar_name(nv, cookiep);
+       vdefn = bhnd_nvram_find_vardefn(name);
+       if (vdefn != NULL)
+               fmt = vdefn->fmt;
+
+       /* Attempt value coercion */
+       error = bhnd_nvram_val_init(&val, fmt, vptr, vlen, vtype,
+           BHND_NVRAM_VAL_BORROW_DATA);
+       if (error)
+               return (error);
+
+       error = bhnd_nvram_val_encode(&val, outp, olen, otype);
+
+       /* Clean up */
+       bhnd_nvram_val_release(&val);
+       return (error);
+}
+
+/**
+ * If available and supported by the NVRAM data instance, return a reference
+ * to the internal buffer containing an entry's variable data,
+ * 
+ * Note that string values may not be NUL terminated.
+ *
+ * @param              nv      The NVRAM data.
+ * @param              cookiep An NVRAM variable cookie previously returned
+ *                             via bhnd_nvram_data_next() or
+ *                             bhnd_nvram_data_find().
+ * @param[out]         len     On success, will be set to the actual size of
+ *                             the requested value.
+ * @param[out]         type    The data type of the entry data.
+ *
+ * @retval non-NULL    success
+ * @retval NULL                if direct data access is unsupported by @p nv, 
or
+ *                     unavailable for @p cookiep.
+ */
+const void *
+bhnd_nvram_data_getvar_ptr(struct bhnd_nvram_data *nv, void *cookiep,
+    size_t *len, bhnd_nvram_type *type)
+{
+       return (nv->cls->op_getvar_ptr(nv, cookiep, len, type));
+}
+
+
+/**
+ * Return the variable name associated with a given @p cookiep.
+ * @param              nv      The NVRAM data to be iterated.
+ * @param[in,out]      cookiep A pointer to a cookiep value previously returned
+ *                             via bhnd_nvram_data_next() or
+ *                             bhnd_nvram_data_find().
+ *
+ * @return Returns the variable's name.
+ */
+const char *
+bhnd_nvram_data_getvar_name(struct bhnd_nvram_data *nv, void *cookiep)
+{
+       return (nv->cls->op_getvar_name(nv, cookiep));
+}

Added: head/sys/dev/bhnd/nvram/bhnd_nvram_data.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data.h   Sat Nov 26 23:22:32 2016        
(r309202)
@@ -0,0 +1,137 @@
+/*-
+ * 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.
+ * 
+ * $FreeBSD$
+ */
+
+#ifndef _BHND_NVRAM_BHND_NVRAM_DATA_H_
+#define _BHND_NVRAM_BHND_NVRAM_DATA_H_
+
+#ifdef _KERNEL
+#include <sys/param.h>
+#include <sys/bus.h>
+#else /* !_KERNEL */
+#include <errno.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#endif /* _KERNEL */
+
+#include "bhnd_nvram.h"
+#include "bhnd_nvram_io.h"
+
+/* NVRAM data class */
+typedef struct bhnd_nvram_data_class bhnd_nvram_data_class_t;
+
+/* NVRAM data instance */
+struct bhnd_nvram_data;
+
+/** Declare a bhnd_nvram_data_class with name @p _n */
+#define        BHND_NVRAM_DATA_CLASS_DECL(_n) \
+       extern  struct bhnd_nvram_data_class bhnd_nvram_ ## _n ## _class
+
+BHND_NVRAM_DATA_CLASS_DECL(bcm);
+BHND_NVRAM_DATA_CLASS_DECL(bcmraw);
+BHND_NVRAM_DATA_CLASS_DECL(tlv);
+BHND_NVRAM_DATA_CLASS_DECL(btxt);
+BHND_NVRAM_DATA_CLASS_DECL(sprom);
+
+/** bhnd_nvram_data capabilities */
+enum {
+       /** Supports efficient lookup of variables by name */
+       BHND_NVRAM_DATA_CAP_INDEXED     = (1<<0),
+
+       /** Supports direct access to backing buffer */
+       BHND_NVRAM_DATA_CAP_READ_PTR    = (1<<1),
+
+       /** Supports device path prefixed variables */
+       BHND_NVRAM_DATA_CAP_DEVPATHS    = (1<<2),
+};
+
+/**
+ * A standard set of probe priorities returned by bhnd_nvram_data_probe().
+ * 
+ * Priority is defined in ascending order, with 0 being the highest priority.
+ * Return values greater than zero are interpreted as regular unix error codes.
+ */
+enum {
+       BHND_NVRAM_DATA_PROBE_MAYBE     = -40,  /**< Possible match */
+       BHND_NVRAM_DATA_PROBE_DEFAULT   = -20,  /**< Definite match of a base
+                                                    OS-supplied data class */
+       BHND_NVRAM_DATA_PROBE_SPECIFIC  = 0,    /**< Terminate search and use
+                                                    this data class for
+                                                    parsing */
+};
+
+const char             *bhnd_nvram_data_class_desc(
+                            bhnd_nvram_data_class_t *cls);
+
+int                     bhnd_nvram_data_probe(bhnd_nvram_data_class_t *cls,
+                            struct bhnd_nvram_io *io);
+int                     bhnd_nvram_data_probe_classes(
+                            struct bhnd_nvram_data **data,
+                            struct bhnd_nvram_io *io,
+                            bhnd_nvram_data_class_t *classes[],
+                            size_t num_classes);
+
+int                     bhnd_nvram_data_new(bhnd_nvram_data_class_t *cls,
+                            struct bhnd_nvram_data **nv,
+                          struct bhnd_nvram_io *io);
+
+struct bhnd_nvram_data *bhnd_nvram_data_retain(struct bhnd_nvram_data *nv);
+void                    bhnd_nvram_data_release(struct bhnd_nvram_data *nv);
+
+bhnd_nvram_data_class_t        *bhnd_nvram_data_class(struct bhnd_nvram_data 
*nv);
+
+size_t                  bhnd_nvram_data_count(struct bhnd_nvram_data *nv);
+
+int                     bhnd_nvram_data_size(struct bhnd_nvram_data *nv,
+                            size_t *size);
+
+int                     bhnd_nvram_data_serialize(struct bhnd_nvram_data *nv,
+                            void *buf, size_t *len);
+
+uint32_t                bhnd_nvram_data_caps(struct bhnd_nvram_data *nv);
+
+const char             *bhnd_nvram_data_next(struct bhnd_nvram_data *nv,
+                            void **cookiep);
+
+void                   *bhnd_nvram_data_find(struct bhnd_nvram_data *nv,
+                            const char *name);
+
+int                     bhnd_nvram_data_getvar(struct bhnd_nvram_data *nv,
+                            void *cookiep, void *buf, size_t *len,
+                            bhnd_nvram_type type);
+
+const void             *bhnd_nvram_data_getvar_ptr(struct bhnd_nvram_data *nv,
+                            void *cookiep, size_t *len, bhnd_nvram_type *type);
+
+const char             *bhnd_nvram_data_getvar_name(struct bhnd_nvram_data *nv,
+                            void *cookiep);
+
+#endif /* _BHND_NVRAM_BHND_NVRAM_DATA_H_ */

Added: head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c       Sat Nov 26 23:22:32 
2016        (r309202)
@@ -0,0 +1,748 @@
+/*-
+ * Copyright (c) 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/endian.h>
+
+#ifdef _KERNEL
+
+#include <sys/bus.h>
+#include <sys/ctype.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+#else /* !_KERNEL */
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#endif /* _KERNEL */
+
+#include "bhnd_nvram_private.h"
+
+#include "bhnd_nvram_datavar.h"
+
+#include "bhnd_nvram_data_bcmreg.h"
+#include "bhnd_nvram_data_bcmvar.h"
+
+/*
+ * Broadcom NVRAM data class.
+ * 
+ * The Broadcom NVRAM NUL-delimited ASCII format is used by most
+ * Broadcom SoCs.
+ * 
+ * The NVRAM data is encoded as a standard header, followed by series of
+ * NUL-terminated 'key=value' strings; the end of the stream is denoted
+ * by a single extra NUL character.
+ */
+
+struct bhnd_nvram_bcm;
+
+static struct bhnd_nvram_bcm_hvar      *bhnd_nvram_bcm_gethdrvar(
+                                            struct bhnd_nvram_bcm *bcm,
+                                            const char *name);
+static struct bhnd_nvram_bcm_hvar      *bhnd_nvram_bcm_to_hdrvar(
+                                            struct bhnd_nvram_bcm *bcm,
+                                            void *cookiep);
+static size_t                           bhnd_nvram_bcm_hdrvar_index(
+                                            struct bhnd_nvram_bcm *bcm,
+                                            struct bhnd_nvram_bcm_hvar *hvar);
+/*
+ * Set of BCM NVRAM header values that are required to be mirrored in the
+ * NVRAM data itself.
+ *
+ * If they're not included in the parsed NVRAM data, we need to vend the
+ * header-parsed values with their appropriate keys, and add them in any
+ * updates to the NVRAM data.
+ *
+ * If they're modified in NVRAM, we need to sync the changes with the
+ * the NVRAM header values.
+ */
+static const struct bhnd_nvram_bcm_hvar bhnd_nvram_bcm_hvars[] = {
+       {
+               .name   = BCM_NVRAM_CFG0_SDRAM_INIT_VAR,
+               .type   = BHND_NVRAM_TYPE_UINT16,
+               .len    = sizeof(uint16_t),
+               .nelem  = 1,
+       },
+       {
+               .name   = BCM_NVRAM_CFG1_SDRAM_CFG_VAR,
+               .type   = BHND_NVRAM_TYPE_UINT16,
+               .len    = sizeof(uint16_t),
+               .nelem  = 1,
+       },
+       {
+               .name   = BCM_NVRAM_CFG1_SDRAM_REFRESH_VAR,
+               .type   = BHND_NVRAM_TYPE_UINT16,
+               .len    = sizeof(uint16_t),
+               .nelem  = 1,
+       },
+       {
+               .name   = BCM_NVRAM_SDRAM_NCDL_VAR,
+               .type   = BHND_NVRAM_TYPE_UINT32,
+               .len    = sizeof(uint32_t),
+               .nelem  = 1,
+       },
+};
+
+/** BCM NVRAM data class instance */
+struct bhnd_nvram_bcm {
+       struct bhnd_nvram_data           nv;    /**< common instance state */
+       struct bhnd_nvram_io            *data;  /**< backing buffer */
+
+       /** BCM header values */
+       struct bhnd_nvram_bcm_hvar       hvars[nitems(bhnd_nvram_bcm_hvars)];
+
+       size_t                           count; /**< total variable count */
+};
+
+BHND_NVRAM_DATA_CLASS_DEFN(bcm, "Broadcom", sizeof(struct bhnd_nvram_bcm))
+
+static int
+bhnd_nvram_bcm_probe(struct bhnd_nvram_io *io)
+{
+       struct bhnd_nvram_bcmhdr        hdr;
+       int                             error;
+
+       if ((error = bhnd_nvram_io_read(io, 0x0, &hdr, sizeof(hdr))))
+               return (error);
+
+       if (le32toh(hdr.magic) != BCM_NVRAM_MAGIC)
+               return (ENXIO);
+
+       return (BHND_NVRAM_DATA_PROBE_DEFAULT);
+}
+
+/**
+ * Initialize @p bcm with the provided NVRAM data mapped by @p src.
+ * 
+ * @param bcm A newly allocated data instance.
+ */
+static int
+bhnd_nvram_bcm_init(struct bhnd_nvram_bcm *bcm, struct bhnd_nvram_io *src)
+{
+       struct bhnd_nvram_bcmhdr         hdr;
+       uint8_t                         *p;
+       void                            *ptr;
+       size_t                           io_offset, io_size;
+       uint8_t                          crc, valid;
+       int                              error;
+
+       if ((error = bhnd_nvram_io_read(src, 0x0, &hdr, sizeof(hdr))))
+               return (error);
+
+       if (le32toh(hdr.magic) != BCM_NVRAM_MAGIC)
+               return (ENXIO);
+
+       /* Fetch the actual NVRAM image size */

*** 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"

Reply via email to