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