svn commit: r310292 - in head/sys: conf dev/bhnd/nvram modules/bhnd
Landon J. Fuller
landonf at FreeBSD.org
Mon Dec 19 20:20:35 UTC 2016
Author: landonf
Date: Mon Dec 19 20:20:33 2016
New Revision: 310292
URL: https://svnweb.freebsd.org/changeset/base/310292
Log:
bhnd(4): support direct conversion of bhnd_nvram_val
This adds support for bhnd_nvram_val_convert_init() and
bhnd_nvram_val_convert_new(), which may be used to perform value
format-aware encoding of an NVRAM value to a new target format/type.
This will be used to simplify converting to/from serialized
format-specific NVRAM value representations to common external
representations.
Approved by: adrian (mentor)
Differential Revision: https://reviews.freebsd.org/D8757
Added:
head/sys/dev/bhnd/nvram/bhnd_nvram_value_subr.c (contents, props changed)
Modified:
head/sys/conf/files
head/sys/dev/bhnd/nvram/bhnd_nvram.h
head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c
head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c
head/sys/dev/bhnd/nvram/bhnd_nvram_private.h
head/sys/dev/bhnd/nvram/bhnd_nvram_store.c
head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c
head/sys/dev/bhnd/nvram/bhnd_nvram_value.c
head/sys/dev/bhnd/nvram/bhnd_nvram_value.h
head/sys/dev/bhnd/nvram/bhnd_nvram_value_fmts.c
head/sys/dev/bhnd/nvram/bhnd_nvram_value_prf.c
head/sys/dev/bhnd/nvram/bhnd_nvram_valuevar.h
head/sys/modules/bhnd/Makefile
Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files Mon Dec 19 20:11:48 2016 (r310291)
+++ head/sys/conf/files Mon Dec 19 20:20:33 2016 (r310292)
@@ -1247,6 +1247,7 @@ dev/bhnd/nvram/bhnd_nvram_subr.c optiona
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
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram.h
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram.h Mon Dec 19 20:11:48 2016 (r310291)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram.h Mon Dec 19 20:20:33 2016 (r310292)
@@ -111,14 +111,16 @@ typedef enum {
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_ */
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c Mon Dec 19 20:11:48 2016 (r310291)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c Mon Dec 19 20:20:33 2016 (r310292)
@@ -647,10 +647,8 @@ bhnd_nvram_bcm_getvar_ptr(struct bhnd_nv
/* 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;
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c Mon Dec 19 20:11:48 2016 (r310291)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c Mon Dec 19 20:20:33 2016 (r310292)
@@ -597,7 +597,7 @@ bhnd_nvram_sprom_read_offset(struct bhnd
} 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 @@ bhnd_nvram_sprom_getvar(struct bhnd_nvra
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 @@ sprom_opcode_set_type(struct sprom_opcod
}
/* 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);
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_private.h
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_private.h Mon Dec 19 20:11:48 2016 (r310291)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_private.h Mon Dec 19 20:20:33 2016 (r310292)
@@ -167,11 +167,15 @@ int bhnd_nvram_value_coerce(const vo
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 @@ int bhnd_nvram_value_vprintf(const c
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(
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_store.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_store.c Mon Dec 19 20:11:48 2016 (r310291)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_store.c Mon Dec 19 20:20:33 2016 (r310292)
@@ -288,7 +288,7 @@ bhnd_nvram_store_setvar(struct bhnd_nvra
/* 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) */
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c Mon Dec 19 20:11:48 2016 (r310291)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_subr.c Mon Dec 19 20:20:33 2016 (r310292)
@@ -71,12 +71,6 @@ __FBSDID("$FreeBSD$");
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 @@ bhnd_nvram_base_type(bhnd_nvram_type typ
}
/**
- * 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 @@ bhnd_nvram_value_nelem(bhnd_nvram_type t
}
/**
- * 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 @@ bhnd_nvram_value_size(bhnd_nvram_type ty
}
/**
- * 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 @@ bhnd_nvram_validate_name(const char *nam
}
/**
- * 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 @@ bhnd_nvram_parse_int(const char *str, si
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)
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_value.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_value.c Mon Dec 19 20:11:48 2016 (r310291)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_value.c Mon Dec 19 20:20:33 2016 (r310292)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL
+#include <sys/ctype.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/systm.h>
@@ -43,6 +44,7 @@ __FBSDID("$FreeBSD$");
#else /* !_KERNEL */
+#include <ctype.h>
#include <inttypes.h>
#include <errno.h>
#include <stdlib.h>
@@ -54,6 +56,8 @@ __FBSDID("$FreeBSD$");
#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(bhnd_nvra
static int bhnd_nvram_val_set_inline(bhnd_nvram_val *value,
const void *inp, size_t ilen, bhnd_nvram_type itype);
+static int bhnd_nvram_val_encode_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 @@ static int bhnd_nvram_val_set_inline(bh
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 @@ bhnd_nvram_val_init_common(bhnd_nvram_va
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 @@ bhnd_nvram_val_new(bhnd_nvram_val **valu
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.
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-head
mailing list