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
This commit is contained in:
Landon J. Fuller 2016-12-19 20:23:19 +00:00
parent 9be0790d19
commit 6cffadf0f0
9 changed files with 537 additions and 3 deletions

View file

@ -39,6 +39,14 @@
#include <stdint.h>
#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.
*/
@ -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);

View file

@ -742,6 +742,27 @@ bhnd_nvram_plist_get_uint64(bhnd_nvram_plist *plist, const char *name,
BHND_NVRAM_TYPE_UINT64));
}
/**
* 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.
*
@ -900,6 +921,18 @@ bhnd_nvram_prop_type(bhnd_nvram_prop *prop)
return (bhnd_nvram_val_type(prop->val));
}
/**
* 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.
*

View file

@ -104,6 +104,8 @@ int bhnd_nvram_plist_get_uint64(bhnd_nvram_plist *plist,
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_nvram_prop *prop);
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,

View file

@ -301,6 +301,9 @@ bhnd_nvram_store_setvar(struct bhnd_nvram_store *sc, const char *name,
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_nvram_store *sc, const char *name,
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);

View file

@ -136,6 +136,12 @@ bhnd_nvram_type_name(bhnd_nvram_type type)
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 type)
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_type type)
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_type 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 (false);
}
@ -243,6 +255,9 @@ bhnd_nvram_is_int_type(bhnd_nvram_type type)
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 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 (false);
}
@ -279,6 +295,9 @@ bhnd_nvram_is_array_type(bhnd_nvram_type 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 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 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 (type);
case BHND_NVRAM_TYPE_UINT8_ARRAY: return (BHND_NVRAM_TYPE_UINT8);
@ -330,6 +353,63 @@ bhnd_nvram_base_type(bhnd_nvram_type type)
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 type)
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_type type)
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));

View file

@ -66,9 +66,19 @@ static int bhnd_nvram_val_set(bhnd_nvram_val *value, const void *inp,
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(const void *inp, size_t ilen,
.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_storage; /**< data storage */
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_type type)
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_type type)
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 */
@ -634,6 +661,156 @@ bhnd_nvram_val_release(bhnd_nvram_val *value)
bhnd_nv_free(value);
}
/**
* 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.
*
@ -673,6 +850,14 @@ bhnd_nvram_val_encode_string(const void *inp, size_t ilen,
/* 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 *inp, size_t ilen,
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 *inp, size_t ilen, bhnd_nvram_type itype,
/* 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_nvram_val *value, const void *inp,
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 *value, const void *inp, size_t ilen,
/* 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 *value, const void *inp, size_t ilen,
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 *value, const void *inp, size_t ilen,
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))

View file

@ -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_ */

View file

@ -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, INT16_ARRAY);
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);
/**

View file

@ -66,6 +66,15 @@ bhnd_nvram_value_check_aligned(const void *inp, size_t ilen,
{
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, size_t ilen, bhnd_nvram_type itype,
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, size_t ilen, bhnd_nvram_type itype,
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, size_t ilen, bhnd_nvram_type itype,
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, size_t ilen, bhnd_nvram_type itype,
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, size_t ilen, bhnd_nvram_type itype,
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: