freebsd-dev/sys/dev/bhnd/nvram/bhnd_nvram_storevar.h
Landon J. Fuller a7c43ebd55 bhnd(4): Add support for exporting all (or a subtree) of NVRAM
properties backed by an NVRAM store.

This will be used to support:

- Serializing the current NVRAM state for writing back to flash.
- Exporting subsidiary device paths for serialization and upload to fullmac
  chipsets.

Additionally, this includes an improvement to BCM-RAW format detection
to avoid matching on BCM-TEXT NVRAM data.

Approved by:	adrian (mentor)
Differential Revision:	https://reviews.freebsd.org/D8761
2016-12-19 20:31:27 +00:00

310 lines
10 KiB
C

/*-
* Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
* redistribution must be conditioned upon including a substantially
* similar Disclaimer requirement for further binary redistribution.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
* $FreeBSD$
*/
#ifndef _BHND_NVRAM_BHND_NVRAM_STOREVAR_H_
#define _BHND_NVRAM_BHND_NVRAM_STOREVAR_H_
#include <sys/types.h>
#ifndef _KERNEL
#include <pthread.h>
#endif
#include "bhnd_nvram_plist.h"
#include "bhnd_nvram_store.h"
/** Index is only generated if minimum variable count is met */
#define BHND_NV_IDX_VAR_THRESHOLD 15
#define BHND_NVSTORE_ROOT_PATH "/"
#define BHND_NVSTORE_ROOT_PATH_LEN sizeof(BHND_NVSTORE_ROOT_PATH)
#define BHND_NVSTORE_GET_FLAG(_value, _flag) \
(((_value) & BHND_NVSTORE_ ## _flag) != 0)
#define BHND_NVSTORE_GET_BITS(_value, _field) \
((_value) & BHND_NVSTORE_ ## _field ## _MASK)
/* Forward declarations */
typedef struct bhnd_nvstore_name_info bhnd_nvstore_name_info;
typedef struct bhnd_nvstore_index bhnd_nvstore_index;
typedef struct bhnd_nvstore_path bhnd_nvstore_path;
typedef struct bhnd_nvstore_alias bhnd_nvstore_alias;
typedef struct bhnd_nvstore_alias_list bhnd_nvstore_alias_list;
typedef struct bhnd_nvstore_update_list bhnd_nvstore_update_list;
typedef struct bhnd_nvstore_path_list bhnd_nvstore_path_list;
LIST_HEAD(bhnd_nvstore_alias_list, bhnd_nvstore_alias);
LIST_HEAD(bhnd_nvstore_update_list, bhnd_nvstore_update);
LIST_HEAD(bhnd_nvstore_path_list, bhnd_nvstore_path);
/**
* NVRAM store variable entry types.
*/
typedef enum {
BHND_NVSTORE_VAR = 0, /**< simple variable (var=...) */
BHND_NVSTORE_ALIAS_DECL = 1, /**< alias declaration ('devpath0=pci/1/1') */
} bhnd_nvstore_var_type;
/**
* NVRAM path descriptor types.
*/
typedef enum {
BHND_NVSTORE_PATH_STRING = 0, /**< path is a string value */
BHND_NVSTORE_PATH_ALIAS = 1 /**< path is an alias reference */
} bhnd_nvstore_path_type;
/**
* NVRAM variable namespaces.
*/
typedef enum {
BHND_NVSTORE_NAME_INTERNAL = 1, /**< internal namespace. permits
use of reserved devpath and
alias name prefixes. */
BHND_NVSTORE_NAME_EXTERNAL = 2, /**< external namespace. forbids
use of name prefixes used
for device path handling */
} bhnd_nvstore_name_type;
bhnd_nvstore_path *bhnd_nvstore_path_new(const char *path_str,
size_t path_len);
void bhnd_nvstore_path_free(struct bhnd_nvstore_path *path);
bhnd_nvstore_index *bhnd_nvstore_index_new(size_t capacity);
void bhnd_nvstore_index_free(bhnd_nvstore_index *index);
int bhnd_nvstore_index_append(struct bhnd_nvram_store *sc,
bhnd_nvstore_index *index,
void *cookiep);
int bhnd_nvstore_index_prepare(
struct bhnd_nvram_store *sc,
bhnd_nvstore_index *index);
void *bhnd_nvstore_index_lookup(struct bhnd_nvram_store *sc,
bhnd_nvstore_index *index, const char *name);
bhnd_nvstore_path *bhnd_nvstore_get_root_path(
struct bhnd_nvram_store *sc);
bool bhnd_nvstore_is_root_path(struct bhnd_nvram_store *sc,
bhnd_nvstore_path *path);
void *bhnd_nvstore_path_data_next(
struct bhnd_nvram_store *sc,
bhnd_nvstore_path *path, void **indexp);
void *bhnd_nvstore_path_data_lookup(
struct bhnd_nvram_store *sc,
bhnd_nvstore_path *path, const char *name);
bhnd_nvram_prop *bhnd_nvstore_path_get_update(
struct bhnd_nvram_store *sc,
bhnd_nvstore_path *path, const char *name);
int bhnd_nvstore_path_register_update(
struct bhnd_nvram_store *sc,
bhnd_nvstore_path *path, const char *name,
bhnd_nvram_val *value);
bhnd_nvstore_alias *bhnd_nvstore_find_alias(struct bhnd_nvram_store *sc,
const char *path);
bhnd_nvstore_alias *bhnd_nvstore_get_alias(struct bhnd_nvram_store *sc,
u_long alias_val);
bhnd_nvstore_path *bhnd_nvstore_get_path(struct bhnd_nvram_store *sc,
const char *path, size_t path_len);
bhnd_nvstore_path *bhnd_nvstore_resolve_path_alias(
struct bhnd_nvram_store *sc, u_long aval);
bhnd_nvstore_path *bhnd_nvstore_var_get_path(struct bhnd_nvram_store *sc,
bhnd_nvstore_name_info *info);
int bhnd_nvstore_var_register_path(
struct bhnd_nvram_store *sc,
bhnd_nvstore_name_info *info, void *cookiep);
int bhnd_nvstore_register_path(struct bhnd_nvram_store *sc,
const char *path, size_t path_len);
int bhnd_nvstore_register_alias(
struct bhnd_nvram_store *sc,
const bhnd_nvstore_name_info *info, void *cookiep);
const char *bhnd_nvstore_parse_relpath(const char *parent,
const char *child);
int bhnd_nvstore_parse_name_info(const char *name,
bhnd_nvstore_name_type name_type,
uint32_t data_caps, bhnd_nvstore_name_info *info);
/**
* NVRAM variable name descriptor.
*
* For NVRAM data instances supporting BHND_NVRAM_DATA_CAP_DEVPATHS, the
* NVRAM-vended variable name will be in one of four formats:
*
* - Simple Variable:
* 'variable'
* - Device Variable:
* 'pci/1/1/variable'
* - Device Alias Variable:
* '0:variable'
* - Device Path Alias Definition:
* 'devpath0=pci/1/1/variable'
*
* Device Paths:
*
* The device path format is device class-specific; the known supported device
* classes are:
* - sb: BCMA/SIBA SoC core device path.
* - pci: PCI device path (and PCIe on some earlier devices).
* - pcie: PCIe device path.
* - usb: USB device path.
*
* The device path format is loosely defined as '[class]/[domain]/[bus]/[slot]',
* with missing values either assumed to be zero, a value specific to the
* device class, or irrelevant to the device class in question.
*
* Examples:
* sb/1 BCMA/SIBA backplane 0, core 1.
* pc/1/1 PCMCIA bus 1, slot 1
* pci/1/1 PCI/PCIe domain 0, bus 1, device 1
* pcie/1/1 PCIe domain 0, bus 1, device 1
* usb/0xbd17 USB PID 0xbd17 (VID defaults to Broadcom 0x0a5c)
*
* Device Path Aliases:
*
* Device path aliases reduce duplication of device paths in the flash encoding
* of NVRAM data; a single devpath[alias]=[devpath] variable entry is defined,
* and then later variables may reference the device path via its alias:
* devpath1=usb/0xbd17
* 1:mcs5gpo0=0x1100
*
* Alias values are always positive, base 10 integers.
*/
struct bhnd_nvstore_name_info {
const char *name; /**< variable name */
bhnd_nvstore_var_type type; /**< variable type */
bhnd_nvstore_path_type path_type; /**< path type */
/** Path information */
union {
/* BHND_NVSTORE_PATH_STRING */
struct {
const char *value; /**< device path */
size_t value_len; /**< device path length */
} str;
/** BHND_NVSTORE_PATH_ALIAS */
struct {
u_long value; /**< device alias */
} alias;
} path;
};
/**
* NVRAM variable index.
*
* Provides effecient name-based lookup by maintaining an array of cached
* cookiep values, sorted lexicographically by relative variable name.
*/
struct bhnd_nvstore_index {
size_t count; /**< entry count */
size_t capacity; /**< entry capacity */
void *cookiep[]; /**< cookiep values */
};
/**
* NVRAM device path.
*/
struct bhnd_nvstore_path {
char *path_str; /**< canonical path string */
size_t num_vars; /**< per-path count of committed
(non-pending) variables */
bhnd_nvstore_index *index; /**< per-path index, or NULL if
this is a root path for
which the data source
may be queried directly. */
bhnd_nvram_plist *pending; /**< pending changes */
LIST_ENTRY(bhnd_nvstore_path) np_link;
};
/**
* NVRAM device path alias.
*/
struct bhnd_nvstore_alias {
bhnd_nvstore_path *path; /**< borrowed path reference */
void *cookiep; /**< NVRAM variable's cookiep value */
u_long alias; /**< alias value */
LIST_ENTRY(bhnd_nvstore_alias) na_link;
};
/** bhnd nvram store instance state */
struct bhnd_nvram_store {
#ifdef _KERNEL
struct mtx mtx;
#else
pthread_mutex_t mtx;
#endif
struct bhnd_nvram_data *data; /**< backing data */
uint32_t data_caps; /**< data capability flags */
bhnd_nvram_plist *data_opts; /**< data serialization options */
bhnd_nvstore_alias_list aliases[4]; /**< path alias hash table */
size_t num_aliases; /**< alias count */
bhnd_nvstore_path *root_path; /**< root path instance */
bhnd_nvstore_path_list paths[4]; /**< path hash table */
size_t num_paths; /**< path count */
};
#ifdef _KERNEL
#define BHND_NVSTORE_LOCK_INIT(sc) \
mtx_init(&(sc)->mtx, "BHND NVRAM store lock", NULL, MTX_DEF)
#define BHND_NVSTORE_LOCK(sc) mtx_lock(&(sc)->mtx)
#define BHND_NVSTORE_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
#define BHND_NVSTORE_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what)
#define BHND_NVSTORE_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx)
#else /* !_KERNEL */
#define BHND_NVSTORE_LOCK_INIT(sc) do { \
int error = pthread_mutex_init(&(sc)->mtx, NULL); \
if (error) \
BHND_NV_PANIC("pthread_mutex_init() failed: %d", \
error); \
} while(0)
#define BHND_NVSTORE_LOCK(sc) pthread_mutex_lock(&(sc)->mtx)
#define BHND_NVSTORE_UNLOCK(sc) pthread_mutex_unlock(&(sc)->mtx)
#define BHND_NVSTORE_LOCK_DESTROY(sc) pthread_mutex_destroy(&(sc)->mtx)
#define BHND_NVSTORE_LOCK_ASSERT(sc, what)
#endif /* _KERNEL */
#endif /* _BHND_NVRAM_BHND_NVRAM_STOREVAR_H_ */