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:
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to