bhnd(4): NVRAM serialization support.

This adds support for:

- Serializing an bhnd_nvram_plist (as exported from bhnd_nvram_store, etc) to
  an arbitrary NVRAM data format.
- Generating a serialized representation of the current NVRAM store's state
  suitable for writing back to flash, or re-encoding for upload to a
  FullMAC device.

Approved by:	adrian (mentor)
Differential Revision:	https://reviews.freebsd.org/D8762
This commit is contained in:
landonf 2016-12-19 20:34:05 +00:00
parent 3299d2687a
commit 378d13bcd3
17 changed files with 2810 additions and 1814 deletions

View File

@ -1236,6 +1236,7 @@ dev/bhnd/nvram/bhnd_nvram_data_bcm.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_data_bcmraw.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_data_btxt.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_data_sprom.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_data_sprom_subr.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_data_tlv.c optional bhnd
dev/bhnd/nvram/bhnd_nvram_if.m optional bhnd
dev/bhnd/nvram/bhnd_nvram_io.c optional bhnd

View File

@ -64,6 +64,54 @@ bhnd_nvram_data_class_desc(bhnd_nvram_data_class *cls)
return (cls->desc);
}
/**
* Return the class-level capability flags (@see BHND_NVRAM_DATA_CAP_*) for
* of @p cls.
*
* @param cls The NVRAM class.
*/
uint32_t
bhnd_nvram_data_class_caps(bhnd_nvram_data_class *cls)
{
return (cls->caps);
}
/**
* Serialize all NVRAM properties in @p plist using @p cls's NVRAM data
* format, writing the result to @p outp.
*
* @param cls The NVRAM data class to be used to perform
* serialization.
* @param props The raw property values to be serialized to
* @p outp, in serialization order.
* @param options Serialization options for @p cls, or NULL.
* @param[out] outp On success, the serialed NVRAM data will be
* written to this buffer. This argment may be
* NULL if the value is not desired.
* @param[in,out] olen The capacity of @p buf. On success, will be set
* to the actual length of the serialized data.
*
* @retval 0 success
*
* @retval ENOMEM If @p outp is non-NULL and a buffer of @p olen is too
* small to hold the serialized data.
* @retval EINVAL If a property value required by @p cls is not found in
* @p plist.
* @retval EFTYPE If a property value in @p plist cannot be represented
* as the data type required by @p cls.
* @retval ERANGE If a property value in @p plist would would overflow
* (or underflow) the data type required by @p cls.
* @retval non-zero If serialization otherwise fails, a regular unix error
* code will be returned.
*/
int
bhnd_nvram_data_serialize(bhnd_nvram_data_class *cls,
bhnd_nvram_plist *props, bhnd_nvram_plist *options, void *outp,
size_t *olen)
{
return (cls->op_serialize(cls, props, options, outp, olen));
}
/**
* Probe to see if this NVRAM data class class supports the data mapped by the
* given I/O context, returning a BHND_NVRAM_DATA_PROBE probe result.
@ -292,51 +340,6 @@ bhnd_nvram_data_options(struct bhnd_nvram_data *nv)
return (nv->cls->op_options(nv));
}
/**
* Compute the size of the serialized form of @p nv.
*
* Serialization may be performed via bhnd_nvram_data_serialize().
*
* @param nv The NVRAM data to be queried.
* @param[out] len On success, will be set to the computed size.
*
* @retval 0 success
* @retval non-zero if computing the serialized size otherwise fails, a
* regular unix error code will be returned.
*/
int
bhnd_nvram_data_size(struct bhnd_nvram_data *nv, size_t *len)
{
return (nv->cls->op_size(nv, len));
}
/**
* Serialize the NVRAM data to @p buf, using the NVRAM data class' native
* format.
*
* The resulting serialization may be reparsed with @p nv's BHND NVRAM data
* class.
*
* @param nv The NVRAM data to be serialized.
* @param[out] buf On success, the serialed NVRAM data will be
* written to this buffer. This argment may be
* NULL if the value is not desired.
* @param[in,out] len The capacity of @p buf. On success, will be set
* to the actual length of the serialized data.
*
* @retval 0 success
* @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too
* small to hold the serialized data.
* @retval non-zero If serialization otherwise fails, a regular unix error
* code will be returned.
*/
int
bhnd_nvram_data_serialize(struct bhnd_nvram_data *nv,
void *buf, size_t *len)
{
return (nv->cls->op_serialize(nv, buf, len));
}
/**
* Return the capability flags (@see BHND_NVRAM_DATA_CAP_*) for @p nv.
*

View File

@ -91,6 +91,11 @@ enum {
};
const char *bhnd_nvram_data_class_desc(bhnd_nvram_data_class *cls);
uint32_t bhnd_nvram_data_class_caps(bhnd_nvram_data_class *cls);
int bhnd_nvram_data_serialize(bhnd_nvram_data_class *cls,
bhnd_nvram_plist *props, bhnd_nvram_plist *options,
void *outp, size_t *olen);
int bhnd_nvram_data_probe(bhnd_nvram_data_class *cls,
struct bhnd_nvram_io *io);
@ -110,12 +115,6 @@ void bhnd_nvram_data_release(struct bhnd_nvram_data *nv);
bhnd_nvram_data_class *bhnd_nvram_data_get_class(struct bhnd_nvram_data *nv);
size_t bhnd_nvram_data_count(struct bhnd_nvram_data *nv);
int bhnd_nvram_data_size(struct bhnd_nvram_data *nv,
size_t *size);
int bhnd_nvram_data_serialize(struct bhnd_nvram_data *nv,
void *buf, size_t *len);
bhnd_nvram_plist *bhnd_nvram_data_options(struct bhnd_nvram_data *nv);
uint32_t bhnd_nvram_data_caps(struct bhnd_nvram_data *nv);

View File

@ -129,7 +129,8 @@ struct bhnd_nvram_bcm {
size_t count; /**< total variable count */
};
BHND_NVRAM_DATA_CLASS_DEFN(bcm, "Broadcom", sizeof(struct bhnd_nvram_bcm))
BHND_NVRAM_DATA_CLASS_DEFN(bcm, "Broadcom", BHND_NVRAM_DATA_CAP_DEVPATHS,
sizeof(struct bhnd_nvram_bcm))
static int
bhnd_nvram_bcm_probe(struct bhnd_nvram_io *io)
@ -146,6 +147,190 @@ bhnd_nvram_bcm_probe(struct bhnd_nvram_io *io)
return (BHND_NVRAM_DATA_PROBE_DEFAULT);
}
static int
bhnd_nvram_bcm_serialize(bhnd_nvram_data_class *cls, bhnd_nvram_plist *props,
bhnd_nvram_plist *options, void *outp, size_t *olen)
{
struct bhnd_nvram_bcmhdr hdr;
bhnd_nvram_prop *prop;
size_t limit, nbytes;
uint32_t sdram_ncdl;
uint16_t sdram_init, sdram_cfg, sdram_refresh;
uint8_t bcm_ver, crc8;
int error;
/* Determine output byte limit */
if (outp != NULL)
limit = *olen;
else
limit = 0;
/* Fetch required header variables */
#define PROPS_GET_HDRVAR(_name, _dest, _type) do { \
const char *name = BCM_NVRAM_ ## _name ## _VAR; \
if (!bhnd_nvram_plist_contains(props, name)) { \
BHND_NV_LOG("missing required property: %s\n", \
name); \
return (EFTYPE); \
} \
\
error = bhnd_nvram_plist_get_encoded(props, name, \
(_dest), sizeof(*(_dest)), \
BHND_NVRAM_TYPE_ ##_type); \
if (error) { \
BHND_NV_LOG("error reading required header " \
"%s property: %d\n", name, error); \
return (EFTYPE); \
} \
} while (0)
PROPS_GET_HDRVAR(SDRAM_NCDL, &sdram_ncdl, UINT32);
PROPS_GET_HDRVAR(CFG0_SDRAM_INIT, &sdram_init, UINT16);
PROPS_GET_HDRVAR(CFG1_SDRAM_CFG, &sdram_cfg, UINT16);
PROPS_GET_HDRVAR(CFG1_SDRAM_REFRESH, &sdram_refresh, UINT16);
#undef PROPS_GET_HDRVAR
/* Fetch BCM nvram version from options */
if (options != NULL &&
bhnd_nvram_plist_contains(options, BCM_NVRAM_ENCODE_OPT_VERSION))
{
error = bhnd_nvram_plist_get_uint8(options,
BCM_NVRAM_ENCODE_OPT_VERSION, &bcm_ver);
if (error) {
BHND_NV_LOG("error reading %s uint8 option value: %d\n",
BCM_NVRAM_ENCODE_OPT_VERSION, error);
return (EINVAL);
}
} else {
bcm_ver = BCM_NVRAM_CFG0_VER_DEFAULT;
}
/* Construct our header */
hdr = (struct bhnd_nvram_bcmhdr) {
.magic = htole32(BCM_NVRAM_MAGIC),
.size = 0,
.cfg0 = 0,
.cfg1 = 0,
.sdram_ncdl = htole32(sdram_ncdl)
};
hdr.cfg0 = BCM_NVRAM_SET_BITS(hdr.cfg0, BCM_NVRAM_CFG0_CRC, 0x0);
hdr.cfg0 = BCM_NVRAM_SET_BITS(hdr.cfg0, BCM_NVRAM_CFG0_VER, bcm_ver);
hdr.cfg0 = BCM_NVRAM_SET_BITS(hdr.cfg0, BCM_NVRAM_CFG0_SDRAM_INIT,
htole16(sdram_init));
hdr.cfg1 = BCM_NVRAM_SET_BITS(hdr.cfg1, BCM_NVRAM_CFG1_SDRAM_CFG,
htole16(sdram_cfg));
hdr.cfg1 = BCM_NVRAM_SET_BITS(hdr.cfg1, BCM_NVRAM_CFG1_SDRAM_REFRESH,
htole16(sdram_refresh));
/* Write the header */
nbytes = sizeof(hdr);
if (limit >= nbytes)
memcpy(outp, &hdr, sizeof(hdr));
/* Write all properties */
prop = NULL;
while ((prop = bhnd_nvram_plist_next(props, prop)) != NULL) {
const char *name;
char *p;
size_t prop_limit;
size_t name_len, value_len;
if (outp == NULL || limit < nbytes) {
p = NULL;
prop_limit = 0;
} else {
p = ((char *)outp) + nbytes;
prop_limit = limit - nbytes;
}
/* Fetch and write name + '=' to output */
name = bhnd_nvram_prop_name(prop);
name_len = strlen(name) + 1;
if (prop_limit > name_len) {
memcpy(p, name, name_len - 1);
p[name_len - 1] = '=';
prop_limit -= name_len;
p += name_len;
} else {
prop_limit = 0;
p = NULL;
}
/* Advance byte count */
if (SIZE_MAX - nbytes < name_len)
return (EFTYPE); /* would overflow size_t */
nbytes += name_len;
/* Attempt to write NUL-terminated value to output */
value_len = prop_limit;
error = bhnd_nvram_prop_encode(prop, p, &value_len,
BHND_NVRAM_TYPE_STRING);
/* If encoding failed for any reason other than ENOMEM (which
* we'll detect and report after encoding all properties),
* return immediately */
if (error && error != ENOMEM) {
BHND_NV_LOG("error serializing %s to required type "
"%s: %d\n", name,
bhnd_nvram_type_name(BHND_NVRAM_TYPE_STRING),
error);
return (error);
}
/* Advance byte count */
if (SIZE_MAX - nbytes < value_len)
return (EFTYPE); /* would overflow size_t */
nbytes += value_len;
}
/* Write terminating '\0' */
if (limit > nbytes)
*((char *)outp + nbytes) = '\0';
if (nbytes == SIZE_MAX)
return (EFTYPE); /* would overflow size_t */
else
nbytes++;
/* Update header length; this must fit within the header's 32-bit size
* field */
if (nbytes <= UINT32_MAX) {
hdr.size = (uint32_t)nbytes;
} else {
BHND_NV_LOG("size %zu exceeds maximum supported size of %u "
"bytes\n", nbytes, UINT32_MAX);
return (EFTYPE);
}
/* Provide required length */
*olen = nbytes;
if (limit < *olen) {
if (outp == NULL)
return (0);
return (ENOMEM);
}
/* Calculate the CRC value */
BHND_NV_ASSERT(nbytes >= BCM_NVRAM_CRC_SKIP, ("invalid output size"));
crc8 = bhnd_nvram_crc8((uint8_t *)outp + BCM_NVRAM_CRC_SKIP,
nbytes - BCM_NVRAM_CRC_SKIP, BHND_NVRAM_CRC8_INITIAL);
/* Update CRC and write the finalized header */
BHND_NV_ASSERT(nbytes >= sizeof(hdr), ("invalid output size"));
hdr.cfg0 = BCM_NVRAM_SET_BITS(hdr.cfg0, BCM_NVRAM_CFG0_CRC, crc8);
memcpy(outp, &hdr, sizeof(hdr));
return (0);
}
/**
* Initialize @p bcm with the provided NVRAM data mapped by @p src.
*
@ -411,127 +596,6 @@ bhnd_nvram_bcm_options(struct bhnd_nvram_data *nv)
return (bcm->opts);
}
static int
bhnd_nvram_bcm_size(struct bhnd_nvram_data *nv, size_t *size)
{
return (bhnd_nvram_bcm_serialize(nv, NULL, size));
}
static int
bhnd_nvram_bcm_serialize(struct bhnd_nvram_data *nv, void *buf, size_t *len)
{
struct bhnd_nvram_bcm *bcm;
struct bhnd_nvram_bcmhdr hdr;
void *cookiep;
const char *name;
size_t nbytes, limit;
uint8_t crc;
int error;
bcm = (struct bhnd_nvram_bcm *)nv;
nbytes = 0;
/* Save the output buffer limit */
if (buf == NULL)
limit = 0;
else
limit = *len;
/* Reserve space for the NVRAM header */
nbytes += sizeof(struct bhnd_nvram_bcmhdr);
/* Write all variables to the output buffer */
cookiep = NULL;
while ((name = bhnd_nvram_data_next(nv, &cookiep))) {
uint8_t *outp;
size_t olen;
size_t name_len, val_len;
if (limit > nbytes) {
outp = (uint8_t *)buf + nbytes;
olen = limit - nbytes;
} else {
outp = NULL;
olen = 0;
}
/* Determine length of variable name */
name_len = strlen(name) + 1;
/* Write the variable name and '=' delimiter */
if (olen >= name_len) {
/* Copy name */
memcpy(outp, name, name_len - 1);
/* Append '=' */
*(outp + name_len - 1) = '=';
}
/* Adjust byte counts */
if (SIZE_MAX - name_len < nbytes)
return (ERANGE);
nbytes += name_len;
/* Reposition output */
if (limit > nbytes) {
outp = (uint8_t *)buf + nbytes;
olen = limit - nbytes;
} else {
outp = NULL;
olen = 0;
}
/* Coerce to NUL-terminated C string, writing to the output
* buffer (or just calculating the length if outp is NULL) */
val_len = olen;
error = bhnd_nvram_data_getvar(nv, cookiep, outp, &val_len,
BHND_NVRAM_TYPE_STRING);
if (error && error != ENOMEM)
return (error);
/* Adjust byte counts */
if (SIZE_MAX - val_len < nbytes)
return (ERANGE);
nbytes += val_len;
}
/* Write terminating NUL */
if (nbytes < limit)
*((uint8_t *)buf + nbytes) = '\0';
nbytes++;
/* Provide actual size */
*len = nbytes;
if (buf == NULL || nbytes > limit) {
if (buf != NULL)
return (ENOMEM);
return (0);
}
/* Fetch current NVRAM header */
if ((error = bhnd_nvram_io_read(bcm->data, 0x0, &hdr, sizeof(hdr))))
return (error);
/* Update values covered by CRC and write to output buffer */
hdr.size = htole32(*len);
memcpy(buf, &hdr, sizeof(hdr));
/* Calculate new CRC */
crc = bhnd_nvram_crc8((uint8_t *)buf + BCM_NVRAM_CRC_SKIP,
*len - BCM_NVRAM_CRC_SKIP, BHND_NVRAM_CRC8_INITIAL);
/* Update header with valid CRC */
hdr.cfg0 &= ~BCM_NVRAM_CFG0_CRC_MASK;
hdr.cfg0 |= (crc << BCM_NVRAM_CFG0_CRC_SHIFT);
memcpy(buf, &hdr, sizeof(hdr));
return (0);
}
static uint32_t
bhnd_nvram_bcm_caps(struct bhnd_nvram_data *nv)
{

View File

@ -72,7 +72,7 @@ struct bhnd_nvram_bcmraw {
};
BHND_NVRAM_DATA_CLASS_DEFN(bcmraw, "Broadcom (RAW)",
sizeof(struct bhnd_nvram_bcmraw))
BHND_NVRAM_DATA_CAP_DEVPATHS, sizeof(struct bhnd_nvram_bcmraw))
static int
bhnd_nvram_bcmraw_probe(struct bhnd_nvram_io *io)
@ -132,6 +132,103 @@ bhnd_nvram_bcmraw_probe(struct bhnd_nvram_io *io)
return (BHND_NVRAM_DATA_PROBE_MAYBE + 1);
}
static int
bhnd_nvram_bcmraw_serialize(bhnd_nvram_data_class *cls, bhnd_nvram_plist *props,
bhnd_nvram_plist *options, void *outp, size_t *olen)
{
bhnd_nvram_prop *prop;
size_t limit, nbytes;
int error;
/* Determine output byte limit */
if (outp != NULL)
limit = *olen;
else
limit = 0;
nbytes = 0;
/* Write all properties */
prop = NULL;
while ((prop = bhnd_nvram_plist_next(props, prop)) != NULL) {
const char *name;
char *p;
size_t prop_limit;
size_t name_len, value_len;
if (outp == NULL || limit < nbytes) {
p = NULL;
prop_limit = 0;
} else {
p = ((char *)outp) + nbytes;
prop_limit = limit - nbytes;
}
/* Fetch and write name + '=' to output */
name = bhnd_nvram_prop_name(prop);
name_len = strlen(name) + 1;
if (prop_limit > name_len) {
memcpy(p, name, name_len - 1);
p[name_len - 1] = '=';
prop_limit -= name_len;
p += name_len;
} else {
prop_limit = 0;
p = NULL;
}
/* Advance byte count */
if (SIZE_MAX - nbytes < name_len)
return (EFTYPE); /* would overflow size_t */
nbytes += name_len;
/* Attempt to write NUL-terminated value to output */
value_len = prop_limit;
error = bhnd_nvram_prop_encode(prop, p, &value_len,
BHND_NVRAM_TYPE_STRING);
/* If encoding failed for any reason other than ENOMEM (which
* we'll detect and report after encoding all properties),
* return immediately */
if (error && error != ENOMEM) {
BHND_NV_LOG("error serializing %s to required type "
"%s: %d\n", name,
bhnd_nvram_type_name(BHND_NVRAM_TYPE_STRING),
error);
return (error);
}
/* Advance byte count */
if (SIZE_MAX - nbytes < value_len)
return (EFTYPE); /* would overflow size_t */
nbytes += value_len;
}
/* Write terminating '\0' */
if (limit > nbytes)
*((char *)outp + nbytes) = '\0';
if (nbytes == SIZE_MAX)
return (EFTYPE); /* would overflow size_t */
else
nbytes++;
/* Provide required length */
*olen = nbytes;
if (limit < *olen) {
if (outp == NULL)
return (0);
return (ENOMEM);
}
return (0);
}
/**
* Initialize @p bcm with the provided NVRAM data mapped by @p src.
*
@ -249,85 +346,18 @@ bhnd_nvram_bcmraw_free(struct bhnd_nvram_data *nv)
bhnd_nv_free(bcm->data);
}
static size_t
bhnd_nvram_bcmraw_count(struct bhnd_nvram_data *nv)
{
struct bhnd_nvram_bcmraw *bcm = (struct bhnd_nvram_bcmraw *)nv;
return (bcm->count);
}
static bhnd_nvram_plist *
bhnd_nvram_bcmraw_options(struct bhnd_nvram_data *nv)
{
return (NULL);
}
static int
bhnd_nvram_bcmraw_size(struct bhnd_nvram_data *nv, size_t *size)
static size_t
bhnd_nvram_bcmraw_count(struct bhnd_nvram_data *nv)
{
return (bhnd_nvram_bcmraw_serialize(nv, NULL, size));
}
struct bhnd_nvram_bcmraw *bcm = (struct bhnd_nvram_bcmraw *)nv;
static int
bhnd_nvram_bcmraw_serialize(struct bhnd_nvram_data *nv, void *buf, size_t *len)
{
struct bhnd_nvram_bcmraw *bcm;
char * const p = (char *)buf;
size_t limit;
size_t offset;
bcm = (struct bhnd_nvram_bcmraw *)nv;
/* Save the output buffer limit */
if (buf == NULL)
limit = 0;
else
limit = *len;
/* The serialized form will be exactly the length
* of our backing buffer representation */
*len = bcm->size;
/* Skip serialization if not requested, or report ENOMEM if
* buffer is too small */
if (buf == NULL) {
return (0);
} else if (*len > limit) {
return (ENOMEM);
}
/* Write all variables to the output buffer */
memcpy(buf, bcm->data, *len);
/* Rewrite all '\0' delimiters back to '=' */
offset = 0;
while (offset < bcm->size) {
size_t name_len, value_len;
name_len = strlen(p + offset);
/* EOF? */
if (name_len == 0) {
BHND_NV_ASSERT(*(p + offset) == '\0',
("no NUL terminator"));
offset++;
break;
}
/* Rewrite 'name\0' to 'name=' */
offset += name_len;
BHND_NV_ASSERT(*(p + offset) == '\0', ("incorrect offset"));
*(p + offset) = '=';
offset++;
value_len = strlen(p + offset);
offset += value_len + 1;
}
return (0);
return (bcm->count);
}
static uint32_t

