Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Aug 2016 21:32:05 +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: r304243 - in head/sys: conf dev/bhnd dev/bhnd/cores/chipc dev/bhnd/nvram dev/bhnd/tools dev/bwn mips/conf modules/bhnd
Message-ID:  <201608162132.u7GLW5Q2083485@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: landonf
Date: Tue Aug 16 21:32:05 2016
New Revision: 304243
URL: https://svnweb.freebsd.org/changeset/base/304243

Log:
  bhnd(4): Implement NVRAM support required for PMU bring-up.
  
  - Added a generic bhnd_nvram_parser API, with support for the TLV format
    used on WGT634U devices, the standard BCM NVRAM format used on most
    modern devices, and the "board text file" format used on some hardware
    to supply external NVRAM data at runtime (e.g. via an EFI variable).
  
  - Extended the bhnd_bus_if and bhnd_nvram_if interfaces to support both
    string-based and primitive data type variable access, required for
    common behavior across both SPROM and NVRAM data sources.
  - Extended the existing SPROM implementation to support the new
    string-based NVRAM APIs.
  
  - Added an abstract bhnd_nvram driver, implementing the bhnd_nvram_if
    atop the bhnd_nvram_parser API.
  - Added a CFE-based bhnd_nvram driver to provide read-only access to
    NVRAM data on MIPS SoCs, pending implementation of a flash-aware
    bhnd_nvram driver.
  
  Approved by:	adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D7489

Added:
  head/sys/dev/bhnd/nvram/bhnd_nvram.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_cfe.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_common.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_common.h
     - copied, changed from r304242, head/sys/dev/bhnd/nvram/nvramvar.h
  head/sys/dev/bhnd/nvram/bhnd_nvram_parser.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_parser.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_parserreg.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvram_parservar.h   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_nvramvar.h
     - copied, changed from r304242, head/sys/dev/bhnd/nvram/bhnd_spromreg.h
  head/sys/dev/bhnd/nvram/bhnd_sprom_parser.c
     - copied, changed from r304242, head/sys/dev/bhnd/nvram/bhnd_sprom_subr.c
  head/sys/dev/bhnd/nvram/bhnd_sprom_parser.h
     - copied, changed from r304242, head/sys/dev/bhnd/nvram/bhnd_spromvar.h
  head/sys/dev/bhnd/nvram/bhnd_sprom_parservar.h
     - copied, changed from r304242, head/sys/dev/bhnd/nvram/bhnd_spromreg.h
Deleted:
  head/sys/dev/bhnd/nvram/bhnd_sprom_subr.c
  head/sys/dev/bhnd/nvram/bhnd_spromreg.h
  head/sys/dev/bhnd/nvram/nvram_subr.c
  head/sys/dev/bhnd/nvram/nvramvar.h
Modified:
  head/sys/conf/files
  head/sys/dev/bhnd/bhnd.c
  head/sys/dev/bhnd/bhnd.h
  head/sys/dev/bhnd/bhnd_bus_if.m
  head/sys/dev/bhnd/bhnd_subr.c
  head/sys/dev/bhnd/bhnd_types.h
  head/sys/dev/bhnd/bhndvar.h
  head/sys/dev/bhnd/cores/chipc/chipc.c
  head/sys/dev/bhnd/nvram/bhnd_nvram.h
  head/sys/dev/bhnd/nvram/bhnd_nvram_if.m
  head/sys/dev/bhnd/nvram/bhnd_sprom.c
  head/sys/dev/bhnd/nvram/bhnd_spromvar.h
  head/sys/dev/bhnd/tools/nvram_map_gen.awk
  head/sys/dev/bwn/bwn_mac.c
  head/sys/mips/conf/BCM
  head/sys/mips/conf/BCM.hints
  head/sys/mips/conf/SENTRY5
  head/sys/mips/conf/SENTRY5.hints
  head/sys/modules/bhnd/Makefile

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Tue Aug 16 21:20:05 2016	(r304242)
+++ head/sys/conf/files	Tue Aug 16 21:32:05 2016	(r304243)
@@ -1163,10 +1163,14 @@ dev/bhnd/cores/pci/bhnd_pcib.c		optional
 dev/bhnd/cores/pcie2/bhnd_pcie2.c	optional bhnd pci
 dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c	optional bhndb bhnd pci
 dev/bhnd/cores/pcie2/bhnd_pcie2b.c	optional bhnd_pcie2b bhnd pci
