svn commit: r310293 - head/sys/dev/bhnd/nvram

Landon J. Fuller landonf at FreeBSD.org
Mon Dec 19 20:23:21 UTC 2016


Author: landonf
Date: Mon Dec 19 20:23:19 2016
New Revision: 310293
URL: https://svnweb.freebsd.org/changeset/base/310293

Log:
  bhnd(4): Add support for three new NVRAM value types; booleans,
  NULL (which we'll use to denote deleted values in bhnd_nvram_store), and
  opaque data (aka octet-strings).
  
  Approved by:	adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D8758

Modified:
  head/sys/dev/bhnd/nvram/bhnd_nvram.h
  head/sys/dev/bhnd/nvram/bhnd_nvram_plist.c
  head/sys/dev/bhnd/nvram/bhnd_nvram_plist.h
  head/sys/dev/bhnd/nvram/bhnd_nvram_store.c
  head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c
  head/sys/dev/bhnd/nvram/bhnd_nvram_value.c
  head/sys/dev/bhnd/nvram/bhnd_nvram_value.h
  head/sys/dev/bhnd/nvram/bhnd_nvram_value_fmts.c
  head/sys/dev/bhnd/nvram/bhnd_nvram_value_subr.c

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram.h
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram.h	Mon Dec 19 20:20:33 2016	(r310292)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram.h	Mon Dec 19 20:23:19 2016	(r310293)
@@ -40,6 +40,14 @@
 #endif /* _KERNEL */
 
 /**
+ * BHND NVRAM boolean type; guaranteed to be exactly 8-bits, representing
+ * true as integer constant 1, and false as integer constant 0.
+ * 
+ * Compatible with stdbool constants (true, false).
+ */
+typedef uint8_t	bhnd_nvram_bool_t;
+
+/**
  * NVRAM data sources supported by bhnd(4) devices.
  */
 typedef enum {
@@ -94,6 +102,10 @@ typedef enum {
 	BHND_NVRAM_TYPE_CHAR		= 8,	/**< ASCII/UTF-8 character */
 	BHND_NVRAM_TYPE_STRING		= 9,	/**< ASCII/UTF-8 NUL-terminated
 						     string */
+	BHND_NVRAM_TYPE_BOOL		= 10,	/**< uint8 boolean value. see
+						     bhnd_nvram_bool_t. */
+	BHND_NVRAM_TYPE_NULL		= 11,	/**< NULL (empty) value */
+	BHND_NVRAM_TYPE_DATA		= 12,	/**< opaque octet string */
 
 	/* 10-15 reserved for primitive (non-array) types */
 
@@ -109,13 +121,17 @@ typedef enum {
 						     characters */
 	BHND_NVRAM_TYPE_STRING_ARRAY	= 25,	/**< array of ASCII/UTF-8
 						     NUL-terminated strings */
+	BHND_NVRAM_TYPE_BOOL_ARRAY	= 26,	/**< array of uint8 boolean
+						     values */
 } bhnd_nvram_type;
 
+
 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);
+bhnd_nvram_type	 bhnd_nvram_raw_type(bhnd_nvram_type type);
 const char	*bhnd_nvram_type_name(bhnd_nvram_type type);
 size_t		 bhnd_nvram_type_width(bhnd_nvram_type type);
 size_t		 bhnd_nvram_type_host_align(bhnd_nvram_type type);

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_plist.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_plist.c	Mon Dec 19 20:20:33 2016	(r310292)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_plist.c	Mon Dec 19 20:23:19 2016	(r310293)
@@ -743,6 +743,27 @@ bhnd_nvram_plist_get_uint64(bhnd_nvram_p
 }
 
 /**
+ * Return the boolean representation of a named property's value.
+ * 
+ * @param	plist	The property list to be queried.
+ * @param	name	The name of the property value to be returned.
+ * @param[out]	val	On success, the boolean value of @p name.
+ *
+ * @retval 0		success
+ * @retval ENOENT	If @p name is not found in @p plist.
+ * @retval EFTYPE	If coercion of the property's value to @p val.
+ * @retval ERANGE	If coercion of the property's value would overflow
+ *			(or underflow) @p val.
+ */
+int
+bhnd_nvram_plist_get_bool(bhnd_nvram_plist *plist, const char *name,
+    bool *val)
+{
+	return (bhnd_nvram_plist_get_encoded(plist, name, val, sizeof(*val),
+	    BHND_NVRAM_TYPE_BOOL));
+}
+
+/**
  * Allocate and initialize a new property value.
  * 
  * The caller is responsible for releasing the returned property value
@@ -901,6 +922,18 @@ bhnd_nvram_prop_type(bhnd_nvram_prop *pr
 }
 
 /**
+ * Return true if @p prop has a NULL value type (BHND_NVRAM_TYPE_NULL), false
+ * otherwise.
+ * 
+ * @param      prop    The property to query.
+ */
+bool
+bhnd_nvram_prop_is_null(bhnd_nvram_prop *prop)
+{
+	return (bhnd_nvram_prop_type(prop) == BHND_NVRAM_TYPE_NULL);
+}
+
+/**
  * Return a borrowed reference to the property's internal value representation.
  *
  * @param	prop	The property to query.

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_plist.h
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_plist.h	Mon Dec 19 20:20:33 2016	(r310292)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_plist.h	Mon Dec 19 20:23:19 2016	(r310293)
@@ -104,6 +104,8 @@ int			 bhnd_nvram_plist_get_uint64(bhnd_
 			     const char *name, uint64_t *val);
 int			 bhnd_nvram_plist_get_string(bhnd_nvram_plist *plist,
 			     const char *name, const char **val);
+int			 bhnd_nvram_plist_get_bool(bhnd_nvram_plist *plist,
+			     const char *name, bool *val);
 
 bhnd_nvram_prop		*bhnd_nvram_prop_new(const char *name,
 			     bhnd_nvram_val *val);
@@ -118,6 +120,8 @@ const char		*bhnd_nvram_prop_name(bhnd_n
 bhnd_nvram_val		*bhnd_nvram_prop_val(bhnd_nvram_prop *prop);
 bhnd_nvram_type		 bhnd_nvram_prop_type(bhnd_nvram_prop *prop);
 
+bool			 bhnd_nvram_prop_is_null(bhnd_nvram_prop *prop);
+
 const void		*bhnd_nvram_prop_bytes(bhnd_nvram_prop *prop,
 			     size_t *olen, bhnd_nvram_type *otype);
 int			 bhnd_nvram_prop_encode(bhnd_nvram_prop *prop,

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_store.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_store.c	Mon Dec 19 20:20:33 2016	(r310292)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_store.c	Mon Dec 19 20:23:19 2016	(r310293)
@@ -301,6 +301,9 @@ bhnd_nvram_store_setvar(struct bhnd_nvra
 	case BHND_NVRAM_TYPE_INT16:
 	case BHND_NVRAM_TYPE_INT32:
 	case BHND_NVRAM_TYPE_INT64:
+	case BHND_NVRAM_TYPE_NULL:
+	case BHND_NVRAM_TYPE_DATA:
+	case BHND_NVRAM_TYPE_BOOL:
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:
 	case BHND_NVRAM_TYPE_UINT16_ARRAY:
 	case BHND_NVRAM_TYPE_UINT32_ARRAY:
@@ -311,6 +314,7 @@ bhnd_nvram_store_setvar(struct bhnd_nvra
 	case BHND_NVRAM_TYPE_INT64_ARRAY:
 	case BHND_NVRAM_TYPE_CHAR_ARRAY:
 	case BHND_NVRAM_TYPE_STRING_ARRAY:
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:
 		// TODO: non-char/string value support
 		return (EOPNOTSUPP);
 

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c	Mon Dec 19 20:20:33 2016	(r310292)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c	Mon Dec 19 20:23:19 2016	(r310293)
@@ -136,6 +136,12 @@ bhnd_nvram_type_name(bhnd_nvram_type typ
 		return ("int64");
 	case BHND_NVRAM_TYPE_STRING:
 		return ("string");
+	case BHND_NVRAM_TYPE_BOOL:
+		return ("bool");
+	case BHND_NVRAM_TYPE_NULL:
+		return ("null");
+	case BHND_NVRAM_TYPE_DATA:
+		return ("data");
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:
 		return ("uint8[]");
 	case BHND_NVRAM_TYPE_UINT16_ARRAY:
@@ -156,6 +162,8 @@ bhnd_nvram_type_name(bhnd_nvram_type typ
 		return ("char[]");
 	case BHND_NVRAM_TYPE_STRING_ARRAY:
 		return ("string[]");
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:
+		return ("bool[]");
 	}
 
 	/* Quiesce gcc4.2 */
@@ -186,6 +194,9 @@ bhnd_nvram_is_signed_type(bhnd_nvram_typ
 	case BHND_NVRAM_TYPE_UINT32:
 	case BHND_NVRAM_TYPE_UINT64:
 	case BHND_NVRAM_TYPE_STRING:
+	case BHND_NVRAM_TYPE_BOOL:
+	case BHND_NVRAM_TYPE_NULL:
+	case BHND_NVRAM_TYPE_DATA:
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:
 	case BHND_NVRAM_TYPE_UINT16_ARRAY:
 	case BHND_NVRAM_TYPE_UINT32_ARRAY:
@@ -196,6 +207,7 @@ bhnd_nvram_is_signed_type(bhnd_nvram_typ
 	case BHND_NVRAM_TYPE_INT64_ARRAY:
 	case BHND_NVRAM_TYPE_CHAR_ARRAY:
 	case BHND_NVRAM_TYPE_STRING_ARRAY:
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:
 		return (false);
 	}
 
@@ -243,6 +255,9 @@ bhnd_nvram_is_int_type(bhnd_nvram_type t
 
 	case BHND_NVRAM_TYPE_CHAR:
 	case BHND_NVRAM_TYPE_STRING:
+	case BHND_NVRAM_TYPE_BOOL:
+	case BHND_NVRAM_TYPE_NULL:
+	case BHND_NVRAM_TYPE_DATA:
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:
 	case BHND_NVRAM_TYPE_UINT16_ARRAY:
 	case BHND_NVRAM_TYPE_UINT32_ARRAY:
@@ -253,6 +268,7 @@ bhnd_nvram_is_int_type(bhnd_nvram_type t
 	case BHND_NVRAM_TYPE_INT64_ARRAY:
 	case BHND_NVRAM_TYPE_CHAR_ARRAY:
 	case BHND_NVRAM_TYPE_STRING_ARRAY:
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:
 		return (false);
 	}
 
@@ -279,6 +295,9 @@ bhnd_nvram_is_array_type(bhnd_nvram_type
 	case BHND_NVRAM_TYPE_INT64:
 	case BHND_NVRAM_TYPE_CHAR:
 	case BHND_NVRAM_TYPE_STRING:
+	case BHND_NVRAM_TYPE_BOOL:
+	case BHND_NVRAM_TYPE_NULL:
+	case BHND_NVRAM_TYPE_DATA:
 		return (false);
 
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:
@@ -291,6 +310,7 @@ bhnd_nvram_is_array_type(bhnd_nvram_type
 	case BHND_NVRAM_TYPE_INT64_ARRAY:
 	case BHND_NVRAM_TYPE_CHAR_ARRAY:
 	case BHND_NVRAM_TYPE_STRING_ARRAY:
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:
 		return (true);
 	}
 
@@ -318,6 +338,9 @@ bhnd_nvram_base_type(bhnd_nvram_type typ
 	case BHND_NVRAM_TYPE_INT64:
 	case BHND_NVRAM_TYPE_CHAR:
 	case BHND_NVRAM_TYPE_STRING:
+	case BHND_NVRAM_TYPE_BOOL:
+	case BHND_NVRAM_TYPE_NULL:
+	case BHND_NVRAM_TYPE_DATA:
 		return (type);
 
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:	return (BHND_NVRAM_TYPE_UINT8);
@@ -330,6 +353,63 @@ bhnd_nvram_base_type(bhnd_nvram_type typ
 	case BHND_NVRAM_TYPE_INT64_ARRAY:	return (BHND_NVRAM_TYPE_INT64);
 	case BHND_NVRAM_TYPE_CHAR_ARRAY:	return (BHND_NVRAM_TYPE_CHAR);
 	case BHND_NVRAM_TYPE_STRING_ARRAY:	return (BHND_NVRAM_TYPE_STRING);
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:	return (BHND_NVRAM_TYPE_BOOL);
+	}
+
+	/* Quiesce gcc4.2 */
+	BHND_NV_PANIC("bhnd nvram type %u unknown", type);
+}
+
+/**
+ * Return the raw data type used to represent values of @p type, or return
+ * @p type is @p type is not a complex type.
+ *
+ * @param type The type to query.
+ */
+bhnd_nvram_type
+bhnd_nvram_raw_type(bhnd_nvram_type type)
+{
+	switch (type) {
+	case BHND_NVRAM_TYPE_CHAR:
+		return (BHND_NVRAM_TYPE_UINT8);
+
+	case BHND_NVRAM_TYPE_CHAR_ARRAY:
+		return (BHND_NVRAM_TYPE_UINT8_ARRAY);
+
+	case BHND_NVRAM_TYPE_BOOL: {
+		_Static_assert(sizeof(bhnd_nvram_bool_t) == sizeof(uint8_t),
+		    "bhnd_nvram_bool_t must be uint8-representable");
+		return (BHND_NVRAM_TYPE_UINT8);
+	}
+
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:
+		return (BHND_NVRAM_TYPE_UINT8_ARRAY);
+
+	case BHND_NVRAM_TYPE_DATA:
+		return (BHND_NVRAM_TYPE_UINT8_ARRAY);
+
+	case BHND_NVRAM_TYPE_STRING:
+	case BHND_NVRAM_TYPE_STRING_ARRAY:
+		return (BHND_NVRAM_TYPE_UINT8_ARRAY);
+
+	case BHND_NVRAM_TYPE_UINT8:
+	case BHND_NVRAM_TYPE_UINT16:
+	case BHND_NVRAM_TYPE_UINT32:
+	case BHND_NVRAM_TYPE_UINT64:
+	case BHND_NVRAM_TYPE_INT8:
+	case BHND_NVRAM_TYPE_INT16:
+	case BHND_NVRAM_TYPE_INT32:
+	case BHND_NVRAM_TYPE_INT64:
+	case BHND_NVRAM_TYPE_NULL:
+	case BHND_NVRAM_TYPE_UINT8_ARRAY:
+	case BHND_NVRAM_TYPE_UINT16_ARRAY:
+	case BHND_NVRAM_TYPE_UINT32_ARRAY:
+	case BHND_NVRAM_TYPE_UINT64_ARRAY:
+	case BHND_NVRAM_TYPE_INT8_ARRAY:
+	case BHND_NVRAM_TYPE_INT16_ARRAY:
+	case BHND_NVRAM_TYPE_INT32_ARRAY:
+	case BHND_NVRAM_TYPE_INT64_ARRAY:
+		return (type);
 	}
 
 	/* Quiesce gcc4.2 */
@@ -348,8 +428,16 @@ bhnd_nvram_type_width(bhnd_nvram_type ty
 	switch (type) {
 	case BHND_NVRAM_TYPE_STRING:
 	case BHND_NVRAM_TYPE_STRING_ARRAY:
+	case BHND_NVRAM_TYPE_DATA:
 		return (0);
 
+	case BHND_NVRAM_TYPE_NULL:
+		return (0);
+
+	case BHND_NVRAM_TYPE_BOOL:
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:
+		return (sizeof(bhnd_nvram_bool_t));
+
 	case BHND_NVRAM_TYPE_CHAR:
 	case BHND_NVRAM_TYPE_CHAR_ARRAY:
 	case BHND_NVRAM_TYPE_UINT8:
@@ -392,9 +480,18 @@ bhnd_nvram_type_host_align(bhnd_nvram_ty
 	switch (type) {
 	case BHND_NVRAM_TYPE_CHAR:
 	case BHND_NVRAM_TYPE_CHAR_ARRAY:
+	case BHND_NVRAM_TYPE_DATA:
 	case BHND_NVRAM_TYPE_STRING:
 	case BHND_NVRAM_TYPE_STRING_ARRAY:
 		return (_Alignof(uint8_t));
+	case BHND_NVRAM_TYPE_BOOL:
+	case BHND_NVRAM_TYPE_BOOL_ARRAY: {
+		_Static_assert(sizeof(bhnd_nvram_bool_t) == sizeof(uint8_t),
+		    "bhnd_nvram_bool_t must be uint8-representable");
+		return (_Alignof(uint8_t));
+	}
+	case BHND_NVRAM_TYPE_NULL:
+		return (1);
 	case BHND_NVRAM_TYPE_UINT8:
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:
 		return (_Alignof(uint8_t));

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_value.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_value.c	Mon Dec 19 20:20:33 2016	(r310292)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_value.c	Mon Dec 19 20:23:19 2016	(r310293)
@@ -66,9 +66,19 @@ static int	 bhnd_nvram_val_set(bhnd_nvra
 static int	 bhnd_nvram_val_set_inline(bhnd_nvram_val *value,
 		     const void *inp, size_t ilen, bhnd_nvram_type itype);
 
+
+static int	 bhnd_nvram_val_encode_data(const void *inp, size_t ilen,
+		     bhnd_nvram_type itype, void *outp, size_t *olen,
+		     bhnd_nvram_type otype);
 static int	 bhnd_nvram_val_encode_int(const void *inp, size_t ilen,
 		     bhnd_nvram_type itype, void *outp, size_t *olen,
 		     bhnd_nvram_type otype);
+static int	 bhnd_nvram_val_encode_null(const void *inp, size_t ilen,
+		     bhnd_nvram_type itype, void *outp, size_t *olen,
+		     bhnd_nvram_type otype);
+static int	 bhnd_nvram_val_encode_bool(const void *inp, size_t ilen,
+		     bhnd_nvram_type itype, void *outp, size_t *olen,
+		     bhnd_nvram_type otype);
 static int	 bhnd_nvram_val_encode_string(const void *inp, size_t ilen,
 		     bhnd_nvram_type itype, void *outp, size_t *olen,
 		     bhnd_nvram_type otype);
@@ -83,7 +93,6 @@ static int	 bhnd_nvram_val_encode_string
 		.data_storage = BHND_NVRAM_VAL_DATA_NONE,	\
 	};
 
-
 /** Assert that @p value's backing representation state has initialized
  *  as empty. */
 #define	BHND_NVRAM_VAL_ASSERT_EMPTY(_value)			\
@@ -120,6 +129,16 @@ bhnd_nvram_val_data_storage	 data_storag
 bhnd_nvram_type			 data_type;	/**< data type */
 size_t				 data_len;	/**< data size */
 
+/* Shared NULL value instance */
+bhnd_nvram_val bhnd_nvram_val_null = {
+	.refs		= 1,
+	.val_storage	= BHND_NVRAM_VAL_STORAGE_STATIC,
+	.fmt		= &bhnd_nvram_val_null_fmt,
+	.data_storage	= BHND_NVRAM_VAL_DATA_INLINE,
+	.data_type	= BHND_NVRAM_TYPE_NULL,
+	.data_len	= 0,
+};
+
 /**
  * Return the human-readable name of @p fmt.
  */
@@ -156,6 +175,12 @@ bhnd_nvram_val_default_fmt(bhnd_nvram_ty
 		return (&bhnd_nvram_val_char_fmt);
 	case BHND_NVRAM_TYPE_STRING:
 		return (&bhnd_nvram_val_string_fmt);
+	case BHND_NVRAM_TYPE_BOOL:
+		return (&bhnd_nvram_val_bool_fmt);
+	case BHND_NVRAM_TYPE_NULL:
+		return (&bhnd_nvram_val_null_fmt);
+	case BHND_NVRAM_TYPE_DATA:
+		return (&bhnd_nvram_val_data_fmt);
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:
 		return (&bhnd_nvram_val_uint8_array_fmt);
 	case BHND_NVRAM_TYPE_UINT16_ARRAY:
@@ -176,6 +201,8 @@ bhnd_nvram_val_default_fmt(bhnd_nvram_ty
 		return (&bhnd_nvram_val_char_array_fmt);
 	case BHND_NVRAM_TYPE_STRING_ARRAY:
 		return (&bhnd_nvram_val_string_array_fmt);
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:
+		return (&bhnd_nvram_val_bool_array_fmt);
 	}
 	
 	/* Quiesce gcc4.2 */
@@ -635,6 +662,156 @@ bhnd_nvram_val_release(bhnd_nvram_val *v
 }
 
 /**
+ * Standard BHND_NVRAM_TYPE_NULL encoding implementation.
+ */
+static int
+bhnd_nvram_val_encode_null(const void *inp, size_t ilen, bhnd_nvram_type itype,
+    void *outp, size_t *olen, bhnd_nvram_type otype)
+{
+	size_t	limit, nbytes;
+
+	BHND_NV_ASSERT(itype == BHND_NVRAM_TYPE_NULL,
+	    ("unsupported type: %d", itype));
+
+	/* Determine output byte limit */
+	if (outp != NULL)
+		limit = *olen;
+	else
+		limit = 0;
+
+	nbytes = 0;
+
+	/* Write to output */
+	switch (otype) {
+	case BHND_NVRAM_TYPE_NULL:
+		/* Can be directly encoded as a zero-length NULL value */
+		nbytes = 0;
+		break;
+	default:
+		/* Not representable */
+		return (EFTYPE);
+	}
+
+	/* Provide required length */
+	*olen = nbytes;
+	if (limit < *olen) {
+		if (outp == NULL)
+			return (0);
+
+		return (ENOMEM);
+	}
+
+	return (0);
+}
+
+/**
+ * Standard BHND_NVRAM_TYPE_BOOL encoding implementation.
+ */
+static int
+bhnd_nvram_val_encode_bool(const void *inp, size_t ilen, bhnd_nvram_type itype,
+    void *outp, size_t *olen, bhnd_nvram_type otype)
+{
+	bhnd_nvram_bool_t	bval;
+	size_t			limit, nbytes, nelem;
+	int			error;
+
+	BHND_NV_ASSERT(itype == BHND_NVRAM_TYPE_BOOL,
+	    ("unsupported type: %d", itype));
+
+	/* Determine output byte limit */
+	if (outp != NULL)
+		limit = *olen;
+	else
+		limit = 0;
+
+	/* Must be exactly one element in input */
+	if ((error = bhnd_nvram_value_nelem(inp, ilen, itype, &nelem)))
+		return (error);
+
+	if (nelem != 1)
+		return (EFTYPE);
+
+	/* Fetch (and normalize) boolean value */
+	bval = (*(const bhnd_nvram_bool_t *)inp != 0) ? true : false;
+
+	/* Write to output */
+	switch (otype) {
+	case BHND_NVRAM_TYPE_NULL:
+		/* False can be directly encoded as a zero-length NULL value */
+		if (bval != false)
+			return (EFTYPE);
+
+		nbytes = 0;
+		break;
+
+	case BHND_NVRAM_TYPE_STRING:
+	case BHND_NVRAM_TYPE_STRING_ARRAY: {
+		/* Can encode as "true" or "false" */
+		const char *str = bval ? "true" : "false";
+
+		nbytes = strlen(str) + 1;
+		if (limit > nbytes)
+			strcpy(outp, str);
+
+		break;
+	}
+
+	default:
+		/* If output type is an integer, we can delegate to standard
+		 * integer encoding to encode as zero or one. */
+		if (bhnd_nvram_is_int_type(otype)) {
+			uint8_t	ival = bval ? 1 : 0;
+
+			return (bhnd_nvram_val_encode_int(&ival, sizeof(ival),
+			    BHND_NVRAM_TYPE_UINT8, outp, olen, otype));
+		}
+
+		/* Otherwise not representable */
+		return (EFTYPE);
+	}
+
+	/* Provide required length */
+	*olen = nbytes;
+	if (limit < *olen) {
+		if (outp == NULL)
+			return (0);
+
+		return (ENOMEM);
+	}
+
+	return (0);
+}
+
+/**
+ * Standard BHND_NVRAM_TYPE_DATA encoding implementation.
+ */
+static int
+bhnd_nvram_val_encode_data(const void *inp, size_t ilen, bhnd_nvram_type itype,
+    void *outp, size_t *olen, bhnd_nvram_type otype)
+{
+	BHND_NV_ASSERT(itype == BHND_NVRAM_TYPE_DATA,
+	    ("unsupported type: %d", itype));
+
+	/* Write to output */
+	switch (otype) {
+	case BHND_NVRAM_TYPE_STRING:
+	case BHND_NVRAM_TYPE_STRING_ARRAY:
+		/* If encoding as a string, produce an EFI-style hexadecimal
+		 * byte array (HF1F...) by interpreting the octet string
+		 * as an array of uint8 values */
+		return (bhnd_nvram_value_printf("H%[]02hhX", inp, ilen,
+		    BHND_NVRAM_TYPE_UINT8_ARRAY, outp, olen, ""));
+
+	default:
+		/* Fall back on direct interpretation as an array of 8-bit
+		 * integers array */
+		return (bhnd_nvram_value_coerce(inp, ilen,
+		    BHND_NVRAM_TYPE_UINT8_ARRAY, outp, olen, otype));
+	}
+}
+
+
+/**
  * Standard string/char array/char encoding implementation.
  *
  * Input type must be one of:
@@ -673,6 +850,14 @@ bhnd_nvram_val_encode_string(const void 
 
 	/* Parse the string data and write to output */
 	switch (otype) {
+	case BHND_NVRAM_TYPE_NULL:
+		/* Only an empty string may be represented as a NULL value */
+		if (cstr_len != 0)
+			return (EFTYPE);
+
+		*olen = 0;
+		return (0);
+
 	case BHND_NVRAM_TYPE_CHAR:
 	case BHND_NVRAM_TYPE_CHAR_ARRAY:
 		/* String must contain exactly 1 non-terminating-NUL character
@@ -696,6 +881,99 @@ bhnd_nvram_val_encode_string(const void 
 
 		return (0);
 
+	case BHND_NVRAM_TYPE_BOOL:
+	case BHND_NVRAM_TYPE_BOOL_ARRAY: {
+		const char		*p;
+		size_t			 plen;
+		bhnd_nvram_bool_t	 bval;
+
+		/* Trim leading/trailing whitespace */
+		p = cstr;
+		plen = bhnd_nvram_trim_field(&p, cstr_len, '\0');
+
+		/* Parse string representation */
+		if (strncasecmp(p, "true", plen) == 0 ||
+		    strncasecmp(p, "yes", plen) == 0 ||
+		    strncmp(p, "1", plen) == 0)
+		{
+			bval = true;
+		} else if (strncasecmp(p, "false", plen) == 0 ||
+		    strncasecmp(p, "no", plen) == 0 ||
+		    strncmp(p, "0", plen) == 0)
+		{
+			bval = false;
+		} else {
+			/* Not a recognized boolean string */
+			return (EFTYPE);
+		}
+
+		/* Write to output */
+		nbytes = sizeof(bhnd_nvram_bool_t);
+		if (limit >= nbytes)
+			*((bhnd_nvram_bool_t *)outp) = bval;
+
+		/* Provide required length */
+		*olen = nbytes;
+		if (limit < *olen && outp != NULL)
+			return (ENOMEM);
+
+		return (0);
+	}
+
+	case BHND_NVRAM_TYPE_DATA: {
+		const char	*p;
+		size_t		 plen, parsed_len;
+		int		 error;
+
+		/* Trim leading/trailing whitespace */
+		p = cstr;
+		plen = bhnd_nvram_trim_field(&p, cstr_len, '\0');
+
+		/* Check for EFI-style hexadecimal byte array string format.
+		 * Must have a 'H' prefix  */
+		if (plen < 1 || bhnd_nv_toupper(*p) != 'H')
+			return (EFTYPE);
+
+		/* Skip leading 'H' */
+		p++;
+		plen--;
+
+		/* Parse the input string's two-char octets until the end
+		 * of input is reached. The last octet may contain only
+		 * one char */
+		while (plen > 0) {
+			uint8_t	byte;
+			size_t	byte_len = sizeof(byte);
+
+			/* Parse next two-character hex octet */
+			error = bhnd_nvram_parse_int(p, bhnd_nv_ummin(plen, 2),
+			    16, &parsed_len, &byte, &byte_len, otype_base);
+			if (error) {
+				BHND_NV_DEBUG("error parsing '%.*s' as "
+				    "integer: %d\n", BHND_NV_PRINT_WIDTH(plen),
+				     p, error);
+
+				return (error);
+			}
+
+			/* Write to output */
+			if (limit > nbytes)
+				*((uint8_t *)outp + nbytes) = byte;
+			nbytes++;
+
+			/* Advance input */
+			p += parsed_len;
+			plen -= parsed_len;
+		}
+
+		/* Provide required length */
+		*olen = nbytes;
+		if (limit < *olen && outp != NULL)
+			return (ENOMEM);
+
+		return (0);
+	}
+
 	case BHND_NVRAM_TYPE_UINT8:
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:
 	case BHND_NVRAM_TYPE_UINT16:
@@ -896,8 +1174,30 @@ bhnd_nvram_val_encode_int(const void *in
 
 	/* Write output */
 	switch (otype) {
+	case BHND_NVRAM_TYPE_NULL:
+		/* Cannot encode an integer value as NULL */
+		return (EFTYPE);
+
+	case BHND_NVRAM_TYPE_BOOL: {
+		bhnd_nvram_bool_t bval;
+
+		if (intv.u64 == 0 || intv.u64 == 1) {
+			bval = intv.u64;
+		} else {
+			/* Encoding as a bool would lose information */
+			return (ERANGE);
+		}
+
+		nbytes = sizeof(bhnd_nvram_bool_t);
+		if (limit >= nbytes)
+			*((bhnd_nvram_bool_t *)outp) = bval;
+
+		break;
+	}
+
 	case BHND_NVRAM_TYPE_CHAR:
 	case BHND_NVRAM_TYPE_CHAR_ARRAY:
+	case BHND_NVRAM_TYPE_DATA:
 	case BHND_NVRAM_TYPE_UINT8:
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:
 		if (intv.u64 > UINT8_MAX)
@@ -1335,11 +1635,23 @@ bhnd_nvram_val_generic_encode_elem(bhnd_
 
 	itype = bhnd_nvram_val_elem_type(value);
 	switch (itype) {
+	case BHND_NVRAM_TYPE_NULL:
+		return (bhnd_nvram_val_encode_null(inp, ilen, itype, outp, olen,
+		    otype));
+
+	case BHND_NVRAM_TYPE_DATA:
+		return (bhnd_nvram_val_encode_data(inp, ilen, itype, outp,
+		    olen, otype));
+
 	case BHND_NVRAM_TYPE_STRING:
 	case BHND_NVRAM_TYPE_CHAR:
 		return (bhnd_nvram_val_encode_string(inp, ilen, itype, outp,
 		    olen, otype));
 
+	case BHND_NVRAM_TYPE_BOOL:
+		return (bhnd_nvram_val_encode_bool(inp, ilen, itype, outp, olen,
+		    otype));
+
 	case BHND_NVRAM_TYPE_UINT8:
 	case BHND_NVRAM_TYPE_UINT16:
 	case BHND_NVRAM_TYPE_UINT32:
@@ -1486,10 +1798,22 @@ bhnd_nvram_val_set_inline(bhnd_nvram_val
 
 	/* Attempt to copy to inline storage */
 	switch (itype) {
+	case BHND_NVRAM_TYPE_NULL:
+		if (ilen != 0)
+			return (EFAULT);
+
+		/* Nothing to copy */
+		NV_STORE_INIT_INLINE();
+		return (0);
+
 	case BHND_NVRAM_TYPE_CHAR:
 		NV_STORE_INLINE(uint8_t, ch);
 		return (0);
 
+	case BHND_NVRAM_TYPE_BOOL:
+		NV_STORE_INLINE(bhnd_nvram_bool_t, b);
+		return(0);
+
 	case BHND_NVRAM_TYPE_UINT8:
 	case BHND_NVRAM_TYPE_INT8:
 		NV_STORE_INLINE(uint8_t, u8);
@@ -1514,6 +1838,7 @@ bhnd_nvram_val_set_inline(bhnd_nvram_val
 		NV_COPY_ARRRAY_INLINE(uint8_t, ch);
 		return (0);
 
+	case BHND_NVRAM_TYPE_DATA:
 	case BHND_NVRAM_TYPE_UINT8_ARRAY:
 	case BHND_NVRAM_TYPE_INT8_ARRAY:
 		NV_COPY_ARRRAY_INLINE(uint8_t, u8);
@@ -1534,6 +1859,10 @@ bhnd_nvram_val_set_inline(bhnd_nvram_val
 		NV_COPY_ARRRAY_INLINE(uint64_t, u64);
 		return (0);
 
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:
+		NV_COPY_ARRRAY_INLINE(bhnd_nvram_bool_t, b);
+		return(0);
+
 	case BHND_NVRAM_TYPE_STRING:
 	case BHND_NVRAM_TYPE_STRING_ARRAY:
 		if (ilen > sizeof(value->data.ch))

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_value.h
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_value.h	Mon Dec 19 20:20:33 2016	(r310292)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_value.h	Mon Dec 19 20:23:19 2016	(r310293)
@@ -235,6 +235,7 @@ struct bhnd_nvram_val {
 		int32_t			 i32[2];	/**< 32-bit signed data */
 		int64_t			 i64[1];	/**< 64-bit signed data */
 		unsigned char		 ch[8];		/**< 8-bit character data */
+		bhnd_nvram_bool_t	 b[8];		/**< 8-bit boolean data */
 		const void		*ptr;		/**< external data */
 	} data;
 };
@@ -258,7 +259,10 @@ BHND_NVRAM_VAL_FMT_DECL(int16);
 BHND_NVRAM_VAL_FMT_DECL(int32);
 BHND_NVRAM_VAL_FMT_DECL(int64);
 BHND_NVRAM_VAL_FMT_DECL(char);
+BHND_NVRAM_VAL_FMT_DECL(bool);
 BHND_NVRAM_VAL_FMT_DECL(string);
+BHND_NVRAM_VAL_FMT_DECL(data);
+BHND_NVRAM_VAL_FMT_DECL(null);
 
 BHND_NVRAM_VAL_FMT_DECL(uint8_array);
 BHND_NVRAM_VAL_FMT_DECL(uint16_array);
@@ -269,6 +273,11 @@ BHND_NVRAM_VAL_FMT_DECL(int16_array);
 BHND_NVRAM_VAL_FMT_DECL(int32_array);
 BHND_NVRAM_VAL_FMT_DECL(int64_array);
 BHND_NVRAM_VAL_FMT_DECL(char_array);
+BHND_NVRAM_VAL_FMT_DECL(bool_array);
 BHND_NVRAM_VAL_FMT_DECL(string_array);
 
+/** Shared NULL value instance */
+#define	BHND_NVRAM_VAL_NULL	(&bhnd_nvram_val_null)
+extern bhnd_nvram_val bhnd_nvram_val_null;
+
 #endif /* _BHND_NVRAM_BHND_NVRAM_VALUE_H_ */

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_value_fmts.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_value_fmts.c	Mon Dec 19 20:20:33 2016	(r310292)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_value_fmts.c	Mon Dec 19 20:23:19 2016	(r310293)
@@ -215,7 +215,10 @@ BHND_NVRAM_VAL_FMT_NATIVE(int16,	INT16);
 BHND_NVRAM_VAL_FMT_NATIVE(int32,	INT32);
 BHND_NVRAM_VAL_FMT_NATIVE(int64,	INT64);
 BHND_NVRAM_VAL_FMT_NATIVE(char,		CHAR);
+BHND_NVRAM_VAL_FMT_NATIVE(bool,		BOOL);
 BHND_NVRAM_VAL_FMT_NATIVE(string,	STRING);
+BHND_NVRAM_VAL_FMT_NATIVE(data,		DATA);
+BHND_NVRAM_VAL_FMT_NATIVE(null,		NULL);
 
 BHND_NVRAM_VAL_FMT_NATIVE(uint8_array,	UINT8_ARRAY);
 BHND_NVRAM_VAL_FMT_NATIVE(uint16_array,	UINT16_ARRAY);
@@ -226,6 +229,7 @@ BHND_NVRAM_VAL_FMT_NATIVE(int16_array,	I
 BHND_NVRAM_VAL_FMT_NATIVE(int32_array,	INT32_ARRAY);
 BHND_NVRAM_VAL_FMT_NATIVE(int64_array,	INT64_ARRAY);
 BHND_NVRAM_VAL_FMT_NATIVE(char_array,	CHAR_ARRAY);
+BHND_NVRAM_VAL_FMT_NATIVE(bool_array,	BOOL_ARRAY);
 BHND_NVRAM_VAL_FMT_NATIVE(string_array,	STRING_ARRAY);
 
 /**

Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_value_subr.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_value_subr.c	Mon Dec 19 20:20:33 2016	(r310292)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_value_subr.c	Mon Dec 19 20:23:19 2016	(r310293)
@@ -66,6 +66,15 @@ bhnd_nvram_value_check_aligned(const voi
 {
 	size_t align, width;
 
+	/* As a special case, NULL values have no alignment, but must
+	 * always have a length of zero */
+	if (itype == BHND_NVRAM_TYPE_NULL) {
+		if (ilen != 0)
+			return (EFAULT);
+
+		return (0);
+	}
+
 	/* Check pointer alignment against the required host alignment */
 	align = bhnd_nvram_type_host_align(itype);
 	BHND_NV_ASSERT(align != 0, ("invalid zero alignment"));
@@ -119,6 +128,20 @@ bhnd_nvram_value_nelem(const void *inp, 
 		return (error);
 
 	switch (itype) {
+	case BHND_NVRAM_TYPE_DATA:
+		/* Always exactly one element */
+		*nelem = 1;
+		return (0);
+
+	case BHND_NVRAM_TYPE_NULL:
+		/* Must be zero length */
+		if (ilen != 0)
+			return (EFAULT);
+
+		/* Always exactly one element */
+		*nelem = 1;
+		return (0);
+
 	case BHND_NVRAM_TYPE_STRING:
 		/* Always exactly one element */
 		*nelem = 1;
@@ -165,7 +188,8 @@ bhnd_nvram_value_nelem(const void *inp, 
 	case BHND_NVRAM_TYPE_INT16_ARRAY:
 	case BHND_NVRAM_TYPE_INT32_ARRAY:
 	case BHND_NVRAM_TYPE_INT64_ARRAY:
-	case BHND_NVRAM_TYPE_CHAR_ARRAY: {
+	case BHND_NVRAM_TYPE_CHAR_ARRAY:
+	case BHND_NVRAM_TYPE_BOOL_ARRAY: {
 		size_t width = bhnd_nvram_type_width(itype);
 		BHND_NV_ASSERT(width != 0, ("invalid width"));
 
@@ -182,6 +206,7 @@ bhnd_nvram_value_nelem(const void *inp, 
 	case BHND_NVRAM_TYPE_UINT32:
 	case BHND_NVRAM_TYPE_INT64:
 	case BHND_NVRAM_TYPE_UINT64:
+	case BHND_NVRAM_TYPE_BOOL:
 		/* Length must be equal to the size of exactly one
 		 * element (arrays can represent zero elements -- non-array
 		 * types cannot) */
@@ -236,7 +261,8 @@ bhnd_nvram_value_size(const void *inp, s
 	case BHND_NVRAM_TYPE_INT16_ARRAY:
 	case BHND_NVRAM_TYPE_INT32_ARRAY:
 	case BHND_NVRAM_TYPE_INT64_ARRAY:
-	case BHND_NVRAM_TYPE_CHAR_ARRAY: {
+	case BHND_NVRAM_TYPE_CHAR_ARRAY:
+	case BHND_NVRAM_TYPE_BOOL_ARRAY:{
 		size_t width;
 
 		width = bhnd_nvram_type_width(itype);
@@ -305,6 +331,18 @@ bhnd_nvram_value_size(const void *inp, s
 		return (size);
 	}
 
+	case BHND_NVRAM_TYPE_NULL:
+		return (0);
+
+	case BHND_NVRAM_TYPE_DATA:
+		if (inp == NULL)
+			return (0);
+
+		return (ilen);
+
+	case BHND_NVRAM_TYPE_BOOL:
+		return (sizeof(bhnd_nvram_bool_t));
+
 	case BHND_NVRAM_TYPE_INT8:
 	case BHND_NVRAM_TYPE_UINT8:
 	case BHND_NVRAM_TYPE_CHAR:


More information about the svn-src-all mailing list