aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/bhnd/bhnd_subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/bhnd/bhnd_subr.c')
-rw-r--r--sys/dev/bhnd/bhnd_subr.c329
1 files changed, 324 insertions, 5 deletions
diff --git a/sys/dev/bhnd/bhnd_subr.c b/sys/dev/bhnd/bhnd_subr.c
index a21d88bf99be..fbbd841fc564 100644
--- a/sys/dev/bhnd/bhnd_subr.c
+++ b/sys/dev/bhnd/bhnd_subr.c
@@ -30,7 +30,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/systm.h>
@@ -881,6 +880,325 @@ cleanup:
}
/**
+ * Read an NVRAM variable's NUL-terminated string value.
+ *
+ * @param dev A bhnd bus child device.
+ * @param name The NVRAM variable name.
+ * @param[out] buf A buffer large enough to hold @p len bytes. On
+ * success, the NUL-terminated string value will be
+ * written to this buffer. This argment may be NULL if
+ * the value is not desired.
+ * @param len The maximum capacity of @p buf.
+ * @param[out] rlen On success, will be set to the actual size of
+ * the requested value (including NUL termination). This
+ * argment may be NULL if the size is not desired.
+ *
+ * @retval 0 success
+ * @retval ENOENT The requested variable was not found.
+ * @retval ENODEV No valid NVRAM source could be found.
+ * @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too
+ * small to hold the requested value.
+ * @retval EFTYPE If the variable data cannot be coerced to a valid
+ * string representation.
+ * @retval ERANGE If value coercion would overflow @p type.
+ * @retval non-zero If reading @p name otherwise fails, a regular unix
+ * error code will be returned.
+ */
+int
+bhnd_nvram_getvar_str(device_t dev, const char *name, char *buf, size_t len,
+ size_t *rlen)
+{
+ size_t larg;
+ int error;
+
+ larg = len;
+ error = bhnd_nvram_getvar(dev, name, buf, &larg, BHND_NVRAM_TYPE_CSTR);
+ if (rlen != NULL)
+ *rlen = larg;
+
+ return (error);
+}
+
+/**
+ * Read an NVRAM variable's unsigned integer value.
+ *
+ * @param dev A bhnd bus child device.
+ * @param name The NVRAM variable name.
+ * @param[out] value On success, the requested value will be written
+ * to this pointer.
+ * @param width The output integer type width (1, 2, or
+ * 4 bytes).
+ *
+ * @retval 0 success
+ * @retval ENOENT The requested variable was not found.
+ * @retval ENODEV No valid NVRAM source could be found.
+ * @retval EFTYPE If the variable data cannot be coerced to a
+ * a valid unsigned integer representation.
+ * @retval ERANGE If value coercion would overflow (or underflow) an
+ * unsigned representation of the given @p width.
+ * @retval non-zero If reading @p name otherwise fails, a regular unix
+ * error code will be returned.
+ */
+int
+bhnd_nvram_getvar_uint(device_t dev, const char *name, void *value, int width)
+{
+ bhnd_nvram_type type;
+ size_t len;
+
+ switch (width) {
+ case 1:
+ type = BHND_NVRAM_TYPE_UINT8;
+ break;
+ case 2:
+ type = BHND_NVRAM_TYPE_UINT16;
+ break;
+ case 4:
+ type = BHND_NVRAM_TYPE_UINT32;
+ break;
+ default:
+ device_printf(dev, "unsupported NVRAM integer width: %d\n",
+ width);
+ return (EINVAL);
+ }
+
+ len = width;
+ return (bhnd_nvram_getvar(dev, name, value, &len, type));
+}
+
+/**
+ * Read an NVRAM variable's unsigned 8-bit integer value.
+ *
+ * @param dev A bhnd bus child device.
+ * @param name The NVRAM variable name.
+ * @param[out] value On success, the requested value will be written
+ * to this pointer.
+ *
+ * @retval 0 success
+ * @retval ENOENT The requested variable was not found.
+ * @retval ENODEV No valid NVRAM source could be found.
+ * @retval EFTYPE If the variable data cannot be coerced to a
+ * a valid unsigned integer representation.
+ * @retval ERANGE If value coercion would overflow (or underflow) uint8_t.
+ * @retval non-zero If reading @p name otherwise fails, a regular unix
+ * error code will be returned.
+ */
+int
+bhnd_nvram_getvar_uint8(device_t dev, const char *name, uint8_t *value)
+{
+ return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value)));
+}
+
+/**
+ * Read an NVRAM variable's unsigned 16-bit integer value.
+ *
+ * @param dev A bhnd bus child device.
+ * @param name The NVRAM variable name.
+ * @param[out] value On success, the requested value will be written
+ * to this pointer.
+ *
+ * @retval 0 success
+ * @retval ENOENT The requested variable was not found.
+ * @retval ENODEV No valid NVRAM source could be found.
+ * @retval EFTYPE If the variable data cannot be coerced to a
+ * a valid unsigned integer representation.
+ * @retval ERANGE If value coercion would overflow (or underflow)
+ * uint16_t.
+ * @retval non-zero If reading @p name otherwise fails, a regular unix
+ * error code will be returned.
+ */
+int
+bhnd_nvram_getvar_uint16(device_t dev, const char *name, uint16_t *value)
+{
+ return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value)));
+}
+
+/**
+ * Read an NVRAM variable's unsigned 32-bit integer value.
+ *
+ * @param dev A bhnd bus child device.
+ * @param name The NVRAM variable name.
+ * @param[out] value On success, the requested value will be written
+ * to this pointer.
+ *
+ * @retval 0 success
+ * @retval ENOENT The requested variable was not found.
+ * @retval ENODEV No valid NVRAM source could be found.
+ * @retval EFTYPE If the variable data cannot be coerced to a
+ * a valid unsigned integer representation.
+ * @retval ERANGE If value coercion would overflow (or underflow)
+ * uint32_t.
+ * @retval non-zero If reading @p name otherwise fails, a regular unix
+ * error code will be returned.
+ */
+int
+bhnd_nvram_getvar_uint32(device_t dev, const char *name, uint32_t *value)
+{
+ return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value)));
+}
+
+/**
+ * Read an NVRAM variable's signed integer value.
+ *
+ * @param dev A bhnd bus child device.
+ * @param name The NVRAM variable name.
+ * @param[out] value On success, the requested value will be written
+ * to this pointer.
+ * @param width The output integer type width (1, 2, or
+ * 4 bytes).
+ *
+ * @retval 0 success
+ * @retval ENOENT The requested variable was not found.
+ * @retval ENODEV No valid NVRAM source could be found.
+ * @retval EFTYPE If the variable data cannot be coerced to a
+ * a valid integer representation.
+ * @retval ERANGE If value coercion would overflow (or underflow) an
+ * signed representation of the given @p width.
+ * @retval non-zero If reading @p name otherwise fails, a regular unix
+ * error code will be returned.
+ */
+int
+bhnd_nvram_getvar_int(device_t dev, const char *name, void *value, int width)
+{
+ bhnd_nvram_type type;
+ size_t len;
+
+ switch (width) {
+ case 1:
+ type = BHND_NVRAM_TYPE_INT8;
+ break;
+ case 2:
+ type = BHND_NVRAM_TYPE_INT16;
+ break;
+ case 4:
+ type = BHND_NVRAM_TYPE_INT32;
+ break;
+ default:
+ device_printf(dev, "unsupported NVRAM integer width: %d\n",
+ width);
+ return (EINVAL);
+ }
+
+ len = width;
+ return (bhnd_nvram_getvar(dev, name, value, &len, type));
+}
+
+/**
+ * Read an NVRAM variable's signed 8-bit integer value.
+ *
+ * @param dev A bhnd bus child device.
+ * @param name The NVRAM variable name.
+ * @param[out] value On success, the requested value will be written
+ * to this pointer.
+ *
+ * @retval 0 success
+ * @retval ENOENT The requested variable was not found.
+ * @retval ENODEV No valid NVRAM source could be found.
+ * @retval EFTYPE If the variable data cannot be coerced to a
+ * a valid integer representation.
+ * @retval ERANGE If value coercion would overflow (or underflow) int8_t.
+ * @retval non-zero If reading @p name otherwise fails, a regular unix
+ * error code will be returned.
+ */
+int
+bhnd_nvram_getvar_int8(device_t dev, const char *name, int8_t *value)
+{
+ return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value)));
+}
+
+/**
+ * Read an NVRAM variable's signed 16-bit integer value.
+ *
+ * @param dev A bhnd bus child device.
+ * @param name The NVRAM variable name.
+ * @param[out] value On success, the requested value will be written
+ * to this pointer.
+ *
+ * @retval 0 success
+ * @retval ENOENT The requested variable was not found.
+ * @retval ENODEV No valid NVRAM source could be found.
+ * @retval EFTYPE If the variable data cannot be coerced to a
+ * a valid integer representation.
+ * @retval ERANGE If value coercion would overflow (or underflow)
+ * int16_t.
+ * @retval non-zero If reading @p name otherwise fails, a regular unix
+ * error code will be returned.
+ */
+int
+bhnd_nvram_getvar_int16(device_t dev, const char *name, int16_t *value)
+{
+ return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value)));
+}
+
+/**
+ * Read an NVRAM variable's signed 32-bit integer value.
+ *
+ * @param dev A bhnd bus child device.
+ * @param name The NVRAM variable name.
+ * @param[out] value On success, the requested value will be written
+ * to this pointer.
+ *
+ * @retval 0 success
+ * @retval ENOENT The requested variable was not found.
+ * @retval ENODEV No valid NVRAM source could be found.
+ * @retval EFTYPE If the variable data cannot be coerced to a
+ * a valid integer representation.
+ * @retval ERANGE If value coercion would overflow (or underflow)
+ * int32_t.
+ * @retval non-zero If reading @p name otherwise fails, a regular unix
+ * error code will be returned.
+ */
+int
+bhnd_nvram_getvar_int32(device_t dev, const char *name, int32_t *value)
+{
+ return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value)));
+}
+
+
+/**
+ * Read an NVRAM variable's array value.
+ *
+ * @param dev A bhnd bus child device.
+ * @param name The NVRAM variable name.
+ * @param[out] buf A buffer large enough to hold @p size bytes.
+ * On success, the requested value will be written
+ * to this buffer.
+ * @param[in,out] size The required number of bytes to write to
+ * @p buf.
+ * @param type The desired array element data representation.
+ *
+ * @retval 0 success
+ * @retval ENOENT The requested variable was not found.
+ * @retval ENODEV No valid NVRAM source could be found.
+ * @retval ENXIO If less than @p size bytes are available.
+ * @retval ENOMEM If a buffer of @p size is too small to hold the
+ * requested value.
+ * @retval EFTYPE If the variable data cannot be coerced to a
+ * a valid instance of @p type.
+ * @retval ERANGE If value coercion would overflow (or underflow) a
+ * representation of @p type.
+ * @retval non-zero If reading @p name otherwise fails, a regular unix
+ * error code will be returned.
+ */
+int
+bhnd_nvram_getvar_array(device_t dev, const char *name, void *buf, size_t size,
+ bhnd_nvram_type type)
+{
+ size_t nbytes;
+ int error;
+
+ /* Attempt read */
+ nbytes = size;
+ if ((error = bhnd_nvram_getvar(dev, name, buf, &nbytes, type)))
+ return (error);
+
+ /* Verify that the expected number of bytes were fetched */
+ if (nbytes < size)
+ return (ENXIO);
+
+ return (0);
+}
+
+/**
* Using the bhnd(4) bus-level core information and a custom core name,
* populate @p dev's device description.
*
@@ -953,7 +1271,8 @@ bhnd_bus_generic_get_chipid(device_t dev, device_t child)
/* nvram board_info population macros for bhnd_bus_generic_read_board_info() */
#define BHND_GV(_dest, _name) \
- bhnd_nvram_getvar(child, BHND_NVAR_ ## _name, &_dest, sizeof(_dest))
+ bhnd_nvram_getvar_uint(child, BHND_NVAR_ ## _name, &_dest, \
+ sizeof(_dest))
#define REQ_BHND_GV(_dest, _name) do { \
if ((error = BHND_GV(_dest, _name))) { \
@@ -1017,7 +1336,7 @@ bhnd_bus_generic_read_board_info(device_t dev, device_t child,
*/
int
bhnd_bus_generic_get_nvram_var(device_t dev, device_t child, const char *name,
- void *buf, size_t *size)
+ void *buf, size_t *size, bhnd_nvram_type type)
{
device_t nvram;
device_t parent;
@@ -1027,14 +1346,14 @@ bhnd_bus_generic_get_nvram_var(device_t dev, device_t child, const char *name,
/* Look for a directly-attached NVRAM child */
if ((nvram = device_find_child(dev, "bhnd_nvram", -1)) != NULL)
- return BHND_NVRAM_GETVAR(nvram, name, buf, size);
+ return BHND_NVRAM_GETVAR(nvram, name, buf, size, type);
/* Try to delegate to parent */
if ((parent = device_get_parent(dev)) == NULL)
return (ENODEV);
return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
- name, buf, size));
+ name, buf, size, type));
}
/**