+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_if.m		optional bhnd
+dev/bhnd/nvram/bhnd_nvram_parser.c	optional bhnd
 dev/bhnd/nvram/bhnd_sprom.c		optional bhnd
-dev/bhnd/nvram/bhnd_sprom_subr.c	optional bhnd
-dev/bhnd/nvram/nvram_subr.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_nexus.c		optional siba_nexus siba bhnd

Modified: head/sys/dev/bhnd/bhnd.c
==============================================================================
--- head/sys/dev/bhnd/bhnd.c	Tue Aug 16 21:20:05 2016	(r304242)
+++ head/sys/dev/bhnd/bhnd.c	Tue Aug 16 21:32:05 2016	(r304243)
@@ -361,7 +361,7 @@ bhnd_finish_attach(struct bhnd_softc *sc
 	if (ccaps->nvram_src != BHND_NVRAM_SRC_UNKNOWN) {
 		if ((sc->nvram_dev = bhnd_find_nvram(sc)) == NULL) {
 			device_printf(sc->dev,
-			    "warning: %s NVRAM device not found\n",
+			    "warning: NVRAM %s device not found\n",
 			    bhnd_nvram_src_name(ccaps->nvram_src));
 		}
 	}
@@ -459,6 +459,11 @@ bhnd_find_platform_dev(struct bhnd_softc
 	}
 
 	child = device_find_child(chipc, classname, -1);
+	if (child != NULL)
+		goto found;
+
+	/* Look for a parent-attached device (e.g. nexus0 -> bhnd_nvram) */
+	child = device_find_child(device_get_parent(sc->dev), classname, -1);
 	if (child == NULL)
 		return (NULL);
 
@@ -651,7 +656,7 @@ bhnd_generic_is_region_valid(device_t de
  */
 int
 bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
-    void *buf, size_t *size)
+    void *buf, size_t *size, bhnd_nvram_type type)
 {
 	struct bhnd_softc	*sc;
 	device_t		 nvram, parent;
@@ -660,14 +665,14 @@ bhnd_generic_get_nvram_var(device_t dev,
 
 	/* If a NVRAM device is available, consult it first */
 	if ((nvram = bhnd_find_nvram(sc)) != NULL)
-		return BHND_NVRAM_GETVAR(nvram, name, buf, size);
+		return BHND_NVRAM_GETVAR(nvram, name, buf, size, type);
 
 	/* Otherwise, try to delegate to parent */
 	if ((parent = device_get_parent(dev)) == NULL)
 		return (ENODEV);
 
 	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
-	    name, buf, size));
+	    name, buf, size, type));
 }
 
 /**

Modified: head/sys/dev/bhnd/bhnd.h
==============================================================================
--- head/sys/dev/bhnd/bhnd.h	Tue Aug 16 21:20:05 2016	(r304242)
+++ head/sys/dev/bhnd/bhnd.h	Tue Aug 16 21:32:05 2016	(r304243)
@@ -321,6 +321,31 @@ void				 bhnd_set_custom_core_desc(devic
 				     const char *name);
 void				 bhnd_set_default_core_desc(device_t dev);
 
+int				 bhnd_nvram_getvar_str(device_t dev,
+				     const char *name, char *buf, size_t len,
+				     size_t *rlen);
+
+int				 bhnd_nvram_getvar_uint(device_t dev,
+				     const char *name, void *value, int width);
+int				 bhnd_nvram_getvar_uint8(device_t dev,
+				     const char *name, uint8_t *value);
+int				 bhnd_nvram_getvar_uint16(device_t dev,
+				     const char *name, uint16_t *value);
+int				 bhnd_nvram_getvar_uint32(device_t dev,
+				     const char *name, uint32_t *value);
+
+int				 bhnd_nvram_getvar_int(device_t dev,
+				     const char *name, void *value, int width);
+int				 bhnd_nvram_getvar_int8(device_t dev,
+				     const char *name, int8_t *value);
+int				 bhnd_nvram_getvar_int16(device_t dev,
+				     const char *name, int16_t *value);
+int				 bhnd_nvram_getvar_int32(device_t dev,
+				     const char *name, int32_t *value);
+
+int				 bhnd_nvram_getvar_array(device_t dev,
+				     const char *name, void *buf, size_t count,
+				     bhnd_nvram_type type);
 
 bool				 bhnd_bus_generic_is_hw_disabled(device_t dev,
 				     device_t child);
@@ -329,7 +354,8 @@ bool				 bhnd_bus_generic_is_region_vali
 				     u_int port, u_int region);
 int				 bhnd_bus_generic_get_nvram_var(device_t dev,
 				     device_t child, const char *name,
-				     void *buf, size_t *size);
+				     void *buf, size_t *size,
+				     bhnd_nvram_type type);
 const struct bhnd_chipid	*bhnd_bus_generic_get_chipid(device_t dev,
 				     device_t child);
 int				 bhnd_bus_generic_read_board_info(device_t dev,
@@ -428,55 +454,36 @@ bhnd_read_board_info(device_t dev, struc
 }
 
 /**
- * Determine an NVRAM variable's expected size.
- *
- * @param 	dev	A bhnd bus child device.
- * @param	name	The variable name.
- * @param[out]	len	On success, the variable's size, in bytes.
- *
- * @retval 0		success
- * @retval ENOENT	The requested variable was not found.
- * @retval ENODEV	No valid NVRAM source could be found.
- * @retval non-zero	If reading @p name otherwise fails, a regular unix
- *			error code will be returned.
- */
-static inline int
-bhnd_nvram_getvarlen(device_t dev, const char *name, size_t *len)
-{
-	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, NULL,
-	    len));
-}
-
-/**
- * Read an NVRAM variable.
- *
- * @param 	dev	A bhnd bus child device.
- * @param	name	The NVRAM variable name.
- * @param	buf	A buffer large enough to hold @p len bytes. On success,
- * 			the requested value will be written to this buffer.
- * @param	len	The required variable length.
+ * Read an NVRAM variable, coerced to the requested @p type.
  *
+ * @param 		dev	A bhnd bus child device.
+ * @param		name	The NVRAM variable name.
+ * @param[out]		buf	A buffer large enough to hold @p len bytes. 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 maximum capacity of @p buf. On success,
+ *				will be set to the actual size of the requested
+ *				value.
+ * @param		type	The desired data representation to be written
+ *				to @p buf.
+ * 
  * @retval 0		success
  * @retval ENOENT	The requested variable was not found.
- * @retval EINVAL	If @p len does not match the actual variable size.
  * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval ENOMEM	If a buffer of @p size is too small to hold the
+ *			requested value.
+ * @retval EOPNOTSUPP	If the value cannot be coerced to @p type.
+ * @retval ERANGE	If value coercion would overflow @p type.
  * @retval non-zero	If reading @p name otherwise fails, a regular unix
  *			error code will be returned.
  */
 static inline int
