Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148401335
D8757.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
69 KB
Referenced Files
None
Subscribers
None
D8757.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D8757: bhnd(4): Implement support for directly converting a bhnd_nvram_val to a new type.
Attached
Detach File
Event Timeline
Log In to Comment