View File

@ -32,9 +32,13 @@
#ifndef _BHND_NVRAM_BHND_NVRAM_BCMREG_H_
#define _BHND_NVRAM_BHND_NVRAM_BCMREG_H_
#define BCM_NVRAM_GET_BITS(_value, _field) \
#define BCM_NVRAM_GET_BITS(_value, _field) \
((_value & _field ## _MASK) >> _field ## _SHIFT)
#define BCM_NVRAM_SET_BITS(_value, _field, _bits) \
((_value & ~(_field ## _MASK)) | \
(((_bits) << _field ## _SHIFT) & _field ## _MASK))
/* BCM NVRAM header fields */
#define BCM_NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
#define BCM_NVRAM_VERSION 1
@ -45,6 +49,7 @@
#define BCM_NVRAM_CFG0_CRC_SHIFT 0
#define BCM_NVRAM_CFG0_VER_MASK 0x0000FF00
#define BCM_NVRAM_CFG0_VER_SHIFT 8
#define BCM_NVRAM_CFG0_VER_DEFAULT 1 /* default version */
#define BCM_NVRAM_CFG0_SDRAM_INIT_FIELD cfg0
#define BCM_NVRAM_CFG0_SDRAM_INIT_MASK 0xFFFF0000

View File

@ -69,7 +69,7 @@ struct bhnd_nvram_btxt {
};
BHND_NVRAM_DATA_CLASS_DEFN(btxt, "Broadcom Board Text",
sizeof(struct bhnd_nvram_btxt))
BHND_NVRAM_DATA_CAP_DEVPATHS, sizeof(struct bhnd_nvram_btxt))
/** Minimal identification header */
union bhnd_nvram_btxt_ident {
@ -124,6 +124,100 @@ bhnd_nvram_btxt_probe(struct bhnd_nvram_io *io)
return (BHND_NVRAM_DATA_PROBE_MAYBE);
}
static int
bhnd_nvram_btxt_serialize(bhnd_nvram_data_class *cls, bhnd_nvram_plist *props,
bhnd_nvram_plist *options, void *outp, size_t *olen)
{
bhnd_nvram_prop *prop;
size_t limit, nbytes;
int error;
/* Determine output byte limit */
if (outp != NULL)
limit = *olen;
else
limit = 0;
nbytes = 0;
/* Write all properties */
prop = NULL;
while ((prop = bhnd_nvram_plist_next(props, prop)) != NULL) {
const char *name;
char *p;
size_t prop_limit;
size_t name_len, value_len;
if (outp == NULL || limit < nbytes) {
p = NULL;
prop_limit = 0;
} else {
p = ((char *)outp) + nbytes;
prop_limit = limit - nbytes;
}
/* Fetch and write 'name=' to output */
name = bhnd_nvram_prop_name(prop);
name_len = strlen(name) + 1;
if (prop_limit > name_len) {
memcpy(p, name, name_len - 1);
p[name_len - 1] = '=';
prop_limit -= name_len;
p += name_len;
} else {
prop_limit = 0;
p = NULL;
}
/* Advance byte count */
if (SIZE_MAX - nbytes < name_len)
return (EFTYPE); /* would overflow size_t */
nbytes += name_len;
/* Write NUL-terminated value to output, rewrite NUL as
* '\n' record delimiter */
value_len = prop_limit;
error = bhnd_nvram_prop_encode(prop, p, &value_len,
BHND_NVRAM_TYPE_STRING);
if (p != NULL && error == 0) {
/* Replace trailing '\0' with newline */
BHND_NV_ASSERT(value_len > 0, ("string length missing "
"minimum required trailing NUL"));
*(p + (value_len - 1)) = '\n';
} else if (error && error != ENOMEM) {
/* If encoding failed for any reason other than ENOMEM
* (which we'll detect and report after encoding all
* properties), return immediately */
BHND_NV_LOG("error serializing %s to required type "
"%s: %d\n", name,
bhnd_nvram_type_name(BHND_NVRAM_TYPE_STRING),
error);
return (error);
}
/* Advance byte count */
if (SIZE_MAX - nbytes < value_len)
return (EFTYPE); /* would overflow size_t */
nbytes += value_len;
}
/* Provide required length */
*olen = nbytes;
if (limit < *olen) {
if (outp == NULL)
return (0);
return (ENOMEM);
}
return (0);
}
/**
* Initialize @p btxt with the provided board text data mapped by @p src.
*
@ -261,52 +355,6 @@ bhnd_nvram_btxt_options(struct bhnd_nvram_data *nv)
return (NULL);
}
static int
bhnd_nvram_btxt_size(struct bhnd_nvram_data *nv, size_t *size)
{
struct bhnd_nvram_btxt *btxt = (struct bhnd_nvram_btxt *)nv;
/* The serialized form will be identical in length
* to our backing buffer representation */
*size = bhnd_nvram_io_getsize(btxt->data);
return (0);
}
static int
bhnd_nvram_btxt_serialize(struct bhnd_nvram_data *nv, void *buf, size_t *len)
{
struct bhnd_nvram_btxt *btxt;
size_t limit;
int error;
btxt = (struct bhnd_nvram_btxt *)nv;
limit = *len;
/* Provide actual output size */
if ((error = bhnd_nvram_data_size(nv, len)))
return (error);
if (buf == NULL) {
return (0);
} else if (limit < *len) {
return (ENOMEM);
}
/* Copy our internal representation to the output buffer */
if ((error = bhnd_nvram_io_read(btxt->data, 0x0, buf, *len)))
return (error);
/* Restore the original key=value format, rewriting all '\0'
* key\0value delimiters back to '=' */
for (char *p = buf; (size_t)(p - (char *)buf) < *len; p++) {
if (*p == '\0')
*p = '=';
}
return (0);
}
static uint32_t
bhnd_nvram_btxt_caps(struct bhnd_nvram_data *nv)
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -44,12 +44,43 @@
#include "bhnd_nvram_io.h"
/** The maximum number of array elements encoded in a single SPROM variable */
#define SPROM_ARRAY_MAXLEN 12
#define BHND_SPROM_ARRAY_MAXLEN 12
typedef struct bhnd_sprom_opcode_state bhnd_sprom_opcode_state;
typedef struct bhnd_sprom_opcode_bind bhnd_sprom_opcode_bind;
typedef struct bhnd_sprom_opcode_var bhnd_sprom_opcode_var;
typedef struct bhnd_sprom_opcode_idx_entry bhnd_sprom_opcode_idx_entry;
int bhnd_sprom_opcode_init(
bhnd_sprom_opcode_state *state,
const bhnd_sprom_layout *layout);
void bhnd_sprom_opcode_fini(
bhnd_sprom_opcode_state *state);
bhnd_sprom_opcode_idx_entry *bhnd_sprom_opcode_index_find(
bhnd_sprom_opcode_state *state,
const char *name);
bhnd_sprom_opcode_idx_entry *bhnd_sprom_opcode_index_next(
bhnd_sprom_opcode_state *state,
bhnd_sprom_opcode_idx_entry *prev);
int bhnd_sprom_opcode_parse_var(
bhnd_sprom_opcode_state *state,
bhnd_sprom_opcode_idx_entry *entry);
int bhnd_sprom_opcode_seek(
bhnd_sprom_opcode_state *state,
bhnd_sprom_opcode_idx_entry *entry);
int bhnd_sprom_opcode_next_binding(
bhnd_sprom_opcode_state *state);
int bhnd_sprom_opcode_apply_scale(
bhnd_sprom_opcode_state *state,
uint32_t *value);
/**
* SPROM opcode per-bind evaluation state.
*/
struct sprom_opcode_bind {
struct bhnd_sprom_opcode_bind {
uint8_t count;
uint32_t skip_in; /**< input element skips */
bool skip_in_negative; /**< skip_in should be subtracted */
@ -59,15 +90,15 @@ struct sprom_opcode_bind {
/**
* SPROM opcode per-variable evaluation state.
*/
struct sprom_opcode_var {
uint8_t nelem; /**< variable array length */
uint32_t mask; /**< current bind input mask */
int8_t shift; /**< current bind input shift */
bhnd_nvram_type base_type; /**< current bind input type */
uint32_t scale; /**< current scale to apply to scaled encodings */
struct sprom_opcode_bind bind; /**< current bind state */
bool have_bind; /**< if bind state is defined */
size_t bind_total; /**< total count of bind operations performed */
struct bhnd_sprom_opcode_var {
uint8_t nelem; /**< variable array length */
uint32_t mask; /**< current bind input mask */
int8_t shift; /**< current bind input shift */
bhnd_nvram_type base_type; /**< current bind input type */
uint32_t scale; /**< current scale to apply to scaled encodings */
bhnd_sprom_opcode_bind bind; /**< current bind state */
bool have_bind; /**< if bind state is defined */
size_t bind_total; /**< total count of bind operations performed */
};
/**
@ -80,13 +111,16 @@ typedef enum {
SPROM_OPCODE_VAR_STATE_NONE = 1, /**< no variable entry available */
SPROM_OPCODE_VAR_STATE_OPEN = 2, /**< currently parsing a variable entry */
SPROM_OPCODE_VAR_STATE_DONE = 3 /**< full variable entry has been parsed */
} sprom_opcode_var_state;
} bhnd_sprom_opcode_var_state;
/**
* SPROM opcode evaluation state
*/
struct sprom_opcode_state {
const struct bhnd_sprom_layout *layout; /**< SPROM layout */
struct bhnd_sprom_opcode_state {
const bhnd_sprom_layout *layout; /**< SPROM layout */
bhnd_sprom_opcode_idx_entry *idx; /**< variable index (NULL during initialization) */
size_t num_idx; /**< variable index entry count */
/** Current SPROM revision range */
bitstr_t bit_decl(revs, SPROM_OP_REV_MAX);
@ -98,14 +132,14 @@ struct sprom_opcode_state {
size_t vid; /**< Variable ID */
/* State reset after end of each variable definition */
struct sprom_opcode_var var; /**< variable record (if any) */
sprom_opcode_var_state var_state; /**< variable record state */
bhnd_sprom_opcode_var var; /**< variable record (if any) */
bhnd_sprom_opcode_var_state var_state; /**< variable record state */
};
/**
* SPROM opcode variable index entry
*/
struct sprom_opcode_idx {
struct bhnd_sprom_opcode_idx_entry {
uint16_t vid; /**< SPROM variable ID */
uint16_t offset; /**< SPROM input offset */
uint16_t opcodes; /**< SPROM opcode offset */
@ -118,33 +152,23 @@ struct sprom_opcode_idx {
* variable.
*/
union bhnd_nvram_sprom_storage {
uint8_t u8[SPROM_ARRAY_MAXLEN];
uint16_t u16[SPROM_ARRAY_MAXLEN];
uint32_t u32[SPROM_ARRAY_MAXLEN];
int8_t i8[SPROM_ARRAY_MAXLEN];
int16_t i16[SPROM_ARRAY_MAXLEN];
int32_t i32[SPROM_ARRAY_MAXLEN];
char ch[SPROM_ARRAY_MAXLEN];
};
/**
* SPROM common integer value representation.
*/
union bhnd_nvram_sprom_intv {
uint32_t u32;
int32_t s32;
uint8_t u8[BHND_SPROM_ARRAY_MAXLEN];
uint16_t u16[BHND_SPROM_ARRAY_MAXLEN];
uint32_t u32[BHND_SPROM_ARRAY_MAXLEN];
int8_t i8[BHND_SPROM_ARRAY_MAXLEN];
int16_t i16[BHND_SPROM_ARRAY_MAXLEN];
int32_t i32[BHND_SPROM_ARRAY_MAXLEN];
char ch[BHND_SPROM_ARRAY_MAXLEN];
};
/**
* SPROM data class instance state.
*/
struct bhnd_nvram_sprom {
struct bhnd_nvram_data nv; /**< common instance state */
struct bhnd_nvram_io *data; /**< backing SPROM image */
const struct bhnd_sprom_layout *layout; /**< layout definition */
struct sprom_opcode_state state; /**< opcode eval state */
struct sprom_opcode_idx *idx; /**< opcode index entries */
size_t num_idx; /**< opcode index entry count */
struct bhnd_nvram_data nv; /**< common instance state */
struct bhnd_nvram_io *data; /**< backing SPROM image */
const bhnd_sprom_layout *layout; /**< layout definition */
bhnd_sprom_opcode_state state; /**< opcode eval state */
};
#endif /* _BHND_NVRAM_BHND_NVRAM_SPROMVAR_H_ */

View File

@ -62,7 +62,8 @@ struct bhnd_nvram_tlv {
size_t count; /**< variable count */
};
BHND_NVRAM_DATA_CLASS_DEFN(tlv, "WGT634U", sizeof(struct bhnd_nvram_tlv))
BHND_NVRAM_DATA_CLASS_DEFN(tlv, "WGT634U", BHND_NVRAM_DATA_CAP_DEVPATHS,
sizeof(struct bhnd_nvram_tlv))
/** Minimal TLV_ENV record header */
struct bhnd_nvram_tlv_env_hdr {
@ -163,6 +164,123 @@ bhnd_nvram_tlv_probe(struct bhnd_nvram_io *io)
return (BHND_NVRAM_DATA_PROBE_DEFAULT);
}
static int
bhnd_nvram_tlv_serialize(bhnd_nvram_data_class *cls, bhnd_nvram_plist *props,
bhnd_nvram_plist *options, void *outp, size_t *olen)
{
bhnd_nvram_prop *prop;
size_t limit, nbytes;
int error;
/* Determine output byte limit */
if (outp != NULL)
limit = *olen;
else
limit = 0;
nbytes = 0;
/* Write all properties */
prop = NULL;
while ((prop = bhnd_nvram_plist_next(props, prop)) != NULL) {
struct bhnd_nvram_tlv_env env;
const char *name;
uint8_t *p;
size_t name_len, value_len;
size_t rec_size;
env.hdr.tag = NVRAM_TLV_TYPE_ENV;
env.hdr.size = sizeof(env.flags);
env.flags = 0x0;
/* Fetch name value and add to record length */
name = bhnd_nvram_prop_name(prop);
name_len = strlen(name) + 1 /* '=' */;
if (UINT8_MAX - env.hdr.size < name_len) {
BHND_NV_LOG("%s name exceeds maximum TLV record "
"length\n", name);
return (EFTYPE); /* would overflow TLV size */
}
env.hdr.size += name_len;
/* Add string value to record length */
error = bhnd_nvram_prop_encode(prop, NULL, &value_len,
BHND_NVRAM_TYPE_STRING);
if (error) {
BHND_NV_LOG("error serializing %s to required type "
"%s: %d\n", name,
bhnd_nvram_type_name(BHND_NVRAM_TYPE_STRING),
error);
return (error);
}
if (UINT8_MAX - env.hdr.size < value_len) {
BHND_NV_LOG("%s value exceeds maximum TLV record "
"length\n", name);
return (EFTYPE); /* would overflow TLV size */
}
env.hdr.size += value_len;
/* Calculate total record size */
rec_size = sizeof(env.hdr) + env.hdr.size;
if (SIZE_MAX - nbytes < rec_size)
return (EFTYPE); /* would overflow size_t */
/* Calculate our output pointer */
if (nbytes > limit || limit - nbytes < rec_size) {
/* buffer is full; cannot write */
p = NULL;
} else {
p = (uint8_t *)outp + nbytes;
}
/* Write to output */
if (p != NULL) {
memcpy(p, &env, sizeof(env));
p += sizeof(env);
memcpy(p, name, name_len - 1);
p[name_len - 1] = '=';
p += name_len;
error = bhnd_nvram_prop_encode(prop, p, &value_len,
BHND_NVRAM_TYPE_STRING);
if (error) {
BHND_NV_LOG("error serializing %s to required "
"type %s: %d\n", name,
bhnd_nvram_type_name(
BHND_NVRAM_TYPE_STRING),
error);
return (error);
}
}
nbytes += rec_size;
}
/* Write terminating END record */
if (limit > nbytes)
*((uint8_t *)outp + nbytes) = NVRAM_TLV_TYPE_END;
if (nbytes == SIZE_MAX)
return (EFTYPE); /* would overflow size_t */
nbytes++;
/* Provide required length */
*olen = nbytes;
if (limit < *olen) {
if (outp == NULL)
return (0);
return (ENOMEM);
}
return (0);
}
/**
* Initialize @p tlv with the provided NVRAM TLV data mapped by @p src.
*
@ -256,91 +374,13 @@ bhnd_nvram_tlv_count(struct bhnd_nvram_data *nv)
return (tlv->count);
}
static bhnd_nvram_plist *
bhnd_nvram_tlv_options(struct bhnd_nvram_data *nv)
{
return (NULL);
}
static int
bhnd_nvram_tlv_size(struct bhnd_nvram_data *nv, size_t *size)
{
/* Let the serialization implementation calculate the length */
return (bhnd_nvram_data_serialize(nv, NULL, size));
}
static int
bhnd_nvram_tlv_serialize(struct bhnd_nvram_data *nv, void *buf, size_t *len)
{
struct bhnd_nvram_tlv *tlv;
size_t limit;
size_t next;
uint8_t tag;
int error;
tlv = (struct bhnd_nvram_tlv *)nv;
/* Save the buffer capacity */
if (buf == NULL)
limit = 0;
else
limit = *len;
/* Write all of our TLV records to the output buffer (or just
* calculate the buffer size that would be required) */
next = 0;
do {
struct bhnd_nvram_tlv_env *env;
uint8_t *p;
size_t name_len;
size_t rec_offset, rec_size;
/* Parse the TLV record */
error = bhnd_nvram_tlv_next_record(tlv->data, &next,
&rec_offset, &tag);
if (error)
return (error);
rec_size = next - rec_offset;
/* Calculate our output pointer */
if (rec_offset > limit || limit - rec_offset < rec_size) {
/* buffer is full; cannot write */
p = NULL;
} else {
p = (uint8_t *)buf + rec_offset;
}
/* If not writing, nothing further to do for this record */
if (p == NULL)
continue;
/* Copy to the output buffer */
error = bhnd_nvram_io_read(tlv->data, rec_offset, p, rec_size);
if (error)
return (error);
/* All further processing is TLV_ENV-specific */
if (tag != NVRAM_TLV_TYPE_ENV)
continue;
/* Restore the original key=value format, rewriting '\0'
* delimiter back to '=' */
env = (struct bhnd_nvram_tlv_env *)p;
name_len = strlen(env->envp); /* skip variable name */
*(env->envp + name_len) = '='; /* set '=' */
} while (tag != NVRAM_TLV_TYPE_END);
/* The 'next' offset should now point at EOF, and represents
* the total length of the serialized output. */
*len = next;
if (buf != NULL && limit < *len)
return (ENOMEM);
return (0);
}
static uint32_t
bhnd_nvram_tlv_caps(struct bhnd_nvram_data *nv)
{

View File

@ -55,6 +55,13 @@ int bhnd_nvram_data_generic_rp_copy_val(
/** @see bhnd_nvram_data_probe() */
typedef int (bhnd_nvram_data_op_probe)(struct bhnd_nvram_io *io);
/** @see bhnd_nvram_data_serialize() */
typedef int (bhnd_nvram_data_op_serialize)(
bhnd_nvram_data_class *cls,
bhnd_nvram_plist *props,
bhnd_nvram_plist *options, void *outp,
size_t *olen);
/** @see bhnd_nvram_data_new() */
typedef int (bhnd_nvram_data_op_new)(struct bhnd_nvram_data *nv,
struct bhnd_nvram_io *io);
@ -66,15 +73,6 @@ typedef void (bhnd_nvram_data_op_free)(struct bhnd_nvram_data *nv);
/** @see bhnd_nvram_data_count() */
typedef size_t (bhnd_nvram_data_op_count)(struct bhnd_nvram_data *nv);
/** @see bhnd_nvram_data_size() */
typedef int (bhnd_nvram_data_op_size)(struct bhnd_nvram_data *nv,
size_t *len);
/** @see bhnd_nvram_data_serialize() */
typedef int (bhnd_nvram_data_op_serialize)(
struct bhnd_nvram_data *nv, void *buf,
size_t *len);
/** @see bhnd_nvram_data_options() */
typedef bhnd_nvram_plist*(bhnd_nvram_data_op_options)(
struct bhnd_nvram_data *nv);
@ -129,14 +127,14 @@ typedef int (bhnd_nvram_data_op_filter_unsetvar)(
*/
struct bhnd_nvram_data_class {
const char *desc; /**< description */
uint32_t caps; /**< capabilities (BHND_NVRAM_DATA_CAP_*) */
size_t size; /**< instance size */
bhnd_nvram_data_op_probe *op_probe;
bhnd_nvram_data_op_serialize *op_serialize;
bhnd_nvram_data_op_new *op_new;
bhnd_nvram_data_op_free *op_free;
bhnd_nvram_data_op_count *op_count;
bhnd_nvram_data_op_size *op_size;
bhnd_nvram_data_op_serialize *op_serialize;
bhnd_nvram_data_op_options *op_options;
bhnd_nvram_data_op_caps *op_caps;
bhnd_nvram_data_op_next *op_next;
@ -186,11 +184,10 @@ struct bhnd_nvram_data {
*/
#define BHND_NVRAM_DATA_CLASS_ITER_METHODS(_cname, _macro) \
_macro(_cname, probe) \
_macro(_cname, serialize) \
_macro(_cname, new) \
_macro(_cname, free) \
_macro(_cname, count) \
_macro(_cname, size) \
_macro(_cname, serialize) \
_macro(_cname, options) \
_macro(_cname, caps) \
_macro(_cname, next) \
@ -207,12 +204,13 @@ struct bhnd_nvram_data {
* Define a bhnd_nvram_data_class with class name @p _n and description
* @p _desc, and register with bhnd_nvram_data_class_set.
*/
#define BHND_NVRAM_DATA_CLASS_DEFN(_cname, _desc, _size) \
#define BHND_NVRAM_DATA_CLASS_DEFN(_cname, _desc, _caps, _size) \
BHND_NVRAM_DATA_CLASS_ITER_METHODS(_cname, \
BHND_NVRAM_DATA_CLASS_DECL_METHOD) \
\
struct bhnd_nvram_data_class bhnd_nvram_## _cname ## _class = { \
.desc = (_desc), \
.caps = (_caps), \
.size = (_size), \
BHND_NVRAM_DATA_CLASS_ITER_METHODS(_cname, \
BHND_NVRAM_DATA_CLASS_ASSIGN_METHOD) \

View File

@ -314,7 +314,7 @@ struct bhnd_nvram_vardefn {
bhnd_nvram_type type; /**< variable type */
uint8_t nelem; /**< element count, or 1 if not
an array-typed variable */
const bhnd_nvram_val_fmt *fmt; /**< value format, or NULL */
const bhnd_nvram_val_fmt *fmt; /**< value format */
uint32_t flags; /**< flags (BHND_NVRAM_VF_*) */
};
@ -327,19 +327,20 @@ extern const size_t bhnd_nvram_num_vardefns;
/**
* SPROM layout descriptor.
*/
struct bhnd_sprom_layout {
typedef struct bhnd_sprom_layout {
size_t size; /**< SPROM image size, in bytes */
uint8_t rev; /**< SPROM revision */
uint8_t flags; /**< layout flags (SPROM_LAYOUT_*) */
size_t srev_offset; /**< offset to SROM revision */
size_t magic_offset; /**< offset to magic value */
uint16_t magic_value; /**< expected magic value */
size_t crc_offset; /**< offset to crc8 value */
const uint8_t *bindings; /**< SPROM binding opcode table */
size_t bindings_size; /**< SPROM binding opcode table size */
uint16_t num_vars; /**< total number of variables defined
for this layout by the binding
table */
};
} bhnd_sprom_layout;
/*
* SPROM layout descriptions generated from nvram_map.

View File

@ -997,6 +997,90 @@ bhnd_nvram_store_export(struct bhnd_nvram_store *sc, const char *path,
return (error);
}
/**
* Encode all NVRAM properties at @p path, using the @p store's current NVRAM
* data format.
*
* @param sc The NVRAM store instance.
* @param path The NVRAM path to export, or NULL to select the root
* path.
* @param[out] data On success, will be set to the newly serialized value.
* The caller is responsible for freeing this value
* via bhnd_nvram_io_free().
* @param flags Export flags. See BHND_NVSTORE_EXPORT_*.
*
* @retval 0 success
* @retval EINVAL If @p flags is invalid.
* @retval ENOENT The requested path was not found.
* @retval ENOMEM If allocation fails.
* @retval non-zero If serialization of @p path otherwise fails, a regular
* unix error code will be returned.
*/
int
bhnd_nvram_store_serialize(struct bhnd_nvram_store *sc, const char *path,
struct bhnd_nvram_io **data, uint32_t flags)
{
bhnd_nvram_plist *props;
bhnd_nvram_plist *options;
bhnd_nvram_data_class *cls;
struct bhnd_nvram_io *io;
void *outp;
size_t olen;
int error;
props = NULL;
options = NULL;
io = NULL;
/* Perform requested export */
error = bhnd_nvram_store_export(sc, path, &cls, &props, &options,
flags);
if (error)
return (error);
/* Determine serialized size */
error = bhnd_nvram_data_serialize(cls, props, options, NULL, &olen);
if (error)
goto failed;
/* Allocate output buffer */
if ((io = bhnd_nvram_iobuf_empty(olen, olen)) == NULL) {
error = ENOMEM;
goto failed;
}
/* Fetch write pointer */
if ((error = bhnd_nvram_io_write_ptr(io, 0, &outp, olen, NULL)))
goto failed;
/* Perform serialization */
error = bhnd_nvram_data_serialize(cls, props, options, outp, &olen);
if (error)
goto failed;
if ((error = bhnd_nvram_io_setsize(io, olen)))
goto failed;
/* Success */
bhnd_nvram_plist_release(props);
bhnd_nvram_plist_release(options);
*data = io;
return (0);
failed:
if (props != NULL)
bhnd_nvram_plist_release(props);
if (options != NULL)
bhnd_nvram_plist_release(options);
if (io != NULL)
bhnd_nvram_io_free(io);
return (error);
}
/**
* Read an NVRAM variable.
*

View File

@ -76,6 +76,9 @@ int bhnd_nvram_store_export(struct bhnd_nvram_store *store,
bhnd_nvram_plist **props, bhnd_nvram_plist **options,
uint32_t flags);
int bhnd_nvram_store_serialize(struct bhnd_nvram_store *store,
const char *path, struct bhnd_nvram_io **data, uint32_t flags);
int bhnd_nvram_store_getvar(struct bhnd_nvram_store *sc, const char *name,
void *outp, size_t *olen, bhnd_nvram_type otype);
int bhnd_nvram_store_setvar(struct bhnd_nvram_store *sc, const char *name,

View File

@ -253,14 +253,19 @@ function main(_i) {
# Value Formats
Fmt = class_new("Fmt")
class_add_prop(Fmt, p_name, "name")
class_add_prop(Fmt, p_symbol, "const")
class_add_prop(Fmt, p_symbol, "symbol")
class_add_prop(Fmt, p_array_fmt, "array_fmt")
FmtHex = fmt_new("hex", "bhnd_nvram_val_bcm_hex_fmt")
FmtDec = fmt_new("decimal", "bhnd_nvram_val_bcm_decimal_fmt")
FmtMAC = fmt_new("macaddr", "bhnd_nvram_val_bcm_macaddr_fmt")
FmtLEDDC = fmt_new("leddc", "bhnd_nvram_val_bcm_leddc_fmt")
FmtCharArray = fmt_new("char_array", "bhnd_nvram_val_char_array_fmt")
FmtChar = fmt_new("char", "bhnd_nvram_val_char_array_fmt",
FmtCharArray)
FmtStr = fmt_new("string", "bhnd_nvram_val_bcm_string_fmt")
# User-specifiable value formats
ValueFormats = map_new()
map_set(ValueFormats, get(FmtHex, p_name), FmtHex)
map_set(ValueFormats, get(FmtDec, p_name), FmtDec)
@ -315,7 +320,7 @@ function main(_i) {
"BHND_NVRAM_TYPE_INT32_ARRAY", FmtDec, UInt32Max, 6, 22)
Char = type_new("char", 1, 1, "BHND_NVRAM_TYPE_CHAR",
"BHND_NVRAM_TYPE_CHAR_ARRAY", FmtStr, UInt8Max, 8, 24)
"BHND_NVRAM_TYPE_CHAR_ARRAY", FmtChar, UInt8Max, 8, 24)
BaseTypes = map_new()
map_set(BaseTypes, get(UInt8, p_name), UInt8)
@ -634,7 +639,7 @@ function write_data_nvram_vardefn(v, _desc, _help, _type, _fmt) {
# Write a top-level bhnd_sprom_layout entry for the given revision
# and layout definition
function write_data_srom_layout(layout, revision, _flags, _size,
_sromcrc, _crc_seg,
_sromcrc, _crc_seg, _crc_off,
_sromsig, _sig_seg, _sig_offset, _sig_value,
_sromrev, _rev_seg, _rev_off,
_num_vars)
@ -648,7 +653,8 @@ function write_data_srom_layout(layout, revision, _flags, _size,
"cannot compute total size")
} else {
_crc_seg = srom_entry_get_single_segment(_sromcrc)
_size = get(_crc_seg, p_offset)
_crc_off = get(_crc_seg, p_offset)
_size = _crc_off
_size += get(get(_crc_seg, p_type), p_width)
}
@ -703,6 +709,8 @@ function write_data_srom_layout(layout, revision, _flags, _size,
emit(".magic_value = 0,\n")
}
emit(".crc_offset = " _crc_off ",\n")
emit(".bindings = " srom_layout_get_variable_name(layout) ",\n")
emit(".bindings_size = nitems(" \
srom_layout_get_variable_name(layout) "),\n")
@ -1741,6 +1749,9 @@ function class_has_prop_id(class, prop_id, _super) {
if (class == null)
return (0)
if (prop_id == null)
return (0)
# Check class<->prop cache
if ((class, prop_id) in _g_class_prop_cache)
return (1)
@ -2538,9 +2549,17 @@ function type_get_base(type) {
}
# Return the default fmt for a given type instance
function type_get_default_fmt(type, _base) {
function type_get_default_fmt(type, _base, _fmt, _array_fmt) {
_base = type_get_base(type)
return (get(_base, p_default_fmt))
_fmt = get(_base, p_default_fmt)
if (obj_is_instanceof(type, ArrayType)) {
_array_fmt = get(_fmt, p_array_fmt)
if (_array_fmt != null)
_fmt = _array_fmt
}
return (_fmt)
}
# Return a string representation of the given type
@ -2641,11 +2660,14 @@ function type_named(name, _n, _type) {
}
# Create a new Fmt instance
function fmt_new(name, symbol, _obj) {
function fmt_new(name, symbol, array_fmt, _obj) {
_obj = obj_new(Fmt)
set(_obj, p_name, name)
set(_obj, p_symbol, symbol)
if (array_fmt != null)
set(_obj, p_array_fmt, array_fmt)
return (_obj)
}

View File

@ -32,6 +32,7 @@ SRCS+= bhnd_nvram_data.c \
bhnd_nvram_data_bcmraw.c \
bhnd_nvram_data_btxt.c \
bhnd_nvram_data_sprom.c \
bhnd_nvram_data_sprom_subr.c \
bhnd_nvram_data_tlv.c \
bhnd_nvram_io.c \
bhnd_nvram_iobuf.c \