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