Page MenuHomeFreeBSD

D8757.diff
No OneTemporary

D8757.diff

Index: head/sys/conf/files
===================================================================
--- head/sys/conf/files
+++ head/sys/conf/files
@@ -1247,6 +1247,7 @@
dev/bhnd/nvram/bhnd_nvram_value.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_value_fmts.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_value_prf.c optional bhnd
+dev/bhnd/nvram/bhnd_nvram_value_subr.c optional bhnd
dev/bhnd/nvram/bhnd_sprom.c optional bhnd
dev/bhnd/siba/siba.c optional siba bhnd
dev/bhnd/siba/siba_bhndb.c optional siba bhnd bhndb
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
@@ -111,14 +111,16 @@
NUL-terminated strings */
} bhnd_nvram_type;
-const char *bhnd_nvram_string_array_next(const char *inp, size_t ilen,
- const char *prev);
-
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);
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);
+
+const char *bhnd_nvram_string_array_next(const char *inp, size_t ilen,
+ const char *prev, size_t *olen);
#endif /* _BHND_NVRAM_BHND_NVRAM_H_ */
Index: head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c
===================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c
@@ -647,10 +647,8 @@
/* Handle header variables */
if ((hvar = bhnd_nvram_bcm_to_hdrvar(bcm, cookiep)) != NULL) {
- BHND_NV_ASSERT(
- hvar->len % bhnd_nvram_value_size(hvar->type, NULL, 0,
- hvar->nelem) == 0,
- ("length is not aligned to type width"));
+ BHND_NV_ASSERT(bhnd_nvram_value_check_aligned(&hvar->value,
+ hvar->len, hvar->type) == 0, ("value misaligned"));
*type = hvar->type;
*len = hvar->len;
Index: head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c
===================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c
@@ -597,7 +597,7 @@
} sp_value;
/* Determine type width */
- sp_width = bhnd_nvram_value_size(type, NULL, 0, 1);
+ sp_width = bhnd_nvram_type_width(type);
if (sp_width == 0) {
/* Variable-width types are unsupported */
BHND_NV_LOG("invalid %s SPROM offset type %d\n", var->name,
@@ -716,7 +716,7 @@
var_btype = bhnd_nvram_base_type(var->type);
/* Calculate total byte length of the native encoding */
- if ((iwidth = bhnd_nvram_value_size(var_btype, NULL, 0, 1)) == 0) {
+ if ((iwidth = bhnd_nvram_value_size(NULL, 0, var_btype, 1)) == 0) {
/* SPROM does not use (and we do not support) decoding of
* variable-width data types */
BHND_NV_LOG("invalid SPROM data type: %d", var->type);
@@ -1219,7 +1219,7 @@
}
/* Fetch type width for use as our scale value */
- width = bhnd_nvram_value_size(type, NULL, 0, 1);
+ width = bhnd_nvram_type_width(type);
if (width == 0) {
SPROM_OP_BAD(state, "unsupported variable-width type: %d\n",
type);
Index: head/sys/dev/bhnd/nvram/bhnd_nvram_private.h
===================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_private.h
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_private.h
@@ -167,11 +167,15 @@
void *outp, size_t *olen,
bhnd_nvram_type otype);
-int bhnd_nvram_value_nelem(bhnd_nvram_type type,
- const void *data, size_t len,
+int bhnd_nvram_value_check_aligned(const void *inp,
+ size_t ilen, bhnd_nvram_type itype);
+
+int bhnd_nvram_value_nelem(const void *inp,
+ size_t ilen, bhnd_nvram_type itype,
size_t *nelem);
-size_t bhnd_nvram_value_size(bhnd_nvram_type type,
- const void *data, size_t nbytes,
+
+size_t bhnd_nvram_value_size(const void *inp,
+ size_t ilen, bhnd_nvram_type itype,
size_t nelem);
int bhnd_nvram_value_printf(const char *fmt,
@@ -183,6 +187,10 @@
bhnd_nvram_type itype, char *outp,
size_t *olen, va_list ap);
+const void *bhnd_nvram_value_array_next(const void *inp,
+ size_t ilen, bhnd_nvram_type itype,
+ const void *prev, size_t *olen);
+
const struct bhnd_nvram_vardefn *bhnd_nvram_find_vardefn(const char *varname);
const struct bhnd_nvram_vardefn *bhnd_nvram_get_vardefn(size_t id);
size_t bhnd_nvram_get_vardefn_id(
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
@@ -288,7 +288,7 @@
/* Verify buffer size alignment for the given type. If this is a
* variable width type, a width of 0 will always pass this check */
- if (len % bhnd_nvram_value_size(type, buf, len, 1) != 0)
+ if (len % bhnd_nvram_value_size(buf, len, type, 1) != 0)
return (EINVAL);
/* Determine string format (or directly add variable, if a C string) */
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
@@ -71,12 +71,6 @@
MALLOC_DEFINE(M_BHND_NVRAM, "bhnd_nvram", "bhnd nvram data");
#endif
-/** signed/unsigned 32-bit integer value storage */
-union bhnd_nvram_int_storage {
- uint32_t u32;
- int32_t s32;
-};
-
/*
* CRC-8 lookup table used to checksum SPROM and NVRAM data via
* bhnd_nvram_crc8().
@@ -343,112 +337,44 @@
}
/**
- * Calculate the number of elements represented by a value of @p len bytes
- * with @p type.
- *
- * @param type The value type.
- * @param data The actual data to be queried, or NULL if unknown.
- * @param len The length in bytes of @p data, or if @p data is NULL,
- * the expected length in bytes.
- * @param[out] nelem On success, the number of elements. If @p type is not
- * a fixed width type (e.g. BHND_NVRAM_TYPE_STRING_ARRAY),
- * and @p data is NULL, an @p nelem value of 0 will be
- * returned.
- *
- * @retval 0 success
- * @retval EFTYPE if @p type is not an array type, and @p len is not
- * equal to the size of a single element of @p type.
- * @retval EFAULT if @p len is not correctly aligned for elements of
- * @p type.
+ * Return the size, in bytes, of a single element of @p type, or 0
+ * if @p type is a variable-width type.
+ *
+ * @param type The type to query.
*/
-int
-bhnd_nvram_value_nelem(bhnd_nvram_type type, const void *data, size_t len,
- size_t *nelem)
+size_t
+bhnd_nvram_type_width(bhnd_nvram_type type)
{
- bhnd_nvram_type base_type;
- size_t base_size;
-
- /* Length must be aligned to the element size */
- base_type = bhnd_nvram_base_type(type);
- base_size = bhnd_nvram_value_size(base_type, NULL, 0, 1);
- if (base_size != 0 && len % base_size != 0)
- return (EFAULT);
-
switch (type) {
case BHND_NVRAM_TYPE_STRING:
- case BHND_NVRAM_TYPE_STRING_ARRAY: {
- const char *p;
- size_t nleft;
-
- /* Cannot determine the element count without parsing
- * the actual data */
- if (data == NULL) {
- *nelem = 0;
- return (0);
- }
-
- /* Iterate over the NUL-terminated strings to calculate
- * total element count */
- p = data;
- nleft = len;
- *nelem = 0;
- while (nleft > 0) {
- size_t slen;
-
- /* Increment element count */
- (*nelem)++;
-
- /* If not a string array, data must not contain more
- * than one entry. */
- if (!bhnd_nvram_is_array_type(type) && *nelem > 1)
- return (EFTYPE);
-
- /* Determine string length */
- slen = strnlen(p, nleft);
- nleft -= slen;
-
- /* Advance input */
- p += slen;
-
- /* Account for trailing NUL, if we haven't hit the end
- * of the input */
- if (nleft > 0) {
- nleft--;
- p++;
- }
- }
-
- return (0);
- }
- case BHND_NVRAM_TYPE_INT8:
- case BHND_NVRAM_TYPE_UINT8:
- case BHND_NVRAM_TYPE_CHAR:
- case BHND_NVRAM_TYPE_INT16:
- case BHND_NVRAM_TYPE_UINT16:
- case BHND_NVRAM_TYPE_INT32:
- case BHND_NVRAM_TYPE_UINT32:
- case BHND_NVRAM_TYPE_INT64:
- case BHND_NVRAM_TYPE_UINT64:
- /* Length must be equal to the size of exactly one
- * element (arrays can represent zero elements -- non-array
- * types cannot) */
- if (len != base_size)
- return (EFTYPE);
- *nelem = 1;
+ case BHND_NVRAM_TYPE_STRING_ARRAY:
return (0);
+ case BHND_NVRAM_TYPE_CHAR:
+ case BHND_NVRAM_TYPE_CHAR_ARRAY:
+ case BHND_NVRAM_TYPE_UINT8:
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:
case BHND_NVRAM_TYPE_INT8_ARRAY:
+ return (sizeof(uint8_t));
+
+ case BHND_NVRAM_TYPE_UINT16:
+ case BHND_NVRAM_TYPE_UINT16_ARRAY:
+ case BHND_NVRAM_TYPE_INT16:
case BHND_NVRAM_TYPE_INT16_ARRAY:
+ return (sizeof(uint16_t));
+
+ case BHND_NVRAM_TYPE_UINT32:
+ case BHND_NVRAM_TYPE_UINT32_ARRAY:
+ case BHND_NVRAM_TYPE_INT32:
case BHND_NVRAM_TYPE_INT32_ARRAY:
+ return (sizeof(uint32_t));
+
+ case BHND_NVRAM_TYPE_UINT64:
+ case BHND_NVRAM_TYPE_UINT64_ARRAY:
+ case BHND_NVRAM_TYPE_INT64:
case BHND_NVRAM_TYPE_INT64_ARRAY:
- case BHND_NVRAM_TYPE_CHAR_ARRAY:
- BHND_NV_ASSERT(base_size != 0, ("invalid base size"));
- *nelem = len / base_size;
- return (0);
+ return (sizeof(uint64_t));
}
/* Quiesce gcc4.2 */
@@ -456,130 +382,43 @@
}
/**
- * Return the size, in bytes, of a value of @p type with @p nelem elements.
+ * Return the native host alignment for values of @p type.
*
- * @param type The value type.
- * @param data The actual data to be queried, or NULL if unknown. If
- * NULL and the base type is not a fixed width type
- * (e.g. BHND_NVRAM_TYPE_STRING), 0 will be returned.
- * @param nbytes The size of @p data, in bytes, or 0 if @p data is NULL.
- * @param nelem The number of elements. If @p type is not an array type,
- * this value must be 1.
- *
- * @retval 0 If @p type has a variable width, and @p data is NULL.
- * @retval 0 If a @p nelem value greater than 1 is provided for a
- * non-array @p type.
- * @retval 0 If a @p nelem value of 0 is provided.
- * @retval 0 If the result would exceed the maximum value
- * representable by size_t.
- * @retval non-zero The size, in bytes, of @p type with @p nelem elements.
+ * @param type The type to query.
*/
size_t
-bhnd_nvram_value_size(bhnd_nvram_type type, const void *data, size_t nbytes,
- size_t nelem)
+bhnd_nvram_type_host_align(bhnd_nvram_type type)
{
- /* If nelem 0, nothing to do */
- if (nelem == 0)
- return (0);
-
- /* Non-array types must have an nelem value of 1 */
- if (!bhnd_nvram_is_array_type(type) && nelem != 1)
- return (0);
-
switch (type) {
+ case BHND_NVRAM_TYPE_CHAR:
+ case BHND_NVRAM_TYPE_CHAR_ARRAY:
+ case BHND_NVRAM_TYPE_STRING:
+ case BHND_NVRAM_TYPE_STRING_ARRAY:
+ return (_Alignof(uint8_t));
+ case BHND_NVRAM_TYPE_UINT8:
case BHND_NVRAM_TYPE_UINT8_ARRAY:
+ return (_Alignof(uint8_t));
+ case BHND_NVRAM_TYPE_UINT16:
case BHND_NVRAM_TYPE_UINT16_ARRAY:
+ return (_Alignof(uint16_t));
+ case BHND_NVRAM_TYPE_UINT32:
case BHND_NVRAM_TYPE_UINT32_ARRAY:
+ return (_Alignof(uint32_t));
+ case BHND_NVRAM_TYPE_UINT64:
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:
- case BHND_NVRAM_TYPE_CHAR_ARRAY: {
- bhnd_nvram_type base_type;
- size_t base_size;
-
- base_type = bhnd_nvram_base_type(type);
- base_size = bhnd_nvram_value_size(base_type, NULL, 0, 1);
-
- /* Would nelem * base_size overflow? */
- if (SIZE_MAX / nelem < base_size) {
- BHND_NV_LOG("cannot represent size %s * %zu\n",
- bhnd_nvram_type_name(base_type), nelem);
- return (0);
- }
-
- return (nelem * base_size);
- }
-
- case BHND_NVRAM_TYPE_STRING_ARRAY: {
- const char *p;
- size_t total_size;
-
- if (data == NULL)
- return (0);
-
- /* Iterate over the NUL-terminated strings to calculate
- * total byte length */
- p = data;
- total_size = 0;
- for (size_t i = 0; i < nelem; i++) {
- size_t elem_size;
-
- elem_size = strnlen(p, nbytes - total_size);
- p += elem_size;
-
- /* Check for (and skip) terminating NUL */
- if (total_size < nbytes && *p == '\0') {
- elem_size++;
- p++;
- }
-
- /* Would total_size + elem_size overflow?
- *
- * A memory range larger than SIZE_MAX shouldn't be,
- * possible, but include the check for completeness */
- if (SIZE_MAX - total_size < elem_size)
- return (0);
-
- total_size += elem_size;
- }
-
- return (total_size);
- }
-
- case BHND_NVRAM_TYPE_STRING: {
- size_t size;
-
- if (data == NULL)
- return (0);
-
- /* Find length */
- size = strnlen(data, nbytes);
-
- /* Is there a terminating NUL, or did we just hit the
- * end of the string input */
- if (size < nbytes)
- size++;
-
- return (size);
- }
+ return (_Alignof(uint64_t));
case BHND_NVRAM_TYPE_INT8:
- case BHND_NVRAM_TYPE_UINT8:
- case BHND_NVRAM_TYPE_CHAR:
- return (sizeof(uint8_t));
-
+ case BHND_NVRAM_TYPE_INT8_ARRAY:
+ return (_Alignof(int8_t));
case BHND_NVRAM_TYPE_INT16:
- case BHND_NVRAM_TYPE_UINT16:
- return (sizeof(uint16_t));
-
+ case BHND_NVRAM_TYPE_INT16_ARRAY:
+ return (_Alignof(int16_t));
case BHND_NVRAM_TYPE_INT32:
- case BHND_NVRAM_TYPE_UINT32:
- return (sizeof(uint32_t));
-
- case BHND_NVRAM_TYPE_UINT64:
+ case BHND_NVRAM_TYPE_INT32_ARRAY:
+ return (_Alignof(int32_t));
case BHND_NVRAM_TYPE_INT64:
- return (sizeof(uint64_t));
+ case BHND_NVRAM_TYPE_INT64_ARRAY:
+ return (_Alignof(int64_t));
}
/* Quiesce gcc4.2 */
@@ -587,132 +426,30 @@
}
/**
- * Iterate over all strings in the @p inp string array.
+ * Iterate over all strings in the @p inp string array (@see
+ * BHNF_NVRAM_TYPE_STRING_ARRAY).
*
- * @param inp The string array to be iterated. This must be a buffer
- * of one or more NUL-terminated strings --
- * @see BHND_NVRAM_TYPE_STRING_ARRAY.
- * @param ilen The size, in bytes, of @p inp, including any
- * terminating NUL character(s).
- * @param prev The value previously returned by
- * bhnd_nvram_string_array_next(), or NULL to begin
- * iteration.
+ * @param inp The string array to be iterated. This must be a
+ * buffer of one or more NUL-terminated strings.
+ * @param ilen The size, in bytes, of @p inp, including any
+ * terminating NUL character(s).
+ * @param prev The pointer previously returned by
+ * bhnd_nvram_string_array_next(), or NULL to begin
+ * iteration.
+* @param[in,out] olen If @p prev is non-NULL, @p olen must be a
+ * pointer to the length previously returned by
+ * bhnd_nvram_string_array_next(). On success, will
+ * be set to the next element's length, in bytes.
*
* @retval non-NULL A reference to the next NUL-terminated string
* @retval NULL If the end of the string array is reached.
*/
const char *
-bhnd_nvram_string_array_next(const char *inp, size_t ilen, const char *prev)
+bhnd_nvram_string_array_next(const char *inp, size_t ilen, const char *prev,
+ size_t *olen)
{
- size_t nremain, plen;
-
- if (ilen == 0)
- return (NULL);
-
- if (prev == NULL)
- return (inp);
-
- /* Advance to next value */
- BHND_NV_ASSERT(prev >= inp, ("invalid prev pointer"));
- BHND_NV_ASSERT(prev < (inp+ilen), ("invalid prev pointer"));
-
- nremain = ilen - (size_t)(prev - inp);
- plen = strnlen(prev, nremain);
- nremain -= plen;
-
- /* Only a trailing NUL remains? */
- if (nremain <= 1)
- return (NULL);
-
- return (prev + plen + 1);
-}
-
-/**
- * Format a string representation of @p inp using @p fmt, with, writing the
- * result to @p outp.
- *
- * Refer to bhnd_nvram_val_vprintf() for full format string documentation.
- *
- * @param fmt The format string.
- * @param inp The value to be formatted.
- * @param ilen The size of @p inp, in bytes.
- * @param itype The type of @p inp.
- * @param[out] outp On success, the string value will be written to
- * this buffer. This argment may be NULL if the
- * value is not desired.
- * @param[in,out] olen The capacity of @p outp. On success, will be set
- * to the actual size of the formatted string.
- *
- * @retval 0 success
- * @retval EINVAL If @p fmt contains unrecognized format string
- * specifiers.
- * @retval ENOMEM If the @p outp is non-NULL, and the provided @p olen
- * is too small to hold the encoded value.
- * @retval EFTYPE If value coercion from @p inp to a string value via
- * @p fmt is unsupported.
- * @retval ERANGE If value coercion of @p value would overflow (or
- * underflow) the representation defined by @p fmt.
- */
-int
-bhnd_nvram_value_printf(const char *fmt, const void *inp, size_t ilen,
- bhnd_nvram_type itype, char *outp, size_t *olen, ...)
-{
- va_list ap;
- int error;
-
- va_start(ap, olen);
- error = bhnd_nvram_value_vprintf(fmt, inp, ilen, itype, outp, olen, ap);
- va_end(ap);
-
- return (error);
-}
-
-/**
- * Format a string representation of @p inp using @p fmt, with, writing the
- * result to @p outp.
- *
- * Refer to bhnd_nvram_val_vprintf() for full format string documentation.
- *
- * @param fmt The format string.
- * @param inp The value to be formatted.
- * @param ilen The size of @p inp, in bytes.
- * @param itype The type of @p inp.
- * @param[out] outp On success, the string value will be written to
- * this buffer. This argment may be NULL if the
- * value is not desired.
- * @param[in,out] olen The capacity of @p outp. On success, will be set
- * to the actual size of the formatted string.
- * @param ap Argument list.
- *
- * @retval 0 success
- * @retval EINVAL If @p fmt contains unrecognized format string
- * specifiers.
- * @retval ENOMEM If the @p outp is non-NULL, and the provided @p olen
- * is too small to hold the encoded value.
- * @retval EFTYPE If value coercion from @p inp to a string value via
- * @p fmt is unsupported.
- * @retval ERANGE If value coercion of @p value would overflow (or
- * underflow) the representation defined by @p fmt.
- */
-int
-bhnd_nvram_value_vprintf(const char *fmt, const void *inp, size_t ilen,
- bhnd_nvram_type itype, char *outp, size_t *olen, va_list ap)
-{
- bhnd_nvram_val val;
- int error;
-
- /* Map input buffer as a value instance */
- error = bhnd_nvram_val_init(&val, NULL, inp, ilen, itype,
- BHND_NVRAM_VAL_BORROW_DATA);
- if (error)
- return (error);
-
- /* Attempt to format the value */
- error = bhnd_nvram_val_vprintf(&val, fmt, outp, olen, ap);
-
- /* Clean up */
- bhnd_nvram_val_release(&val);
- return (error);
+ return (bhnd_nvram_value_array_next(inp, ilen,
+ BHND_NVRAM_TYPE_STRING_ARRAY, prev, olen));
}
/* used by bhnd_nvram_find_vardefn() */
@@ -825,47 +562,6 @@
}
/**
- * Coerce value @p inp of type @p itype to @p otype, writing the
- * result to @p outp.
- *
- * @param inp The value to be coerced.
- * @param ilen The size of @p inp, in bytes.
- * @param itype The base data type of @p inp.
- * @param[out] outp On success, the value will be written to this
- * buffer. This argment may be NULL if the value
- * is not desired.
- * @param[in,out] olen The capacity of @p outp. On success, will be set
- * to the actual size of the requested value.
- * @param otype The data type to be written to @p outp.
- *
- * @retval 0 success
- * @retval ENOMEM If @p outp is non-NULL and a buffer of @p olen is too
- * small to hold the requested value.
- * @retval EFTYPE If the variable data cannot be coerced to @p otype.
- * @retval ERANGE If value coercion would overflow @p otype.
- */
-int
-bhnd_nvram_value_coerce(const void *inp, size_t ilen, bhnd_nvram_type itype,
- void *outp, size_t *olen, bhnd_nvram_type otype)
-{
- bhnd_nvram_val val;
- int error;
-
- /* Wrap input buffer in a value instance */
- error = bhnd_nvram_val_init(&val, NULL, inp, ilen,
- itype, BHND_NVRAM_VAL_BORROW_DATA|BHND_NVRAM_VAL_FIXED);
- if (error)
- return (error);
-
- /* Try to encode as requested type */
- error = bhnd_nvram_val_encode(&val, outp, olen, otype);
-
- /* Clean up and return error */
- bhnd_nvram_val_release(&val);
- return (error);
-}
-
-/**
* Parses the string in the optionally NUL-terminated @p str to as an integer
* value of @p otype, accepting any integer format supported by the standard
* strtoul().
@@ -1114,7 +810,7 @@
value = -value;
/* Provide (and verify) required length */
- *olen = bhnd_nvram_value_size(otype, NULL, 0, 1);
+ *olen = bhnd_nvram_type_width(otype);
if (outp == NULL)
return (0);
else if (limit < *olen)
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
@@ -32,6 +32,7 @@
#ifndef _BHND_NVRAM_BHND_NVRAM_VALUE_H_
#define _BHND_NVRAM_BHND_NVRAM_VALUE_H_
+
#include <sys/refcount.h>
#ifdef _KERNEL
@@ -45,16 +46,32 @@
typedef struct bhnd_nvram_val_fmt bhnd_nvram_val_fmt;
typedef struct bhnd_nvram_val bhnd_nvram_val;
+const char *bhnd_nvram_val_fmt_name(
+ const bhnd_nvram_val_fmt *fmt);
+
+const bhnd_nvram_val_fmt *bhnd_nvram_val_default_fmt(
+ bhnd_nvram_type type);
+
int bhnd_nvram_val_init(bhnd_nvram_val *value,
const bhnd_nvram_val_fmt *fmt,
const void *inp, size_t ilen,
bhnd_nvram_type itype, uint32_t flags);
+int bhnd_nvram_val_convert_init(
+ bhnd_nvram_val *value,
+ const bhnd_nvram_val_fmt *fmt,
+ bhnd_nvram_val *src, uint32_t flags);
+
int bhnd_nvram_val_new(bhnd_nvram_val **value,
const bhnd_nvram_val_fmt *fmt,
const void *inp, size_t ilen,
bhnd_nvram_type itype, uint32_t flags);
+int bhnd_nvram_val_convert_new(
+ bhnd_nvram_val **value,
+ const bhnd_nvram_val_fmt *fmt,
+ bhnd_nvram_val *src, uint32_t flags);
+
bhnd_nvram_val *bhnd_nvram_val_copy(bhnd_nvram_val *value);
void bhnd_nvram_val_release(
@@ -78,14 +95,14 @@
const void *bhnd_nvram_val_bytes(bhnd_nvram_val *value,
- size_t *len, bhnd_nvram_type *itype);
+ size_t *olen, bhnd_nvram_type *otype);
bhnd_nvram_type bhnd_nvram_val_type(bhnd_nvram_val *value);
bhnd_nvram_type bhnd_nvram_val_elem_type(
bhnd_nvram_val *value);
const void *bhnd_nvram_val_next(bhnd_nvram_val *value,
- const void *prev, size_t *len);
+ const void *prev, size_t *olen);
size_t bhnd_nvram_val_nelem(bhnd_nvram_val *value);
@@ -136,7 +153,7 @@
*/
typedef enum {
/**
- * The value structure has an automatic or static storage duration
+ * The value structure has an automatic storage duration
* (e.g. it is stack allocated, or is otherwise externally managed),
* and no destructors will be run prior to deallocation of the value.
*
@@ -153,6 +170,15 @@
* as-is.
*/
BHND_NVRAM_VAL_STORAGE_DYNAMIC = 2,
+
+ /**
+ * The value structure has a static storage duration, and will never
+ * be deallocated.
+ *
+ * When performing copy/retain, the existing structure may be referenced
+ * without modification.
+ */
+ BHND_NVRAM_VAL_STORAGE_STATIC = 3,
} bhnd_nvram_val_storage;
/**
@@ -169,20 +195,21 @@
BHND_NVRAM_VAL_DATA_INLINE = 1,
/**
- * Value represented by an external reference to data with a static
- * storage location. The data need not be copied if copying the value.
- */
+ * Value represented by an external reference to data with a static
+ * storage location. The data need not be copied if copying the value.
+ */
BHND_NVRAM_VAL_DATA_EXT_STATIC = 2,
/**
- * Value represented by weak external reference, which must be copied
- * if copying the value */
+ * Value represented by weak external reference, which must be copied
+ * if copying the value.
+ */
BHND_NVRAM_VAL_DATA_EXT_WEAK = 3,
/**
- * Value represented by an external reference that must be deallocated
- * when deallocating the value
- */
+ * Value represented by an external reference that must be deallocated
+ * when deallocating the value.
+ */
BHND_NVRAM_VAL_DATA_EXT_ALLOC = 4,
} bhnd_nvram_val_data_storage;
@@ -192,34 +219,56 @@
struct bhnd_nvram_val {
volatile u_int refs; /**< reference count */
bhnd_nvram_val_storage val_storage; /**< value structure storage */
- const bhnd_nvram_val_fmt *fmt; /**< value format, or NULL for default behavior */
+ const bhnd_nvram_val_fmt *fmt; /**< value format */
bhnd_nvram_val_data_storage data_storage; /**< data storage */
bhnd_nvram_type data_type; /**< data type */
size_t data_len; /**< data size */
/** data representation */
union {
- uint8_t u8[8]; /**< 8-bit unsigned data */
- uint16_t u16[4]; /**< 16-bit unsigned data */
- uint32_t u32[2]; /**< 32-bit unsigned data */
- uint32_t u64[1]; /**< 64-bit unsigned data */
- int8_t i8[8]; /**< 8-bit signed data */
- int16_t i16[4]; /**< 16-bit signed data */
- int32_t i32[2]; /**< 32-bit signed data */
- int64_t i64[1]; /**< 64-bit signed data */
- unsigned char ch[8]; /**< 8-bit character data */
- const void *ptr; /**< external data */
+ uint8_t u8[8]; /**< 8-bit unsigned data */
+ uint16_t u16[4]; /**< 16-bit unsigned data */
+ uint32_t u32[2]; /**< 32-bit unsigned data */
+ uint32_t u64[1]; /**< 64-bit unsigned data */
+ int8_t i8[8]; /**< 8-bit signed data */
+ int16_t i16[4]; /**< 16-bit signed data */
+ int32_t i32[2]; /**< 32-bit signed data */
+ int64_t i64[1]; /**< 64-bit signed data */
+ unsigned char ch[8]; /**< 8-bit character data */
+ const void *ptr; /**< external data */
} data;
};
/** Declare a bhnd_nvram_val_fmt with name @p _n */
-#define BHND_NVRAM_VAL_TYPE_DECL(_n) \
+#define BHND_NVRAM_VAL_FMT_DECL(_n) \
extern const bhnd_nvram_val_fmt bhnd_nvram_val_ ## _n ## _fmt;
-BHND_NVRAM_VAL_TYPE_DECL(bcm_decimal);
-BHND_NVRAM_VAL_TYPE_DECL(bcm_hex);
-BHND_NVRAM_VAL_TYPE_DECL(bcm_leddc);
-BHND_NVRAM_VAL_TYPE_DECL(bcm_macaddr);
-BHND_NVRAM_VAL_TYPE_DECL(bcm_string);
+BHND_NVRAM_VAL_FMT_DECL(bcm_decimal);
+BHND_NVRAM_VAL_FMT_DECL(bcm_hex);
+BHND_NVRAM_VAL_FMT_DECL(bcm_leddc);
+BHND_NVRAM_VAL_FMT_DECL(bcm_macaddr);
+BHND_NVRAM_VAL_FMT_DECL(bcm_string);
+
+BHND_NVRAM_VAL_FMT_DECL(uint8);
+BHND_NVRAM_VAL_FMT_DECL(uint16);
+BHND_NVRAM_VAL_FMT_DECL(uint32);
+BHND_NVRAM_VAL_FMT_DECL(uint64);
+BHND_NVRAM_VAL_FMT_DECL(int8);
+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(string);
+
+BHND_NVRAM_VAL_FMT_DECL(uint8_array);
+BHND_NVRAM_VAL_FMT_DECL(uint16_array);
+BHND_NVRAM_VAL_FMT_DECL(uint32_array);
+BHND_NVRAM_VAL_FMT_DECL(uint64_array);
+BHND_NVRAM_VAL_FMT_DECL(int8_array);
+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(string_array);
#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
@@ -35,6 +35,7 @@
#ifdef _KERNEL
+#include <sys/ctype.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/systm.h>
@@ -43,6 +44,7 @@
#else /* !_KERNEL */
+#include <ctype.h>
#include <inttypes.h>
#include <errno.h>
#include <stdlib.h>
@@ -54,6 +56,8 @@
#include "bhnd_nvram_valuevar.h"
+static int bhnd_nvram_val_fmt_filter(const bhnd_nvram_val_fmt **fmt,
+ const void *inp, size_t ilen, bhnd_nvram_type itype);
static void *bhnd_nvram_val_alloc_bytes(bhnd_nvram_val *value, size_t ilen,
bhnd_nvram_type itype, uint32_t flags);
@@ -62,6 +66,15 @@
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_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_string(const void *inp, size_t ilen,
+ bhnd_nvram_type itype, void *outp, size_t *olen,
+ bhnd_nvram_type otype);
+
+/** Initialize an empty value instance with @p _fmt, @p _storage, and
+ * an implicit callee-owned reference */
#define BHND_NVRAM_VAL_INITIALIZER(_fmt, _storage) \
(bhnd_nvram_val) { \
.refs = 1, \
@@ -80,6 +93,156 @@
value->data.ptr == NULL, \
("previously initialized value"))
+/** Return true if BHND_NVRAM_VAL_BORROW_DATA or BHND_NVRAM_VAL_STATIC_DATA is
+ * set in @p _flags (e.g. we should attempt to directly reference external
+ * data */
+#define BHND_NVRAM_VAL_EXTREF_BORROWED_DATA(_flags) \
+ (((_flags) & BHND_NVRAM_VAL_BORROW_DATA) || \
+ ((_flags) & BHND_NVRAM_VAL_STATIC_DATA))
+
+/** Flags permitted when performing val-based initialization via
+ * bhnd_nvram_val_convert_init() or bhnd_nvram_val_convert_new() */
+#define BHND_NVRAM_VALID_CONV_FLAGS \
+ (BHND_NVRAM_VAL_FIXED | \
+ BHND_NVRAM_VAL_DYNAMIC | \
+ BHND_NVRAM_VAL_COPY_DATA)
+
+/** Returns true if @p _val must be copied in bhnd_nvram_val_copy(), false
+ * if its reference count may be safely incremented */
+#define BHND_NVRAM_VAL_NEED_COPY(_val) \
+ ((_val)->val_storage == BHND_NVRAM_VAL_STORAGE_AUTO || \
+ (_val)->data_storage == BHND_NVRAM_VAL_DATA_EXT_WEAK)
+
+volatile u_int refs; /**< reference count */
+bhnd_nvram_val_storage val_storage; /**< value structure storage */
+const bhnd_nvram_val_fmt *fmt; /**< value format */
+bhnd_nvram_val_data_storage data_storage; /**< data storage */
+bhnd_nvram_type data_type; /**< data type */
+size_t data_len; /**< data size */
+
+/**
+ * Return the human-readable name of @p fmt.
+ */
+const char *
+bhnd_nvram_val_fmt_name(const bhnd_nvram_val_fmt *fmt)
+{
+ return (fmt->name);
+}
+
+/**
+ * Return the default format for values of @p type.
+ */
+const bhnd_nvram_val_fmt *
+bhnd_nvram_val_default_fmt(bhnd_nvram_type type)
+{
+ switch (type) {
+ case BHND_NVRAM_TYPE_UINT8:
+ return (&bhnd_nvram_val_uint8_fmt);
+ case BHND_NVRAM_TYPE_UINT16:
+ return (&bhnd_nvram_val_uint16_fmt);
+ case BHND_NVRAM_TYPE_UINT32:
+ return (&bhnd_nvram_val_uint32_fmt);
+ case BHND_NVRAM_TYPE_UINT64:
+ return (&bhnd_nvram_val_uint64_fmt);
+ case BHND_NVRAM_TYPE_INT8:
+ return (&bhnd_nvram_val_int8_fmt);
+ case BHND_NVRAM_TYPE_INT16:
+ return (&bhnd_nvram_val_int16_fmt);
+ case BHND_NVRAM_TYPE_INT32:
+ return (&bhnd_nvram_val_int32_fmt);
+ case BHND_NVRAM_TYPE_INT64:
+ return (&bhnd_nvram_val_int64_fmt);
+ case BHND_NVRAM_TYPE_CHAR:
+ return (&bhnd_nvram_val_char_fmt);
+ case BHND_NVRAM_TYPE_STRING:
+ return (&bhnd_nvram_val_string_fmt);
+ case BHND_NVRAM_TYPE_UINT8_ARRAY:
+ return (&bhnd_nvram_val_uint8_array_fmt);
+ case BHND_NVRAM_TYPE_UINT16_ARRAY:
+ return (&bhnd_nvram_val_uint16_array_fmt);
+ case BHND_NVRAM_TYPE_UINT32_ARRAY:
+ return (&bhnd_nvram_val_uint32_array_fmt);
+ case BHND_NVRAM_TYPE_UINT64_ARRAY:
+ return (&bhnd_nvram_val_uint64_array_fmt);
+ case BHND_NVRAM_TYPE_INT8_ARRAY:
+ return (&bhnd_nvram_val_int8_array_fmt);
+ case BHND_NVRAM_TYPE_INT16_ARRAY:
+ return (&bhnd_nvram_val_int16_array_fmt);
+ case BHND_NVRAM_TYPE_INT32_ARRAY:
+ return (&bhnd_nvram_val_int32_array_fmt);
+ case BHND_NVRAM_TYPE_INT64_ARRAY:
+ return (&bhnd_nvram_val_int64_array_fmt);
+ case BHND_NVRAM_TYPE_CHAR_ARRAY:
+ return (&bhnd_nvram_val_char_array_fmt);
+ case BHND_NVRAM_TYPE_STRING_ARRAY:
+ return (&bhnd_nvram_val_string_array_fmt);
+ }
+
+ /* Quiesce gcc4.2 */
+ BHND_NV_PANIC("bhnd nvram type %u unknown", type);
+}
+
+/**
+ * Determine whether @p fmt (or new format delegated to by @p fmt) is
+ * capable of direct initialization from buffer @p inp.
+ *
+ * @param[in,out] fmt Indirect pointer to the NVRAM value format. If
+ * the format instance cannot handle the data type
+ * directly, it may delegate to a new format
+ * instance. On success, this parameter will be
+ * set to the format that should be used when
+ * performing initialization from @p inp.
+ * @param inp Input data.
+ * @param ilen Input data length.
+ * @param itype Input data type.
+ *
+ * @retval 0 If initialization from @p inp is supported.
+ * @retval EFTYPE If initialization from @p inp is unsupported.
+ * @retval EFAULT if @p ilen is not correctly aligned for elements of
+ * @p itype.
+ */
+static int
+bhnd_nvram_val_fmt_filter(const bhnd_nvram_val_fmt **fmt, const void *inp,
+ size_t ilen, bhnd_nvram_type itype)
+{
+ const bhnd_nvram_val_fmt *ofmt, *nfmt;
+ int error;
+
+ nfmt = ofmt = *fmt;
+
+ /* Validate alignment */
+ if ((error = bhnd_nvram_value_check_aligned(inp, ilen, itype)))
+ return (error);
+
+ /* If the format does not provide a filter function, it only supports
+ * direct initialization from its native type */
+ if (ofmt->op_filter == NULL) {
+ if (itype == ofmt->native_type)
+ return (0);
+
+ return (EFTYPE);
+ }
+
+ /* Use the filter function to determine whether direct initialization
+ * from itype is permitted */
+ error = ofmt->op_filter(&nfmt, inp, ilen, itype);
+ if (error)
+ return (error);
+
+ /* Retry filter with new format? */
+ if (ofmt != nfmt) {
+ error = bhnd_nvram_val_fmt_filter(&nfmt, inp, ilen, itype);
+ if (error)
+ return (error);
+
+ /* Success -- provide delegated format to caller */
+ *fmt = nfmt;
+ }
+
+ /* Value can be initialized with provided format and input type */
+ return (0);
+}
+
/* Common initialization support for bhnd_nvram_val_init() and
* bhnd_nvram_val_new() */
static int
@@ -92,35 +255,20 @@
size_t olen;
int error;
+ /* If the value format is unspecified, we use the default format
+ * for the input data type */
+ if (fmt == NULL)
+ fmt = bhnd_nvram_val_default_fmt(itype);
+
/* Determine expected data type, and allow the format to delegate to
* a new format instance */
- if (fmt != NULL && fmt->op_filter != NULL) {
- const bhnd_nvram_val_fmt *nfmt = fmt;
-
- /* Use the filter function to determine whether direct
- * initialization from is itype permitted */
- error = fmt->op_filter(&nfmt, inp, ilen, itype);
- if (error)
- return (error);
-
- /* Retry initialization with new format? */
- if (nfmt != fmt) {
- return (bhnd_nvram_val_init_common(value, val_storage,
- nfmt, inp, ilen, itype, flags));
- }
-
- /* Value can be initialized with provided input type */
- otype = itype;
-
- } else if (fmt != NULL) {
- /* Value must be initialized with the format's native
- * type */
+ if ((error = bhnd_nvram_val_fmt_filter(&fmt, inp, ilen, itype))) {
+ /* Direct initialization from the provided input type is
+ * not supported; alue must be initialized with the format's
+ * native type */
otype = fmt->native_type;
-
} else {
- /* No format specified; we can initialize directly from the
- * input data, and we'll handle all format operations
- * internally. */
+ /* Value can be initialized with provided input type */
otype = itype;
}
@@ -236,6 +384,145 @@
return (error);
}
+
+/* Common initialization support for bhnd_nvram_val_convert_init() and
+ * bhnd_nvram_val_convert_new() */
+static int
+bhnd_nvram_val_convert_common(bhnd_nvram_val *value,
+ bhnd_nvram_val_storage val_storage, const bhnd_nvram_val_fmt *fmt,
+ bhnd_nvram_val *src, uint32_t flags)
+{
+ const void *inp;
+ void *outp;
+ bhnd_nvram_type itype, otype;
+ size_t ilen, olen;
+ int error;
+
+ /* Determine whether direct initialization from the source value's
+ * existing data type is supported by the new format */
+ inp = bhnd_nvram_val_bytes(src, &ilen, &itype);
+ if (bhnd_nvram_val_fmt_filter(&fmt, inp, ilen, itype) == 0) {
+ /* Adjust value flags based on the source data storage */
+ switch (src->data_storage) {
+ case BHND_NVRAM_VAL_DATA_NONE:
+ case BHND_NVRAM_VAL_DATA_INLINE:
+ case BHND_NVRAM_VAL_DATA_EXT_WEAK:
+ case BHND_NVRAM_VAL_DATA_EXT_ALLOC:
+ break;
+
+ case BHND_NVRAM_VAL_DATA_EXT_STATIC:
+ /* If the source data has static storage duration,
+ * we should apply that transitively */
+ if (flags & BHND_NVRAM_VAL_BORROW_DATA)
+ flags |= BHND_NVRAM_VAL_STATIC_DATA;
+
+ break;
+ }
+
+ /* Delegate to standard initialization */
+ return (bhnd_nvram_val_init_common(value, val_storage, fmt, inp,
+ ilen, itype, flags));
+ }
+
+ /* Value must be initialized with the format's native type */
+ otype = fmt->native_type;
+
+ /* Initialize value instance */
+ *value = BHND_NVRAM_VAL_INITIALIZER(fmt, val_storage);
+
+ /* Determine size when encoded in native format */
+ if ((error = bhnd_nvram_val_encode(src, NULL, &olen, otype)))
+ return (error);
+
+ /* Fetch reference to (or allocate) an appropriately sized buffer */
+ outp = bhnd_nvram_val_alloc_bytes(value, olen, otype, flags);
+ if (outp == NULL)
+ return (ENOMEM);
+
+ /* Perform encode */
+ if ((error = bhnd_nvram_val_encode(src, outp, &olen, otype)))
+ return (error);
+
+ return (0);
+}
+
+/**
+ * Initialize an externally allocated instance of @p value with @p fmt, and
+ * attempt to initialize its internal representation from the given @p src
+ * value.
+ *
+ * On success, the caller owns a reference to @p value, and is responsible for
+ * freeing any resources allocated for @p value via bhnd_nvram_val_release().
+ *
+ * @param value The externally allocated value instance to be
+ * initialized.
+ * @param fmt The value's format.
+ * @param src Input value to be converted.
+ * @param flags Value flags (see BHND_NVRAM_VAL_*).
+ *
+ * @retval 0 success
+ * @retval ENOMEM If allocation fails.
+ * @retval EFTYPE If @p fmt initialization from @p src is unsupported.
+ * @retval EFAULT if @p ilen is not correctly aligned for elements of
+ * @p itype.
+ * @retval ERANGE If value coercion of @p src would overflow
+ * (or underflow) the @p fmt representation.
+ */
+int
+bhnd_nvram_val_convert_init(bhnd_nvram_val *value,
+ const bhnd_nvram_val_fmt *fmt, bhnd_nvram_val *src, uint32_t flags)
+{
+ int error;
+
+ error = bhnd_nvram_val_convert_common(value,
+ BHND_NVRAM_VAL_STORAGE_AUTO, fmt, src, flags);
+ if (error)
+ bhnd_nvram_val_release(value);
+
+ return (error);
+}
+
+/**
+ * Allocate a value instance with @p fmt, and attempt to initialize its internal
+ * representation from the given @p src value.
+ *
+ * On success, the caller owns a reference to @p value, and is responsible for
+ * freeing any resources allocated for @p value via bhnd_nvram_val_release().
+ *
+ * @param[out] value On success, the allocated value instance.
+ * @param fmt The value's format.
+ * @param src Input value to be converted.
+ * @param flags Value flags (see BHND_NVRAM_VAL_*).
+ *
+ * @retval 0 success
+ * @retval ENOMEM If allocation fails.
+ * @retval EFTYPE If @p fmt initialization from @p src is unsupported.
+ * @retval EFAULT if @p ilen is not correctly aligned for elements of
+ * @p itype.
+ * @retval ERANGE If value coercion of @p src would overflow
+ * (or underflow) the @p fmt representation.
+ */
+int
+bhnd_nvram_val_convert_new(bhnd_nvram_val **value,
+ const bhnd_nvram_val_fmt *fmt, bhnd_nvram_val *src, uint32_t flags)
+{
+ int error;
+
+ /* Allocate new instance */
+ if ((*value = bhnd_nv_malloc(sizeof(**value))) == NULL)
+ return (ENOMEM);
+
+ /* Perform common initialization. */
+ error = bhnd_nvram_val_convert_common(*value,
+ BHND_NVRAM_VAL_STORAGE_DYNAMIC, fmt, src, flags);
+ if (error) {
+ /* Will also free() the value allocation */
+ bhnd_nvram_val_release(*value);
+ }
+
+ return (error);
+}
+
/**
* Copy or retain a reference to @p value.
*
@@ -250,22 +537,35 @@
bhnd_nvram_val *
bhnd_nvram_val_copy(bhnd_nvram_val *value)
{
- bhnd_nvram_val *result;
+ bhnd_nvram_val *result;
const void *bytes;
bhnd_nvram_type type;
size_t len;
uint32_t flags;
int error;
- /* If dynamically allocated, simply bump the reference count */
- if (value->val_storage == BHND_NVRAM_VAL_STORAGE_DYNAMIC) {
- refcount_acquire(&value->refs);
+ switch (value->val_storage) {
+ case BHND_NVRAM_VAL_STORAGE_STATIC:
+ /* If static, can return as-is */
return (value);
+
+ case BHND_NVRAM_VAL_STORAGE_DYNAMIC:
+ if (!BHND_NVRAM_VAL_NEED_COPY(value)) {
+ refcount_acquire(&value->refs);
+ return (value);
+ }
+
+ /* Perform copy below */
+ break;
+
+ case BHND_NVRAM_VAL_STORAGE_AUTO:
+ BHND_NV_ASSERT(value->refs == 1, ("non-allocated value has "
+ "active refcount (%u)", value->refs));
+
+ /* Perform copy below */
+ break;
}
- /* Otherwise, we need to perform an actual copy */
- BHND_NV_ASSERT(value->refs == 1, ("non-allocated value has "
- "active refcount (%u)", value->refs));
/* Compute the new value's flags based on the source value */
switch (value->data_storage) {
@@ -308,13 +608,26 @@
{
BHND_NV_ASSERT(value->refs >= 1, ("value over-released"));
+ /* Skip if value is static */
+ if (value->val_storage == BHND_NVRAM_VAL_STORAGE_STATIC)
+ return;
+
/* Drop reference */
if (!refcount_release(&value->refs))
return;
/* Free allocated external representation data */
- if (value->data_storage == BHND_NVRAM_VAL_DATA_EXT_ALLOC)
+ switch (value->data_storage) {
+ case BHND_NVRAM_VAL_DATA_EXT_ALLOC:
bhnd_nv_free(__DECONST(void *, value->data.ptr));
+ break;
+ case BHND_NVRAM_VAL_DATA_NONE:
+ case BHND_NVRAM_VAL_DATA_INLINE:
+ case BHND_NVRAM_VAL_DATA_EXT_WEAK:
+ case BHND_NVRAM_VAL_DATA_EXT_STATIC:
+ /* Nothing to free */
+ break;
+ }
/* Free instance if dynamically allocated */
if (value->val_storage == BHND_NVRAM_VAL_STORAGE_DYNAMIC)
@@ -330,8 +643,8 @@
* - BHND_NVRAM_TYPE_CHAR_ARRAY
*/
static int
-bhnd_nvram_val_encode_string(void *outp, size_t *olen, bhnd_nvram_type otype,
- const void *inp, size_t ilen, bhnd_nvram_type itype)
+bhnd_nvram_val_encode_string(const void *inp, size_t ilen,
+ bhnd_nvram_type itype, void *outp, size_t *olen, bhnd_nvram_type otype)
{
const char *cstr;
bhnd_nvram_type otype_base;
@@ -358,7 +671,7 @@
/* Determine string length, minus trailing NUL (if any) */
cstr_len = strnlen(cstr, cstr_size);
- /* Parse the field data */
+ /* Parse the string data and write to output */
switch (otype) {
case BHND_NVRAM_TYPE_CHAR:
case BHND_NVRAM_TYPE_CHAR_ARRAY:
@@ -459,8 +772,8 @@
* Standard integer encoding implementation.
*/
static int
-bhnd_nvram_val_encode_int(void *outp, size_t *olen, bhnd_nvram_type otype,
- const void *inp, size_t ilen, bhnd_nvram_type itype)
+bhnd_nvram_val_encode_int(const void *inp, size_t ilen, bhnd_nvram_type itype,
+ void *outp, size_t *olen, bhnd_nvram_type otype)
{
bhnd_nvram_type otype_base;
size_t limit, nbytes;
@@ -722,7 +1035,7 @@
bhnd_nvram_type otype)
{
/* Prefer format implementation */
- if (value->fmt != NULL && value->fmt->op_encode != NULL)
+ if (value->fmt->op_encode != NULL)
return (value->fmt->op_encode(value, outp, olen, otype));
return (bhnd_nvram_val_generic_encode(value, outp, olen, otype));
@@ -757,7 +1070,7 @@
size_t ilen, void *outp, size_t *olen, bhnd_nvram_type otype)
{
/* Prefer format implementation */
- if (value->fmt != NULL && value->fmt->op_encode_elem != NULL) {
+ if (value->fmt->op_encode_elem != NULL) {
return (value->fmt->op_encode_elem(value, inp, ilen, outp,
olen, otype));
}
@@ -807,8 +1120,8 @@
* @param prev A value pointer previously returned by
* bhnd_nvram_val_next() or bhnd_nvram_val_elem(),
* or NULL to begin iteration at the first element.
- * @param[in,out] len If prev is non-NULL, len must be a pointer
- * to the length previously returned by
+ * @param[in,out] olen If @p prev is non-NULL, @p olen must be a
+ * pointer to the length previously returned by
* bhnd_nvram_val_next() or bhnd_nvram_val_elem().
* On success, will be set to the next element's
* length, in bytes.
@@ -817,13 +1130,13 @@
* @retval NULL If the end of the element array is reached.
*/
const void *
-bhnd_nvram_val_next(bhnd_nvram_val *value, const void *prev, size_t *len)
+bhnd_nvram_val_next(bhnd_nvram_val *value, const void *prev, size_t *olen)
{
/* Prefer the format implementation */
- if (value->fmt != NULL && value->fmt->op_next != NULL)
- return (value->fmt->op_next(value, prev, len));
+ if (value->fmt->op_next != NULL)
+ return (value->fmt->op_next(value, prev, olen));
- return (bhnd_nvram_val_generic_next(value, prev, len));
+ return (bhnd_nvram_val_generic_next(value, prev, olen));
}
/**
@@ -860,7 +1173,7 @@
int error;
/* Prefer format implementation */
- if (value->fmt != NULL && value->fmt->op_nelem != NULL)
+ if (value->fmt->op_nelem != NULL)
return (value->fmt->op_nelem(value));
/*
@@ -871,7 +1184,7 @@
* Instead, use bhnd_nvram_val_next() to parse the backing data and
* produce a total count.
*/
- if (value->fmt != NULL && value->fmt->op_next != NULL) {
+ if (value->fmt->op_next != NULL) {
const void *next;
next = NULL;
@@ -884,7 +1197,7 @@
/* Otherwise, compute the standard element count */
bytes = bhnd_nvram_val_bytes(value, &len, &type);
- if ((error = bhnd_nvram_value_nelem(type, bytes, len, &nelem))) {
+ if ((error = bhnd_nvram_value_nelem(bytes, len, type, &nelem))) {
/* Should always succeed */
BHND_NV_PANIC("error calculating element count for type '%s' "
"with length %zu: %d\n", bhnd_nvram_type_name(type), len,
@@ -914,28 +1227,31 @@
nbytes = 0;
nelem = 0;
otype_base = bhnd_nvram_base_type(otype);
+ inp = bhnd_nvram_val_bytes(value, &ilen, &itype);
/*
- * Normally, a rank polymorphic type like a character array would not
- * be representable as a rank 1 type.
+ * Normally, an array type is not universally representable as
+ * non-array type.
*
- * As a special-cased exception, we can support conversion directly
- * from CHAR_ARRAY to STRING by treating the character array as a
- * non-NUL-terminated string.
- *
- * This conversion is isomorphic; we also support conversion directly
- * from a STRING to a CHAR_ARRAY by the same mechanism.
+ * As exceptions, we support conversion directly to/from:
+ * - CHAR_ARRAY/STRING:
+ * ->STRING Interpret the character array as a
+ * non-NUL-terminated string.
+ * ->CHAR_ARRAY Trim the trailing NUL from the string.
*/
- inp = bhnd_nvram_val_bytes(value, &ilen, &itype);
- if ((itype == BHND_NVRAM_TYPE_CHAR_ARRAY &&
- otype == BHND_NVRAM_TYPE_STRING) ||
- (itype == BHND_NVRAM_TYPE_STRING &&
- otype == BHND_NVRAM_TYPE_CHAR_ARRAY))
- {
+#define BHND_NV_IS_ISO_CONV(_lhs, _rhs) \
+ ((itype == BHND_NVRAM_TYPE_ ## _lhs && \
+ otype == BHND_NVRAM_TYPE_ ## _rhs) || \
+ (itype == BHND_NVRAM_TYPE_ ## _rhs && \
+ otype == BHND_NVRAM_TYPE_ ## _lhs))
+
+ if (BHND_NV_IS_ISO_CONV(CHAR_ARRAY, STRING)) {
return (bhnd_nvram_val_encode_elem(value, inp, ilen, outp, olen,
otype));
}
+#undef BHND_NV_IS_ISO_CONV
+
/*
* If both input and output are non-array types, try to encode them
* without performing element iteration.
@@ -1021,9 +1337,8 @@
switch (itype) {
case BHND_NVRAM_TYPE_STRING:
case BHND_NVRAM_TYPE_CHAR:
- case BHND_NVRAM_TYPE_CHAR_ARRAY:
- return (bhnd_nvram_val_encode_string(outp, olen, otype, inp,
- ilen, itype));
+ return (bhnd_nvram_val_encode_string(inp, ilen, itype, outp,
+ olen, otype));
case BHND_NVRAM_TYPE_UINT8:
case BHND_NVRAM_TYPE_UINT16:
@@ -1033,9 +1348,8 @@
case BHND_NVRAM_TYPE_INT16:
case BHND_NVRAM_TYPE_INT32:
case BHND_NVRAM_TYPE_INT64:
- return (bhnd_nvram_val_encode_int(outp, olen, otype, inp, ilen,
- itype));
-
+ return (bhnd_nvram_val_encode_int(inp, ilen, itype, outp, olen,
+ otype));
default:
BHND_NV_PANIC("missing encode_elem() implementation");
}
@@ -1047,55 +1361,20 @@
*/
const void *
bhnd_nvram_val_generic_next(bhnd_nvram_val *value, const void *prev,
- size_t *len)
+ size_t *olen)
{
const uint8_t *inp;
- const uint8_t *next;
bhnd_nvram_type itype;
size_t ilen;
- size_t offset;
- /* Otherwise, default to iterating over the backing representation
- * according to its native representation */
+ /* Iterate over the backing representation */
inp = bhnd_nvram_val_bytes(value, &ilen, &itype);
-
- /* First element */
- if (prev == NULL) {
- /* Zero-length array? */
- if (ilen == 0)
- return (NULL);
-
- *len = bhnd_nvram_value_size(itype, inp, ilen, 1);
- return (inp);
- }
-
- /* Advance to next element */
- BHND_NV_ASSERT(prev >= (const void *)inp, ("invalid cookiep"));
- next = (const uint8_t *)prev + *len;
- offset = (size_t)(next - inp);
-
- if (offset >= ilen) {
- /* Hit end of the array */
- return (NULL);
- }
-
- /* Determine element size */
- *len = bhnd_nvram_value_size(itype, next, ilen - offset, 1);
- if (ilen - offset < *len)
- BHND_NV_PANIC("short element -- misaligned representation");
-
- return (next);
+ return (bhnd_nvram_value_array_next(inp, ilen, itype, prev, olen));
}
/**
* Initialize the representation of @p value with @p ptr.
- *
- * If @p value is an externally allocated instance and the representation
- * cannot be represented inline, the given data will not be copied, and @p ptr
- * must remain valid for the lifetime of @p value.
*
- * Otherwise, @p value will be initialized with a copy of the @p ptr.
- *
* @param value The value to be initialized.
* @param inp The external representation.
* @param ilen The external representation length, in bytes.
@@ -1114,17 +1393,22 @@
bhnd_nvram_type itype, uint32_t flags)
{
void *bytes;
+ int error;
BHND_NVRAM_VAL_ASSERT_EMPTY(value);
+ /* Validate alignment */
+ if ((error = bhnd_nvram_value_check_aligned(inp, ilen, itype)))
+ return (error);
+
/* Reference the external data */
if ((flags & BHND_NVRAM_VAL_BORROW_DATA) ||
(flags & BHND_NVRAM_VAL_STATIC_DATA))
{
- if (flags & BHND_NVRAM_VAL_BORROW_DATA)
- value->data_storage = BHND_NVRAM_VAL_DATA_EXT_WEAK;
- else
+ if (flags & BHND_NVRAM_VAL_STATIC_DATA)
value->data_storage = BHND_NVRAM_VAL_DATA_EXT_STATIC;
+ else
+ value->data_storage = BHND_NVRAM_VAL_DATA_EXT_WEAK;
value->data.ptr = inp;
value->data_type = itype;
@@ -1170,6 +1454,7 @@
#define NV_STORE_INIT_INLINE() do { \
value->data_len = ilen; \
+ value->data_type = itype; \
} while(0)
#define NV_STORE_INLINE(_type, _dest) do { \
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
@@ -143,7 +143,6 @@
.op_encode_elem = bhnd_nvram_val_bcm_leddc_encode_elem,
};
-
/**
* Broadcom NVRAM decimal integer format.
*
@@ -199,6 +198,36 @@
.op_next = bhnd_nvram_val_bcmstr_csv_next,
};
+
+/* Built-in format definitions */
+#define BHND_NVRAM_VAL_FMT_NATIVE(_n, _type) \
+ const bhnd_nvram_val_fmt bhnd_nvram_val_ ## _n ## _fmt = { \
+ .name = __STRING(_n), \
+ .native_type = BHND_NVRAM_TYPE_ ## _type, \
+ }
+
+BHND_NVRAM_VAL_FMT_NATIVE(uint8, UINT8);
+BHND_NVRAM_VAL_FMT_NATIVE(uint16, UINT16);
+BHND_NVRAM_VAL_FMT_NATIVE(uint32, UINT32);
+BHND_NVRAM_VAL_FMT_NATIVE(uint64, UINT64);
+BHND_NVRAM_VAL_FMT_NATIVE(int8, INT8);
+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(string, STRING);
+
+BHND_NVRAM_VAL_FMT_NATIVE(uint8_array, UINT8_ARRAY);
+BHND_NVRAM_VAL_FMT_NATIVE(uint16_array, UINT16_ARRAY);
+BHND_NVRAM_VAL_FMT_NATIVE(uint32_array, UINT32_ARRAY);
+BHND_NVRAM_VAL_FMT_NATIVE(uint64_array, UINT64_ARRAY);
+BHND_NVRAM_VAL_FMT_NATIVE(int8_array, INT8_ARRAY);
+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(string_array, STRING_ARRAY);
+
/**
* Common hex/decimal integer filter implementation.
*/
@@ -292,9 +321,7 @@
* their native width (width * two hex characters), and we do the same
* for compatibility
*/
-
- width = bhnd_nvram_value_size(itype, NULL, 0, 1) * 2;
-
+ width = bhnd_nvram_type_width(itype) * 2;
return (bhnd_nvram_value_printf("0x%0*I64X", inp, ilen, itype,
outp, olen, width));
}
@@ -652,16 +679,9 @@
return (next);
case BHND_NVRAM_TYPE_STRING_ARRAY:
- next = bhnd_nvram_string_array_next(inp, ilen, prev);
- if (next != NULL) {
- *len = strlen(next);
-
- /* Account for trailing NUL */
- if (*len + (size_t)(next - inp) < ilen)
- (*len)++;
- }
-
- return (next);
+ /* Delegate to default array iteration */
+ return (bhnd_nvram_value_array_next(inp, ilen, itype, prev,
+ len));
default:
BHND_NV_PANIC("unsupported type: %d", itype);
}
Index: head/sys/dev/bhnd/nvram/bhnd_nvram_value_prf.c
===================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_value_prf.c
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_value_prf.c
@@ -830,8 +830,7 @@
char c;
arg_type = BHND_NVRAM_TYPE_CHAR;
- arg_size = bhnd_nvram_value_size(arg_type, NULL,
- 0, 1);
+ arg_size = bhnd_nvram_type_width(arg_type);
/* Encode as single character */
error = bhnd_nvram_val_encode_elem(value, elem,
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
@@ -0,0 +1,513 @@
+/*-
+ * Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#ifdef _KERNEL
+
+#include <sys/systm.h>
+
+#else /* !_KERNEL */
+
+#include <errno.h>
+#include <string.h>
+
+#endif /* _KERNEL */
+
+#include "bhnd_nvram_private.h"
+#include "bhnd_nvram_valuevar.h"
+
+/**
+ * Validate the alignment of a value of @p type.
+ *
+ * @param inp The value data.
+ * @param ilen The value length, in bytes.
+ * @param itype The value type.
+ *
+ * @retval 0 success
+ * @retval EFTYPE if @p type is not an array type, and @p len is not
+ * equal to the size of a single element of @p type.
+ * @retval EFAULT if @p data is not correctly aligned to the required
+ * host alignment.
+ * @retval EFAULT if @p len is not aligned to the @p type width.
+ */
+int
+bhnd_nvram_value_check_aligned(const void *inp, size_t ilen,
+ bhnd_nvram_type itype)
+{
+ size_t align, width;
+
+ /* Check pointer alignment against the required host alignment */
+ align = bhnd_nvram_type_host_align(itype);
+ BHND_NV_ASSERT(align != 0, ("invalid zero alignment"));
+ if ((uintptr_t)inp % align != 0)
+ return (EFAULT);
+
+ /* If type is not fixed width, nothing else to check */
+ width = bhnd_nvram_type_width(itype);
+ if (width == 0)
+ return (0);
+
+ /* Length must be aligned to the element width */
+ if (ilen % width != 0)
+ return (EFAULT);
+
+ /* If the type is not an array type, the length must be equal to the
+ * size of a single element of @p type. */
+ if (!bhnd_nvram_is_array_type(itype) && ilen != width)
+ return (EFTYPE);
+
+ return (0);
+}
+
+/**
+ * Calculate the number of elements represented by a value of @p ilen bytes
+ * with @p itype.
+ *
+ * @param inp The value data.
+ * @param ilen The value length.
+ * @param itype The value type.
+ * @param[out] nelem On success, the number of elements.
+ *
+ * @retval 0 success
+ * @retval EINVAL if @p inp is NULL and the element count of @p itype
+ * cannot be determined without parsing the value data.
+ * @retval EFTYPE if @p itype is not an array type, and @p ilen is not
+ * equal to the size of a single element of @p itype.
+ * @retval EFAULT if @p ilen is not correctly aligned for elements of
+ * @p itype.
+ */
+int
+bhnd_nvram_value_nelem(const void *inp, size_t ilen, bhnd_nvram_type itype,
+ size_t *nelem)
+{
+ int error;
+
+ BHND_NV_ASSERT(inp != NULL, ("NULL inp"));
+
+ /* Check alignment */
+ if ((error = bhnd_nvram_value_check_aligned(inp, ilen, itype)))
+ return (error);
+
+ switch (itype) {
+ case BHND_NVRAM_TYPE_STRING:
+ /* Always exactly one element */
+ *nelem = 1;
+ return (0);
+
+ case BHND_NVRAM_TYPE_STRING_ARRAY: {
+ const char *p;
+ size_t nleft;
+
+ /* Iterate over the NUL-terminated strings to calculate
+ * total element count */
+ p = inp;
+ nleft = ilen;
+ *nelem = 0;
+ while (nleft > 0) {
+ size_t slen;
+
+ /* Increment element count */
+ (*nelem)++;
+
+ /* Determine string length */
+ slen = strnlen(p, nleft);
+ nleft -= slen;
+
+ /* Advance input */
+ p += slen;
+
+ /* Account for trailing NUL, if we haven't hit the end
+ * of the input */
+ if (nleft > 0) {
+ nleft--;
+ p++;
+ }
+ }
+
+ return (0);
+ }
+
+ 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:
+ case BHND_NVRAM_TYPE_CHAR_ARRAY: {
+ size_t width = bhnd_nvram_type_width(itype);
+ BHND_NV_ASSERT(width != 0, ("invalid width"));
+
+ *nelem = ilen / width;
+ return (0);
+ }
+
+ case BHND_NVRAM_TYPE_INT8:
+ case BHND_NVRAM_TYPE_UINT8:
+ case BHND_NVRAM_TYPE_CHAR:
+ case BHND_NVRAM_TYPE_INT16:
+ case BHND_NVRAM_TYPE_UINT16:
+ case BHND_NVRAM_TYPE_INT32:
+ case BHND_NVRAM_TYPE_UINT32:
+ case BHND_NVRAM_TYPE_INT64:
+ case BHND_NVRAM_TYPE_UINT64:
+ /* Length must be equal to the size of exactly one
+ * element (arrays can represent zero elements -- non-array
+ * types cannot) */
+ if (ilen != bhnd_nvram_type_width(itype))
+ return (EFTYPE);
+ *nelem = 1;
+ return (0);
+ }
+
+ /* Quiesce gcc4.2 */
+ BHND_NV_PANIC("bhnd nvram type %u unknown", itype);
+}
+
+/**
+ * Return the size, in bytes, of a value of @p itype with @p nelem elements.
+ *
+ * @param inp The actual data to be queried, or NULL if unknown. If
+ * NULL and the base type is not a fixed width type
+ * (e.g. BHND_NVRAM_TYPE_STRING), 0 will be returned.
+ * @param ilen The size of @p inp, in bytes, or 0 if @p inp is NULL.
+ * @param itype The value type.
+ * @param nelem The number of elements. If @p itype is not an array
+ * type, this value must be 1.
+ *
+ * @retval 0 If @p itype has a variable width, and @p inp is NULL.
+ * @retval 0 If a @p nelem value greater than 1 is provided for a
+ * non-array @p itype.
+ * @retval 0 If a @p nelem value of 0 is provided.
+ * @retval 0 If the result would exceed the maximum value
+ * representable by size_t.
+ * @retval 0 If @p itype is BHND_NVRAM_TYPE_NULL.
+ * @retval non-zero The size, in bytes, of @p itype with @p nelem elements.
+ */
+size_t
+bhnd_nvram_value_size(const void *inp, size_t ilen, bhnd_nvram_type itype,
+ size_t nelem)
+{
+ /* If nelem 0, nothing to do */
+ if (nelem == 0)
+ return (0);
+
+ /* Non-array types must have an nelem value of 1 */
+ if (!bhnd_nvram_is_array_type(itype) && nelem != 1)
+ return (0);
+
+ switch (itype) {
+ 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:
+ case BHND_NVRAM_TYPE_CHAR_ARRAY: {
+ size_t width;
+
+ width = bhnd_nvram_type_width(itype);
+
+ /* Would nelem * width overflow? */
+ if (SIZE_MAX / nelem < width) {
+ BHND_NV_LOG("cannot represent size %s[%zu]\n",
+ bhnd_nvram_type_name(bhnd_nvram_base_type(itype)),
+ nelem);
+ return (0);
+ }
+
+ return (nelem * width);
+ }
+
+ case BHND_NVRAM_TYPE_STRING_ARRAY: {
+ const char *p;
+ size_t total_size;
+
+ if (inp == NULL)
+ return (0);
+
+ /* Iterate over the NUL-terminated strings to calculate
+ * total byte length */
+ p = inp;
+ total_size = 0;
+ for (size_t i = 0; i < nelem; i++) {
+ size_t elem_size;
+
+ elem_size = strnlen(p, ilen - total_size);
+ p += elem_size;
+
+ /* Check for (and skip) terminating NUL */
+ if (total_size < ilen && *p == '\0') {
+ elem_size++;
+ p++;
+ }
+
+ /* Would total_size + elem_size overflow?
+ *
+ * A memory range larger than SIZE_MAX shouldn't be,
+ * possible, but include the check for completeness */
+ if (SIZE_MAX - total_size < elem_size)
+ return (0);
+
+ total_size += elem_size;
+ }
+
+ return (total_size);
+ }
+
+ case BHND_NVRAM_TYPE_STRING: {
+ size_t size;
+
+ if (inp == NULL)
+ return (0);
+
+ /* Find length */
+ size = strnlen(inp, ilen);
+
+ /* Is there a terminating NUL, or did we just hit the
+ * end of the string input */
+ if (size < ilen)
+ size++;
+
+ return (size);
+ }
+
+ case BHND_NVRAM_TYPE_INT8:
+ case BHND_NVRAM_TYPE_UINT8:
+ case BHND_NVRAM_TYPE_CHAR:
+ return (sizeof(uint8_t));
+
+ case BHND_NVRAM_TYPE_INT16:
+ case BHND_NVRAM_TYPE_UINT16:
+ return (sizeof(uint16_t));
+
+ case BHND_NVRAM_TYPE_INT32:
+ case BHND_NVRAM_TYPE_UINT32:
+ return (sizeof(uint32_t));
+
+ case BHND_NVRAM_TYPE_UINT64:
+ case BHND_NVRAM_TYPE_INT64:
+ return (sizeof(uint64_t));
+ }
+
+ /* Quiesce gcc4.2 */
+ BHND_NV_PANIC("bhnd nvram type %u unknown", itype);
+}
+
+
+/**
+ * Format a string representation of @p inp using @p fmt, with, writing the
+ * result to @p outp.
+ *
+ * Refer to bhnd_nvram_val_vprintf() for full format string documentation.
+ *
+ * @param fmt The format string.
+ * @param inp The value to be formatted.
+ * @param ilen The size of @p inp, in bytes.
+ * @param itype The type of @p inp.
+ * @param[out] outp On success, the string value will be written to
+ * this buffer. This argment may be NULL if the
+ * value is not desired.
+ * @param[in,out] olen The capacity of @p outp. On success, will be set
+ * to the actual size of the formatted string.
+ *
+ * @retval 0 success
+ * @retval EINVAL If @p fmt contains unrecognized format string
+ * specifiers.
+ * @retval ENOMEM If the @p outp is non-NULL, and the provided @p olen
+ * is too small to hold the encoded value.
+ * @retval EFTYPE If value coercion from @p inp to a string value via
+ * @p fmt is unsupported.
+ * @retval ERANGE If value coercion of @p value would overflow (or
+ * underflow) the representation defined by @p fmt.
+ */
+int
+bhnd_nvram_value_printf(const char *fmt, const void *inp, size_t ilen,
+ bhnd_nvram_type itype, char *outp, size_t *olen, ...)
+{
+ va_list ap;
+ int error;
+
+ va_start(ap, olen);
+ error = bhnd_nvram_value_vprintf(fmt, inp, ilen, itype, outp, olen, ap);
+ va_end(ap);
+
+ return (error);
+}
+
+/**
+ * Format a string representation of @p inp using @p fmt, with, writing the
+ * result to @p outp.
+ *
+ * Refer to bhnd_nvram_val_vprintf() for full format string documentation.
+ *
+ * @param fmt The format string.
+ * @param inp The value to be formatted.
+ * @param ilen The size of @p inp, in bytes.
+ * @param itype The type of @p inp.
+ * @param[out] outp On success, the string value will be written to
+ * this buffer. This argment may be NULL if the
+ * value is not desired.
+ * @param[in,out] olen The capacity of @p outp. On success, will be set
+ * to the actual size of the formatted string.
+ * @param ap Argument list.
+ *
+ * @retval 0 success
+ * @retval EINVAL If @p fmt contains unrecognized format string
+ * specifiers.
+ * @retval ENOMEM If the @p outp is non-NULL, and the provided @p olen
+ * is too small to hold the encoded value.
+ * @retval EFTYPE If value coercion from @p inp to a string value via
+ * @p fmt is unsupported.
+ * @retval ERANGE If value coercion of @p value would overflow (or
+ * underflow) the representation defined by @p fmt.
+ */
+int
+bhnd_nvram_value_vprintf(const char *fmt, const void *inp, size_t ilen,
+ bhnd_nvram_type itype, char *outp, size_t *olen, va_list ap)
+{
+ bhnd_nvram_val val;
+ int error;
+
+ /* Map input buffer as a value instance */
+ error = bhnd_nvram_val_init(&val, NULL, inp, ilen, itype,
+ BHND_NVRAM_VAL_BORROW_DATA);
+ if (error)
+ return (error);
+
+ /* Attempt to format the value */
+ error = bhnd_nvram_val_vprintf(&val, fmt, outp, olen, ap);
+
+ /* Clean up */
+ bhnd_nvram_val_release(&val);
+ return (error);
+}
+
+/**
+ * Iterate over all elements in @p inp.
+ *
+ * @param inp The value to be iterated.
+ * @param ilen The size, in bytes, of @p inp.
+ * @param itype The data type of @p inp.
+ * @param prev The value previously returned by
+ * bhnd_nvram_value_array_next(), or NULL to begin
+ * iteration.
+ * @param[in,out] olen If @p prev is non-NULL, @p olen must be a
+ * pointer to the length previously returned by
+ * bhnd_nvram_value_array_next(). On success, will
+ * be set to the next element's length, in bytes.
+ *
+ * @retval non-NULL A borrowed reference to the next element of @p inp.
+ * @retval NULL If the end of the array is reached.
+ */
+const void *
+bhnd_nvram_value_array_next(const void *inp, size_t ilen, bhnd_nvram_type itype,
+ const void *prev, size_t *olen)
+{
+ const u_char *next;
+ size_t offset;
+
+ /* Handle first element */
+ if (prev == NULL) {
+ /* Zero-length array? */
+ if (ilen == 0)
+ return (NULL);
+
+ *olen = bhnd_nvram_value_size(inp, ilen, itype, 1);
+ return (inp);
+ }
+
+ /* Advance to next element */
+ BHND_NV_ASSERT(prev >= (const void *)inp, ("invalid cookiep"));
+ next = (const u_char *)prev + *olen;
+ offset = (size_t)(next - (const u_char *)inp);
+
+ if (offset >= ilen) {
+ /* Hit end of the array */
+ return (NULL);
+ }
+
+ /* Determine element size */
+ *olen = bhnd_nvram_value_size(next, ilen - offset, itype, 1);
+ if (ilen - offset < *olen) {
+ BHND_NV_LOG("short element of type %s -- misaligned "
+ "representation", bhnd_nvram_type_name(itype));
+ return (NULL);
+ }
+
+ return (next);
+}
+
+/**
+ * Coerce value @p inp of type @p itype to @p otype, writing the
+ * result to @p outp.
+ *
+ * @param inp The value to be coerced.
+ * @param ilen The size of @p inp, in bytes.
+ * @param itype The base data type of @p inp.
+ * @param[out] outp On success, the value will be written to this
+ * buffer. This argment may be NULL if the value
+ * is not desired.
+ * @param[in,out] olen The capacity of @p outp. On success, will be set
+ * to the actual size of the requested value.
+ * @param otype The data type to be written to @p outp.
+ *
+ * @retval 0 success
+ * @retval ENOMEM If @p outp is non-NULL and a buffer of @p olen is too
+ * small to hold the requested value.
+ * @retval EFTYPE If the variable data cannot be coerced to @p otype.
+ * @retval ERANGE If value coercion would overflow @p otype.
+ */
+int
+bhnd_nvram_value_coerce(const void *inp, size_t ilen, bhnd_nvram_type itype,
+ void *outp, size_t *olen, bhnd_nvram_type otype)
+{
+ bhnd_nvram_val val;
+ int error;
+
+ /* Wrap input buffer in a value instance */
+ error = bhnd_nvram_val_init(&val, NULL, inp, ilen,
+ itype, BHND_NVRAM_VAL_BORROW_DATA|BHND_NVRAM_VAL_FIXED);
+ if (error)
+ return (error);
+
+ /* Try to encode as requested type */
+ error = bhnd_nvram_val_encode(&val, outp, olen, otype);
+
+ /* Clean up and return error */
+ bhnd_nvram_val_release(&val);
+ return (error);
+}
Index: head/sys/dev/bhnd/nvram/bhnd_nvram_valuevar.h
===================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_valuevar.h
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_valuevar.h
@@ -40,7 +40,8 @@
const void *inp, size_t ilen, void *outp, size_t *olen,
bhnd_nvram_type otype);
const void *bhnd_nvram_val_generic_next(bhnd_nvram_val *value,
- const void *prev, size_t *len);
+ const void *prev, size_t *olen);
+
/**
* Filter input data prior to initialization.
*
@@ -74,7 +75,7 @@
/** @see bhnd_nvram_val_next() */
typedef const void *(bhnd_nvram_val_op_next)(bhnd_nvram_val *value,
- const void *prev, size_t *len);
+ const void *prev, size_t *olen);
/** @see bhnd_nvram_val_nelem() */
typedef size_t (bhnd_nvram_val_op_nelem)(bhnd_nvram_val *value);
@@ -89,7 +90,6 @@
struct bhnd_nvram_val_fmt {
const char *name; /**< type name */
bhnd_nvram_type native_type; /**< native value representation */
-
bhnd_nvram_val_op_filter *op_filter;
bhnd_nvram_val_op_encode *op_encode;
bhnd_nvram_val_op_encode_elem *op_encode_elem;
Index: head/sys/modules/bhnd/Makefile
===================================================================
--- head/sys/modules/bhnd/Makefile
+++ head/sys/modules/bhnd/Makefile
@@ -42,6 +42,7 @@
bhnd_nvram_value.c \
bhnd_nvram_value_fmts.c \
bhnd_nvram_value_prf.c \
+ bhnd_nvram_value_subr.c \
bhnd_sprom.c
SRCS+= bhnd_nvram_map.h bhnd_nvram_map_data.h
SRCS+= bhnd_nvram_if.c bhnd_nvram_if.h

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 18, 3:02 PM (15 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29871666
Default Alt Text
D8757.diff (69 KB)

Event Timeline