Index: head/sys/dev/bhnd/nvram/bhnd_nvram.h =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram.h +++ head/sys/dev/bhnd/nvram/bhnd_nvram.h @@ -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 @@ 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 @@ 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); Index: head/sys/dev/bhnd/nvram/bhnd_nvram_plist.h =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram_plist.h +++ head/sys/dev/bhnd/nvram/bhnd_nvram_plist.h @@ -104,6 +104,8 @@ 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 @@ 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, Index: head/sys/dev/bhnd/nvram/bhnd_nvram_plist.c =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram_plist.c +++ head/sys/dev/bhnd/nvram/bhnd_nvram_plist.c @@ -743,6 +743,27 @@ } /** + * 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 @@ } /** + * 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. Index: head/sys/dev/bhnd/nvram/bhnd_nvram_store.c =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram_store.c +++ head/sys/dev/bhnd/nvram/bhnd_nvram_store.c @@ -301,6 +301,9 @@ 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 @@ 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); Index: head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c +++ head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c @@ -136,6 +136,12 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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)); Index: head/sys/dev/bhnd/nvram/bhnd_nvram_value.h =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram_value.h +++ head/sys/dev/bhnd/nvram/bhnd_nvram_value.h @@ -235,6 +235,7 @@ 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(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(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_ */ Index: head/sys/dev/bhnd/nvram/bhnd_nvram_value.c =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram_value.c +++ head/sys/dev/bhnd/nvram/bhnd_nvram_value.c @@ -66,9 +66,19 @@ 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 @@ .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_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 @@ 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 @@ 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 @@ } /** + * 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 @@ /* 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 @@ 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 @@ /* 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 @@ 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 @@ /* 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 @@ 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 @@ 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)) Index: head/sys/dev/bhnd/nvram/bhnd_nvram_value_fmts.c =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram_value_fmts.c +++ head/sys/dev/bhnd/nvram/bhnd_nvram_value_fmts.c @@ -215,7 +215,10 @@ 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(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); /** Index: head/sys/dev/bhnd/nvram/bhnd_nvram_value_subr.c =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram_value_subr.c +++ head/sys/dev/bhnd/nvram/bhnd_nvram_value_subr.c @@ -66,6 +66,15 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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: