bhnd(4): Implement NVRAM support required for PMU bring-up.
- Added a generic bhnd_nvram_parser API, with support for the TLV format used on WGT634U devices, the standard BCM NVRAM format used on most modern devices, and the "board text file" format used on some hardware to supply external NVRAM data at runtime (e.g. via an EFI variable). - Extended the bhnd_bus_if and bhnd_nvram_if interfaces to support both string-based and primitive data type variable access, required for common behavior across both SPROM and NVRAM data sources. - Extended the existing SPROM implementation to support the new string-based NVRAM APIs. - Added an abstract bhnd_nvram driver, implementing the bhnd_nvram_if atop the bhnd_nvram_parser API. - Added a CFE-based bhnd_nvram driver to provide read-only access to NVRAM data on MIPS SoCs, pending implementation of a flash-aware bhnd_nvram driver. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D7489
This commit is contained in:
parent
9dfeb4140c
commit
1728aef23d
@ -1163,10 +1163,14 @@ dev/bhnd/cores/pci/bhnd_pcib.c optional bhnd_pcib bhnd pci
|
||||
dev/bhnd/cores/pcie2/bhnd_pcie2.c optional bhnd pci
|
||||
dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c optional bhndb bhnd pci
|
||||
dev/bhnd/cores/pcie2/bhnd_pcie2b.c optional bhnd_pcie2b bhnd pci
|
||||
dev/bhnd/nvram/bhnd_nvram.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_nvram_common.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_nvram_cfe.c optional bhnd siba_nexus cfe | \
|
||||
bhnd bcma_nexus cfe
|
||||
dev/bhnd/nvram/bhnd_nvram_if.m optional bhnd
|
||||
dev/bhnd/nvram/bhnd_nvram_parser.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_sprom.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_sprom_subr.c optional bhnd
|
||||
dev/bhnd/nvram/nvram_subr.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_sprom_parser.c optional bhnd
|
||||
dev/bhnd/siba/siba.c optional siba bhnd
|
||||
dev/bhnd/siba/siba_bhndb.c optional siba bhnd bhndb
|
||||
dev/bhnd/siba/siba_nexus.c optional siba_nexus siba bhnd
|
||||
|
@ -361,7 +361,7 @@ bhnd_finish_attach(struct bhnd_softc *sc)
|
||||
if (ccaps->nvram_src != BHND_NVRAM_SRC_UNKNOWN) {
|
||||
if ((sc->nvram_dev = bhnd_find_nvram(sc)) == NULL) {
|
||||
device_printf(sc->dev,
|
||||
"warning: %s NVRAM device not found\n",
|
||||
"warning: NVRAM %s device not found\n",
|
||||
bhnd_nvram_src_name(ccaps->nvram_src));
|
||||
}
|
||||
}
|
||||
@ -459,6 +459,11 @@ bhnd_find_platform_dev(struct bhnd_softc *sc, const char *classname)
|
||||
}
|
||||
|
||||
child = device_find_child(chipc, classname, -1);
|
||||
if (child != NULL)
|
||||
goto found;
|
||||
|
||||
/* Look for a parent-attached device (e.g. nexus0 -> bhnd_nvram) */
|
||||
child = device_find_child(device_get_parent(sc->dev), classname, -1);
|
||||
if (child == NULL)
|
||||
return (NULL);
|
||||
|
||||
@ -651,7 +656,7 @@ bhnd_generic_is_region_valid(device_t dev, device_t child,
|
||||
*/
|
||||
int
|
||||
bhnd_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)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
device_t nvram, parent;
|
||||
@ -660,14 +665,14 @@ bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
|
||||
|
||||
/* If a NVRAM device is available, consult it first */
|
||||
if ((nvram = bhnd_find_nvram(sc)) != NULL)
|
||||
return BHND_NVRAM_GETVAR(nvram, name, buf, size);
|
||||
return BHND_NVRAM_GETVAR(nvram, name, buf, size, type);
|
||||
|
||||
/* Otherwise, 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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -321,6 +321,31 @@ void bhnd_set_custom_core_desc(device_t dev,
|
||||
const char *name);
|
||||
void bhnd_set_default_core_desc(device_t dev);
|
||||
|
||||
int bhnd_nvram_getvar_str(device_t dev,
|
||||
const char *name, char *buf, size_t len,
|
||||
size_t *rlen);
|
||||
|
||||
int bhnd_nvram_getvar_uint(device_t dev,
|
||||
const char *name, void *value, int width);
|
||||
int bhnd_nvram_getvar_uint8(device_t dev,
|
||||
const char *name, uint8_t *value);
|
||||
int bhnd_nvram_getvar_uint16(device_t dev,
|
||||
const char *name, uint16_t *value);
|
||||
int bhnd_nvram_getvar_uint32(device_t dev,
|
||||
const char *name, uint32_t *value);
|
||||
|
||||
int bhnd_nvram_getvar_int(device_t dev,
|
||||
const char *name, void *value, int width);
|
||||
int bhnd_nvram_getvar_int8(device_t dev,
|
||||
const char *name, int8_t *value);
|
||||
int bhnd_nvram_getvar_int16(device_t dev,
|
||||
const char *name, int16_t *value);
|
||||
int bhnd_nvram_getvar_int32(device_t dev,
|
||||
const char *name, int32_t *value);
|
||||
|
||||
int bhnd_nvram_getvar_array(device_t dev,
|
||||
const char *name, void *buf, size_t count,
|
||||
bhnd_nvram_type type);
|
||||
|
||||
bool bhnd_bus_generic_is_hw_disabled(device_t dev,
|
||||
device_t child);
|
||||
@ -329,7 +354,8 @@ bool bhnd_bus_generic_is_region_valid(device_t dev,
|
||||
u_int port, u_int region);
|
||||
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);
|
||||
const struct bhnd_chipid *bhnd_bus_generic_get_chipid(device_t dev,
|
||||
device_t child);
|
||||
int bhnd_bus_generic_read_board_info(device_t dev,
|
||||
@ -428,55 +454,36 @@ bhnd_read_board_info(device_t dev, struct bhnd_board_info *info)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine an NVRAM variable's expected size.
|
||||
*
|
||||
* @param dev A bhnd bus child device.
|
||||
* @param name The variable name.
|
||||
* @param[out] len On success, the variable's size, in bytes.
|
||||
* Read an NVRAM variable, coerced to the requested @p type.
|
||||
*
|
||||
* @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 requested value will be written to
|
||||
* this buffer. This argment may be NULL if
|
||||
* the value is not desired.
|
||||
* @param[in,out] len The maximum capacity of @p buf. On success,
|
||||
* will be set to the actual size of the requested
|
||||
* value.
|
||||
* @param type The desired data representation to be written
|
||||
* to @p buf.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The requested variable was not found.
|
||||
* @retval ENODEV No valid NVRAM source could be found.
|
||||
* @retval ENOMEM If a buffer of @p size is too small to hold the
|
||||
* requested value.
|
||||
* @retval EOPNOTSUPP If the value cannot be coerced to @p type.
|
||||
* @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.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_nvram_getvarlen(device_t dev, const char *name, size_t *len)
|
||||
bhnd_nvram_getvar(device_t dev, const char *name, void *buf, size_t *len,
|
||||
bhnd_nvram_type type)
|
||||
{
|
||||
return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, NULL,
|
||||
len));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an NVRAM variable.
|
||||
*
|
||||
* @param dev A bhnd bus child device.
|
||||
* @param name The NVRAM variable name.
|
||||
* @param buf A buffer large enough to hold @p len bytes. On success,
|
||||
* the requested value will be written to this buffer.
|
||||
* @param len The required variable length.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The requested variable was not found.
|
||||
* @retval EINVAL If @p len does not match the actual variable size.
|
||||
* @retval ENODEV No valid NVRAM source could be found.
|
||||
* @retval non-zero If reading @p name otherwise fails, a regular unix
|
||||
* error code will be returned.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_nvram_getvar(device_t dev, const char *name, void *buf, size_t len)
|
||||
{
|
||||
size_t var_len;
|
||||
int error;
|
||||
|
||||
if ((error = bhnd_nvram_getvarlen(dev, name, &var_len)))
|
||||
return (error);
|
||||
|
||||
if (len != var_len)
|
||||
return (EINVAL);
|
||||
|
||||
return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, buf,
|
||||
&len));
|
||||
len, type));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,7 +116,7 @@ CODE {
|
||||
|
||||
static int
|
||||
bhnd_bus_null_get_nvram_var(device_t dev, device_t child,
|
||||
const char *name, void *buf, size_t *size)
|
||||
const char *name, void *buf, size_t *size, bhnd_nvram_type type)
|
||||
{
|
||||
return (ENODEV);
|
||||
}
|
||||
@ -492,12 +492,15 @@ METHOD int get_region_addr {
|
||||
* the value is not desired.
|
||||
* @param[in,out] size The capacity of @p buf. On success, will be set
|
||||
* to the actual size of the requested value.
|
||||
* @param type The data type to be written to @p buf.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The requested variable was not found.
|
||||
* @retval ENOMEM If @p buf is non-NULL and a buffer of @p size is too
|
||||
* small to hold the requested value.
|
||||
* @retval ENODEV No valid NVRAM source could be found.
|
||||
* @retval EFTYPE If the @p name's data type cannot be coerced to @p type.
|
||||
* @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.
|
||||
*/
|
||||
@ -507,6 +510,7 @@ METHOD int get_nvram_var {
|
||||
const char *name;
|
||||
void *buf;
|
||||
size_t *size;
|
||||
bhnd_nvram_type type;
|
||||
} DEFAULT bhnd_bus_null_get_nvram_var;
|
||||
|
||||
|
||||
|
@ -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>
|
||||
@ -880,6 +879,325 @@ cleanup:
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,6 +34,8 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "nvram/bhnd_nvram.h"
|
||||
|
||||
/** bhnd(4) device classes. */
|
||||
typedef enum {
|
||||
BHND_DEVCLASS_CC, /**< chipcommon i/o controller */
|
||||
|
@ -92,6 +92,6 @@ int bhnd_generic_resume_child(device_t dev,
|
||||
|
||||
int bhnd_generic_get_nvram_var(device_t dev,
|
||||
device_t child, const char *name, void *buf,
|
||||
size_t *size);
|
||||
size_t *size, bhnd_nvram_type type);
|
||||
|
||||
#endif /* _BHND_BHNDVAR_H_ */
|
||||
|
@ -369,19 +369,11 @@ chipc_find_nvram_src(struct chipc_softc *sc, struct chipc_caps *caps)
|
||||
{
|
||||
uint32_t otp_st, srom_ctrl;
|
||||
|
||||
/* Very early devices vend SPROM/OTP/CIS (if at all) via the
|
||||
* host bridge interface instead of ChipCommon. */
|
||||
if (!CHIPC_QUIRK(sc, SUPPORTS_SPROM))
|
||||
return (BHND_NVRAM_SRC_UNKNOWN);
|
||||
|
||||
/*
|
||||
* Later chipset revisions standardized the SPROM capability flags and
|
||||
* register interfaces.
|
||||
*
|
||||
* We check for hardware presence in order of precedence. For example,
|
||||
* SPROM is is always used in preference to internal OTP if found.
|
||||
*/
|
||||
if (caps->sprom) {
|
||||
if (CHIPC_QUIRK(sc, SUPPORTS_SPROM) && caps->sprom) {
|
||||
srom_ctrl = bhnd_bus_read_4(sc->core, CHIPC_SPROM_CTRL);
|
||||
if (srom_ctrl & CHIPC_SRC_PRESENT)
|
||||
return (BHND_NVRAM_SRC_SPROM);
|
||||
|
189
sys/dev/bhnd/nvram/bhnd_nvram.c
Normal file
189
sys/dev/bhnd/nvram/bhnd_nvram.c
Normal file
@ -0,0 +1,189 @@
|
||||
/*-
|
||||
* Copyright (c) 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$");
|
||||
|
||||
/*
|
||||
* BHND CFE NVRAM driver.
|
||||
*
|
||||
* Provides access to device NVRAM via CFE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
#include <dev/cfe/cfe_api.h>
|
||||
#include <dev/cfe/cfe_error.h>
|
||||
#include <dev/cfe/cfe_ioctl.h>
|
||||
|
||||
#include "bhnd_nvram_if.h"
|
||||
|
||||
#include "bhnd_nvramvar.h"
|
||||
|
||||
/**
|
||||
* Default bhnd_nvram driver implementation of DEVICE_PROBE().
|
||||
*/
|
||||
int
|
||||
bhnd_nvram_probe(device_t dev)
|
||||
{
|
||||
device_set_desc(dev, "Broadcom NVRAM");
|
||||
|
||||
/* Refuse wildcard attachments */
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call from subclass DEVICE_ATTACH() implementations to handle
|
||||
* device attachment.
|
||||
*
|
||||
* @param dev BHND NVRAM device.
|
||||
* @param data NVRAM data to be copied and parsed. No reference to data
|
||||
* will be held after return.
|
||||
* @param size Size of @p data, in bytes.
|
||||
* @param fmt NVRAM format.
|
||||
*/
|
||||
int
|
||||
bhnd_nvram_attach(device_t dev, void *data, size_t size, bhnd_nvram_format fmt)
|
||||
{
|
||||
struct bhnd_nvram_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
/* Initialize NVRAM parser */
|
||||
error = bhnd_nvram_parser_init(&sc->nvram, dev, data, size, fmt);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* Initialize mutex */
|
||||
BHND_NVRAM_LOCK_INIT(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_nvram driver implementation of DEVICE_RESUME().
|
||||
*/
|
||||
int
|
||||
bhnd_nvram_resume(device_t dev)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_nvram driver implementation of DEVICE_SUSPEND().
|
||||
*/
|
||||
int
|
||||
bhnd_nvram_suspend(device_t dev)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_nvram driver implementation of DEVICE_DETACH().
|
||||
*/
|
||||
int
|
||||
bhnd_nvram_detach(device_t dev)
|
||||
{
|
||||
struct bhnd_nvram_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
bhnd_nvram_parser_fini(&sc->nvram);
|
||||
BHND_NVRAM_LOCK_DESTROY(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_nvram driver implementation of BHND_NVRAM_GETVAR().
|
||||
*/
|
||||
static int
|
||||
bhnd_nvram_getvar_method(device_t dev, const char *name, void *buf, size_t *len,
|
||||
bhnd_nvram_type type)
|
||||
{
|
||||
struct bhnd_nvram_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
BHND_NVRAM_LOCK(sc);
|
||||
error = bhnd_nvram_parser_getvar(&sc->nvram, name, buf, len, type);
|
||||
BHND_NVRAM_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_nvram driver implementation of BHND_NVRAM_SETVAR().
|
||||
*/
|
||||
static int
|
||||
bhnd_nvram_setvar_method(device_t dev, const char *name, const void *buf,
|
||||
size_t len, bhnd_nvram_type type)
|
||||
{
|
||||
struct bhnd_nvram_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
BHND_NVRAM_LOCK(sc);
|
||||
error = bhnd_nvram_parser_setvar(&sc->nvram, name, buf, len, type);
|
||||
BHND_NVRAM_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static device_method_t bhnd_nvram_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhnd_nvram_probe),
|
||||
DEVMETHOD(device_resume, bhnd_nvram_resume),
|
||||
DEVMETHOD(device_suspend, bhnd_nvram_suspend),
|
||||
DEVMETHOD(device_detach, bhnd_nvram_detach),
|
||||
|
||||
/* NVRAM interface */
|
||||
DEVMETHOD(bhnd_nvram_getvar, bhnd_nvram_getvar_method),
|
||||
DEVMETHOD(bhnd_nvram_setvar, bhnd_nvram_setvar_method),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(bhnd_nvram, bhnd_nvram_driver, bhnd_nvram_methods, sizeof(struct bhnd_nvram_softc));
|
@ -67,4 +67,50 @@ typedef enum {
|
||||
*/
|
||||
} bhnd_nvram_src;
|
||||
|
||||
/** Supported NVRAM formats. */
|
||||
typedef enum {
|
||||
BHND_NVRAM_FMT_BCM = 0, /**< Broadcom NUL-delimited key=value pairs */
|
||||
BHND_NVRAM_FMT_TLV = 1, /**< CFE TLV encoding, as used on WGT634U */
|
||||
BHND_NVRAM_FMT_BTXT = 2, /**< Broadcom board text file. This is used
|
||||
to provide external NVRAM data for some
|
||||
fullmac WiFi devices. */
|
||||
BHND_NVRAM_FMT_SPROM = 3, /**< SPROM/OTP-specific encoding used by
|
||||
Broadcom network adapters */
|
||||
BHND_NVRAM_FMT_CIS = 4, /**< A mostly CIS-compatible encoding used
|
||||
on some Broadcom network adapters */
|
||||
BHND_NVRAM_FMT_UNKNOWN = 5 /**< Unknown or unrecognized format */
|
||||
} bhnd_nvram_format;
|
||||
|
||||
|
||||
/** bhnd_nvram_type bit flags */
|
||||
enum {
|
||||
BHND_NVRAM_TF_SIGNED = (1<<7),
|
||||
};
|
||||
|
||||
#define BHND_NVRAM_TYPE_ID_MASK 0xF
|
||||
#define BHND_NVRAM_TYPE_FLAGS_MASK 0x70
|
||||
|
||||
#define BHND_NVRAM_TYPE_ID(_id, _flags) \
|
||||
(((_id) & BHND_NVRAM_TYPE_ID_MASK) | \
|
||||
((_flags) & BHND_NVRAM_TYPE_FLAGS_MASK))
|
||||
|
||||
/** Supported NVRAM data types */
|
||||
typedef enum {
|
||||
BHND_NVRAM_TYPE_UINT8 = BHND_NVRAM_TYPE_ID(0, 0), /**< unsigned 8-bit integer */
|
||||
BHND_NVRAM_TYPE_UINT16 = BHND_NVRAM_TYPE_ID(1, 0), /**< unsigned 16-bit integer */
|
||||
BHND_NVRAM_TYPE_UINT32 = BHND_NVRAM_TYPE_ID(2, 0), /**< unsigned 32-bit integer */
|
||||
BHND_NVRAM_TYPE_INT8 = BHND_NVRAM_TYPE_ID(4, BHND_NVRAM_TF_SIGNED), /**< signed 8-bit integer */
|
||||
BHND_NVRAM_TYPE_INT16 = BHND_NVRAM_TYPE_ID(5, BHND_NVRAM_TF_SIGNED), /**< signed 16-bit integer */
|
||||
BHND_NVRAM_TYPE_INT32 = BHND_NVRAM_TYPE_ID(6, BHND_NVRAM_TF_SIGNED), /**< signed 32-bit integer */
|
||||
BHND_NVRAM_TYPE_CHAR = BHND_NVRAM_TYPE_ID(7, BHND_NVRAM_TF_SIGNED), /**< ASCII character */
|
||||
BHND_NVRAM_TYPE_CSTR = BHND_NVRAM_TYPE_ID(8, 0), /**< NUL-terminated C string */
|
||||
} bhnd_nvram_type;
|
||||
|
||||
#undef BHND_NVRAM_TYPE_ID_MASK
|
||||
#undef BHND_NVRAM_TYPE_FLAGS_MASK
|
||||
#undef BHND_NVRAM_TYPE_ID
|
||||
|
||||
#define BHND_NVRAM_SIGNED_TYPE(_type) \
|
||||
(((_type) & BHND_NVRAM_TF_SIGNED) == BHND_NVRAM_TF_SIGNED)
|
||||
|
||||
#endif /* _BHND_NVRAM_BHND_NVRAM_H_ */
|
||||
|
373
sys/dev/bhnd/nvram/bhnd_nvram_cfe.c
Normal file
373
sys/dev/bhnd/nvram/bhnd_nvram_cfe.c
Normal file
@ -0,0 +1,373 @@
|
||||
/*-
|
||||
* Copyright (c) 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$");
|
||||
|
||||
/*
|
||||
* BHND CFE NVRAM driver.
|
||||
*
|
||||
* Provides access to device NVRAM via CFE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
#include <dev/cfe/cfe_api.h>
|
||||
#include <dev/cfe/cfe_error.h>
|
||||
#include <dev/cfe/cfe_ioctl.h>
|
||||
|
||||
#include "bhnd_nvram_if.h"
|
||||
|
||||
#include "bhnd_nvramvar.h"
|
||||
|
||||
static int nvram_open_cfedev(device_t dev, char *devname, int fd,
|
||||
int64_t *offset, uint32_t *size, bhnd_nvram_format fmt);
|
||||
static char *nvram_find_cfedev(device_t dev, int *fd, int64_t *offset,
|
||||
uint32_t *size, bhnd_nvram_format *fmt);
|
||||
|
||||
/** Known CFE NVRAM device names, in probe order. */
|
||||
static char *nvram_cfe_devs[] = {
|
||||
"nflash0.nvram", /* NAND */
|
||||
"nflash1.nvram",
|
||||
"flash0.nvram",
|
||||
"flash1.nvram",
|
||||
};
|
||||
|
||||
/** Supported CFE NVRAM formats, in probe order. */
|
||||
bhnd_nvram_format nvram_cfe_fmts[] = {
|
||||
BHND_NVRAM_FMT_BCM,
|
||||
BHND_NVRAM_FMT_TLV
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
bhnd_nvram_cfe_probe(device_t dev)
|
||||
{
|
||||
char *devname;
|
||||
bhnd_nvram_format fmt;
|
||||
int64_t offset;
|
||||
uint32_t size;
|
||||
int error;
|
||||
int fd;
|
||||
|
||||
/* Defer to default driver implementation */
|
||||
if ((error = bhnd_nvram_probe(dev)) > 0)
|
||||
return (error);
|
||||
|
||||
/* Locate a usable CFE device */
|
||||
devname = nvram_find_cfedev(dev, &fd, &offset, &size, &fmt);
|
||||
if (devname == NULL)
|
||||
return (ENXIO);
|
||||
cfe_close(fd);
|
||||
|
||||
switch (fmt) {
|
||||
case BHND_NVRAM_FMT_BCM:
|
||||
device_set_desc(dev, "Broadcom NVRAM");
|
||||
break;
|
||||
case BHND_NVRAM_FMT_TLV:
|
||||
device_set_desc(dev, "Broadcom WGT634U NVRAM");
|
||||
break;
|
||||
default:
|
||||
device_printf(dev, "unknown NVRAM format: %d\n", fmt);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Refuse wildcard attachments */
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
bhnd_nvram_cfe_attach(device_t dev)
|
||||
{
|
||||
char *devname;
|
||||
unsigned char *buffer;
|
||||
bhnd_nvram_format fmt;
|
||||
int64_t offset;
|
||||
uint32_t size;
|
||||
int error;
|
||||
int fd;
|
||||
|
||||
error = 0;
|
||||
buffer = NULL;
|
||||
fd = CFE_ERR;
|
||||
|
||||
/* Locate NVRAM device via CFE */
|
||||
devname = nvram_find_cfedev(dev, &fd, &offset, &size, &fmt);
|
||||
if (devname == NULL) {
|
||||
device_printf(dev, "CFE NVRAM device not found\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Copy out NVRAM buffer */
|
||||
buffer = malloc(size, M_TEMP, M_NOWAIT);
|
||||
if (buffer == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
for (size_t remain = size; remain > 0;) {
|
||||
int nr, req;
|
||||
|
||||
req = ulmin(INT_MAX, remain);
|
||||
nr = cfe_readblk(fd, size-remain, buffer+(size-remain),
|
||||
req);
|
||||
if (nr < 0) {
|
||||
device_printf(dev, "%s: cfe_readblk() failed: %d\n",
|
||||
devname, fd);
|
||||
|
||||
error = ENXIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
remain -= nr;
|
||||
|
||||
if (nr == 0 && remain > 0) {
|
||||
device_printf(dev, "%s: cfe_readblk() unexpected EOF: "
|
||||
"%zu of %zu pending\n", devname, remain, size);
|
||||
|
||||
error = ENXIO;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
device_printf(dev, "CFE %s (%#jx+%#jx)\n", devname, (uintmax_t)offset,
|
||||
(uintmax_t)size);
|
||||
|
||||
/* Delegate to default driver implementation */
|
||||
error = bhnd_nvram_attach(dev, buffer, size, fmt);
|
||||
|
||||
cleanup:
|
||||
if (buffer != NULL)
|
||||
free(buffer, M_TEMP);
|
||||
|
||||
if (fd >= 0)
|
||||
cfe_close(fd);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify and open a CFE NVRAM device.
|
||||
*
|
||||
* @param dev bhnd_nvram_cfe device.
|
||||
* @param devname The name of the CFE device to be probed.
|
||||
* @param fd An open CFE file descriptor for @p devname.
|
||||
* @param[out] offset On success, the NVRAM data offset within @p @fd.
|
||||
* @param[out] size On success, maximum the NVRAM data size within @p fd.
|
||||
* @param fmt The expected NVRAM data format for this device.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero If probing @p devname fails, a regular unix
|
||||
* error code will be returned.
|
||||
*/
|
||||
static int
|
||||
nvram_open_cfedev(device_t dev, char *devname, int fd, int64_t *offset,
|
||||
uint32_t *size, bhnd_nvram_format fmt)
|
||||
{
|
||||
union bhnd_nvram_ident ident;
|
||||
nvram_info_t nvram_info;
|
||||
int cerr, devinfo, dtype, rlen;
|
||||
int error;
|
||||
|
||||
/* Try to fetch device info */
|
||||
if ((devinfo = cfe_getdevinfo(devname)) == CFE_ERR_DEVNOTFOUND)
|
||||
return (ENODEV);
|
||||
|
||||
if (devinfo < 0) {
|
||||
device_printf(dev, "cfe_getdevinfo() failed: %d",
|
||||
devinfo);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Verify device type */
|
||||
dtype = devinfo & CFE_DEV_MASK;
|
||||
switch (dtype) {
|
||||
case CFE_DEV_FLASH:
|
||||
case CFE_DEV_NVRAM:
|
||||
/* Valid device type */
|
||||
break;
|
||||
default:
|
||||
device_printf(dev, "%s: unknown device type %d\n",
|
||||
devname, dtype);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Try to fetch nvram info from CFE */
|
||||
cerr = cfe_ioctl(fd, IOCTL_NVRAM_GETINFO, (unsigned char *)&nvram_info,
|
||||
sizeof(nvram_info), &rlen, 0);
|
||||
if (cerr != CFE_OK && cerr != CFE_ERR_INV_COMMAND) {
|
||||
device_printf(dev, "%s: IOCTL_NVRAM_GETINFO failed: %d\n",
|
||||
devname, cerr);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Fall back on flash info.
|
||||
*
|
||||
* This is known to be required on the Asus RT-N53 (CFE 5.70.55.33,
|
||||
* BBP 1.0.37, BCM5358UB0), where IOCTL_NVRAM_GETINFO returns
|
||||
* CFE_ERR_INV_COMMAND.
|
||||
*/
|
||||
if (cerr == CFE_ERR_INV_COMMAND) {
|
||||
flash_info_t fi;
|
||||
|
||||
cerr = cfe_ioctl(fd, IOCTL_FLASH_GETINFO, (unsigned char *)&fi,
|
||||
sizeof(fi), &rlen, 0);
|
||||
|
||||
if (cerr != CFE_OK) {
|
||||
device_printf(dev, "%s: IOCTL_FLASH_GETINFO failed: "
|
||||
"%d\n", devname, cerr);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
nvram_info.nvram_eraseflg =
|
||||
!(fi.flash_flags & FLASH_FLAG_NOERASE);
|
||||
nvram_info.nvram_offset = 0x0;
|
||||
nvram_info.nvram_size = fi.flash_size;
|
||||
}
|
||||
|
||||
/* Try to read NVRAM header/format identification */
|
||||
cerr = cfe_readblk(fd, 0, (unsigned char *)&ident, sizeof(ident));
|
||||
if (cerr < 0) {
|
||||
device_printf(dev, "%s: cfe_readblk() failed: %d\n",
|
||||
devname, cerr);
|
||||
return (ENXIO);
|
||||
} else if (cerr == 0) {
|
||||
/* EOF */
|
||||
return (ENODEV);
|
||||
} else if (cerr != sizeof(ident)) {
|
||||
device_printf(dev, "%s: cfe_readblk() short read: %d\n",
|
||||
devname, cerr);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Verify expected format */
|
||||
if ((error = bhnd_nvram_parser_identify(&ident, fmt)))
|
||||
return (error);
|
||||
|
||||
/* Provide offset and size */
|
||||
switch (fmt) {
|
||||
case BHND_NVRAM_FMT_TLV:
|
||||
/* No size field is available; must assume the NVRAM data
|
||||
* consumes up to the full CFE NVRAM range */
|
||||
*offset = nvram_info.nvram_offset;
|
||||
*size = nvram_info.nvram_size;
|
||||
break;
|
||||
case BHND_NVRAM_FMT_BCM:
|
||||
if (ident.bcm.size > nvram_info.nvram_size) {
|
||||
device_printf(dev, "%s: NVRAM size %#x overruns %#x "
|
||||
"device limit\n", devname, ident.bcm.size,
|
||||
nvram_info.nvram_size);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
*offset = nvram_info.nvram_offset;
|
||||
*size = ident.bcm.size;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find (and open) a CFE NVRAM device.
|
||||
*
|
||||
* @param dev bhnd_nvram_cfe device.
|
||||
* @param[out] fd On success, a valid CFE file descriptor. The callee
|
||||
* is responsible for closing this file descriptor via
|
||||
* cfe_close().
|
||||
* @param[out] offset On success, the NVRAM data offset within @p @fd.
|
||||
* @param[out] size On success, maximum the NVRAM data size within @p fd.
|
||||
* @param fmt The expected NVRAM data format for this device.
|
||||
*
|
||||
* @return On success, the opened CFE device's name will be returned. On
|
||||
* error, returns NULL.
|
||||
*/
|
||||
static char *
|
||||
nvram_find_cfedev(device_t dev, int *fd, int64_t *offset,
|
||||
uint32_t *size, bhnd_nvram_format *fmt)
|
||||
{
|
||||
char *devname;
|
||||
int error;
|
||||
|
||||
for (u_int i = 0; i < nitems(nvram_cfe_fmts); i++) {
|
||||
*fmt = nvram_cfe_fmts[i];
|
||||
|
||||
for (u_int j = 0; j < nitems(nvram_cfe_devs); j++) {
|
||||
devname = nvram_cfe_devs[j];
|
||||
|
||||
/* Open for reading */
|
||||
*fd = cfe_open(devname);
|
||||
if (*fd == CFE_ERR_DEVNOTFOUND) {
|
||||
continue;
|
||||
} else if (*fd < 0) {
|
||||
device_printf(dev, "%s: cfe_open() failed: "
|
||||
"%d\n", devname, *fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Probe */
|
||||
error = nvram_open_cfedev(dev, devname, *fd, offset,
|
||||
size, *fmt);
|
||||
if (error == 0)
|
||||
return (devname);
|
||||
|
||||
/* Keep searching */
|
||||
devname = NULL;
|
||||
cfe_close(*fd);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static device_method_t bhnd_nvram_cfe_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhnd_nvram_cfe_probe),
|
||||
DEVMETHOD(device_attach, bhnd_nvram_cfe_attach),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_1(bhnd_nvram, bhnd_nvram_cfe, bhnd_nvram_cfe_methods,
|
||||
sizeof(struct bhnd_nvram_softc), bhnd_nvram_driver);
|
||||
EARLY_DRIVER_MODULE(bhnd_nvram_cfe, nexus, bhnd_nvram_cfe,
|
||||
bhnd_nvram_devclass, NULL, NULL, BUS_PASS_BUS + BUS_PASS_ORDER_EARLY);
|
661
sys/dev/bhnd/nvram/bhnd_nvram_common.c
Normal file
661
sys/dev/bhnd/nvram/bhnd_nvram_common.c
Normal file
@ -0,0 +1,661 @@
|
||||
/*-
|
||||
* Copyright (c) 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/ctype.h>
|
||||
#include <sys/hash.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/_inttypes.h>
|
||||
|
||||
#include "bhnd_nvram_common.h"
|
||||
|
||||
#include "bhnd_nvram_map_data.h"
|
||||
|
||||
/*
|
||||
* Common NVRAM/SPROM support, including NVRAM variable map
|
||||
* lookup.
|
||||
*/
|
||||
|
||||
MALLOC_DEFINE(M_BHND_NVRAM, "bhnd_nvram", "bhnd nvram data");
|
||||
|
||||
/*
|
||||
* CRC-8 lookup table used to checksum SPROM and NVRAM data via
|
||||
* bhnd_nvram_crc8().
|
||||
*
|
||||
* Generated with following parameters:
|
||||
* polynomial: CRC-8 (x^8 + x^7 + x^6 + x^4 + x^2 + 1)
|
||||
* reflected bits: false
|
||||
* reversed: true
|
||||
*/
|
||||
const uint8_t bhnd_nvram_crc8_tab[] = {
|
||||
0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b, 0x4a, 0xbd, 0xf3,
|
||||
0x04, 0x6f, 0x98, 0xd6, 0x21, 0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46,
|
||||
0x08, 0xff, 0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5, 0x7f,
|
||||
0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14, 0x35, 0xc2, 0x8c, 0x7b,
|
||||
0x10, 0xe7, 0xa9, 0x5e, 0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77,
|
||||
0x80, 0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca, 0xfe, 0x09,
|
||||
0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95, 0xb4, 0x43, 0x0d, 0xfa, 0x91,
|
||||
0x66, 0x28, 0xdf, 0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01,
|
||||
0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b, 0x81, 0x76, 0x38,
|
||||
0xcf, 0xa4, 0x53, 0x1d, 0xea, 0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19,
|
||||
0x57, 0xa0, 0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e, 0x5f,
|
||||
0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34, 0xab, 0x5c, 0x12, 0xe5,
|
||||
0x8e, 0x79, 0x37, 0xc0, 0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d,
|
||||
0x8a, 0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54, 0x75, 0x82,
|
||||
0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e, 0xd4, 0x23, 0x6d, 0x9a, 0xf1,
|
||||
0x06, 0x48, 0xbf, 0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5,
|
||||
0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b, 0x0a, 0xfd, 0xb3,
|
||||
0x44, 0x2f, 0xd8, 0x96, 0x61, 0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87,
|
||||
0xc9, 0x3e, 0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74, 0xc1,
|
||||
0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa, 0x8b, 0x7c, 0x32, 0xc5,
|
||||
0xae, 0x59, 0x17, 0xe0, 0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6,
|
||||
0x41, 0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b, 0xbe, 0x49,
|
||||
0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5, 0xf4, 0x03, 0x4d, 0xba, 0xd1,
|
||||
0x26, 0x68, 0x9f
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the size of type @p type, or 0 if @p type has a variable width
|
||||
* (e.g. a C string).
|
||||
*
|
||||
* @param type NVRAM data type.
|
||||
* @result the byte width of @p type.
|
||||
*/
|
||||
size_t
|
||||
bhnd_nvram_type_width(bhnd_nvram_type type)
|
||||
{
|
||||
switch (type) {
|
||||
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_CSTR:
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Quiesce gcc4.2 */
|
||||
panic("bhnd nvram type %u unknown", type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the format string to use when printing @p type with @p sfmt
|
||||
*
|
||||
* @param type The value type being printed.
|
||||
* @param sfmt The string format required for @p type.
|
||||
* @param elem_num The element index being printed. If this is the first
|
||||
* value in an array of elements, the index would be 0, the next would be 1,
|
||||
* and so on.
|
||||
*
|
||||
* @retval non-NULL A valid printf format string.
|
||||
* @retval NULL If no format string is available for @p type and @p sfmt.
|
||||
*/
|
||||
const char *
|
||||
bhnd_nvram_type_fmt(bhnd_nvram_type type, bhnd_nvram_sfmt sfmt,
|
||||
size_t elem_num)
|
||||
{
|
||||
size_t width;
|
||||
|
||||
width = bhnd_nvram_type_width(type);
|
||||
|
||||
/* Sanity-check the type width */
|
||||
switch (width) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Special-cased string formats */
|
||||
switch (sfmt) {
|
||||
case BHND_NVRAM_SFMT_LEDDC:
|
||||
/* If this is the first element, use the 0x-prefixed
|
||||
* SFMT_HEX */
|
||||
if (elem_num == 0)
|
||||
sfmt = BHND_NVRAM_SFMT_HEX;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return the format string */
|
||||
switch (sfmt) {
|
||||
case BHND_NVRAM_SFMT_MACADDR:
|
||||
switch (width) {
|
||||
case 1: return ("%02" PRIx8);
|
||||
}
|
||||
break;
|
||||
|
||||
case BHND_NVRAM_SFMT_HEX:
|
||||
switch (width) {
|
||||
case 1: return ("0x%02" PRIx8);
|
||||
case 2: return ("0x%04" PRIx16);
|
||||
case 4: return ("0x%08" PRIx32);
|
||||
}
|
||||
break;
|
||||
case BHND_NVRAM_SFMT_DEC:
|
||||
if (BHND_NVRAM_SIGNED_TYPE(type)) {
|
||||
switch (width) {
|
||||
case 1: return ("%" PRId8);
|
||||
case 2: return ("%" PRId16);
|
||||
case 4: return ("%" PRId32);
|
||||
}
|
||||
} else {
|
||||
switch (width) {
|
||||
case 1: return ("%" PRIu8);
|
||||
case 2: return ("%" PRIu16);
|
||||
case 4: return ("%" PRIu32);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BHND_NVRAM_SFMT_LEDDC:
|
||||
switch (width) {
|
||||
case 1: return ("%02" PRIx8);
|
||||
case 2: return ("%04" PRIx16);
|
||||
case 4: return ("%08" PRIx32);
|
||||
}
|
||||
break;
|
||||
|
||||
case BHND_NVRAM_SFMT_CCODE:
|
||||
switch (width) {
|
||||
case 1: return ("%c");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return the variable definition for @p varname, if any.
|
||||
*
|
||||
* @param varname variable name
|
||||
*
|
||||
* @retval bhnd_nvram_vardefn If a valid definition for @p varname is found.
|
||||
* @retval NULL If no definition for @p varname is found.
|
||||
*/
|
||||
const struct bhnd_nvram_vardefn *
|
||||
bhnd_nvram_find_vardefn(const char *varname)
|
||||
{
|
||||
size_t min, mid, max;
|
||||
int order;
|
||||
|
||||
/*
|
||||
* Locate the requested variable using a binary search.
|
||||
*
|
||||
* The variable table is guaranteed to be sorted in lexicographical
|
||||
* order (using the 'C' locale for collation rules)
|
||||
*/
|
||||
min = 0;
|
||||
mid = 0;
|
||||
max = nitems(bhnd_nvram_vardefs) - 1;
|
||||
|
||||
while (max >= min) {
|
||||
/* Select midpoint */
|
||||
mid = (min + max) / 2;
|
||||
|
||||
/* Determine which side of the partition to search */
|
||||
order = strcmp(bhnd_nvram_vardefs[mid].name, varname);
|
||||
if (order < 0) {
|
||||
/* Search upper partition */
|
||||
min = mid + 1;
|
||||
} else if (order > 0) {
|
||||
/* Search lower partition */
|
||||
max = mid - 1;
|
||||
} else if (order == 0) {
|
||||
/* Match found */
|
||||
return (&bhnd_nvram_vardefs[mid]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an NVRAM variable name.
|
||||
*
|
||||
* Scans for special characters (path delimiters, value delimiters, path
|
||||
* alias prefixes), returning false if the given name cannot be used
|
||||
* as a relative NVRAM key.
|
||||
*
|
||||
* @param name A relative NVRAM variable name to validate.
|
||||
* @param name_len The length of @p name, in bytes.
|
||||
*
|
||||
* @retval true If @p name is a valid relative NVRAM key.
|
||||
* @retval false If @p name should not be used as a relative NVRAM key.
|
||||
*/
|
||||
bool
|
||||
bhnd_nvram_validate_name(const char *name, size_t name_len)
|
||||
{
|
||||
size_t limit;
|
||||
|
||||
limit = strnlen(name, name_len);
|
||||
if (limit == 0)
|
||||
return (false);
|
||||
|
||||
/* Disallow path alias prefixes ([0-9]+:.*) */
|
||||
if (limit >= 2 && isdigit(*name)) {
|
||||
for (const char *p = name; p - name < limit; p++) {
|
||||
if (isdigit(*p))
|
||||
continue;
|
||||
else if (*p == ':')
|
||||
return (false);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan for special characters */
|
||||
for (const char *p = name; p - name < limit; p++) {
|
||||
switch (*p) {
|
||||
case '/': /* path delimiter */
|
||||
case '=': /* key=value delimiter */
|
||||
return (false);
|
||||
|
||||
default:
|
||||
if (isspace(*p) || !isascii(*p))
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an octet string, such as a MAC address, consisting of hex octets
|
||||
* separated with ':' or '-'.
|
||||
*
|
||||
* @param value The octet string to parse.
|
||||
* @param value_len The length of @p value, in bytes.
|
||||
* @param buf The output buffer to which parsed octets will be written. May be
|
||||
* NULL.
|
||||
* @param[in,out] len The capacity of @p buf. On success, will be set
|
||||
* to the actual size of the requested value.
|
||||
* @param type
|
||||
*/
|
||||
int
|
||||
bhnd_nvram_parse_octet_string(const char *value, size_t value_len, void *buf,
|
||||
size_t *len, bhnd_nvram_type type)
|
||||
{
|
||||
size_t limit, nbytes, width;
|
||||
size_t slen;
|
||||
uint8_t octet;
|
||||
char delim;
|
||||
|
||||
slen = strnlen(value, value_len);
|
||||
|
||||
nbytes = 0;
|
||||
if (buf != NULL)
|
||||
limit = *len;
|
||||
else
|
||||
limit = 0;
|
||||
|
||||
/* Type must have a fixed width */
|
||||
if ((width = bhnd_nvram_type_width(type)) == 0)
|
||||
return (EINVAL);
|
||||
|
||||
/* String length (not including NUL) must be aligned on an octet
|
||||
* boundary ('AA:BB', not 'AA:B', etc), and must be large enough
|
||||
* to contain at least two octet entries. */
|
||||
if (slen % 3 != 2 || slen < sizeof("AA:BB") - 1)
|
||||
return (EINVAL);
|
||||
|
||||
/* Identify the delimiter used. The standard delimiter for
|
||||
* MAC addresses is ':', but some earlier NVRAM formats may use
|
||||
* '-' */
|
||||
switch ((delim = value[2])) {
|
||||
case ':':
|
||||
case '-':
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* Parse octets */
|
||||
for (const char *p = value; p - value < value_len; p++) {
|
||||
void *outp;
|
||||
size_t pos;
|
||||
unsigned char c;
|
||||
|
||||
pos = (p - value);
|
||||
|
||||
/* Skip delimiter after each octet */
|
||||
if (pos % 3 == 2) {
|
||||
if (*p == delim)
|
||||
continue;
|
||||
|
||||
if (*p == '\0')
|
||||
return (0);
|
||||
|
||||
/* No delimiter? */
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
c = *(const unsigned char *)p;
|
||||
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isxdigit(c))
|
||||
c -= islower(c) ? 'a' - 10 : 'A' - 10;
|
||||
else
|
||||
return (EINVAL);
|
||||
|
||||
if (pos % 3 == 0) {
|
||||
/* MSB */
|
||||
octet = (c << 4);
|
||||
continue;
|
||||
} else if (pos % 3 == 1) {
|
||||
/* LSB */
|
||||
octet |= (c & 0xF);
|
||||
}
|
||||
|
||||
/* Skip writing? */
|
||||
if (limit < width || limit - width < nbytes) {
|
||||
nbytes += width;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Write output */
|
||||
outp = ((uint8_t *)buf) + nbytes;
|
||||
switch (type) {
|
||||
case BHND_NVRAM_TYPE_UINT8:
|
||||
*(uint8_t *)outp = octet;
|
||||
break;
|
||||
|
||||
case BHND_NVRAM_TYPE_UINT16:
|
||||
*(uint16_t *)outp = octet;
|
||||
break;
|
||||
|
||||
case BHND_NVRAM_TYPE_UINT32:
|
||||
*(uint32_t *)outp = octet;
|
||||
break;
|
||||
|
||||
case BHND_NVRAM_TYPE_INT8:
|
||||
if (octet > INT8_MAX)
|
||||
return (ERANGE);
|
||||
*(int8_t *)outp = (int8_t)octet;
|
||||
break;
|
||||
|
||||
case BHND_NVRAM_TYPE_INT16:
|
||||
*(int16_t *)outp = (int8_t)octet;
|
||||
break;
|
||||
|
||||
case BHND_NVRAM_TYPE_INT32:
|
||||
*(int32_t *)outp = (int8_t)octet;
|
||||
break;
|
||||
|
||||
case BHND_NVRAM_TYPE_CHAR:
|
||||
#if (CHAR_MAX < UINT8_MAX)
|
||||
if (octet > CHAR_MAX)
|
||||
return (ERANGE);
|
||||
#endif
|
||||
*(char *)outp = (char)octet;
|
||||
break;
|
||||
default:
|
||||
printf("unknown type %d\n", type);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
nbytes += width;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a new variable hash table with @p nelements.
|
||||
*
|
||||
* @param map Hash table instance to be initialized.
|
||||
* @param nelements The number of hash table buckets to allocate.
|
||||
* @param flags Hash table flags (HASH_*).
|
||||
*/
|
||||
int
|
||||
bhnd_nvram_varmap_init(struct bhnd_nvram_varmap *map, size_t nelements,
|
||||
int flags)
|
||||
{
|
||||
map->table = hashinit_flags(nelements, M_BHND_NVRAM, &map->mask,
|
||||
flags);
|
||||
if (map->table == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocate all resources associated with @p map.
|
||||
*
|
||||
* @param map Hash table to be deallocated.
|
||||
*/
|
||||
void
|
||||
bhnd_nvram_varmap_free(struct bhnd_nvram_varmap *map)
|
||||
{
|
||||
struct bhnd_nvram_tuple *t, *tnext;
|
||||
|
||||
/* Free all elements */
|
||||
for (size_t i = 0; i <= map->mask; i++) {
|
||||
LIST_FOREACH_SAFE(t, &map->table[i], t_link, tnext) {
|
||||
LIST_REMOVE(t, t_link);
|
||||
bhnd_nvram_tuple_free(t);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free hash table */
|
||||
hashdestroy(map->table, M_BHND_NVRAM, map->mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a variable entry to @p map.
|
||||
*
|
||||
* @param map Hash table to modify.
|
||||
* @param name Variable name.
|
||||
* @param value Variable value.
|
||||
* @param value_len The length of @p value, in bytes.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENOMEM unable to allocate new entry
|
||||
*/
|
||||
int
|
||||
bhnd_nvram_varmap_add(struct bhnd_nvram_varmap *map, const char *name,
|
||||
const char *value, size_t value_len)
|
||||
{
|
||||
struct bhnd_nvram_tuples *head;
|
||||
struct bhnd_nvram_tuple *t;
|
||||
|
||||
/* Locate target bucket */
|
||||
head = &map->table[hash32_str(name, HASHINIT) & map->mask];
|
||||
|
||||
/* Allocate new entry */
|
||||
if ((t = bhnd_nvram_tuple_alloc(name, value)) == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
/* Remove any existing entry */
|
||||
bhnd_nvram_varmap_remove(map, name);
|
||||
|
||||
/* Insert new entry */
|
||||
LIST_INSERT_HEAD(head, t, t_link);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove @p map in @p tuples, if it exists.
|
||||
*
|
||||
* @param map Hash table to modify.
|
||||
* @param key Key to remove.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENOENT If @p name is not found in @p map.
|
||||
*/
|
||||
int
|
||||
bhnd_nvram_varmap_remove(struct bhnd_nvram_varmap *map, const char *name)
|
||||
{
|
||||
struct bhnd_nvram_tuples *head;
|
||||
struct bhnd_nvram_tuple *t;
|
||||
size_t name_len;
|
||||
|
||||
/* Locate target bucket */
|
||||
head = &map->table[hash32_str(name, HASHINIT) & map->mask];
|
||||
name_len = strlen(name);
|
||||
|
||||
LIST_FOREACH(t, head, t_link) {
|
||||
if (t->name_len != name_len)
|
||||
continue;
|
||||
|
||||
if (strncmp(t->name, name, name_len) != 0)
|
||||
continue;
|
||||
|
||||
LIST_REMOVE(t, t_link);
|
||||
bhnd_nvram_tuple_free(t);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for @p name in @p map.
|
||||
*
|
||||
* @param map Hash table to modify.
|
||||
* @param name Variable name.
|
||||
* @param name_len Length of @p name, not including trailing NUL.
|
||||
*
|
||||
* @retval bhnd_nvram_tuple If @p name is found in @p map.
|
||||
* @retval NULL If @p name is not found.
|
||||
*/
|
||||
struct bhnd_nvram_tuple *
|
||||
bhnd_nvram_varmap_find(struct bhnd_nvram_varmap *map, const char *name,
|
||||
size_t name_len)
|
||||
{
|
||||
struct bhnd_nvram_tuples *head;
|
||||
struct bhnd_nvram_tuple *t;
|
||||
|
||||
head = &map->table[hash32_str(name, HASHINIT) & map->mask];
|
||||
|
||||
LIST_FOREACH(t, head, t_link) {
|
||||
if (t->name_len != name_len)
|
||||
continue;
|
||||
|
||||
if (strncmp(t->name, name, name_len) != 0)
|
||||
continue;
|
||||
|
||||
/* Match */
|
||||
return (t);
|
||||
}
|
||||
|
||||
/* not found */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for @p name in @p map.
|
||||
*
|
||||
* @param map Hash table to modify.
|
||||
* @param name Variable name.
|
||||
* @param name_len Length of @p name, not including trailing NUL.
|
||||
*
|
||||
* @retval true If @p name is found in @p tuples.
|
||||
* @retval false If @p name is not found.
|
||||
*/
|
||||
bool bhnd_nvram_varmap_contains(struct bhnd_nvram_varmap *map,
|
||||
const char *name, size_t name_len)
|
||||
{
|
||||
return (bhnd_nvram_varmap_find(map, name, name_len) != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new tuple with @p name and @p value.
|
||||
*
|
||||
* @param name Variable name.
|
||||
* @param value Variable value.
|
||||
*
|
||||
* @retval bhnd_nvram_tuple success.
|
||||
* @retval NULL if allocation fails.
|
||||
*/
|
||||
struct bhnd_nvram_tuple *
|
||||
bhnd_nvram_tuple_alloc(const char *name, const char *value)
|
||||
{
|
||||
struct bhnd_nvram_tuple *t;
|
||||
|
||||
t = malloc(sizeof(*t), M_BHND_NVRAM, M_NOWAIT);
|
||||
if (t == NULL)
|
||||
return (NULL);
|
||||
|
||||
t->name_len = strlen(name);
|
||||
t->name = malloc(t->name_len+1, M_BHND_NVRAM, M_NOWAIT);
|
||||
|
||||
t->value_len = strlen(value);
|
||||
t->value = malloc(t->value_len+1, M_BHND_NVRAM, M_NOWAIT);
|
||||
|
||||
if (t->name == NULL || t->value == NULL)
|
||||
goto failed;
|
||||
|
||||
strcpy(t->name, name);
|
||||
strcpy(t->value, value);
|
||||
|
||||
return (t);
|
||||
|
||||
failed:
|
||||
if (t->name != NULL)
|
||||
free(t->name, M_BHND_NVRAM);
|
||||
|
||||
if (t->value != NULL)
|
||||
free(t->value, M_BHND_NVRAM);
|
||||
|
||||
free(t, M_BHND_NVRAM);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
bhnd_nvram_tuple_free(struct bhnd_nvram_tuple *tuple)
|
||||
{
|
||||
free(tuple->name, M_BHND_NVRAM);
|
||||
free(tuple->value, M_BHND_NVRAM);
|
||||
free(tuple, M_BHND_NVRAM);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -29,29 +29,74 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_NVRAM_BHND_NVRAMVAR_H_
|
||||
#define _BHND_NVRAM_BHND_NVRAMVAR_H_
|
||||
#ifndef _BHND_NVRAM_BHND_NVRAM_COMMON_H_
|
||||
#define _BHND_NVRAM_BHND_NVRAM_COMMON_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include "bhnd_nvram.h"
|
||||
|
||||
struct bhnd_nvram_tuple;
|
||||
struct bhnd_nvram_varmap;
|
||||
|
||||
struct bhnd_nvram_vardefn;
|
||||
|
||||
MALLOC_DECLARE(M_BHND_NVRAM);
|
||||
|
||||
extern const uint8_t bhnd_nvram_crc8_tab[];
|
||||
|
||||
#define BHND_NVRAM_CRC8_INITIAL 0xFF /**< Initial bhnd_nvram_crc8 value */
|
||||
#define BHND_NVRAM_CRC8_VALID 0x9F /**< Valid CRC-8 checksum */
|
||||
#define BHND_SPROMREV_MAX UINT8_MAX /**< maximum supported SPROM revision */
|
||||
|
||||
/** NVRAM Primitive data types */
|
||||
typedef enum {
|
||||
BHND_NVRAM_DT_UINT8 = 0, /**< unsigned 8-bit integer */
|
||||
BHND_NVRAM_DT_UINT16 = 1, /**< unsigned 16-bit integer */
|
||||
BHND_NVRAM_DT_UINT32 = 2, /**< unsigned 32-bit integer */
|
||||
BHND_NVRAM_DT_INT8 = 3, /**< signed 8-bit integer */
|
||||
BHND_NVRAM_DT_INT16 = 4, /**< signed 16-bit integer */
|
||||
BHND_NVRAM_DT_INT32 = 5, /**< signed 32-bit integer */
|
||||
BHND_NVRAM_DT_CHAR = 6, /**< ASCII char */
|
||||
} bhnd_nvram_dt;
|
||||
|
||||
/** NVRAM data type string representations */
|
||||
typedef enum {
|
||||
BHND_NVRAM_VFMT_HEX = 1, /**< hex format */
|
||||
BHND_NVRAM_VFMT_DEC = 2, /**< decimal format */
|
||||
BHND_NVRAM_VFMT_MACADDR = 3, /**< mac address (canonical form, hex octets,
|
||||
BHND_NVRAM_SFMT_HEX = 1, /**< hex format */
|
||||
BHND_NVRAM_SFMT_DEC = 2, /**< decimal format */
|
||||
BHND_NVRAM_SFMT_MACADDR = 3, /**< mac address (canonical form, hex octets,
|
||||
separated with ':') */
|
||||
BHND_NVRAM_VFMT_LEDDC = 4, /**< LED PWM duty-cycle (2 bytes -- on/off) */
|
||||
BHND_NVRAM_VFMT_CCODE = 5 /**< count code format (2-3 ASCII chars, or hex string) */
|
||||
} bhnd_nvram_fmt;
|
||||
BHND_NVRAM_SFMT_LEDDC = 4, /**< LED PWM duty-cycle (2 bytes -- on/off) */
|
||||
BHND_NVRAM_SFMT_CCODE = 5 /**< count code format (2-3 ASCII chars, or hex string) */
|
||||
} bhnd_nvram_sfmt;
|
||||
|
||||
size_t bhnd_nvram_type_width(bhnd_nvram_type type);
|
||||
const char *bhnd_nvram_type_fmt(bhnd_nvram_type type,
|
||||
bhnd_nvram_sfmt sfmt, size_t elem_num);
|
||||
|
||||
const struct bhnd_nvram_vardefn *bhnd_nvram_find_vardefn(const char *varname);
|
||||
|
||||
bool bhnd_nvram_validate_name(const char *name,
|
||||
size_t name_len);
|
||||
int bhnd_nvram_parse_octet_string(
|
||||
const char *value, size_t value_len,
|
||||
void *buf, size_t *len,
|
||||
bhnd_nvram_type type);
|
||||
|
||||
int bhnd_nvram_varmap_init(
|
||||
struct bhnd_nvram_varmap *map,
|
||||
size_t nelements, int flags);
|
||||
void bhnd_nvram_varmap_free(
|
||||
struct bhnd_nvram_varmap *map);
|
||||
int bhnd_nvram_varmap_add(
|
||||
struct bhnd_nvram_varmap *map,
|
||||
const char *name, const char *value,
|
||||
size_t value_len);
|
||||
int bhnd_nvram_varmap_remove(
|
||||
struct bhnd_nvram_varmap *map,
|
||||
const char *name);
|
||||
struct bhnd_nvram_tuple *bhnd_nvram_varmap_find(
|
||||
struct bhnd_nvram_varmap *map,
|
||||
const char *name, size_t name_len);
|
||||
bool bhnd_nvram_varmap_contains(
|
||||
struct bhnd_nvram_varmap *map,
|
||||
const char *name, size_t name_len);
|
||||
|
||||
struct bhnd_nvram_tuple *bhnd_nvram_tuple_alloc(const char *name,
|
||||
const char *value);
|
||||
void bhnd_nvram_tuple_free(
|
||||
struct bhnd_nvram_tuple *tuple);
|
||||
|
||||
/** NVRAM variable flags */
|
||||
enum {
|
||||
@ -60,8 +105,6 @@ enum {
|
||||
BHND_NVRAM_VF_IGNALL1 = (1<<2) /**< hide variable if its value has all bits set. */
|
||||
};
|
||||
|
||||
#define BHND_SPROMREV_MAX UINT8_MAX /**< maximum supported SPROM revision */
|
||||
|
||||
/** SPROM revision compatibility declaration */
|
||||
struct bhnd_sprom_compat {
|
||||
uint8_t first; /**< first compatible SPROM revision */
|
||||
@ -73,39 +116,49 @@ struct bhnd_sprom_offset {
|
||||
uint16_t offset; /**< byte offset within SPROM */
|
||||
bool cont:1; /**< value should be bitwise OR'd with the
|
||||
* previous offset descriptor */
|
||||
bhnd_nvram_dt type:7; /**< data type */
|
||||
bhnd_nvram_type type:7; /**< data type */
|
||||
int8_t shift; /**< shift to be applied to the value */
|
||||
uint32_t mask; /**< mask to be applied to the value(s) */
|
||||
};
|
||||
|
||||
/** SPROM-specific variable definition */
|
||||
struct bhnd_sprom_var {
|
||||
struct bhnd_sprom_vardefn {
|
||||
struct bhnd_sprom_compat compat; /**< sprom compatibility declaration */
|
||||
const struct bhnd_sprom_offset *offsets; /**< offset descriptors */
|
||||
size_t num_offsets; /**< number of offset descriptors */
|
||||
};
|
||||
|
||||
/** NVRAM variable definition */
|
||||
struct bhnd_nvram_var {
|
||||
const char *name; /**< variable name */
|
||||
bhnd_nvram_dt type; /**< base data type */
|
||||
bhnd_nvram_fmt fmt; /**< string format */
|
||||
uint32_t flags; /**< BHND_NVRAM_VF_* flags */
|
||||
struct bhnd_nvram_vardefn {
|
||||
const char *name; /**< variable name */
|
||||
bhnd_nvram_type type; /**< base data type */
|
||||
bhnd_nvram_sfmt sfmt; /**< string format */
|
||||
uint32_t flags; /**< BHND_NVRAM_VF_* flags */
|
||||
|
||||
const struct bhnd_sprom_var *sprom_descs; /**< SPROM-specific variable descriptors */
|
||||
size_t num_sp_descs; /**< number of sprom descriptors */
|
||||
const struct bhnd_sprom_vardefn *sp_defs; /**< SPROM-specific variable definitions */
|
||||
size_t num_sp_defs; /**< number of sprom definitions */
|
||||
};
|
||||
|
||||
size_t bhnd_nvram_type_width(bhnd_nvram_dt dt);
|
||||
const struct bhnd_nvram_var *bhnd_nvram_var_defn(const char *varname);
|
||||
/**
|
||||
* NVRAM value tuple.
|
||||
*/
|
||||
struct bhnd_nvram_tuple {
|
||||
char *name; /**< variable name. */
|
||||
size_t name_len; /**< variable length. */
|
||||
char *value; /**< value, or NULL if this tuple represents variable
|
||||
deletion */
|
||||
size_t value_len; /**< value length. */
|
||||
|
||||
/** Initial bhnd_nvram_crc8 value */
|
||||
#define BHND_NVRAM_CRC8_INITIAL 0xFF
|
||||
LIST_ENTRY(bhnd_nvram_tuple) t_link;
|
||||
};
|
||||
|
||||
/** Valid CRC-8 checksum */
|
||||
#define BHND_NVRAM_CRC8_VALID 0x9F
|
||||
LIST_HEAD(bhnd_nvram_tuples, bhnd_nvram_tuple);
|
||||
|
||||
extern const uint8_t bhnd_nvram_crc8_tab[];
|
||||
/** NVRAM tuple hash table */
|
||||
struct bhnd_nvram_varmap {
|
||||
struct bhnd_nvram_tuples *table; /**< hash buckets */
|
||||
u_long mask; /**< hash index mask */
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate CRC-8 over @p buf.
|
||||
@ -124,5 +177,4 @@ bhnd_nvram_crc8(const void *buf, size_t size, uint8_t crc)
|
||||
return (crc);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _BHND_NVRAM_BHND_NVRAMVAR_H_ */
|
||||
#endif /* _BHND_NVRAM_BHND_NVRAM_COMMON_H_ */
|
@ -49,6 +49,7 @@ INTERFACE bhnd_nvram;
|
||||
* @param[in,out] len The maximum capacity of @p buf. On success,
|
||||
* will be set to the actual size of the requested
|
||||
* value.
|
||||
* @param type The data type to be written to @p buf.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The requested variable was not found.
|
||||
@ -56,6 +57,9 @@ INTERFACE bhnd_nvram;
|
||||
* small to hold the requested value.
|
||||
* @retval ENODEV If no supported NVRAM hardware is accessible via this
|
||||
* device.
|
||||
* @retval EOPNOTSUPP If any coercion to @p type is unsupported.
|
||||
* @retval EFTYPE If the @p name's data type cannot be coerced to @p type.
|
||||
* @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.
|
||||
*/
|
||||
@ -64,29 +68,35 @@ METHOD int getvar {
|
||||
const char *name;
|
||||
void *buf;
|
||||
size_t *len;
|
||||
bhnd_nvram_type type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set an NVRAM variable's local value.
|
||||
* Set an NVRAM variable's value.
|
||||
*
|
||||
* No changes should be written to non-volatile storage.
|
||||
* No changes will be written to non-volatile storage until explicitly
|
||||
* committed.
|
||||
*
|
||||
* @param dev The NVRAM device.
|
||||
* @param name The NVRAM variable name.
|
||||
* @param buf The new value.
|
||||
* @param len The size of @p buf.
|
||||
* @param value The new value.
|
||||
* @param len The size of @p value.
|
||||
* @param type The data type of @p value.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The specified variable name is not recognized.
|
||||
* @retval EINVAL If @p len does not match the expected variable size.
|
||||
* @retval ENODEV If no supported NVRAM hardware is accessible via this
|
||||
* device.
|
||||
* @retval EOPNOTSUPP If any coercion to @p type is unsupported.
|
||||
* @retval EFTYPE If the @p name's data type cannot be coerced to @p type.
|
||||
* @retval ERANGE If value coercion from @p type would overflow.
|
||||
* @retval non-zero If reading @p name otherwise fails, a regular unix
|
||||
* error code will be returned.
|
||||
*/
|
||||
METHOD int setvar {
|
||||
device_t dev;
|
||||
const char *name;
|
||||
const void *buf;
|
||||
const void *value;
|
||||
size_t len;
|
||||
bhnd_nvram_type type;
|
||||
};
|
||||
|
1578
sys/dev/bhnd/nvram/bhnd_nvram_parser.c
Normal file
1578
sys/dev/bhnd/nvram/bhnd_nvram_parser.c
Normal file
File diff suppressed because it is too large
Load Diff
101
sys/dev/bhnd/nvram/bhnd_nvram_parser.h
Normal file
101
sys/dev/bhnd/nvram/bhnd_nvram_parser.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_NVRAM_BHND_NVRAM_PARSER_H_
|
||||
#define _BHND_NVRAM_BHND_NVRAM_PARSER_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include "bhnd_nvram_common.h"
|
||||
|
||||
union bhnd_nvram_ident;
|
||||
|
||||
struct bhnd_nvram_idx;
|
||||
struct bhnd_nvram_ops;
|
||||
struct bhnd_nvram_devpath;
|
||||
|
||||
struct bhnd_nvram;
|
||||
|
||||
LIST_HEAD(bhnd_nvram_devpaths, bhnd_nvram_devpath);
|
||||
|
||||
int bhnd_nvram_parser_identify(const union bhnd_nvram_ident *ident,
|
||||
bhnd_nvram_format expected);
|
||||
int bhnd_nvram_parser_init(struct bhnd_nvram *sc, device_t owner,
|
||||
const void *data, size_t len, bhnd_nvram_format fmt);
|
||||
void bhnd_nvram_parser_fini(struct bhnd_nvram *sc);
|
||||
|
||||
int bhnd_nvram_parser_getvar(struct bhnd_nvram *sc, const char *name,
|
||||
void *buf, size_t *len, bhnd_nvram_type type);
|
||||
int bhnd_nvram_parser_setvar(struct bhnd_nvram *sc, const char *name,
|
||||
const void *buf, size_t len, bhnd_nvram_type type);
|
||||
|
||||
/** BCM NVRAM header */
|
||||
struct bhnd_nvram_header {
|
||||
uint32_t magic;
|
||||
uint32_t size;
|
||||
uint32_t cfg0; /**< crc:8, version:8, sdram_init:16 */
|
||||
uint32_t cfg1; /**< sdram_config:16, sdram_refresh:16 */
|
||||
uint32_t sdram_ncdl; /**< sdram_ncdl */
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* NVRAM format identification.
|
||||
*
|
||||
* To perform identification of the NVRAM format using bhnd_nvram_identify(),
|
||||
* read `sizeof(bhnd_nvram_indent)` bytes from the head of the NVRAM data.
|
||||
*/
|
||||
union bhnd_nvram_ident {
|
||||
struct bhnd_nvram_header bcm;
|
||||
char btxt[4];
|
||||
struct bhnd_tlv_ident {
|
||||
uint8_t tag;
|
||||
uint8_t size[2];
|
||||
uint8_t flags;
|
||||
} __packed tlv;
|
||||
};
|
||||
|
||||
/** bhnd nvram parser instance state */
|
||||
struct bhnd_nvram {
|
||||
device_t dev; /**< parent device, or NULL */
|
||||
const struct bhnd_nvram_ops *ops;
|
||||
uint8_t *buf; /**< nvram data */
|
||||
size_t buf_size;
|
||||
size_t num_buf_vars; /**< number of records in @p buf (0 if not yet calculated) */
|
||||
|
||||
struct bhnd_nvram_idx *idx; /**< key index */
|
||||
|
||||
struct bhnd_nvram_devpaths devpaths; /**< device paths */
|
||||
struct bhnd_nvram_varmap defaults; /**< default values */
|
||||
struct bhnd_nvram_varmap pending; /**< uncommitted writes */
|
||||
};
|
||||
|
||||
#endif /* _BHND_NVRAM_BHND_NVRAM_PARSER_H_ */
|
75
sys/dev/bhnd/nvram/bhnd_nvram_parserreg.h
Normal file
75
sys/dev/bhnd/nvram/bhnd_nvram_parserreg.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_NVRAM_BHND_NVRAM_PARSERREG_H_
|
||||
#define _BHND_NVRAM_BHND_NVRAM_PARSERREG_H_
|
||||
|
||||
|
||||
|
||||
#define NVRAM_GET_BITS(_value, _field) \
|
||||
((_value & _field ## _MASK) >> _field ## _SHIFT)
|
||||
|
||||
/* NVRAM header fields */
|
||||
#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
|
||||
#define NVRAM_VERSION 1
|
||||
|
||||
#define NVRAM_CRC_SKIP 9 /* skip magic, size, and crc8 */
|
||||
|
||||
#define NVRAM_CFG0_CRC_MASK 0x000000FF
|
||||
#define NVRAM_CFG0_CRC_SHIFT 0
|
||||
#define NVRAM_CFG0_VER_MASK 0x0000FF00
|
||||
#define NVRAM_CFG0_VER_SHIFT 8
|
||||
#define NVRAM_CFG0_SDRAM_INIT_MASK 0xFFFF0000
|
||||
#define NVRAM_CFG0_SDRAM_INIT_SHIFT 16
|
||||
#define NVRAM_CFG0_SDRAM_INIT_VAR "sdram_init"
|
||||
#define NVRAM_CFG0_SDRAM_INIT_FMT "0x%04x"
|
||||
|
||||
#define NVRAM_CFG1_SDRAM_CFG_MASK 0x0000FFFF
|
||||
#define NVRAM_CFG1_SDRAM_CFG_SHIFT 0
|
||||
#define NVRAM_CFG1_SDRAM_CFG_VAR "sdram_config"
|
||||
#define NVRAM_CFG1_SDRAM_CFG_FMT "0x%04x"
|
||||
|
||||
#define NVRAM_CFG1_SDRAM_REFRESH_MASK 0xFFFF0000
|
||||
#define NVRAM_CFG1_SDRAM_REFRESH_SHIFT 16
|
||||
#define NVRAM_CFG1_SDRAM_REFRESH_VAR "sdram_refresh"
|
||||
#define NVRAM_CFG1_SDRAM_REFRESH_FMT "0x%04x"
|
||||
|
||||
#define NVRAM_SDRAM_NCDL_MASK UINT32_MAX
|
||||
#define NVRAM_SDRAM_NCDL_SHIFT 0
|
||||
#define NVRAM_SDRAM_NCDL_VAR "sdram_ncdl"
|
||||
#define NVRAM_SDRAM_NCDL_FMT "0x%08x"
|
||||
|
||||
/* WGT634U-specific TLV encoding */
|
||||
#define NVRAM_TLV_TF_U8_LEN 0x01 /**< type has 8-bit length */
|
||||
#define NVRAM_TLV_TYPE_END 0x00 /**< end of table */
|
||||
#define NVRAM_TLV_TYPE_ENV 0x01 /**< variable record */
|
||||
|
||||
#endif /* _BHND_NVRAM_BHND_NVRAM_PARSERVAR_H_ */
|
86
sys/dev/bhnd/nvram/bhnd_nvram_parservar.h
Normal file
86
sys/dev/bhnd/nvram/bhnd_nvram_parservar.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_NVRAM_BHND_NVRAM_PARSERVAR_H_
|
||||
#define _BHND_NVRAM_BHND_NVRAM_PARSERVAR_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "bhnd_nvram_common.h"
|
||||
|
||||
#include "bhnd_nvram_parser.h"
|
||||
|
||||
#define NVRAM_IDX_VAR_THRESH 15 /**< index is generated if minimum variable count is met */
|
||||
#define NVRAM_IDX_OFFSET_MAX UINT16_MAX /**< maximum indexable offset */
|
||||
#define NVRAM_IDX_LEN_MAX UINT8_MAX /**< maximum indexable key/value length */
|
||||
|
||||
#define NVRAM_KEY_MAX 64 /**< maximum key length (not incl. NUL) */
|
||||
#define NVRAM_VAL_MAX 255 /**< maximum value length (not incl. NUL) */
|
||||
|
||||
#define NVRAM_DEVPATH_STR "devpath" /**< name prefix of device path aliases */
|
||||
#define NVRAM_DEVPATH_LEN (sizeof(NVRAM_DEVPATH_STR) - 1)
|
||||
|
||||
#define NVRAM_SMALL_HASH_SIZE 16 /**< hash table size for pending/default tuples */
|
||||
|
||||
/**
|
||||
* NVRAM devpath record.
|
||||
*
|
||||
* Aliases index values to full device paths.
|
||||
*/
|
||||
struct bhnd_nvram_devpath {
|
||||
u_long index; /** alias index */
|
||||
char *path; /** aliased path */
|
||||
|
||||
LIST_ENTRY(bhnd_nvram_devpath) dp_link;
|
||||
};
|
||||
|
||||
/**
|
||||
* NVRAM index record.
|
||||
*
|
||||
* Provides entry offsets into a backing NVRAM buffer.
|
||||
*/
|
||||
struct bhnd_nvram_idx_entry {
|
||||
uint16_t env_offset; /**< offset to env string */
|
||||
uint8_t key_len; /**< key length */
|
||||
uint8_t val_len; /**< value length */
|
||||
};
|
||||
|
||||
/**
|
||||
* NVRAM index.
|
||||
*
|
||||
* Provides a compact binary search index into the backing NVRAM buffer.
|
||||
*/
|
||||
struct bhnd_nvram_idx {
|
||||
size_t num_entries; /**< entry count */
|
||||
struct bhnd_nvram_idx_entry entries[]; /**< index entries */
|
||||
};
|
||||
|
||||
#endif /* _BHND_NVRAM_BHND_NVRAM_PARSERVAR_H_ */
|
68
sys/dev/bhnd/nvram/bhnd_nvramvar.h
Normal file
68
sys/dev/bhnd/nvram/bhnd_nvramvar.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_NVRAM_BHND_NVRAMVAR_H_
|
||||
#define _BHND_NVRAM_BHND_NVRAMVAR_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include "bhnd_nvram_parser.h"
|
||||
|
||||
DECLARE_CLASS(bhnd_nvram_driver);
|
||||
|
||||
int bhnd_nvram_probe(device_t dev);
|
||||
int bhnd_nvram_attach(device_t dev, void *data, size_t size,
|
||||
bhnd_nvram_format fmt);
|
||||
int bhnd_nvram_resume(device_t dev);
|
||||
int bhnd_nvram_suspend(device_t dev);
|
||||
int bhnd_nvram_detach(device_t dev);
|
||||
|
||||
/**
|
||||
* bhnd_nvram driver instance state. Must be first member of all subclass
|
||||
* softc structures.
|
||||
*/
|
||||
struct bhnd_nvram_softc {
|
||||
device_t dev;
|
||||
struct mtx mtx; /**< nvram mutex */
|
||||
struct bhnd_nvram nvram; /**< nvram shadow */
|
||||
};
|
||||
|
||||
|
||||
#define BHND_NVRAM_LOCK_INIT(sc) \
|
||||
mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
|
||||
"bhnd_nvram lock", MTX_DEF)
|
||||
#define BHND_NVRAM_LOCK(sc) mtx_lock(&(sc)->mtx)
|
||||
#define BHND_NVRAM_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
|
||||
#define BHND_NVRAM_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what)
|
||||
#define BHND_NVRAM_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx)
|
||||
|
||||
#endif /* _BHND_NVRAM_BHND_NVRAMVAR_H_ */
|
@ -169,7 +169,8 @@ bhnd_sprom_detach(device_t dev)
|
||||
* Default bhnd sprom driver implementation of BHND_NVRAM_GETVAR().
|
||||
*/
|
||||
static int
|
||||
bhnd_sprom_getvar_meth(device_t dev, const char *name, void *buf, size_t *len)
|
||||
bhnd_sprom_getvar_method(device_t dev, const char *name, void *buf, size_t *len,
|
||||
bhnd_nvram_type type)
|
||||
{
|
||||
struct bhnd_sprom_softc *sc;
|
||||
int error;
|
||||
@ -177,7 +178,7 @@ bhnd_sprom_getvar_meth(device_t dev, const char *name, void *buf, size_t *len)
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
SPROM_LOCK(sc);
|
||||
error = bhnd_sprom_getvar(&sc->shadow, name, buf, len);
|
||||
error = bhnd_sprom_getvar(&sc->shadow, name, buf, len, type);
|
||||
SPROM_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
@ -187,8 +188,8 @@ bhnd_sprom_getvar_meth(device_t dev, const char *name, void *buf, size_t *len)
|
||||
* Default bhnd sprom driver implementation of BHND_NVRAM_SETVAR().
|
||||
*/
|
||||
static int
|
||||
bhnd_sprom_setvar_meth(device_t dev, const char *name, const void *buf,
|
||||
size_t len)
|
||||
bhnd_sprom_setvar_method(device_t dev, const char *name, const void *buf,
|
||||
size_t len, bhnd_nvram_type type)
|
||||
{
|
||||
struct bhnd_sprom_softc *sc;
|
||||
int error;
|
||||
@ -196,7 +197,7 @@ bhnd_sprom_setvar_meth(device_t dev, const char *name, const void *buf,
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
SPROM_LOCK(sc);
|
||||
error = bhnd_sprom_setvar(&sc->shadow, name, buf, len);
|
||||
error = bhnd_sprom_setvar(&sc->shadow, name, buf, len, type);
|
||||
SPROM_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
@ -211,8 +212,8 @@ static device_method_t bhnd_sprom_methods[] = {
|
||||
DEVMETHOD(device_detach, bhnd_sprom_detach),
|
||||
|
||||
/* NVRAM interface */
|
||||
DEVMETHOD(bhnd_nvram_getvar, bhnd_sprom_getvar_meth),
|
||||
DEVMETHOD(bhnd_nvram_setvar, bhnd_sprom_setvar_meth),
|
||||
DEVMETHOD(bhnd_nvram_getvar, bhnd_sprom_getvar_method),
|
||||
DEVMETHOD(bhnd_nvram_setvar, bhnd_sprom_setvar_method),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Landon Fuller <landon@landonf.org>
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -33,18 +33,16 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/bhnd/bhndvar.h>
|
||||
#include "bhnd_nvram_common.h"
|
||||
|
||||
#include "nvramvar.h"
|
||||
|
||||
#include "bhnd_spromreg.h"
|
||||
#include "bhnd_spromvar.h"
|
||||
#include "bhnd_sprom_parservar.h"
|
||||
|
||||
/*
|
||||
* BHND SPROM Parser
|
||||
@ -52,15 +50,21 @@ __FBSDID("$FreeBSD$");
|
||||
* Provides identification, decoding, and encoding of BHND SPROM data.
|
||||
*/
|
||||
|
||||
static int sprom_direct_read(struct bhnd_sprom *sc, size_t offset,
|
||||
void *buf, size_t nbytes, uint8_t *crc);
|
||||
static int sprom_extend_shadow(struct bhnd_sprom *sc, size_t image_size,
|
||||
uint8_t *crc);
|
||||
static int sprom_populate_shadow(struct bhnd_sprom *sc);
|
||||
static int sprom_direct_read(struct bhnd_sprom *sc, size_t offset,
|
||||
void *buf, size_t nbytes, uint8_t *crc);
|
||||
static int sprom_extend_shadow(struct bhnd_sprom *sc,
|
||||
size_t image_size, uint8_t *crc);
|
||||
static int sprom_populate_shadow(struct bhnd_sprom *sc);
|
||||
|
||||
static int sprom_var_defn(struct bhnd_sprom *sc, const char *name,
|
||||
const struct bhnd_nvram_var **var,
|
||||
const struct bhnd_sprom_var **sprom, size_t *size);
|
||||
static int sprom_get_var_defn(struct bhnd_sprom *sc,
|
||||
const char *name,
|
||||
const struct bhnd_nvram_vardefn **var,
|
||||
const struct bhnd_sprom_vardefn **sprom,
|
||||
size_t *size, size_t *nelem,
|
||||
bhnd_nvram_type req_type);
|
||||
|
||||
static char sprom_get_delim_char(struct bhnd_sprom *sc,
|
||||
bhnd_nvram_sfmt sfmt);
|
||||
|
||||
/* SPROM revision is always located at the second-to-last byte */
|
||||
#define SPROM_REV(_sc) SPROM_READ_1((_sc), (_sc)->sp_size - 2)
|
||||
@ -94,42 +98,61 @@ static int sprom_var_defn(struct bhnd_sprom *sc, const char *name,
|
||||
#define SPROM_WRITE_ENC_4(_sc, _off, _v) \
|
||||
*((uint32_t *)((_sc)->sp_shadow + _off)) = (_v)
|
||||
|
||||
/* Call @p _next macro with the C type, widened (signed or unsigned) C
|
||||
* type, and width associated with @p _dtype */
|
||||
/* Call @p _next macro with the C type, widened (signed or unsigned) 32-bit C
|
||||
* type, width, and min/max values associated with @p _dtype */
|
||||
#define SPROM_SWITCH_TYPE(_dtype, _next, ...) \
|
||||
do { \
|
||||
switch (_dtype) { \
|
||||
case BHND_NVRAM_DT_UINT8: \
|
||||
_next (uint8_t, uint32_t, 1, \
|
||||
## __VA_ARGS__); \
|
||||
case BHND_NVRAM_TYPE_UINT8: \
|
||||
_next (uint8_t, uint32_t, 1, 0, \
|
||||
UINT8_MAX, ## __VA_ARGS__); \
|
||||
break; \
|
||||
case BHND_NVRAM_DT_UINT16: \
|
||||
_next (uint16_t, uint32_t, 2, \
|
||||
## __VA_ARGS__); \
|
||||
case BHND_NVRAM_TYPE_UINT16: \
|
||||
_next (uint16_t, uint32_t, 2, 0, \
|
||||
UINT16_MAX, ## __VA_ARGS__); \
|
||||
break; \
|
||||
case BHND_NVRAM_DT_UINT32: \
|
||||
_next (uint32_t, uint32_t, 4, \
|
||||
## __VA_ARGS__); \
|
||||
case BHND_NVRAM_TYPE_UINT32: \
|
||||
_next (uint32_t, uint32_t, 4, 0, \
|
||||
UINT32_MAX, ## __VA_ARGS__); \
|
||||
break; \
|
||||
case BHND_NVRAM_DT_INT8: \
|
||||
case BHND_NVRAM_TYPE_INT8: \
|
||||
_next (int8_t, int32_t, 1, \
|
||||
## __VA_ARGS__); \
|
||||
INT8_MIN, INT8_MAX, ## __VA_ARGS__); \
|
||||
break; \
|
||||
case BHND_NVRAM_DT_INT16: \
|
||||
case BHND_NVRAM_TYPE_INT16: \
|
||||
_next (int16_t, int32_t, 2, \
|
||||
## __VA_ARGS__); \
|
||||
INT16_MIN, INT16_MAX, ## __VA_ARGS__); \
|
||||
break; \
|
||||
case BHND_NVRAM_DT_INT32: \
|
||||
case BHND_NVRAM_TYPE_INT32: \
|
||||
_next (int32_t, int32_t, 4, \
|
||||
## __VA_ARGS__); \
|
||||
INT32_MIN, INT32_MAX, ## __VA_ARGS__); \
|
||||
break; \
|
||||
case BHND_NVRAM_DT_CHAR: \
|
||||
_next (uint8_t, uint32_t, 1, \
|
||||
## __VA_ARGS__); \
|
||||
case BHND_NVRAM_TYPE_CHAR: \
|
||||
_next (char, int32_t, 1, \
|
||||
CHAR_MIN, CHAR_MAX, ## __VA_ARGS__); \
|
||||
break; \
|
||||
case BHND_NVRAM_TYPE_CSTR: \
|
||||
panic("%s: BHND_NVRAM_TYPE_CSTR unhandled", \
|
||||
__FUNCTION__); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Verify the range of _val of (_stype) within _type */
|
||||
#define SPROM_VERIFY_RANGE(_type, _widen, _width, _min, _max, _val, \
|
||||
_stype) \
|
||||
do { \
|
||||
if (BHND_NVRAM_SIGNED_TYPE(_stype)) { \
|
||||
int32_t sval = (int32_t) (_val); \
|
||||
if (sval > (_max) || sval < (_min)) \
|
||||
return (ERANGE); \
|
||||
} else { \
|
||||
if ((_val) > (_max)) \
|
||||
return (ERANGE); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Table of supported SPROM image formats, sorted by image size, ascending.
|
||||
*/
|
||||
@ -185,7 +208,7 @@ bhnd_sprom_init(struct bhnd_sprom *sprom, struct bhnd_resource *r,
|
||||
/* Allocate and populate SPROM shadow */
|
||||
sprom->sp_size = 0;
|
||||
sprom->sp_capacity = sprom->sp_size_max;
|
||||
sprom->sp_shadow = malloc(sprom->sp_capacity, M_BHND, M_NOWAIT);
|
||||
sprom->sp_shadow = malloc(sprom->sp_capacity, M_BHND_NVRAM, M_NOWAIT);
|
||||
if (sprom->sp_shadow == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
@ -204,12 +227,13 @@ bhnd_sprom_init(struct bhnd_sprom *sprom, struct bhnd_resource *r,
|
||||
void
|
||||
bhnd_sprom_fini(struct bhnd_sprom *sprom)
|
||||
{
|
||||
free(sprom->sp_shadow, M_BHND);
|
||||
free(sprom->sp_shadow, M_BHND_NVRAM);
|
||||
}
|
||||
|
||||
/* Perform a read using a SPROM offset descriptor, safely widening the
|
||||
* result to its 32-bit representation before assigning it to @p _dest. */
|
||||
#define SPROM_GETVAR_READ(_type, _widen, _width, _sc, _off, _dest) \
|
||||
/* Perform a read using a SPROM offset descriptor, safely widening the result
|
||||
* to its 32-bit representation before assigning it to @p _dest. */
|
||||
#define SPROM_GETVAR_READ(_type, _widen, _width, _min, _max, _sc, _off, \
|
||||
_dest) \
|
||||
do { \
|
||||
_type _v = (_type)SPROM_READ_ ## _width(_sc, _off->offset); \
|
||||
if (_off->shift > 0) { \
|
||||
@ -217,20 +241,29 @@ do { \
|
||||
} else if (off->shift < 0) { \
|
||||
_v <<= -_off->shift; \
|
||||
} \
|
||||
_dest = ((uint32_t) (_widen) _v) & _off->mask; \
|
||||
\
|
||||
if (_off->cont) \
|
||||
_dest |= ((uint32_t) (_widen) _v) & _off->mask; \
|
||||
else \
|
||||
_dest = ((uint32_t) (_widen) _v) & _off->mask; \
|
||||
} while(0)
|
||||
|
||||
/* Emit a value read using a SPROM offset descriptor, narrowing the
|
||||
* result output representation and, if necessary, OR'ing it with the
|
||||
* previously read value from @p _buf. */
|
||||
#define SPROM_GETVAR_WRITE(_type, _widen, _width, _off, _src, _buf) \
|
||||
* result output representation. */
|
||||
#define SPROM_GETVAR_WRITE(_type, _widen, _width, _min, _max, _off, \
|
||||
_src, _buf) \
|
||||
do { \
|
||||
_type _v = (_type) (_widen) _src; \
|
||||
if (_off->cont) \
|
||||
_v |= *((_type *)_buf); \
|
||||
*((_type *)_buf) = _v; \
|
||||
} while(0)
|
||||
|
||||
/* String format a value read using a SPROM offset descriptor */
|
||||
#define SPROM_GETVAR_SNPRINTF(_type, _widen, _width, _min, _max, _src, \
|
||||
_buf, _remain, _fmt, _nwrite) \
|
||||
do { \
|
||||
_nwrite = snprintf(_buf, _remain, _fmt, (_type) (_widen) _src); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Read a SPROM variable, performing conversion to host byte order.
|
||||
*
|
||||
@ -241,6 +274,7 @@ do { \
|
||||
* the value is not desired.
|
||||
* @param[in,out] len The capacity of @p buf. On success, will be set
|
||||
* to the actual size of the requested value.
|
||||
* @param type The requested data type to be written to @p buf.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The requested variable was not found.
|
||||
@ -251,42 +285,93 @@ do { \
|
||||
*/
|
||||
int
|
||||
bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf,
|
||||
size_t *len)
|
||||
size_t *len, bhnd_nvram_type type)
|
||||
{
|
||||
const struct bhnd_nvram_var *nv;
|
||||
const struct bhnd_sprom_var *sv;
|
||||
const struct bhnd_nvram_vardefn *nv;
|
||||
const struct bhnd_sprom_vardefn *sv;
|
||||
void *outp;
|
||||
size_t all1_offs;
|
||||
size_t req_size;
|
||||
size_t req_size, nelem;
|
||||
size_t str_remain;
|
||||
char str_delim;
|
||||
uint32_t val;
|
||||
int error;
|
||||
|
||||
if ((error = sprom_var_defn(sc, name, &nv, &sv, &req_size)))
|
||||
error = sprom_get_var_defn(sc, name, &nv, &sv, &req_size, &nelem, type);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* Provide required size */
|
||||
if (buf == NULL) {
|
||||
*len = req_size;
|
||||
return (0);
|
||||
}
|
||||
outp = buf;
|
||||
str_remain = 0;
|
||||
str_delim = '\0';
|
||||
|
||||
/* Check (and update) target buffer len */
|
||||
if (*len < req_size)
|
||||
return (ENOMEM);
|
||||
else
|
||||
*len = req_size;
|
||||
|
||||
if (type != BHND_NVRAM_TYPE_CSTR) {
|
||||
/* Provide required size */
|
||||
if (outp == NULL) {
|
||||
*len = req_size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Check (and update) target buffer len */
|
||||
if (*len < req_size)
|
||||
return (ENOMEM);
|
||||
else
|
||||
*len = req_size;
|
||||
} else {
|
||||
/* String length calculation requires performing
|
||||
* the actual string formatting */
|
||||
KASSERT(req_size == 0,
|
||||
("req_size set for variable-length type"));
|
||||
|
||||
/* If caller is querying length, the len argument
|
||||
* may be uninitialized */
|
||||
if (outp != NULL)
|
||||
str_remain = *len;
|
||||
|
||||
/* Fetch delimiter for the variable's string format */
|
||||
str_delim = sprom_get_delim_char(sc, nv->sfmt);
|
||||
}
|
||||
|
||||
/* Read data */
|
||||
all1_offs = 0;
|
||||
val = 0;
|
||||
for (size_t i = 0; i < sv->num_offsets; i++) {
|
||||
const struct bhnd_sprom_offset *off;
|
||||
uint32_t val;
|
||||
|
||||
|
||||
off = &sv->offsets[i];
|
||||
KASSERT(!off->cont || i > 0, ("cont marked on first offset"));
|
||||
|
||||
/* If not a continuation, advance the output buffer */
|
||||
/* If not a continuation, advance the output buffer; if
|
||||
* a C string, this requires appending a delimiter character */
|
||||
if (i > 0 && !off->cont) {
|
||||
buf = ((uint8_t *)buf) +
|
||||
bhnd_nvram_type_width(sv->offsets[i-1].type);
|
||||
size_t width = bhnd_nvram_type_width(type);
|
||||
|
||||
/* Non-fixed width types (such as CSTR) will have a 0
|
||||
* width value */
|
||||
if (width != 0) {
|
||||
KASSERT(outp != NULL, ("NULL output buffer"));
|
||||
outp = ((uint8_t *)outp) + width;
|
||||
}
|
||||
|
||||
/* Append CSTR delim, if necessary */
|
||||
if (type == BHND_NVRAM_TYPE_CSTR &&
|
||||
str_delim != '\0' &&
|
||||
i != 0)
|
||||
{
|
||||
if (outp != NULL && str_remain >= 1) {
|
||||
*((char *)outp) = str_delim;
|
||||
outp = ((char *)outp + 1);
|
||||
|
||||
/* Drop outp reference if we hit 0 */
|
||||
if (str_remain-- == 0)
|
||||
outp = NULL;
|
||||
}
|
||||
|
||||
if (SIZE_MAX - 1 < req_size)
|
||||
return (EFTYPE); /* too long */
|
||||
req_size++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the value, widening to a common uint32
|
||||
@ -295,8 +380,8 @@ bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf,
|
||||
|
||||
/* If IGNALL1, record whether value has all bits set. */
|
||||
if (nv->flags & BHND_NVRAM_VF_IGNALL1) {
|
||||
uint32_t all1;
|
||||
|
||||
uint32_t all1;
|
||||
|
||||
all1 = off->mask;
|
||||
if (off->shift > 0)
|
||||
all1 >>= off->shift;
|
||||
@ -307,22 +392,84 @@ bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf,
|
||||
all1_offs++;
|
||||
}
|
||||
|
||||
/* Write the value, narrowing to the appropriate output
|
||||
* width. */
|
||||
SPROM_SWITCH_TYPE(nv->type, SPROM_GETVAR_WRITE, off, val, buf);
|
||||
/* Skip writing if additional continuations remain */
|
||||
if (i+1 < sv->num_offsets && sv->offsets[i].cont)
|
||||
continue;
|
||||
|
||||
/* Perform write */
|
||||
if (type == BHND_NVRAM_TYPE_CSTR) {
|
||||
const char *fmtstr;
|
||||
int written;
|
||||
|
||||
fmtstr = bhnd_nvram_type_fmt(off->type, nv->sfmt, i);
|
||||
if (fmtstr == NULL) {
|
||||
device_printf(sc->dev, "no NVRAM format string "
|
||||
"for '%s' (type=%d)\n", name, off->type);
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
SPROM_SWITCH_TYPE(off->type, SPROM_GETVAR_SNPRINTF, val,
|
||||
outp, str_remain, fmtstr, written);
|
||||
|
||||
if (written <= 0)
|
||||
return (EFTYPE);
|
||||
|
||||
/* Calculate remaining capacity, drop outp reference
|
||||
* if we hit 0 -- otherwise, advance the buffer
|
||||
* position */
|
||||
if (written >= str_remain) {
|
||||
str_remain = 0;
|
||||
outp = NULL;
|
||||
} else {
|
||||
str_remain -= written;
|
||||
if (outp != NULL)
|
||||
outp = (char *)outp + written;
|
||||
}
|
||||
|
||||
/* Add additional bytes to total length */
|
||||
if (SIZE_MAX - written < req_size)
|
||||
return (EFTYPE); /* string too long */
|
||||
req_size += written;
|
||||
} else {
|
||||
/* Verify range */
|
||||
SPROM_SWITCH_TYPE(type, SPROM_VERIFY_RANGE, val,
|
||||
off->type);
|
||||
|
||||
/* Write the value, narrowing to the appropriate output
|
||||
* width. */
|
||||
SPROM_SWITCH_TYPE(type, SPROM_GETVAR_WRITE, off, val,
|
||||
outp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Should value should be treated as uninitialized? */
|
||||
if (nv->flags & BHND_NVRAM_VF_IGNALL1 && all1_offs == sv->num_offsets)
|
||||
return (ENOENT);
|
||||
|
||||
/* If this is a C string request, we need to provide the computed
|
||||
* length. */
|
||||
if (type == BHND_NVRAM_TYPE_CSTR) {
|
||||
/* Account for final trailing NUL */
|
||||
if (SIZE_MAX - 1 < req_size)
|
||||
return (EFTYPE); /* string too long */
|
||||
req_size++;
|
||||
|
||||
/* Return an error if a too-small output buffer was provided */
|
||||
if (buf != NULL && *len < req_size) {
|
||||
*len = req_size;
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
*len = req_size;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Perform a read of a variable offset from _src, safely widening the result
|
||||
* to its 32-bit representation before assigning it to @p
|
||||
* _dest. */
|
||||
#define SPROM_SETVAR_READ(_type, _widen, _width, _off, _src, _dest) \
|
||||
* to its 32-bit representation before assigning it to @p _dest. */
|
||||
#define SPROM_SETVAR_READ(_type, _widen, _width, _min, _max, _off, \
|
||||
_src, _dest) \
|
||||
do { \
|
||||
_type _v = *(const _type *)_src; \
|
||||
if (_off->shift > 0) { \
|
||||
@ -337,7 +484,8 @@ do { \
|
||||
/* Emit a value read using a SPROM offset descriptor, narrowing the
|
||||
* result output representation and, if necessary, OR'ing it with the
|
||||
* previously read value from @p _buf. */
|
||||
#define SPROM_SETVAR_WRITE(_type, _widen, _width, _sc, _off, _src) \
|
||||
#define SPROM_SETVAR_WRITE(_type, _widen, _width, _min, _max, _sc, \
|
||||
_off, _src) \
|
||||
do { \
|
||||
_type _v = (_type) (_widen) _src; \
|
||||
if (_off->cont) \
|
||||
@ -355,6 +503,7 @@ do { \
|
||||
* @param name The SPROM variable name.
|
||||
* @param[out] buf The new value.
|
||||
* @param[in,out] len The size of @p buf.
|
||||
* @param type The data type of @p buf.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENOENT The requested variable was not found.
|
||||
@ -362,17 +511,22 @@ do { \
|
||||
*/
|
||||
int
|
||||
bhnd_sprom_setvar(struct bhnd_sprom *sc, const char *name, const void *buf,
|
||||
size_t len)
|
||||
size_t len, bhnd_nvram_type type)
|
||||
{
|
||||
const struct bhnd_nvram_var *nv;
|
||||
const struct bhnd_sprom_var *sv;
|
||||
size_t req_size;
|
||||
const struct bhnd_nvram_vardefn *nv;
|
||||
const struct bhnd_sprom_vardefn *sv;
|
||||
size_t req_size, nelem;
|
||||
int error;
|
||||
uint8_t crc;
|
||||
|
||||
if ((error = sprom_var_defn(sc, name, &nv, &sv, &req_size)))
|
||||
error = sprom_get_var_defn(sc, name, &nv, &sv, &req_size, &nelem, type);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* String parsing is currently unsupported */
|
||||
if (type == BHND_NVRAM_TYPE_CSTR)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
/* Provide required size */
|
||||
if (len != req_size)
|
||||
return (EINVAL);
|
||||
@ -395,6 +549,9 @@ bhnd_sprom_setvar(struct bhnd_sprom *sc, const char *name, const void *buf,
|
||||
* representation */
|
||||
SPROM_SWITCH_TYPE(nv->type, SPROM_SETVAR_READ, off, buf, val);
|
||||
|
||||
/* Verify range */
|
||||
SPROM_SWITCH_TYPE(nv->type, SPROM_VERIFY_RANGE, val, type);
|
||||
|
||||
/* Write the value, narrowing to the appropriate output
|
||||
* width. */
|
||||
SPROM_SWITCH_TYPE(off->type, SPROM_SETVAR_WRITE, sc, off, val);
|
||||
@ -536,19 +693,19 @@ sprom_direct_read(struct bhnd_sprom *sc, size_t offset, void *buf,
|
||||
* for variable with @p name.
|
||||
*/
|
||||
static int
|
||||
sprom_var_defn(struct bhnd_sprom *sc, const char *name,
|
||||
const struct bhnd_nvram_var **var,
|
||||
const struct bhnd_sprom_var **sprom,
|
||||
size_t *size)
|
||||
sprom_get_var_defn(struct bhnd_sprom *sc, const char *name,
|
||||
const struct bhnd_nvram_vardefn **var,
|
||||
const struct bhnd_sprom_vardefn **sprom,
|
||||
size_t *size, size_t *nelem, bhnd_nvram_type req_type)
|
||||
{
|
||||
/* Find variable definition */
|
||||
*var = bhnd_nvram_var_defn(name);
|
||||
*var = bhnd_nvram_find_vardefn(name);
|
||||
if (*var == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
/* Find revision-specific SPROM definition */
|
||||
for (size_t i = 0; i < (*var)->num_sp_descs; i++) {
|
||||
const struct bhnd_sprom_var *sp = &(*var)->sprom_descs[i];
|
||||
for (size_t i = 0; i < (*var)->num_sp_defs; i++) {
|
||||
const struct bhnd_sprom_vardefn *sp = &(*var)->sp_defs[i];
|
||||
|
||||
if (sc->sp_rev < sp->compat.first)
|
||||
continue;
|
||||
@ -558,12 +715,42 @@ sprom_var_defn(struct bhnd_sprom *sc, const char *name,
|
||||
|
||||
/* Found */
|
||||
*sprom = sp;
|
||||
|
||||
/* Calculate size in bytes */
|
||||
*size = bhnd_nvram_type_width((*var)->type) * sp->num_offsets;
|
||||
|
||||
/* Calculate element count and total size, in bytes */
|
||||
*nelem = 0;
|
||||
for (size_t j = 0; j < sp->num_offsets; j++)
|
||||
if (!sp->offsets[j].cont)
|
||||
*nelem += 1;
|
||||
|
||||
*size = bhnd_nvram_type_width(req_type) * (*nelem);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Not supported by this SPROM revision */
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the array element delimiter for @p sfmt, or '\0' if none.
|
||||
*/
|
||||
static char
|
||||
sprom_get_delim_char(struct bhnd_sprom *sc, bhnd_nvram_sfmt sfmt)
|
||||
{
|
||||
switch (sfmt) {
|
||||
case BHND_NVRAM_SFMT_HEX:
|
||||
case BHND_NVRAM_SFMT_DEC:
|
||||
return (',');
|
||||
|
||||
case BHND_NVRAM_SFMT_CCODE:
|
||||
case BHND_NVRAM_SFMT_LEDDC:
|
||||
return ('\0');
|
||||
|
||||
case BHND_NVRAM_SFMT_MACADDR:
|
||||
return (':');
|
||||
|
||||
default:
|
||||
device_printf(sc->dev, "unknown NVRAM string format: %d\n",
|
||||
sfmt);
|
||||
return (',');
|
||||
}
|
||||
}
|
64
sys/dev/bhnd/nvram/bhnd_sprom_parser.h
Normal file
64
sys/dev/bhnd/nvram/bhnd_sprom_parser.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*-
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_NVRAM_BHND_SPROM_PARSER_H_
|
||||
#define _BHND_NVRAM_BHND_SPROM_PARSER_H_
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
struct bhnd_sprom;
|
||||
|
||||
int bhnd_sprom_init(struct bhnd_sprom *sprom, struct bhnd_resource *r,
|
||||
bus_size_t offset);
|
||||
void bhnd_sprom_fini(struct bhnd_sprom *sprom);
|
||||
int bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf,
|
||||
size_t *len, bhnd_nvram_type type);
|
||||
int bhnd_sprom_setvar(struct bhnd_sprom *sc, const char *name,
|
||||
const void *buf, size_t len, bhnd_nvram_type type);
|
||||
|
||||
/**
|
||||
* bhnd sprom parser instance state.
|
||||
*/
|
||||
struct bhnd_sprom {
|
||||
device_t dev; /**< sprom parent device */
|
||||
|
||||
uint8_t sp_rev; /**< sprom revision */
|
||||
|
||||
struct bhnd_resource *sp_res; /**< sprom resource. */
|
||||
bus_size_t sp_res_off; /**< offset to sprom image */
|
||||
|
||||
uint8_t *sp_shadow; /**< sprom shadow */
|
||||
bus_size_t sp_size_max; /**< maximum possible sprom length */
|
||||
size_t sp_size; /**< shadow size */
|
||||
size_t sp_capacity; /**< shadow buffer capacity */
|
||||
};
|
||||
|
||||
#endif /* _BHND_NVRAM_BHND_SPROM_PARSER_H_ */
|
@ -29,8 +29,10 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_NVRAM_SPROMREG_H_
|
||||
#define _BHND_NVRAM_SPROMREG_H_
|
||||
#ifndef _BHND_NVRAM_SPROM_PARSERVAR_H_
|
||||
#define _BHND_NVRAM_SPROM_PARSERVAR_H_
|
||||
|
||||
#include "bhnd_sprom_parser.h"
|
||||
|
||||
#define SPROM_SZ_R1_3 128 /**< SPROM image size (rev 1-3) */
|
||||
#define SPROM_SZ_R4_8_9 440 /**< SPROM image size (rev 4, 8-9) */
|
||||
@ -59,5 +61,4 @@
|
||||
#define SPROM_SIG_R11 0x0634
|
||||
#define SPROM_SIG_R11_OFF 128 /**< SPROM signature offset (rev 11) */
|
||||
|
||||
|
||||
#endif /* _BHND_NVRAM_SPROMREG_H_ */
|
||||
#endif /* _BHND_NVRAM_SPROM_PARSERVAR_H_ */
|
@ -34,8 +34,9 @@
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
#include "bhnd_sprom_parser.h"
|
||||
|
||||
DECLARE_CLASS(bhnd_sprom_driver);
|
||||
struct bhnd_sprom;
|
||||
|
||||
int bhnd_sprom_probe(device_t dev);
|
||||
int bhnd_sprom_attach(device_t dev, bus_size_t offset);
|
||||
@ -43,32 +44,6 @@ int bhnd_sprom_resume(device_t dev);
|
||||
int bhnd_sprom_suspend(device_t dev);
|
||||
int bhnd_sprom_detach(device_t dev);
|
||||
|
||||
int bhnd_sprom_init(struct bhnd_sprom *sprom, struct bhnd_resource *r,
|
||||
bus_size_t offset);
|
||||
void bhnd_sprom_fini(struct bhnd_sprom *sprom);
|
||||
int bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf,
|
||||
size_t *len);
|
||||
int bhnd_sprom_setvar(struct bhnd_sprom *sc, const char *name,
|
||||
const void *buf, size_t len);
|
||||
|
||||
/**
|
||||
* bhnd sprom parser instance state.
|
||||
*/
|
||||
struct bhnd_sprom {
|
||||
device_t dev; /**< sprom parent device */
|
||||
|
||||
uint8_t sp_rev; /**< sprom revision */
|
||||
|
||||
struct bhnd_resource *sp_res; /**< sprom resource. */
|
||||
bus_size_t sp_res_off; /**< offset to sprom image */
|
||||
|
||||
uint8_t *sp_shadow; /**< sprom shadow */
|
||||
bus_size_t sp_size_max; /**< maximum possible sprom length */
|
||||
size_t sp_size; /**< shadow size */
|
||||
size_t sp_capacity; /**< shadow buffer capacity */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* bhnd_sprom driver instance state. Must be first member of all subclass
|
||||
* softc structures.
|
||||
|
@ -1,149 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landon@landonf.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>
|
||||
#include <sys/types.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include "bhnd_nvram_map_data.h"
|
||||
|
||||
/*
|
||||
* CRC-8 lookup table used to checksum SPROM and NVRAM data via
|
||||
* bhnd_nvram_crc8().
|
||||
*
|
||||
* Generated with following parameters:
|
||||
* polynomial: CRC-8 (x^8 + x^7 + x^6 + x^4 + x^2 + 1)
|
||||
* reflected bits: false
|
||||
* reversed: true
|
||||
*/
|
||||
const uint8_t bhnd_nvram_crc8_tab[] = {
|
||||
0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b, 0x4a, 0xbd, 0xf3,
|
||||
0x04, 0x6f, 0x98, 0xd6, 0x21, 0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46,
|
||||
0x08, 0xff, 0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5, 0x7f,
|
||||
0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14, 0x35, 0xc2, 0x8c, 0x7b,
|
||||
0x10, 0xe7, 0xa9, 0x5e, 0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77,
|
||||
0x80, 0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca, 0xfe, 0x09,
|
||||
0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95, 0xb4, 0x43, 0x0d, 0xfa, 0x91,
|
||||
0x66, 0x28, 0xdf, 0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01,
|
||||
0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b, 0x81, 0x76, 0x38,
|
||||
0xcf, 0xa4, 0x53, 0x1d, 0xea, 0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19,
|
||||
0x57, 0xa0, 0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e, 0x5f,
|
||||
0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34, 0xab, 0x5c, 0x12, 0xe5,
|
||||
0x8e, 0x79, 0x37, 0xc0, 0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d,
|
||||
0x8a, 0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54, 0x75, 0x82,
|
||||
0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e, 0xd4, 0x23, 0x6d, 0x9a, 0xf1,
|
||||
0x06, 0x48, 0xbf, 0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5,
|
||||
0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b, 0x0a, 0xfd, 0xb3,
|
||||
0x44, 0x2f, 0xd8, 0x96, 0x61, 0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87,
|
||||
0xc9, 0x3e, 0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74, 0xc1,
|
||||
0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa, 0x8b, 0x7c, 0x32, 0xc5,
|
||||
0xae, 0x59, 0x17, 0xe0, 0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6,
|
||||
0x41, 0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b, 0xbe, 0x49,
|
||||
0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5, 0xf4, 0x03, 0x4d, 0xba, 0xd1,
|
||||
0x26, 0x68, 0x9f
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the size of type @p dt.
|
||||
*
|
||||
* @param dt NVRAM data type.
|
||||
* @result the byte width of @p dt.
|
||||
*/
|
||||
size_t
|
||||
bhnd_nvram_type_width(bhnd_nvram_dt dt)
|
||||
{
|
||||
switch (dt) {
|
||||
case BHND_NVRAM_DT_INT8:
|
||||
case BHND_NVRAM_DT_UINT8:
|
||||
case BHND_NVRAM_DT_CHAR:
|
||||
return (sizeof(uint8_t));
|
||||
|
||||
case BHND_NVRAM_DT_INT16:
|
||||
case BHND_NVRAM_DT_UINT16:
|
||||
return (sizeof(uint16_t));
|
||||
|
||||
case BHND_NVRAM_DT_INT32:
|
||||
case BHND_NVRAM_DT_UINT32:
|
||||
return (sizeof(uint32_t));
|
||||
}
|
||||
|
||||
/* Quiesce gcc4.2 */
|
||||
panic("bhnd nvram data type %u unknown", dt);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the variable definition for @p varname, if any.
|
||||
*
|
||||
* @param varname variable name
|
||||
*
|
||||
* @retval bhnd_nvram_var If a valid definition for @p varname is found.
|
||||
* @retval NULL If no definition for @p varname is found.
|
||||
*/
|
||||
const struct bhnd_nvram_var *
|
||||
bhnd_nvram_var_defn(const char *varname)
|
||||
{
|
||||
size_t min, mid, max;
|
||||
int order;
|
||||
|
||||
/*
|
||||
* Locate the requested variable using a binary search.
|
||||
*
|
||||
* The variable table is guaranteed to be sorted in lexicographical
|
||||
* order (using the 'C' locale for collation rules)
|
||||
*/
|
||||
min = 0;
|
||||
mid = 0;
|
||||
max = nitems(bhnd_nvram_vars) - 1;
|
||||
|
||||
while (max >= min) {
|
||||
/* Select midpoint */
|
||||
mid = (min + max) / 2;
|
||||
|
||||
/* Determine which side of the partition to search */
|
||||
order = strcmp(bhnd_nvram_vars[mid].name, varname);
|
||||
if (order < 0) {
|
||||
/* Search upper partition */
|
||||
min = mid + 1;
|
||||
} else if (order > 0) {
|
||||
/* Search lower partition */
|
||||
max = mid - 1;
|
||||
} else if (order == 0) {
|
||||
/* Match found */
|
||||
return (&bhnd_nvram_vars[mid]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return (NULL);
|
||||
}
|
@ -108,20 +108,20 @@ BEGIN {
|
||||
}
|
||||
|
||||
# Format Constants
|
||||
FMT["hex"] = "BHND_NVRAM_VFMT_HEX"
|
||||
FMT["decimal"] = "BHND_NVRAM_VFMT_DEC"
|
||||
FMT["ccode"] = "BHND_NVRAM_VFMT_CCODE"
|
||||
FMT["macaddr"] = "BHND_NVRAM_VFMT_MACADDR"
|
||||
FMT["led_dc"] = "BHND_NVRAM_VFMT_LEDDC"
|
||||
FMT["hex"] = "BHND_NVRAM_SFMT_HEX"
|
||||
FMT["decimal"] = "BHND_NVRAM_SFMT_DEC"
|
||||
FMT["ccode"] = "BHND_NVRAM_SFMT_CCODE"
|
||||
FMT["macaddr"] = "BHND_NVRAM_SFMT_MACADDR"
|
||||
FMT["led_dc"] = "BHND_NVRAM_SFMT_LEDDC"
|
||||
|
||||
# Data Type Constants
|
||||
DTYPE["u8"] = "BHND_NVRAM_DT_UINT8"
|
||||
DTYPE["u16"] = "BHND_NVRAM_DT_UINT16"
|
||||
DTYPE["u32"] = "BHND_NVRAM_DT_UINT32"
|
||||
DTYPE["i8"] = "BHND_NVRAM_DT_INT8"
|
||||
DTYPE["i16"] = "BHND_NVRAM_DT_INT16"
|
||||
DTYPE["i32"] = "BHND_NVRAM_DT_INT32"
|
||||
DTYPE["char"] = "BHND_NVRAM_DT_CHAR"
|
||||
DTYPE["u8"] = "BHND_NVRAM_TYPE_UINT8"
|
||||
DTYPE["u16"] = "BHND_NVRAM_TYPE_UINT16"
|
||||
DTYPE["u32"] = "BHND_NVRAM_TYPE_UINT32"
|
||||
DTYPE["i8"] = "BHND_NVRAM_TYPE_INT8"
|
||||
DTYPE["i16"] = "BHND_NVRAM_TYPE_INT16"
|
||||
DTYPE["i32"] = "BHND_NVRAM_TYPE_INT32"
|
||||
DTYPE["char"] = "BHND_NVRAM_TYPE_CHAR"
|
||||
|
||||
# Default masking for standard types
|
||||
TMASK["u8"] = "0x000000FF"
|
||||
@ -259,10 +259,10 @@ function emit_var_sprom_offsets (v, revk)
|
||||
emit("}, " num_offs_written "},\n")
|
||||
}
|
||||
|
||||
# emit the bhnd_nvram_var definition for variable name `v`
|
||||
function emit_var_defn (v)
|
||||
# emit a bhnd_nvram_vardef for variable name `v`
|
||||
function emit_nvram_vardef (v)
|
||||
{
|
||||
emit(sprintf("{\"%s\", %s, %s, %s, (struct bhnd_sprom_var[]) {\n",
|
||||
emit(sprintf("{\"%s\", %s, %s, %s, (struct bhnd_sprom_vardefn[]) {\n",
|
||||
v suffix,
|
||||
DTYPE[vars[v,VAR_BASE_TYPE]],
|
||||
FMT[vars[v,VAR_FMT]],
|
||||
@ -430,12 +430,12 @@ END {
|
||||
|
||||
# Emit all variable definitions
|
||||
if (OUT_T == OUT_T_DATA) {
|
||||
emit("#include <dev/bhnd/nvram/nvramvar.h>\n")
|
||||
emit("static const struct bhnd_nvram_var bhnd_nvram_vars[] = "\
|
||||
"{\n")
|
||||
emit("#include <dev/bhnd/nvram/bhnd_nvram_common.h>\n")
|
||||
emit("static const struct bhnd_nvram_vardefn "\
|
||||
"bhnd_nvram_vardefs[] = {\n")
|
||||
output_depth++
|
||||
for (i = 0; i < num_output_vars; i++)
|
||||
emit_var_defn(output_vars[i])
|
||||
emit_nvram_vardef(output_vars[i])
|
||||
output_depth--
|
||||
emit("};\n")
|
||||
} else if (OUT_T == OUT_T_HEADER) {
|
||||
|
@ -103,13 +103,13 @@ bwn_attach(device_t dev)
|
||||
device_printf(dev, "got rid=%d res=%p\n", sc->rspec[0].rid, r);
|
||||
|
||||
uint8_t macaddr[6];
|
||||
error = bhnd_nvram_getvar(dev, BHND_NVAR_MACADDR, macaddr,
|
||||
sizeof(macaddr));
|
||||
error = bhnd_nvram_getvar_array(dev, BHND_NVAR_MACADDR, macaddr,
|
||||
sizeof(macaddr), BHND_NVRAM_TYPE_UINT8);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
device_printf(dev, "got macaddr %6D\n", macaddr, ":");
|
||||
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,8 @@ include "../broadcom/std.broadcom"
|
||||
|
||||
# ships with cfe firmware
|
||||
options CFE
|
||||
device cfe
|
||||
|
||||
options ALT_BREAK_TO_DEBUGGER
|
||||
options BREAK_TO_DEBUGGER
|
||||
options BOOTVERBOSE=0
|
||||
|
@ -2,3 +2,6 @@
|
||||
hint.bhnd.0.at="nexus0"
|
||||
hint.bhnd.0.maddr="0x18000000"
|
||||
hint.bhnd.0.msize="0x00100000"
|
||||
|
||||
# NVRAM via CFE
|
||||
hint.bhnd_nvram.0.at="nexus0"
|
||||
|
@ -35,6 +35,7 @@ include "../broadcom/std.broadcom"
|
||||
options CFE
|
||||
options CFE_CONSOLE
|
||||
options ALT_BREAK_TO_DEBUGGER
|
||||
device cfe
|
||||
|
||||
makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
|
||||
makeoptions MODULES_OVERRIDE=""
|
||||
|
@ -2,3 +2,6 @@
|
||||
hint.bhnd.0.at="nexus0"
|
||||
hint.bhnd.0.maddr="0x18000000"
|
||||
hint.bhnd.0.msize="0x00100000"
|
||||
|
||||
# NVRAM via CFE
|
||||
hint.bhnd_nvram.0.at="nexus0"
|
||||
|
@ -4,10 +4,15 @@
|
||||
.PATH: ${.CURDIR}/../../dev/bhnd/nvram
|
||||
|
||||
KMOD= bhnd
|
||||
SRCS= bhnd.c bhnd_subr.c \
|
||||
bhnd_sprom.c bhnd_sprom_subr.c \
|
||||
nvram_subr.c \
|
||||
bhnd_nvram_map.h bhnd_nvram_map_data.h
|
||||
SRCS= bhnd.c \
|
||||
bhnd_subr.c
|
||||
|
||||
SRCS+= bhnd_nvram.c \
|
||||
bhnd_nvram_parser.c \
|
||||
bhnd_sprom.c \
|
||||
bhnd_sprom_parser.c
|
||||
SRCS+= bhnd_nvram_common.c
|
||||
SRCS+= bhnd_nvram_map.h bhnd_nvram_map_data.h
|
||||
|
||||
SRCS+= bhnd_bus_if.c bhnd_bus_if.h \
|
||||
bhnd_chipc_if.c bhnd_chipc_if.h \
|
||||
|
Loading…
x
Reference in New Issue
Block a user