-bhnd_nvram_getvar(device_t dev, const char *name, void *buf, size_t len)
+bhnd_nvram_getvar(device_t dev, const char *name, void *buf, size_t *len,
+     bhnd_nvram_type type)
 {
-	size_t	var_len;
-	int	error;
-
-	if ((error = bhnd_nvram_getvarlen(dev, name, &var_len)))
-		return (error);
-
-	if (len != var_len)
-		return (EINVAL);
-
 	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, buf,
-	    &len));
+	    len, type));
 }
 
 /**

Modified: head/sys/dev/bhnd/bhnd_bus_if.m
==============================================================================
--- head/sys/dev/bhnd/bhnd_bus_if.m	Tue Aug 16 21:20:05 2016	(r304242)
+++ head/sys/dev/bhnd/bhnd_bus_if.m	Tue Aug 16 21:32:05 2016	(r304243)
@@ -116,7 +116,7 @@ CODE {
 	
 	static int
 	bhnd_bus_null_get_nvram_var(device_t dev, device_t child,
-	    const char *name, void *buf, size_t *size)
+	    const char *name, void *buf, size_t *size, bhnd_nvram_type type)
 	{
 		return (ENODEV);
 	}
@@ -492,12 +492,15 @@ METHOD int get_region_addr {
  *				the value is not desired.
  * @param[in,out]	size	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 ENOENT	The requested variable was not found.
  * @retval ENOMEM	If @p buf is non-NULL and a buffer of @p size is too
  *			small to hold the requested value.
  * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval EFTYPE	If the @p name's data type cannot be coerced to @p type.
+ * @retval ERANGE	If value coercion would overflow @p type.
  * @retval non-zero	If reading @p name otherwise fails, a regular unix
  *			error code will be returned.
  */
