1 /*- 2 * Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 * 29 */ 30 31 #ifndef _BHND_NVRAM_BHND_NVRAM_STOREVAR_H_ 32 #define _BHND_NVRAM_BHND_NVRAM_STOREVAR_H_ 33 34 #include <sys/types.h> 35 36 #ifndef _KERNEL 37 #include <pthread.h> 38 #endif 39 40 #include "bhnd_nvram_plist.h" 41 42 #include "bhnd_nvram_store.h" 43 44 /** Index is only generated if minimum variable count is met */ 45 #define BHND_NV_IDX_VAR_THRESHOLD 15 46 47 #define BHND_NVSTORE_ROOT_PATH "/" 48 #define BHND_NVSTORE_ROOT_PATH_LEN sizeof(BHND_NVSTORE_ROOT_PATH) 49 50 #define BHND_NVSTORE_GET_FLAG(_value, _flag) \ 51 (((_value) & BHND_NVSTORE_ ## _flag) != 0) 52 #define BHND_NVSTORE_GET_BITS(_value, _field) \ 53 ((_value) & BHND_NVSTORE_ ## _field ## _MASK) 54 55 /* Forward declarations */ 56 typedef struct bhnd_nvstore_name_info bhnd_nvstore_name_info; 57 typedef struct bhnd_nvstore_index bhnd_nvstore_index; 58 typedef struct bhnd_nvstore_path bhnd_nvstore_path; 59 60 typedef struct bhnd_nvstore_alias bhnd_nvstore_alias; 61 62 typedef struct bhnd_nvstore_alias_list bhnd_nvstore_alias_list; 63 typedef struct bhnd_nvstore_update_list bhnd_nvstore_update_list; 64 typedef struct bhnd_nvstore_path_list bhnd_nvstore_path_list; 65 66 LIST_HEAD(bhnd_nvstore_alias_list, bhnd_nvstore_alias); 67 LIST_HEAD(bhnd_nvstore_update_list, bhnd_nvstore_update); 68 LIST_HEAD(bhnd_nvstore_path_list, bhnd_nvstore_path); 69 70 /** 71 * NVRAM store variable entry types. 72 */ 73 typedef enum { 74 BHND_NVSTORE_VAR = 0, /**< simple variable (var=...) */ 75 BHND_NVSTORE_ALIAS_DECL = 1, /**< alias declaration ('devpath0=pci/1/1') */ 76 } bhnd_nvstore_var_type; 77 78 /** 79 * NVRAM path descriptor types. 80 */ 81 typedef enum { 82 BHND_NVSTORE_PATH_STRING = 0, /**< path is a string value */ 83 BHND_NVSTORE_PATH_ALIAS = 1 /**< path is an alias reference */ 84 } bhnd_nvstore_path_type; 85 86 /** 87 * NVRAM variable namespaces. 88 */ 89 typedef enum { 90 BHND_NVSTORE_NAME_INTERNAL = 1, /**< internal namespace. permits 91 use of reserved devpath and 92 alias name prefixes. */ 93 BHND_NVSTORE_NAME_EXTERNAL = 2, /**< external namespace. forbids 94 use of name prefixes used 95 for device path handling */ 96 } bhnd_nvstore_name_type; 97 98 bhnd_nvstore_path *bhnd_nvstore_path_new(const char *path_str, 99 size_t path_len); 100 void bhnd_nvstore_path_free(struct bhnd_nvstore_path *path); 101 102 bhnd_nvstore_index *bhnd_nvstore_index_new(size_t capacity); 103 void bhnd_nvstore_index_free(bhnd_nvstore_index *index); 104 int bhnd_nvstore_index_append(struct bhnd_nvram_store *sc, 105 bhnd_nvstore_index *index, 106 void *cookiep); 107 int bhnd_nvstore_index_prepare( 108 struct bhnd_nvram_store *sc, 109 bhnd_nvstore_index *index); 110 void *bhnd_nvstore_index_lookup(struct bhnd_nvram_store *sc, 111 bhnd_nvstore_index *index, const char *name); 112 113 bhnd_nvstore_path *bhnd_nvstore_get_root_path( 114 struct bhnd_nvram_store *sc); 115 bool bhnd_nvstore_is_root_path(struct bhnd_nvram_store *sc, 116 bhnd_nvstore_path *path); 117 118 void *bhnd_nvstore_path_data_next( 119 struct bhnd_nvram_store *sc, 120 bhnd_nvstore_path *path, void **indexp); 121 void *bhnd_nvstore_path_data_lookup( 122 struct bhnd_nvram_store *sc, 123 bhnd_nvstore_path *path, const char *name); 124 bhnd_nvram_prop *bhnd_nvstore_path_get_update( 125 struct bhnd_nvram_store *sc, 126 bhnd_nvstore_path *path, const char *name); 127 int bhnd_nvstore_path_register_update( 128 struct bhnd_nvram_store *sc, 129 bhnd_nvstore_path *path, const char *name, 130 bhnd_nvram_val *value); 131 132 bhnd_nvstore_alias *bhnd_nvstore_find_alias(struct bhnd_nvram_store *sc, 133 const char *path); 134 bhnd_nvstore_alias *bhnd_nvstore_get_alias(struct bhnd_nvram_store *sc, 135 u_long alias_val); 136 137 bhnd_nvstore_path *bhnd_nvstore_get_path(struct bhnd_nvram_store *sc, 138 const char *path, size_t path_len); 139 bhnd_nvstore_path *bhnd_nvstore_resolve_path_alias( 140 struct bhnd_nvram_store *sc, u_long aval); 141 142 bhnd_nvstore_path *bhnd_nvstore_var_get_path(struct bhnd_nvram_store *sc, 143 bhnd_nvstore_name_info *info); 144 int bhnd_nvstore_var_register_path( 145 struct bhnd_nvram_store *sc, 146 bhnd_nvstore_name_info *info, void *cookiep); 147 148 int bhnd_nvstore_register_path(struct bhnd_nvram_store *sc, 149 const char *path, size_t path_len); 150 int bhnd_nvstore_register_alias( 151 struct bhnd_nvram_store *sc, 152 const bhnd_nvstore_name_info *info, void *cookiep); 153 154 const char *bhnd_nvstore_parse_relpath(const char *parent, 155 const char *child); 156 int bhnd_nvstore_parse_name_info(const char *name, 157 bhnd_nvstore_name_type name_type, 158 uint32_t data_caps, bhnd_nvstore_name_info *info); 159 160 /** 161 * NVRAM variable name descriptor. 162 * 163 * For NVRAM data instances supporting BHND_NVRAM_DATA_CAP_DEVPATHS, the 164 * NVRAM-vended variable name will be in one of four formats: 165 * 166 * - Simple Variable: 167 * 'variable' 168 * - Device Variable: 169 * 'pci/1/1/variable' 170 * - Device Alias Variable: 171 * '0:variable' 172 * - Device Path Alias Definition: 173 * 'devpath0=pci/1/1/variable' 174 * 175 * Device Paths: 176 * 177 * The device path format is device class-specific; the known supported device 178 * classes are: 179 * - sb: BCMA/SIBA SoC core device path. 180 * - pci: PCI device path (and PCIe on some earlier devices). 181 * - pcie: PCIe device path. 182 * - usb: USB device path. 183 * 184 * The device path format is loosely defined as '[class]/[domain]/[bus]/[slot]', 185 * with missing values either assumed to be zero, a value specific to the 186 * device class, or irrelevant to the device class in question. 187 * 188 * Examples: 189 * sb/1 BCMA/SIBA backplane 0, core 1. 190 * pc/1/1 PCMCIA bus 1, slot 1 191 * pci/1/1 PCI/PCIe domain 0, bus 1, device 1 192 * pcie/1/1 PCIe domain 0, bus 1, device 1 193 * usb/0xbd17 USB PID 0xbd17 (VID defaults to Broadcom 0x0a5c) 194 * 195 * Device Path Aliases: 196 * 197 * Device path aliases reduce duplication of device paths in the flash encoding 198 * of NVRAM data; a single devpath[alias]=[devpath] variable entry is defined, 199 * and then later variables may reference the device path via its alias: 200 * devpath1=usb/0xbd17 201 * 1:mcs5gpo0=0x1100 202 * 203 * Alias values are always positive, base 10 integers. 204 */ 205 struct bhnd_nvstore_name_info { 206 const char *name; /**< variable name */ 207 bhnd_nvstore_var_type type; /**< variable type */ 208 bhnd_nvstore_path_type path_type; /**< path type */ 209 210 /** Path information */ 211 union { 212 /* BHND_NVSTORE_PATH_STRING */ 213 struct { 214 const char *value; /**< device path */ 215 size_t value_len; /**< device path length */ 216 } str; 217 218 /** BHND_NVSTORE_PATH_ALIAS */ 219 struct { 220 u_long value; /**< device alias */ 221 } alias; 222 } path; 223 }; 224 225 /** 226 * NVRAM variable index. 227 * 228 * Provides effecient name-based lookup by maintaining an array of cached 229 * cookiep values, sorted lexicographically by relative variable name. 230 */ 231 struct bhnd_nvstore_index { 232 size_t count; /**< entry count */ 233 size_t capacity; /**< entry capacity */ 234 void *cookiep[]; /**< cookiep values */ 235 }; 236 237 /** 238 * NVRAM device path. 239 */ 240 struct bhnd_nvstore_path { 241 char *path_str; /**< canonical path string */ 242 size_t num_vars; /**< per-path count of committed 243 (non-pending) variables */ 244 bhnd_nvstore_index *index; /**< per-path index, or NULL if 245 this is a root path for 246 which the data source 247 may be queried directly. */ 248 bhnd_nvram_plist *pending; /**< pending changes */ 249 250 LIST_ENTRY(bhnd_nvstore_path) np_link; 251 }; 252 253 /** 254 * NVRAM device path alias. 255 */ 256 struct bhnd_nvstore_alias { 257 bhnd_nvstore_path *path; /**< borrowed path reference */ 258 void *cookiep; /**< NVRAM variable's cookiep value */ 259 u_long alias; /**< alias value */ 260 261 LIST_ENTRY(bhnd_nvstore_alias) na_link; 262 }; 263 264 /** bhnd nvram store instance state */ 265 struct bhnd_nvram_store { 266 #ifdef _KERNEL 267 struct mtx mtx; 268 #else 269 pthread_mutex_t mtx; 270 #endif 271 struct bhnd_nvram_data *data; /**< backing data */ 272 uint32_t data_caps; /**< data capability flags */ 273 bhnd_nvram_plist *data_opts; /**< data serialization options */ 274 275 bhnd_nvstore_alias_list aliases[4]; /**< path alias hash table */ 276 size_t num_aliases; /**< alias count */ 277 278 bhnd_nvstore_path *root_path; /**< root path instance */ 279 bhnd_nvstore_path_list paths[4]; /**< path hash table */ 280 size_t num_paths; /**< path count */ 281 }; 282 283 #ifdef _KERNEL 284 285 #define BHND_NVSTORE_LOCK_INIT(sc) \ 286 mtx_init(&(sc)->mtx, "BHND NVRAM store lock", NULL, MTX_DEF) 287 #define BHND_NVSTORE_LOCK(sc) mtx_lock(&(sc)->mtx) 288 #define BHND_NVSTORE_UNLOCK(sc) mtx_unlock(&(sc)->mtx) 289 #define BHND_NVSTORE_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what) 290 #define BHND_NVSTORE_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx) 291 292 #else /* !_KERNEL */ 293 294 #define BHND_NVSTORE_LOCK_INIT(sc) do { \ 295 int error = pthread_mutex_init(&(sc)->mtx, NULL); \ 296 if (error) \ 297 BHND_NV_PANIC("pthread_mutex_init() failed: %d", \ 298 error); \ 299 } while(0) 300 301 #define BHND_NVSTORE_LOCK(sc) pthread_mutex_lock(&(sc)->mtx) 302 #define BHND_NVSTORE_UNLOCK(sc) pthread_mutex_unlock(&(sc)->mtx) 303 #define BHND_NVSTORE_LOCK_DESTROY(sc) pthread_mutex_destroy(&(sc)->mtx) 304 #define BHND_NVSTORE_LOCK_ASSERT(sc, what) 305 306 #endif /* _KERNEL */ 307 308 #endif /* _BHND_NVRAM_BHND_NVRAM_STOREVAR_H_ */ 309