Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 26 Nov 2016 23:22:33 +0000 (UTC)
From:      "Landon J. Fuller" <landonf@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r309202 - in head/sys: conf dev/bhnd dev/bhnd/nvram dev/bhnd/tools dev/bwn mips/broadcom modules/bhnd
Message-ID:  <201611262322.uAQNMXR2059108@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <landonf@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 <landonf@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 <landonf@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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201611262322.uAQNMXR2059108>