@@ -507,6 +510,7 @@ METHOD int get_nvram_var {
 	const char	*name;
 	void		*buf;
 	size_t		*size;
+	bhnd_nvram_type	 type;
 } DEFAULT bhnd_bus_null_get_nvram_var;
 
 

Modified: head/sys/dev/bhnd/bhnd_subr.c
==============================================================================
--- head/sys/dev/bhnd/bhnd_subr.c	Tue Aug 16 21:20:05 2016	(r304242)
+++ head/sys/dev/bhnd/bhnd_subr.c	Tue Aug 16 21:32:05 2016	(r304243)
@@ -30,7 +30,6 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/bus.h>
 #include <sys/systm.h>
@@ -881,6 +880,325 @@ cleanup:
 }
 
 /**
+ * Read an NVRAM variable's NUL-terminated string value.
+ *
+ * @param 	dev	A bhnd bus child device.
+ * @param	name	The NVRAM variable name.
+ * @param[out]	buf	A buffer large enough to hold @p len bytes. On
+ *			success, the NUL-terminated string value will be
+ *			written to this buffer. This argment may be NULL if
+ *			the value is not desired.
+ * @param	len	The maximum capacity of @p buf.
+ * @param[out]	rlen	On success, will be set to the actual size of
+ *			the requested value (including NUL termination). This
+ *			argment may be NULL if the size is not desired.
+ *
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval ENODEV	No valid NVRAM source could be found.
+ * @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 a valid
+ *			string representation.
+ * @retval ERANGE	If value coercion would overflow @p type.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+int
+bhnd_nvram_getvar_str(device_t dev, const char *name, char *buf, size_t len,
+    size_t *rlen)
+{
+	size_t	larg;
+	int	error;
+
+	larg = len;
+	error = bhnd_nvram_getvar(dev, name, buf, &larg, BHND_NVRAM_TYPE_CSTR);
+	if (rlen != NULL)
+		*rlen = larg;
+
+	return (error);
+}
+
+/**
+ * Read an NVRAM variable's unsigned integer value.
+ *
+ * @param 		dev	A bhnd bus child device.
+ * @param		name	The NVRAM variable name.
+ * @param[out]		value	On success, the requested value will be written
+ *				to this pointer.
+ * @param		width	The output integer type width (1, 2, or
+ *				4 bytes).
+ * 
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval EFTYPE	If the variable data cannot be coerced to a
+ *			a valid unsigned integer representation.
+ * @retval ERANGE	If value coercion would overflow (or underflow) an
+ *			unsigned representation of the given @p width.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+int
+bhnd_nvram_getvar_uint(device_t dev, const char *name, void *value, int width)
+{
+	bhnd_nvram_type	type;
+	size_t		len;
+
+	switch (width) {
+	case 1:
+		type = BHND_NVRAM_TYPE_UINT8;
+		break;
+	case 2:
+		type = BHND_NVRAM_TYPE_UINT16;
+		break;
+	case 4:
+		type = BHND_NVRAM_TYPE_UINT32;
+		break;
+	default:
+		device_printf(dev, "unsupported NVRAM integer width: %d\n",
+		    width);
+		return (EINVAL);
+	}
+
+	len = width;
+	return (bhnd_nvram_getvar(dev, name, value, &len, type));
+}
+
+/**
+ * Read an NVRAM variable's unsigned 8-bit integer value.
+ *
+ * @param 		dev	A bhnd bus child device.
+ * @param		name	The NVRAM variable name.
+ * @param[out]		value	On success, the requested value will be written
+ *				to this pointer.
+ * 
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval EFTYPE	If the variable data cannot be coerced to a
+ *			a valid unsigned integer representation.
+ * @retval ERANGE	If value coercion would overflow (or underflow) uint8_t.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+int
+bhnd_nvram_getvar_uint8(device_t dev, const char *name, uint8_t *value)
+{
+	return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value)));
+}
+
+/**
+ * Read an NVRAM variable's unsigned 16-bit integer value.
+ *
+ * @param 		dev	A bhnd bus child device.
+ * @param		name	The NVRAM variable name.
+ * @param[out]		value	On success, the requested value will be written
+ *				to this pointer.
+ * 
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval EFTYPE	If the variable data cannot be coerced to a
+ *			a valid unsigned integer representation.
+ * @retval ERANGE	If value coercion would overflow (or underflow)
+ *			uint16_t.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+int
+bhnd_nvram_getvar_uint16(device_t dev, const char *name, uint16_t *value)
+{
+	return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value)));
+}
+
+/**
+ * Read an NVRAM variable's unsigned 32-bit integer value.
+ *
+ * @param 		dev	A bhnd bus child device.
+ * @param		name	The NVRAM variable name.
+ * @param[out]		value	On success, the requested value will be written
+ *				to this pointer.
+ * 
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval EFTYPE	If the variable data cannot be coerced to a
+ *			a valid unsigned integer representation.
+ * @retval ERANGE	If value coercion would overflow (or underflow)
+ *			uint32_t.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+int
+bhnd_nvram_getvar_uint32(device_t dev, const char *name, uint32_t *value)
+{
+	return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value)));
+}
+
+/**
+ * Read an NVRAM variable's signed integer value.
+ *
+ * @param 		dev	A bhnd bus child device.
+ * @param		name	The NVRAM variable name.
+ * @param[out]		value	On success, the requested value will be written
+ *				to this pointer.
+ * @param		width	The output integer type width (1, 2, or
+ *				4 bytes).
+ * 
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval EFTYPE	If the variable data cannot be coerced to a
+ *			a valid integer representation.
+ * @retval ERANGE	If value coercion would overflow (or underflow) an
+ *			signed representation of the given @p width.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+int
+bhnd_nvram_getvar_int(device_t dev, const char *name, void *value, int width)
+{
+	bhnd_nvram_type	type;
+	size_t		len;
+
+	switch (width) {
+	case 1:
+		type = BHND_NVRAM_TYPE_INT8;
+		break;
+	case 2:
+		type = BHND_NVRAM_TYPE_INT16;
+		break;
+	case 4:
+		type = BHND_NVRAM_TYPE_INT32;
+		break;
+	default:
+		device_printf(dev, "unsupported NVRAM integer width: %d\n",
+		    width);
+		return (EINVAL);
+	}
+
+	len = width;
+	return (bhnd_nvram_getvar(dev, name, value, &len, type));
+}
+
+/**
+ * Read an NVRAM variable's signed 8-bit integer value.
+ *
+ * @param 		dev	A bhnd bus child device.
+ * @param		name	The NVRAM variable name.
+ * @param[out]		value	On success, the requested value will be written
+ *				to this pointer.
+ * 
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval EFTYPE	If the variable data cannot be coerced to a
+ *			a valid integer representation.
+ * @retval ERANGE	If value coercion would overflow (or underflow) int8_t.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+int
+bhnd_nvram_getvar_int8(device_t dev, const char *name, int8_t *value)
+{
+	return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value)));
+}
+
+/**
+ * Read an NVRAM variable's signed 16-bit integer value.
+ *
+ * @param 		dev	A bhnd bus child device.
+ * @param		name	The NVRAM variable name.
+ * @param[out]		value	On success, the requested value will be written
+ *				to this pointer.
+ * 
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval EFTYPE	If the variable data cannot be coerced to a
+ *			a valid integer representation.
+ * @retval ERANGE	If value coercion would overflow (or underflow)
+ *			int16_t.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+int
+bhnd_nvram_getvar_int16(device_t dev, const char *name, int16_t *value)
+{
+	return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value)));
+}
+
+/**
+ * Read an NVRAM variable's signed 32-bit integer value.
+ *
+ * @param 		dev	A bhnd bus child device.
+ * @param		name	The NVRAM variable name.
+ * @param[out]		value	On success, the requested value will be written
+ *				to this pointer.
+ * 
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval EFTYPE	If the variable data cannot be coerced to a
+ *			a valid integer representation.
+ * @retval ERANGE	If value coercion would overflow (or underflow)
+ *			int32_t.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+int
+bhnd_nvram_getvar_int32(device_t dev, const char *name, int32_t *value)
+{
+	return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value)));
+}
+
+
+/**
+ * Read an NVRAM variable's array value.
+ *
+ * @param 		dev	A bhnd bus child device.
+ * @param		name	The NVRAM variable name.
+ * @param[out]		buf	A buffer large enough to hold @p size bytes.
+ *				On success, the requested value will be written
+ *				to this buffer.
+ * @param[in,out]	size	The required number of bytes to write to
+ *				@p buf.
+ * @param		type	The desired array element data representation.
+ * 
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval ENODEV	No valid NVRAM source could be found.
+ * @retval ENXIO	If less than @p size bytes are available.
+ * @retval ENOMEM	If a buffer of @p size is too small to hold the
+ *			requested value.
+ * @retval EFTYPE	If the variable data cannot be coerced to a
+ *			a valid instance of @p type.
+ * @retval ERANGE	If value coercion would overflow (or underflow) a
+ *			representation of @p type.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+int
+bhnd_nvram_getvar_array(device_t dev, const char *name, void *buf, size_t size,
+    bhnd_nvram_type type)
+{
+	size_t	nbytes;
+	int	error;
+
+	/* Attempt read */
+	nbytes = size;
+	if ((error = bhnd_nvram_getvar(dev, name, buf, &nbytes, type)))
+		return (error);
+
+	/* Verify that the expected number of bytes were fetched */
+	if (nbytes < size)
+		return (ENXIO);
+
+	return (0);
+}
+
+/**
  * Using the bhnd(4) bus-level core information and a custom core name,
  * populate @p dev's device description.
  * 
@@ -953,7 +1271,8 @@ bhnd_bus_generic_get_chipid(device_t dev
 
 /* nvram board_info population macros for bhnd_bus_generic_read_board_info() */
 #define	BHND_GV(_dest, _name)	\
