svn commit: r310297 - in head/sys: conf dev/bhnd/nvram dev/bhnd/tools modules/bhnd
Landon J. Fuller
landonf at FreeBSD.org
Mon Dec 19 20:34:07 UTC 2016
Author: landonf
Date: Mon Dec 19 20:34:05 2016
New Revision: 310297
URL: https://svnweb.freebsd.org/changeset/base/310297
Log:
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
Added:
head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom_subr.c (contents, props changed)
Modified:
head/sys/conf/files
head/sys/dev/bhnd/nvram/bhnd_nvram_data.c
head/sys/dev/bhnd/nvram/bhnd_nvram_data.h
head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c
head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmraw.c
head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmreg.h
head/sys/dev/bhnd/nvram/bhnd_nvram_data_btxt.c
head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c
head/sys/dev/bhnd/nvram/bhnd_nvram_data_spromvar.h
head/sys/dev/bhnd/nvram/bhnd_nvram_data_tlv.c
head/sys/dev/bhnd/nvram/bhnd_nvram_datavar.h
head/sys/dev/bhnd/nvram/bhnd_nvram_private.h
head/sys/dev/bhnd/nvram/bhnd_nvram_store.c
head/sys/dev/bhnd/nvram/bhnd_nvram_store.h
head/sys/dev/bhnd/tools/nvram_map_gen.awk
head/sys/modules/bhnd/Makefile
Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files Mon Dec 19 20:31:27 2016 (r310296)
+++ head/sys/conf/files Mon Dec 19 20:34:05 2016 (r310297)
@@ -1236,6 +1236,7 @@ dev/bhnd/nvram/bhnd_nvram_data_bcm.c opt
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
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_data.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data.c Mon Dec 19 20:31:27 2016 (r310296)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data.c Mon Dec 19 20:34:05 2016 (r310297)
@@ -65,6 +65,54 @@ bhnd_nvram_data_class_desc(bhnd_nvram_da
}
/**
+ * 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.
*
@@ -293,51 +341,6 @@ bhnd_nvram_data_options(struct bhnd_nvra
}
/**
- * 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.
*
* @param nv The NVRAM data to be queried.
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_data.h
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data.h Mon Dec 19 20:31:27 2016 (r310296)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data.h Mon Dec 19 20:34:05 2016 (r310297)
@@ -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 b
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);
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c Mon Dec 19 20:31:27 2016 (r310296)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcm.c Mon Dec 19 20:34:05 2016 (r310297)
@@ -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_i
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
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)
{
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmraw.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmraw.c Mon Dec 19 20:31:27 2016 (r310296)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmraw.c Mon Dec 19 20:34:05 2016 (r310297)
@@ -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_nvra
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
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)
-{
- return (bhnd_nvram_bcmraw_serialize(nv, NULL, size));
-}
-
-static int
-bhnd_nvram_bcmraw_serialize(struct bhnd_nvram_data *nv, void *buf, size_t *len)
+static size_t
+bhnd_nvram_bcmraw_count(struct bhnd_nvram_data *nv)
{
- 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;
- }
+ struct bhnd_nvram_bcmraw *bcm = (struct bhnd_nvram_bcmraw *)nv;
- return (0);
+ return (bcm->count);
}
static uint32_t
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmreg.h
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmreg.h Mon Dec 19 20:31:27 2016 (r310296)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data_bcmreg.h Mon Dec 19 20:34:05 2016 (r310297)
@@ -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
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_data_btxt.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data_btxt.c Mon Dec 19 20:31:27 2016 (r310296)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data_btxt.c Mon Dec 19 20:34:05 2016 (r310297)
@@ -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_
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_nvra
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)
{
Modified: head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c
==============================================================================
--- head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c Mon Dec 19 20:31:27 2016 (r310296)
+++ head/sys/dev/bhnd/nvram/bhnd_nvram_data_sprom.c Mon Dec 19 20:34:05 2016 (r310297)
@@ -49,8 +49,9 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#endif /* _KERNEL */
-#include "bhnd_nvram_private.h"
+#include "bhnd_nvram_map.h"
+#include "bhnd_nvram_private.h"
#include "bhnd_nvram_datavar.h"
#include "bhnd_nvram_data_spromvar.h"
@@ -62,44 +63,45 @@ __FBSDID("$FreeBSD$");
* used on Broadcom wireless and wired adapters, that provides a subset of the
* variables defined by Broadcom SoC NVRAM formats.
*/
-BHND_NVRAM_DATA_CLASS_DEFN(sprom, "Broadcom SPROM",
- sizeof(struct bhnd_nvram_sprom))
-static int sprom_sort_idx(const void *lhs, const void *rhs);
+static const bhnd_sprom_layout *bhnd_nvram_sprom_get_layout(uint8_t sromrev);
+
+static int bhnd_nvram_sprom_ident(
+ struct bhnd_nvram_io *io,
+ const bhnd_sprom_layout **ident,
+ struct bhnd_nvram_io **shadow);
+
+static int bhnd_nvram_sprom_write_var(
+ bhnd_sprom_opcode_state *state,
+ bhnd_sprom_opcode_idx_entry *entry,
+ bhnd_nvram_val *value,
+ struct bhnd_nvram_io *io);
+
+static int bhnd_nvram_sprom_write_offset(
+ const struct bhnd_nvram_vardefn *var,
+ struct bhnd_nvram_io *data,
+ bhnd_nvram_type type, size_t offset,
+ uint32_t mask, int8_t shift,
+ uint32_t value);
+
+static int bhnd_nvram_sprom_read_offset(
+ const struct bhnd_nvram_vardefn *var,
+ struct bhnd_nvram_io *data,
+ bhnd_nvram_type type, size_t offset,
+ uint32_t mask, int8_t shift,
+ uint32_t *value);
-static int sprom_opcode_state_init(struct sprom_opcode_state *state,
- const struct bhnd_sprom_layout *layout);
-static int sprom_opcode_state_reset(struct sprom_opcode_state *state);
-static int sprom_opcode_state_seek(struct sprom_opcode_state *state,
- struct sprom_opcode_idx *indexed);
-
-static int sprom_opcode_next_var(struct sprom_opcode_state *state);
-static int sprom_opcode_parse_var(struct sprom_opcode_state *state,
- struct sprom_opcode_idx *indexed);
-
-static int sprom_opcode_next_binding(struct sprom_opcode_state *state);
-
-static int sprom_opcode_set_type(struct sprom_opcode_state *state,
- bhnd_nvram_type type);
-
-static int sprom_opcode_set_var(struct sprom_opcode_state *state,
- size_t vid);
-static int sprom_opcode_clear_var(struct sprom_opcode_state *state);
-static int sprom_opcode_flush_bind(struct sprom_opcode_state *state);
-static int sprom_opcode_read_opval32(struct sprom_opcode_state *state,
- uint8_t type, uint32_t *opval);
-static int sprom_opcode_apply_scale(struct sprom_opcode_state *state,
- uint32_t *value);
-
-static int sprom_opcode_step(struct sprom_opcode_state *state,
- uint8_t *opcode);
-
-#define SPROM_OP_BAD(_state, _fmt, ...) \
- BHND_NV_LOG("bad encoding at %td: " _fmt, \
- (_state)->input - (_state)->layout->bindings, ##__VA_ARGS__)
+static bool bhnd_sprom_is_external_immutable(
+ const char *name);
-#define SPROM_COOKIE_TO_NVRAM(_cookie) \
- bhnd_nvram_get_vardefn(((struct sprom_opcode_idx *)_cookie)->vid)
+BHND_NVRAM_DATA_CLASS_DEFN(sprom, "Broadcom SPROM",
+ BHND_NVRAM_DATA_CAP_DEVPATHS, sizeof(struct bhnd_nvram_sprom))
+
+#define SPROM_COOKIE_TO_VID(_cookie) \
+ (((struct bhnd_sprom_opcode_idx_entry *)(_cookie))->vid)
+
+#define SPROM_COOKIE_TO_NVRAM_VAR(_cookie) \
+ bhnd_nvram_get_vardefn(SPROM_COOKIE_TO_VID(_cookie))
/**
* Read the magic value from @p io, and verify that it matches
@@ -118,7 +120,7 @@ static int sprom_opcode_step(struct spro
*/
static int
bhnd_nvram_sprom_check_magic(struct bhnd_nvram_io *io,
- const struct bhnd_sprom_layout *layout, uint16_t *magic)
+ const bhnd_sprom_layout *layout, uint16_t *magic)
{
int error;
@@ -162,7 +164,7 @@ bhnd_nvram_sprom_check_magic(struct bhnd
*/
static int
bhnd_nvram_sprom_ident(struct bhnd_nvram_io *io,
- const struct bhnd_sprom_layout **ident, struct bhnd_nvram_io **shadow)
+ const bhnd_sprom_layout **ident, struct bhnd_nvram_io **shadow)
{
struct bhnd_nvram_io *buf;
uint8_t crc;
@@ -185,13 +187,13 @@ bhnd_nvram_sprom_ident(struct bhnd_nvram
/* We iterate the SPROM layouts smallest to largest, allowing us to
* perform incremental checksum calculation */
for (size_t i = 0; i < bhnd_sprom_num_layouts; i++) {
- const struct bhnd_sprom_layout *layout;
- void *ptr;
- size_t nbytes, nr;
- uint16_t magic;
- uint8_t srev;
- bool crc_valid;
- bool have_magic;
+ const bhnd_sprom_layout *layout;
+ void *ptr;
+ size_t nbytes, nr;
+ uint16_t magic;
+ uint8_t srev;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list