freebsd-dev/sys/dev/bhnd/nvram/bhnd_nvram_data_btxt.c

966 lines
24 KiB
C
Raw Normal View History

bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
/*-
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/endian.h>
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/ctype.h>
#include <sys/malloc.h>
#include <sys/systm.h>
#else /* !_KERNEL */
#include <ctype.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#endif /* _KERNEL */
#include "bhnd_nvram_private.h"
#include "bhnd_nvram_datavar.h"
#include "bhnd_nvram_data_bcmreg.h" /* for BCM_NVRAM_MAGIC */
/**
* Broadcom "Board Text" data class.
*
* This format is used to provide external NVRAM data for some
* fullmac WiFi devices, and as an input format when programming
* NVRAM/SPROM/OTP.
*/
struct bhnd_nvram_btxt {
struct bhnd_nvram_data nv; /**< common instance state */
struct bhnd_nvram_io *data; /**< memory-backed board text data */
size_t count; /**< variable count */
};
BHND_NVRAM_DATA_CLASS_DEFN(btxt, "Broadcom Board Text",
BHND_NVRAM_DATA_CAP_DEVPATHS, sizeof(struct bhnd_nvram_btxt))
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
/** Minimal identification header */
union bhnd_nvram_btxt_ident {
uint32_t bcm_magic;
char btxt[8];
};
static void *bhnd_nvram_btxt_offset_to_cookiep(struct bhnd_nvram_btxt *btxt,
size_t io_offset);
static size_t bhnd_nvram_btxt_cookiep_to_offset(struct bhnd_nvram_btxt *btxt,
void *cookiep);
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
static int bhnd_nvram_btxt_entry_len(struct bhnd_nvram_io *io,
size_t offset, size_t *line_len, size_t *env_len);
static int bhnd_nvram_btxt_seek_next(struct bhnd_nvram_io *io,
size_t *offset);
static int bhnd_nvram_btxt_seek_eol(struct bhnd_nvram_io *io,
size_t *offset);
static int
bhnd_nvram_btxt_probe(struct bhnd_nvram_io *io)
{
union bhnd_nvram_btxt_ident ident;
char c;
int error;
/* Look at the initial header for something that looks like
* an ASCII board text file */
if ((error = bhnd_nvram_io_read(io, 0x0, &ident, sizeof(ident))))
return (error);
/* The BCM NVRAM format uses a 'FLSH' little endian magic value, which
* shouldn't be interpreted as BTXT */
if (le32toh(ident.bcm_magic) == BCM_NVRAM_MAGIC)
return (ENXIO);
/* Don't match on non-ASCII/non-printable data */
for (size_t i = 0; i < nitems(ident.btxt); i++) {
c = ident.btxt[i];
if (!bhnd_nv_isprint(c))
return (ENXIO);
}
/* The first character should either be a valid key char (alpha),
* whitespace, or the start of a comment ('#') */
c = ident.btxt[0];
if (!bhnd_nv_isspace(c) && !bhnd_nv_isalpha(c) && c != '#')
return (ENXIO);
/* We assert a low priority, given that we've only scanned an
* initial few bytes of the file. */
return (BHND_NVRAM_DATA_PROBE_MAYBE);
}
/**
* Parser states for bhnd_nvram_bcm_getvar_direct_common().
*/
typedef enum {
BTXT_PARSE_LINE_START,
BTXT_PARSE_KEY,
BTXT_PARSE_KEY_END,
BTXT_PARSE_NEXT_LINE,
BTXT_PARSE_VALUE_START,
BTXT_PARSE_VALUE
} btxt_parse_state;
static int
bhnd_nvram_btxt_getvar_direct(struct bhnd_nvram_io *io, const char *name,
void *outp, size_t *olen, bhnd_nvram_type otype)
{
char buf[512];
btxt_parse_state pstate;
size_t limit, offset;
size_t buflen, bufpos;
size_t namelen, namepos;
size_t vlen;
int error;
limit = bhnd_nvram_io_getsize(io);
offset = 0;
/* Loop our parser until we find the requested variable, or hit EOF */
pstate = BTXT_PARSE_LINE_START;
buflen = 0;
bufpos = 0;
namelen = strlen(name);
namepos = 0;
vlen = 0;
while ((offset - bufpos) < limit) {
BHND_NV_ASSERT(bufpos <= buflen,
("buf position invalid (%zu > %zu)", bufpos, buflen));
BHND_NV_ASSERT(buflen <= sizeof(buf),
("buf length invalid (%zu > %zu", buflen, sizeof(buf)));
/* Repopulate our parse buffer? */
if (buflen - bufpos == 0) {
BHND_NV_ASSERT(offset < limit, ("offset overrun"));
buflen = bhnd_nv_ummin(sizeof(buf), limit - offset);
bufpos = 0;
error = bhnd_nvram_io_read(io, offset, buf, buflen);
if (error)
return (error);
offset += buflen;
}
switch (pstate) {
case BTXT_PARSE_LINE_START:
BHND_NV_ASSERT(bufpos < buflen, ("empty buffer!"));
/* Reset name matching position */
namepos = 0;
/* Trim any leading whitespace */
while (bufpos < buflen && bhnd_nv_isspace(buf[bufpos]))
{
bufpos++;
}
if (bufpos == buflen) {
/* Continue parsing the line */
pstate = BTXT_PARSE_LINE_START;
} else if (bufpos < buflen && buf[bufpos] == '#') {
/* Comment; skip to next line */
pstate = BTXT_PARSE_NEXT_LINE;
} else {
/* Start name matching */
pstate = BTXT_PARSE_KEY;
}
break;
case BTXT_PARSE_KEY: {
size_t navail, nleft;
nleft = namelen - namepos;
navail = bhnd_nv_ummin(buflen - bufpos, nleft);
if (strncmp(name+namepos, buf+bufpos, navail) == 0) {
/* Matched */
namepos += navail;
bufpos += navail;
if (namepos == namelen) {
/* Matched the full variable; look for
* its trailing delimiter */
pstate = BTXT_PARSE_KEY_END;
} else {
/* Continue matching the name */
pstate = BTXT_PARSE_KEY;
}
} else {
/* No match; advance to next entry and restart
* name matching */
pstate = BTXT_PARSE_NEXT_LINE;
}
break;
}
case BTXT_PARSE_KEY_END:
BHND_NV_ASSERT(bufpos < buflen, ("empty buffer!"));
if (buf[bufpos] == '=') {
/* Key fully matched; advance past '=' and
* parse the value */
bufpos++;
pstate = BTXT_PARSE_VALUE_START;
} else {
/* No match; advance to next line and restart
* name matching */
pstate = BTXT_PARSE_NEXT_LINE;
}
break;
case BTXT_PARSE_NEXT_LINE: {
const char *p;
/* Scan for a '\r', '\n', or '\r\n' terminator */
p = memchr(buf+bufpos, '\n', buflen - bufpos);
if (p == NULL)
p = memchr(buf+bufpos, '\r', buflen - bufpos);
if (p != NULL) {
/* Found entry terminator; restart name
* matching at next line */
pstate = BTXT_PARSE_LINE_START;
bufpos = (p - buf);
} else {
/* Consumed full buffer looking for newline;
* force repopulation of the buffer and
* retry */
pstate = BTXT_PARSE_NEXT_LINE;
bufpos = buflen;
}
break;
}
case BTXT_PARSE_VALUE_START: {
const char *p;
/* Scan for a terminating newline */
p = memchr(buf+bufpos, '\n', buflen - bufpos);
if (p == NULL)
p = memchr(buf+bufpos, '\r', buflen - bufpos);
if (p != NULL) {
/* Found entry terminator; parse the value */
vlen = p - &buf[bufpos];
pstate = BTXT_PARSE_VALUE;
} else if (p == NULL && offset == limit) {
/* Hit EOF without a terminating newline;
* treat the entry as implicitly terminated */
vlen = buflen - bufpos;
pstate = BTXT_PARSE_VALUE;
} else if (p == NULL && bufpos > 0) {
size_t nread;
/* Move existing value data to start of
* buffer */
memmove(buf, buf+bufpos, buflen - bufpos);
buflen = bufpos;
bufpos = 0;
/* Populate full buffer to allow retry of
* value parsing */
nread = bhnd_nv_ummin(sizeof(buf) - buflen,
limit - offset);
error = bhnd_nvram_io_read(io, offset,
buf+buflen, nread);
if (error)
return (error);
offset += nread;
buflen += nread;
} else {
/* Value exceeds our buffer capacity */
BHND_NV_LOG("cannot parse value for '%s' "
"(exceeds %zu byte limit)\n", name,
sizeof(buf));
return (ENXIO);
}
break;
}
case BTXT_PARSE_VALUE:
BHND_NV_ASSERT(vlen <= buflen, ("value buf overrun"));
/* Trim any trailing whitespace */
while (vlen > 0 && bhnd_nv_isspace(buf[bufpos+vlen-1]))
vlen--;
/* Write the value to the caller's buffer */
return (bhnd_nvram_value_coerce(buf+bufpos, vlen,
BHND_NVRAM_TYPE_STRING, outp, olen, otype));
}
}
/* Variable not found */
return (ENOENT);
}
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);
}
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
/**
* Initialize @p btxt with the provided board text data mapped by @p src.
*
* @param btxt A newly allocated data instance.
*/
static int
bhnd_nvram_btxt_init(struct bhnd_nvram_btxt *btxt, struct bhnd_nvram_io *src)
{
const void *ptr;
const char *name, *value;
size_t name_len, value_len;
size_t line_len, env_len;
size_t io_offset, io_size, str_size;
int error;
BHND_NV_ASSERT(btxt->data == NULL, ("btxt data already allocated"));
if ((btxt->data = bhnd_nvram_iobuf_copy(src)) == NULL)
return (ENOMEM);
io_size = bhnd_nvram_io_getsize(btxt->data);
io_offset = 0;
/* Fetch a pointer mapping the entirity of the board text data */
error = bhnd_nvram_io_read_ptr(btxt->data, 0x0, &ptr, io_size, NULL);
if (error)
return (error);
/* Determine the actual size, minus any terminating NUL. We
* parse NUL-terminated C strings, but do not include NUL termination
* in our internal or serialized representations */
str_size = strnlen(ptr, io_size);
/* If the terminating NUL is not found at the end of the buffer,
* this is BCM-RAW or other NUL-delimited NVRAM format. */
if (str_size < io_size && str_size + 1 < io_size)
return (EINVAL);
/* Adjust buffer size to account for NUL termination (if any) */
io_size = str_size;
if ((error = bhnd_nvram_io_setsize(btxt->data, io_size)))
return (error);
/* Process the buffer */
btxt->count = 0;
while (io_offset < io_size) {
const void *envp;
/* Seek to the next key=value entry */
if ((error = bhnd_nvram_btxt_seek_next(btxt->data, &io_offset)))
return (error);
/* Determine the entry and line length */
error = bhnd_nvram_btxt_entry_len(btxt->data, io_offset,
&line_len, &env_len);
if (error)
return (error);
/* EOF? */
if (env_len == 0) {
BHND_NV_ASSERT(io_offset == io_size,
("zero-length record returned from "
"bhnd_nvram_btxt_seek_next()"));
break;
}
/* Fetch a pointer to the line start */
error = bhnd_nvram_io_read_ptr(btxt->data, io_offset, &envp,
env_len, NULL);
if (error)
return (error);
/* Parse the key=value string */
error = bhnd_nvram_parse_env(envp, env_len, '=', &name,
&name_len, &value, &value_len);
if (error) {
return (error);
}
/* Insert a '\0' character, replacing the '=' delimiter and
* allowing us to vend references directly to the variable
* name */
error = bhnd_nvram_io_write(btxt->data, io_offset+name_len,
&(char){'\0'}, 1);
if (error)
return (error);
/* Add to variable count */
btxt->count++;
/* Advance past EOL */
io_offset += line_len;
}
return (0);
}
static int
bhnd_nvram_btxt_new(struct bhnd_nvram_data *nv, struct bhnd_nvram_io *io)
{
struct bhnd_nvram_btxt *btxt;
int error;
/* Allocate and initialize the BTXT data instance */
btxt = (struct bhnd_nvram_btxt *)nv;
/* Parse the BTXT input data and initialize our backing
* data representation */
if ((error = bhnd_nvram_btxt_init(btxt, io))) {
bhnd_nvram_btxt_free(nv);
return (error);
}
return (0);
}
static void
bhnd_nvram_btxt_free(struct bhnd_nvram_data *nv)
{
struct bhnd_nvram_btxt *btxt = (struct bhnd_nvram_btxt *)nv;
if (btxt->data != NULL)
bhnd_nvram_io_free(btxt->data);
}
size_t
bhnd_nvram_btxt_count(struct bhnd_nvram_data *nv)
{
struct bhnd_nvram_btxt *btxt = (struct bhnd_nvram_btxt *)nv;
return (btxt->count);
}
static bhnd_nvram_plist *
bhnd_nvram_btxt_options(struct bhnd_nvram_data *nv)
{
return (NULL);
}
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
static uint32_t
bhnd_nvram_btxt_caps(struct bhnd_nvram_data *nv)
{
return (BHND_NVRAM_DATA_CAP_READ_PTR|BHND_NVRAM_DATA_CAP_DEVPATHS);
}
static void *
bhnd_nvram_btxt_find(struct bhnd_nvram_data *nv, const char *name)
{
return (bhnd_nvram_data_generic_find(nv, name));
}
static const char *
bhnd_nvram_btxt_next(struct bhnd_nvram_data *nv, void **cookiep)
{
struct bhnd_nvram_btxt *btxt;
const void *nptr;
size_t io_offset, io_size;
int error;
btxt = (struct bhnd_nvram_btxt *)nv;
io_size = bhnd_nvram_io_getsize(btxt->data);
if (*cookiep == NULL) {
/* Start search at initial file offset */
io_offset = 0x0;
} else {
/* Start search after the current entry */
io_offset = bhnd_nvram_btxt_cookiep_to_offset(btxt, *cookiep);
/* Scan past the current entry by finding the next newline */
error = bhnd_nvram_btxt_seek_eol(btxt->data, &io_offset);
if (error) {
BHND_NV_LOG("unexpected error in seek_eol(): %d\n",
error);
return (NULL);
}
}
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
/* Already at EOF? */
if (io_offset == io_size)
return (NULL);
/* Seek to the first valid entry, or EOF */
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
if ((error = bhnd_nvram_btxt_seek_next(btxt->data, &io_offset))) {
BHND_NV_LOG("unexpected error in seek_next(): %d\n", error);
return (NULL);
}
/* Hit EOF? */
if (io_offset == io_size)
return (NULL);
/* Provide the new cookie for this offset */
*cookiep = bhnd_nvram_btxt_offset_to_cookiep(btxt, io_offset);
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
/* Fetch the name pointer; it must be at least 1 byte long */
error = bhnd_nvram_io_read_ptr(btxt->data, io_offset, &nptr, 1, NULL);
if (error) {
BHND_NV_LOG("unexpected error in read_ptr(): %d\n", error);
return (NULL);
}
/* Return the name pointer */
return (nptr);
}
static int
bhnd_nvram_btxt_getvar_order(struct bhnd_nvram_data *nv, void *cookiep1,
void *cookiep2)
{
if (cookiep1 < cookiep2)
return (-1);
if (cookiep1 > cookiep2)
return (1);
return (0);
}
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
static int
bhnd_nvram_btxt_getvar(struct bhnd_nvram_data *nv, void *cookiep, void *buf,
size_t *len, bhnd_nvram_type type)
{
return (bhnd_nvram_data_generic_rp_getvar(nv, cookiep, buf, len, type));
}
static int
bhnd_nvram_btxt_copy_val(struct bhnd_nvram_data *nv, void *cookiep,
bhnd_nvram_val **value)
{
return (bhnd_nvram_data_generic_rp_copy_val(nv, cookiep, value));
}
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
const void *
bhnd_nvram_btxt_getvar_ptr(struct bhnd_nvram_data *nv, void *cookiep,
size_t *len, bhnd_nvram_type *type)
{
struct bhnd_nvram_btxt *btxt;
const void *eptr;
const char *vptr;
size_t io_offset, io_size;
size_t line_len, env_len;
int error;
btxt = (struct bhnd_nvram_btxt *)nv;
io_size = bhnd_nvram_io_getsize(btxt->data);
io_offset = bhnd_nvram_btxt_cookiep_to_offset(btxt, cookiep);
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
/* At EOF? */
if (io_offset == io_size)
return (NULL);
/* Determine the entry length */
error = bhnd_nvram_btxt_entry_len(btxt->data, io_offset, &line_len,
&env_len);
if (error) {
BHND_NV_LOG("unexpected error in entry_len(): %d\n", error);
return (NULL);
}
/* Fetch the entry's value pointer and length */
error = bhnd_nvram_io_read_ptr(btxt->data, io_offset, &eptr, env_len,
NULL);
if (error) {
BHND_NV_LOG("unexpected error in read_ptr(): %d\n", error);
return (NULL);
}
error = bhnd_nvram_parse_env(eptr, env_len, '\0', NULL, NULL, &vptr,
len);
if (error) {
BHND_NV_LOG("unexpected error in parse_env(): %d\n", error);
return (NULL);
}
/* Type is always CSTR */
*type = BHND_NVRAM_TYPE_STRING;
return (vptr);
}
static const char *
bhnd_nvram_btxt_getvar_name(struct bhnd_nvram_data *nv, void *cookiep)
{
struct bhnd_nvram_btxt *btxt;
const void *ptr;
size_t io_offset, io_size;
int error;
btxt = (struct bhnd_nvram_btxt *)nv;
io_size = bhnd_nvram_io_getsize(btxt->data);
io_offset = bhnd_nvram_btxt_cookiep_to_offset(btxt, cookiep);
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
/* At EOF? */
if (io_offset == io_size)
BHND_NV_PANIC("invalid cookiep: %p", cookiep);
/* Variable name is found directly at the given offset; trailing
* NUL means we can assume that it's at least 1 byte long */
error = bhnd_nvram_io_read_ptr(btxt->data, io_offset, &ptr, 1, NULL);
if (error)
BHND_NV_PANIC("unexpected error in read_ptr(): %d\n", error);
return (ptr);
}
/**
* Return a cookiep for the given I/O offset.
*/
static void *
bhnd_nvram_btxt_offset_to_cookiep(struct bhnd_nvram_btxt *btxt,
size_t io_offset)
{
const void *ptr;
int error;
BHND_NV_ASSERT(io_offset < bhnd_nvram_io_getsize(btxt->data),
("io_offset %zu out-of-range", io_offset));
BHND_NV_ASSERT(io_offset < UINTPTR_MAX,
("io_offset %#zx exceeds UINTPTR_MAX", io_offset));
error = bhnd_nvram_io_read_ptr(btxt->data, 0x0, &ptr, io_offset, NULL);
if (error)
BHND_NV_PANIC("error mapping offset %zu: %d", io_offset, error);
ptr = (const uint8_t *)ptr + io_offset;
return (__DECONST(void *, ptr));
}
/* Convert a cookiep back to an I/O offset */
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
static size_t
bhnd_nvram_btxt_cookiep_to_offset(struct bhnd_nvram_btxt *btxt, void *cookiep)
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
{
const void *ptr;
intptr_t offset;
size_t io_size;
int error;
BHND_NV_ASSERT(cookiep != NULL, ("null cookiep"));
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
io_size = bhnd_nvram_io_getsize(btxt->data);
error = bhnd_nvram_io_read_ptr(btxt->data, 0x0, &ptr, io_size, NULL);
if (error)
BHND_NV_PANIC("error mapping offset %zu: %d", io_size, error);
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
offset = (const uint8_t *)cookiep - (const uint8_t *)ptr;
BHND_NV_ASSERT(offset >= 0, ("invalid cookiep"));
BHND_NV_ASSERT((uintptr_t)offset < SIZE_MAX, ("cookiep > SIZE_MAX)"));
BHND_NV_ASSERT((uintptr_t)offset <= io_size, ("cookiep > io_size)"));
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
return ((size_t)offset);
bhnd(4): Unify NVRAM/SPROM parsing, implement compact SPROM layout encoding. - Defined an abstract NVRAM I/O API (bhnd_nvram_io), decoupling NVRAM/SPROM parsing from the actual underlying NVRAM data provider (e.g. CFE firmware devices). - Defined an abstract NVRAM data API (bhnd_nvram_data), decoupling higher-level NVRAM operations (indexed lookup, data conversion, etc) from the underlying NVRAM file format parsing/serialization. - Implemented a new high-level bhnd_nvram_store API, providing indexed variable lookup, pending write tracking, etc on top of an arbitrary bhnd_nvram_data instance. - Migrated all bhnd(4) NVRAM device drivers to the common bhnd_nvram_store API. - Implemented a common bhnd_nvram_val API for parsing/encoding NVRAM variable values, including applying format-specific behavior when converting to/from the NVRAM string representations. - Dropped the now unnecessary bhnd_nvram driver, and moved the broadcom/mips-specific CFE NVRAM driver out into sys/mips/broadcom. - Implemented a new nvram_map file format: - Variable definitions are now defined separately from the SPROM layout. This will also allow us to define CIS tuple NVRAM mappings referencing the common NVRAM variable definitions. - Variables can now be defined within arbitrary named groups. - Textual descriptions and help information can be defined inline for both variables and variable groups. - Implemented a new, compact encoding of SPROM image layout offsets. - Source-level (but not build system) support for building the NVRAM file format APIs (bhnd_nvram_io, bhnd_nvram_data, bhnd_nvram_store) as a userspace library. The new compact SPROM image layout encoding is loosely modeled on Apple dyld compressed LINKEDIT symbol binding opcodes; it provides a compact state-machine encoding of the mapping between NVRAM variables and the SPROM image offset, mask, and shift instructions necessary to decode or encode the SPROM variable data. The compact encoding reduces the size of the generated SPROM layout data from roughly 60KB to 3KB. The sequential nature SPROM layout opcode tables also simplify iteration of the SPROM variables, as it's no longer neccessary to iterate the full NVRAM variable definition table, but instead simply scan the SPROM revision's layout opcode table. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D8645
2016-11-26 23:22:32 +00:00
}
/* Determine the entry length and env 'key=value' string length of the entry
* at @p offset */
static int
bhnd_nvram_btxt_entry_len(struct bhnd_nvram_io *io, size_t offset,
size_t *line_len, size_t *env_len)
{
const uint8_t *baseptr, *p;
const void *rbuf;
size_t nbytes;
int error;
/* Fetch read buffer */
if ((error = bhnd_nvram_io_read_ptr(io, offset, &rbuf, 0, &nbytes)))
return (error);
/* Find record termination (EOL, or '#') */
p = rbuf;
baseptr = rbuf;
while ((size_t)(p - baseptr) < nbytes) {
if (*p == '#' || *p == '\n' || *p == '\r')
break;
p++;
}
/* Got line length, now trim any trailing whitespace to determine
* actual env length */
*line_len = p - baseptr;
*env_len = *line_len;
for (size_t i = 0; i < *line_len; i++) {
char c = baseptr[*line_len - i - 1];
if (!bhnd_nv_isspace(c))
break;
*env_len -= 1;
}
return (0);
}
/* Seek past the next line ending (\r, \r\n, or \n) */
static int
bhnd_nvram_btxt_seek_eol(struct bhnd_nvram_io *io, size_t *offset)
{
const uint8_t *baseptr, *p;
const void *rbuf;
size_t nbytes;
int error;
/* Fetch read buffer */
if ((error = bhnd_nvram_io_read_ptr(io, *offset, &rbuf, 0, &nbytes)))
return (error);
baseptr = rbuf;
p = rbuf;
while ((size_t)(p - baseptr) < nbytes) {
char c = *p;
/* Advance to next char. The next position may be EOF, in which
* case a read will be invalid */
p++;
if (c == '\r') {
/* CR, check for optional LF */
if ((size_t)(p - baseptr) < nbytes) {
if (*p == '\n')
p++;
}
break;
} else if (c == '\n') {
break;
}
}
/* Hit newline or EOF */
*offset += (p - baseptr);
return (0);
}
/* Seek to the next valid non-comment line (or EOF) */
static int
bhnd_nvram_btxt_seek_next(struct bhnd_nvram_io *io, size_t *offset)
{
const uint8_t *baseptr, *p;
const void *rbuf;
size_t nbytes;
int error;
/* Fetch read buffer */
if ((error = bhnd_nvram_io_read_ptr(io, *offset, &rbuf, 0, &nbytes)))
return (error);
/* Skip leading whitespace and comments */
baseptr = rbuf;
p = rbuf;
while ((size_t)(p - baseptr) < nbytes) {
char c = *p;
/* Skip whitespace */
if (bhnd_nv_isspace(c)) {
p++;
continue;
}
/* Skip entire comment line */
if (c == '#') {
size_t line_off = *offset + (p - baseptr);
if ((error = bhnd_nvram_btxt_seek_eol(io, &line_off)))
return (error);
p = baseptr + (line_off - *offset);
continue;
}
/* Non-whitespace, non-comment */
break;
}
*offset += (p - baseptr);
return (0);
}
static int
bhnd_nvram_btxt_filter_setvar(struct bhnd_nvram_data *nv, const char *name,
bhnd_nvram_val *value, bhnd_nvram_val **result)
{
bhnd_nvram_val *str;
const char *inp;
bhnd_nvram_type itype;
size_t ilen;
int error;
/* Name (trimmed of any path prefix) must be valid */
if (!bhnd_nvram_validate_name(bhnd_nvram_trim_path_name(name)))
return (EINVAL);
/* Value must be bcm-formatted string */
error = bhnd_nvram_val_convert_new(&str, &bhnd_nvram_val_bcm_string_fmt,
value, BHND_NVRAM_VAL_DYNAMIC);
if (error)
return (error);
/* Value string must not contain our record delimiter character ('\n'),
* or our comment character ('#') */
inp = bhnd_nvram_val_bytes(str, &ilen, &itype);
BHND_NV_ASSERT(itype == BHND_NVRAM_TYPE_STRING, ("non-string value"));
for (size_t i = 0; i < ilen; i++) {
switch (inp[i]) {
case '\n':
case '#':
BHND_NV_LOG("invalid character (%#hhx) in value\n",
inp[i]);
bhnd_nvram_val_release(str);
return (EINVAL);
}
}
/* Success. Transfer result ownership to the caller. */
*result = str;
return (0);
}
static int
bhnd_nvram_btxt_filter_unsetvar(struct bhnd_nvram_data *nv, const char *name)
{
/* We permit deletion of any variable */
return (0);
}