-	bhnd_nvram_getvar(child, BHND_NVAR_ ## _name, &_dest, sizeof(_dest))
+	bhnd_nvram_getvar_uint(child, BHND_NVAR_ ## _name, &_dest,	\
+	    sizeof(_dest))
 
 #define	REQ_BHND_GV(_dest, _name)		do {			\
 	if ((error = BHND_GV(_dest, _name))) {				\
@@ -1017,7 +1336,7 @@ bhnd_bus_generic_read_board_info(device_
  */
 int
 bhnd_bus_generic_get_nvram_var(device_t dev, device_t child, const char *name,
-    void *buf, size_t *size)
+    void *buf, size_t *size, bhnd_nvram_type type)
 {
 	device_t	nvram;
 	device_t	parent;
@@ -1027,14 +1346,14 @@ bhnd_bus_generic_get_nvram_var(device_t 
 
 	/* Look for a directly-attached NVRAM child */
 	if ((nvram = device_find_child(dev, "bhnd_nvram", -1)) != NULL)
-		return BHND_NVRAM_GETVAR(nvram, name, buf, size);
+		return BHND_NVRAM_GETVAR(nvram, name, buf, size, type);
 
 	/* Try to delegate to parent */
 	if ((parent = device_get_parent(dev)) == NULL)
 		return (ENODEV);
 
 	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
-	    name, buf, size));
+	    name, buf, size, type));
 }
 
 /**

Modified: head/sys/dev/bhnd/bhnd_types.h
==============================================================================
--- head/sys/dev/bhnd/bhnd_types.h	Tue Aug 16 21:20:05 2016	(r304242)
+++ head/sys/dev/bhnd/bhnd_types.h	Tue Aug 16 21:32:05 2016	(r304243)
@@ -34,6 +34,8 @@
 
 #include <sys/types.h>
 
+#include "nvram/bhnd_nvram.h"
+
 /** bhnd(4) device classes. */
 typedef enum {
 	BHND_DEVCLASS_CC,		/**< chipcommon i/o controller */

Modified: head/sys/dev/bhnd/bhndvar.h
==============================================================================
--- head/sys/dev/bhnd/bhndvar.h	Tue Aug 16 21:20:05 2016	(r304242)
+++ head/sys/dev/bhnd/bhndvar.h	Tue Aug 16 21:32:05 2016	(r304243)
@@ -92,6 +92,6 @@ int			 bhnd_generic_resume_child(device_
 
 int			 bhnd_generic_get_nvram_var(device_t dev,
 			     device_t child, const char *name, void *buf,
-			     size_t *size);
+			     size_t *size, bhnd_nvram_type type);
 
 #endif /* _BHND_BHNDVAR_H_ */

Modified: head/sys/dev/bhnd/cores/chipc/chipc.c
==============================================================================
--- head/sys/dev/bhnd/cores/chipc/chipc.c	Tue Aug 16 21:20:05 2016	(r304242)
+++ head/sys/dev/bhnd/cores/chipc/chipc.c	Tue Aug 16 21:32:05 2016	(r304243)
@@ -369,19 +369,11 @@ chipc_find_nvram_src(struct chipc_softc 
 {
 	uint32_t		 otp_st, srom_ctrl;
 
-	/* Very early devices vend SPROM/OTP/CIS (if at all) via the
-	 * host bridge interface instead of ChipCommon. */
-	if (!CHIPC_QUIRK(sc, SUPPORTS_SPROM))
-		return (BHND_NVRAM_SRC_UNKNOWN);
-
 	/*
-	 * Later chipset revisions standardized the SPROM capability flags and
-	 * register interfaces.
-	 * 
 	 * We check for hardware presence in order of precedence. For example,
 	 * SPROM is is always used in preference to internal OTP if found.
 	 */
-	if (caps->sprom) {
+	if (CHIPC_QUIRK(sc, SUPPORTS_SPROM) && caps->sprom) {
 		srom_ctrl = bhnd_bus_read_4(sc->core, CHIPC_SPROM_CTRL);
 		if (srom_ctrl & CHIPC_SRC_PRESENT)
 			return (BHND_NVRAM_SRC_SPROM);

Added: head/sys/dev/bhnd/nvram/bhnd_nvram.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram.c	Tue Aug 16 21:32:05 2016	(r304243)
@@ -0,0 +1,189 @@
+/*-
+ * 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$");
+
+/*
+ * BHND CFE NVRAM driver.
+ * 
+ * Provides access to device NVRAM via CFE.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/limits.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/bhnd/bhnd.h>
+
+#include <dev/cfe/cfe_api.h>
+#include <dev/cfe/cfe_error.h>
+#include <dev/cfe/cfe_ioctl.h>
+
+#include "bhnd_nvram_if.h"
+
+#include "bhnd_nvramvar.h"
+
+/**
+ * Default bhnd_nvram driver implementation of DEVICE_PROBE().
+ */
+int
+bhnd_nvram_probe(device_t dev)
+{
+	device_set_desc(dev, "Broadcom NVRAM");
+
+	/* Refuse wildcard attachments */
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+/**
+ * Call from subclass DEVICE_ATTACH() implementations to handle
+ * device attachment.
+ * 
+ * @param dev BHND NVRAM device.
+ * @param data NVRAM data to be copied and parsed. No reference to data
+ * will be held after return.
+ * @param size Size of @p data, in bytes.
+ * @param fmt NVRAM format.
+ */
+int
+bhnd_nvram_attach(device_t dev, void *data, size_t size, bhnd_nvram_format fmt)
+{
+	struct bhnd_nvram_softc	*sc;
+	int			 error;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
+	/* Initialize NVRAM parser */
+	error = bhnd_nvram_parser_init(&sc->nvram, dev, data, size, fmt);
+	if (error)
+		return (error);
+
+	/* Initialize mutex */
+	BHND_NVRAM_LOCK_INIT(sc);
+
+	return (0);
+}
+
+/**
+ * Default bhnd_nvram driver implementation of DEVICE_RESUME().
+ */
+int
+bhnd_nvram_resume(device_t dev)
+{
+	return (0);
+}
+
+/**
+ * Default bhnd_nvram driver implementation of DEVICE_SUSPEND().
+ */
+int
+bhnd_nvram_suspend(device_t dev)
+{
+	return (0);
+}
+
+/**
+ * Default bhnd_nvram driver implementation of DEVICE_DETACH().
+ */
+int
+bhnd_nvram_detach(device_t dev)
+{
+	struct bhnd_nvram_softc	*sc;
+
+	sc = device_get_softc(dev);
+
+	bhnd_nvram_parser_fini(&sc->nvram);
+	BHND_NVRAM_LOCK_DESTROY(sc);
+
+	return (0);
+}
+
+/**
+ * Default bhnd_nvram driver implementation of BHND_NVRAM_GETVAR().
+ */
+static int
+bhnd_nvram_getvar_method(device_t dev, const char *name, void *buf, size_t *len,
+    bhnd_nvram_type type)
+{
+	struct bhnd_nvram_softc	*sc;
+	int			 error;
+
+	sc = device_get_softc(dev);
+
+	BHND_NVRAM_LOCK(sc);
+	error = bhnd_nvram_parser_getvar(&sc->nvram, name, buf, len, type);
+	BHND_NVRAM_UNLOCK(sc);
+
+	return (error);
+}
+
+/**
+ * Default bhnd_nvram driver implementation of BHND_NVRAM_SETVAR().
+ */
+static int
+bhnd_nvram_setvar_method(device_t dev, const char *name, const void *buf,
+    size_t len, bhnd_nvram_type type)
+{
+	struct bhnd_nvram_softc	*sc;
+	int			 error;
+
+	sc = device_get_softc(dev);
+
+	BHND_NVRAM_LOCK(sc);
+	error = bhnd_nvram_parser_setvar(&sc->nvram, name, buf, len, type);
+	BHND_NVRAM_UNLOCK(sc);
+
+	return (error);
+}
+
+static device_method_t bhnd_nvram_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		bhnd_nvram_probe),
+	DEVMETHOD(device_resume,	bhnd_nvram_resume),
+	DEVMETHOD(device_suspend,	bhnd_nvram_suspend),
+	DEVMETHOD(device_detach,	bhnd_nvram_detach),
+
+	/* NVRAM interface */
+	DEVMETHOD(bhnd_nvram_getvar,	bhnd_nvram_getvar_method),
+	DEVMETHOD(bhnd_nvram_setvar,	bhnd_nvram_setvar_method),
+
+	DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(bhnd_nvram, bhnd_nvram_driver, bhnd_nvram_methods, sizeof(struct bhnd_nvram_softc));

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram.h
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram.h	Tue Aug 16 21:20:05 2016	(r304242)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram.h	Tue Aug 16 21:32:05 2016	(r304243)
@@ -67,4 +67,50 @@ 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 */
+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;
+
+#undef	BHND_NVRAM_TYPE_ID_MASK
+#undef	BHND_NVRAM_TYPE_FLAGS_MASK
+#undef	BHND_NVRAM_TYPE_ID
+
+#define	BHND_NVRAM_SIGNED_TYPE(_type)	\
+	(((_type) & BHND_NVRAM_TF_SIGNED) == BHND_NVRAM_TF_SIGNED)
+
 #endif /* _BHND_NVRAM_BHND_NVRAM_H_ */

Added: head/sys/dev/bhnd/nvram/bhnd_nvram_cfe.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_cfe.c	Tue Aug 16 21:32:05 2016	(r304243)
@@ -0,0 +1,373 @@
+/*-
+ * 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$");
+
+/*
+ * BHND CFE NVRAM driver.
+ * 
+ * Provides access to device NVRAM via CFE.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/limits.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/bhnd/bhnd.h>
+
+#include <dev/cfe/cfe_api.h>
+#include <dev/cfe/cfe_error.h>
+#include <dev/cfe/cfe_ioctl.h>
+
+#include "bhnd_nvram_if.h"
+
+#include "bhnd_nvramvar.h"
+
+static int	 nvram_open_cfedev(device_t dev, char *devname, int fd,
+		     int64_t *offset, uint32_t *size, bhnd_nvram_format fmt);
+static char	*nvram_find_cfedev(device_t dev, int *fd, int64_t *offset,
+		     uint32_t *size, bhnd_nvram_format *fmt);
+
+/** Known CFE NVRAM device names, in probe order. */
+static char *nvram_cfe_devs[] = {
+	"nflash0.nvram",	/* NAND */
+	"nflash1.nvram",
+	"flash0.nvram",
+	"flash1.nvram",
+};
+
+/** Supported CFE NVRAM formats, in probe order. */
+bhnd_nvram_format nvram_cfe_fmts[] = {
+	BHND_NVRAM_FMT_BCM,
+	BHND_NVRAM_FMT_TLV
+};
+
+
+static int
+bhnd_nvram_cfe_probe(device_t dev)
+{
+	char				*devname;
+	bhnd_nvram_format		 fmt;
+	int64_t				 offset;
+	uint32_t			 size;
+	int				 error;
+	int				 fd;
+
+	/* Defer to default driver implementation */
+	if ((error = bhnd_nvram_probe(dev)) > 0)
+		return (error);
+
+	/* Locate a usable CFE device */
+	devname = nvram_find_cfedev(dev, &fd, &offset, &size, &fmt);
+	if (devname == NULL)
+		return (ENXIO);
+	cfe_close(fd);
+
+	switch (fmt) {
+	case BHND_NVRAM_FMT_BCM:
+		device_set_desc(dev, "Broadcom NVRAM");
+		break;
+	case BHND_NVRAM_FMT_TLV:
+		device_set_desc(dev, "Broadcom WGT634U NVRAM");
+		break;
+	default:
+		device_printf(dev, "unknown NVRAM format: %d\n", fmt);
+		return (ENXIO);
+	}
+
+	/* Refuse wildcard attachments */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



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