xref: /freebsd/sys/dev/bhnd/nvram/bhnd_nvram_data.c (revision 193d9e768ba63fcfb187cfd17f461f7d41345048)
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 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 
34 #ifdef _KERNEL
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 
39 #include <machine/_inttypes.h>
40 
41 #else /* !_KERNEL */
42 
43 #include <errno.h>
44 #include <stdint.h>
45 #include <stdlib.h>
46 #include <string.h>
47 
48 #endif /* _KERNEL */
49 
50 #include "bhnd_nvram_private.h"
51 #include "bhnd_nvram_io.h"
52 
53 #include "bhnd_nvram_datavar.h"
54 #include "bhnd_nvram_data.h"
55 
56 /**
57  * Return a human-readable description for the given NVRAM data class.
58  *
59  * @param cls The NVRAM class.
60  */
61 const char *
62 bhnd_nvram_data_class_desc(bhnd_nvram_data_class *cls)
63 {
64 	return (cls->desc);
65 }
66 
67 /**
68  * Return the class-level capability flags (@see BHND_NVRAM_DATA_CAP_*) for
69  * of @p cls.
70  *
71  * @param cls The NVRAM class.
72  */
73 uint32_t
74 bhnd_nvram_data_class_caps(bhnd_nvram_data_class *cls)
75 {
76 	return (cls->caps);
77 }
78 
79 /**
80  * Serialize all NVRAM properties in @p plist using @p cls's NVRAM data
81  * format, writing the result to @p outp.
82  *
83  * @param		cls	The NVRAM data class to be used to perform
84  *				serialization.
85  * @param		props	The raw property values to be serialized to
86  *				@p outp, in serialization order.
87  * @param		options	Serialization options for @p cls, or NULL.
88  * @param[out]		outp	On success, the serialed NVRAM data will be
89  *				written to this buffer. This argment may be
90  *				NULL if the value is not desired.
91  * @param[in,out]	olen	The capacity of @p buf. On success, will be set
92  *				to the actual length of the serialized data.
93  *
94  * @retval 0		success
95  *
96  * @retval ENOMEM	If @p outp is non-NULL and a buffer of @p olen is too
97  *			small to hold the serialized data.
98  * @retval EINVAL	If a property value required by @p cls is not found in
99  *			@p plist.
100  * @retval EFTYPE	If a property value in @p plist cannot be represented
101  *			as the data type required by @p cls.
102  * @retval ERANGE	If a property value in @p plist would would overflow
103  *			(or underflow) the data type required by @p cls.
104  * @retval non-zero	If serialization otherwise fails, a regular unix error
105  *			code will be returned.
106  */
107 int
108 bhnd_nvram_data_serialize(bhnd_nvram_data_class *cls,
109     bhnd_nvram_plist *props, bhnd_nvram_plist *options, void *outp,
110     size_t *olen)
111 {
112 	return (cls->op_serialize(cls, props, options, outp, olen));
113 }
114 
115 /**
116  * Probe to see if this NVRAM data class class supports the data mapped by the
117  * given I/O context, returning a BHND_NVRAM_DATA_PROBE probe result.
118  *
119  * @param cls The NVRAM class.
120  * @param io An I/O context mapping the NVRAM data.
121  *
122  * @retval 0 if this is the only possible NVRAM data class for @p io.
123  * @retval negative if the probe succeeds, a negative value should be returned;
124  * the class returning the highest negative value should be selected to handle
125  * NVRAM parsing.
126  * @retval ENXIO If the NVRAM format is not handled by @p cls.
127  * @retval positive if an error occurs during probing, a regular unix error
128  * code should be returned.
129  */
130 int
131 bhnd_nvram_data_probe(bhnd_nvram_data_class *cls, struct bhnd_nvram_io *io)
132 {
133 	return (cls->op_probe(io));
134 }
135 
136 /**
137  * Probe to see if an NVRAM data class in @p classes supports parsing
138  * of the data mapped by @p io, returning the parsed data in @p data.
139  *
140  * The caller is responsible for deallocating the returned instance via
141  * bhnd_nvram_data_release().
142  *
143  * @param[out] data On success, the parsed NVRAM data instance.
144  * @param io An I/O context mapping the NVRAM data to be copied and parsed.
145  * @param classes An array of NVRAM data classes to be probed, or NULL to
146  * probe the default supported set.
147  * @param num_classes The number of NVRAM data classes in @p classes.
148  *
149  * @retval 0 success
150  * @retval ENXIO if no class is found capable of parsing @p io.
151  * @retval non-zero if an error otherwise occurs during allocation,
152  * initialization, or parsing of the NVRAM data, a regular unix error code
153  * will be returned.
154  */
155 int
156 bhnd_nvram_data_probe_classes(struct bhnd_nvram_data **data,
157     struct bhnd_nvram_io *io, bhnd_nvram_data_class *classes[],
158     size_t num_classes)
159 {
160 	bhnd_nvram_data_class	*cls;
161 	int			 error, prio, result;
162 
163 	cls = NULL;
164 	prio = 0;
165 	*data = NULL;
166 
167 	/* If class array is NULL, default to our linker set */
168 	if (classes == NULL) {
169 		classes = SET_BEGIN(bhnd_nvram_data_class_set);
170 		num_classes = SET_COUNT(bhnd_nvram_data_class_set);
171 	}
172 
173 	/* Try to find the best data class capable of parsing io */
174 	for (size_t i = 0; i < num_classes; i++) {
175 		bhnd_nvram_data_class *next_cls;
176 
177 		next_cls = classes[i];
178 
179 		/* Try to probe */
180 		result = bhnd_nvram_data_probe(next_cls, io);
181 
182 		/* The parser did not match if an error was returned */
183 		if (result > 0)
184 			continue;
185 
186 		/* Lower priority than previous match; keep
187 		 * searching */
188 		if (cls != NULL && result <= prio)
189 			continue;
190 
191 		/* Drop any previously parsed data */
192 		if (*data != NULL) {
193 			bhnd_nvram_data_release(*data);
194 			*data = NULL;
195 		}
196 
197 		/* If this is a 'maybe' match, attempt actual parsing to
198 		 * verify that this does in fact match */
199 		if (result <= BHND_NVRAM_DATA_PROBE_MAYBE) {
200 			/* If parsing fails, keep searching */
201 			error = bhnd_nvram_data_new(next_cls, data, io);
202 			if (error)
203 				continue;
204 		}
205 
206 		/* Record best new match */
207 		prio = result;
208 		cls = next_cls;
209 
210 
211 		/* Terminate search immediately on
212 		 * BHND_NVRAM_DATA_PROBE_SPECIFIC */
213 		if (result == BHND_NVRAM_DATA_PROBE_SPECIFIC)
214 			break;
215 	}
216 
217 	/* If no match, return error */
218 	if (cls == NULL)
219 		return (ENXIO);
220 
221 	/* If the NVRAM data was not parsed above, do so now */
222 	if (*data == NULL) {
223 		if ((error = bhnd_nvram_data_new(cls, data, io)))
224 			return (error);
225 	}
226 
227 	return (0);
228 }
229 
230 /**
231  * Allocate and initialize a new instance of data class @p cls, copying and
232  * parsing NVRAM data from @p io.
233  *
234  * The caller is responsible for releasing the returned parser instance
235  * reference via bhnd_nvram_data_release().
236  *
237  * @param cls If non-NULL, the data class to be allocated. If NULL,
238  * bhnd_nvram_data_probe_classes() will be used to determine the data format.
239  * @param[out] nv On success, a pointer to the newly allocated NVRAM data instance.
240  * @param io An I/O context mapping the NVRAM data to be copied and parsed.
241  *
242  * @retval 0 success
243  * @retval non-zero if an error occurs during allocation or initialization, a
244  * regular unix error code will be returned.
245  */
246 int
247 bhnd_nvram_data_new(bhnd_nvram_data_class *cls, struct bhnd_nvram_data **nv,
248     struct bhnd_nvram_io *io)
249 {
250 	struct bhnd_nvram_data	*data;
251 	int			 error;
252 
253 	/* If NULL, try to identify the appropriate class */
254 	if (cls == NULL)
255 		return (bhnd_nvram_data_probe_classes(nv, io, NULL, 0));
256 
257 	/* Allocate new instance */
258 	BHND_NV_ASSERT(sizeof(struct bhnd_nvram_data) <= cls->size,
259 	    ("instance size %zu less than minimum %zu", cls->size,
260 	     sizeof(struct bhnd_nvram_data)));
261 
262 	data = bhnd_nv_calloc(1, cls->size);
263 	data->cls = cls;
264 	refcount_init(&data->refs, 1);
265 
266 	/* Let the class handle initialization */
267 	if ((error = cls->op_new(data, io))) {
268 		bhnd_nv_free(data);
269 		return (error);
270 	}
271 
272 	*nv = data;
273 	return (0);
274 }
275 
276 /**
277  * Retain and return a reference to the given data instance.
278  *
279  * @param nv The reference to be retained.
280  */
281 struct bhnd_nvram_data *
282 bhnd_nvram_data_retain(struct bhnd_nvram_data *nv)
283 {
284 	refcount_acquire(&nv->refs);
285 	return (nv);
286 }
287 
288 /**
289  * Release a reference to the given data instance.
290  *
291  * If this is the last reference, the data instance and its associated
292  * resources will be freed.
293  *
294  * @param nv The reference to be released.
295  */
296 void
297 bhnd_nvram_data_release(struct bhnd_nvram_data *nv)
298 {
299 	if (!refcount_release(&nv->refs))
300 		return;
301 
302 	/* Free any internal resources */
303 	nv->cls->op_free(nv);
304 
305 	/* Free the instance allocation */
306 	bhnd_nv_free(nv);
307 }
308 
309 /**
310  * Return a pointer to @p nv's data class.
311  *
312  * @param nv The NVRAM data instance to be queried.
313  */
314 bhnd_nvram_data_class *
315 bhnd_nvram_data_get_class(struct bhnd_nvram_data *nv)
316 {
317 	return (nv->cls);
318 }
319 
320 /**
321  * Return the number of variables in @p nv.
322  *
323  * @param nv The NVRAM data to be queried.
324  */
325 size_t
326 bhnd_nvram_data_count(struct bhnd_nvram_data *nv)
327 {
328 	return (nv->cls->op_count(nv));
329 }
330 
331 /**
332  * Return a borrowed reference to the serialization options for @p nv,
333  * suitable for use with bhnd_nvram_data_serialize(), or NULL if none.
334  *
335  * @param nv The NVRAM data to be queried.
336  */
337 bhnd_nvram_plist *
338 bhnd_nvram_data_options(struct bhnd_nvram_data *nv)
339 {
340 	return (nv->cls->op_options(nv));
341 }
342 
343 /**
344  * Return the capability flags (@see BHND_NVRAM_DATA_CAP_*) for @p nv.
345  *
346  * @param	nv	The NVRAM data to be queried.
347  */
348 uint32_t
349 bhnd_nvram_data_caps(struct bhnd_nvram_data *nv)
350 {
351 	return (nv->cls->op_caps(nv));
352 }
353 
354 /**
355  * Iterate over @p nv, returning the names of subsequent variables.
356  *
357  * @param		nv	The NVRAM data to be iterated.
358  * @param[in,out]	cookiep	A pointer to a cookiep value previously returned
359  *				by bhnd_nvram_data_next(), or a NULL value to
360  *				begin iteration.
361  *
362  * @return Returns the next variable name, or NULL if there are no more
363  * variables defined in @p nv.
364  */
365 const char *
366 bhnd_nvram_data_next(struct bhnd_nvram_data *nv, void **cookiep)
367 {
368 	const char	*name;
369 #ifdef BHND_NV_INVARIANTS
370 	void		*prev = *cookiep;
371 #endif
372 
373 	/* Fetch next */
374 	if ((name = nv->cls->op_next(nv, cookiep)) == NULL)
375 		return (NULL);
376 
377 	/* Enforce precedence ordering invariant between bhnd_nvram_data_next()
378 	 * and bhnd_nvram_data_getvar_order() */
379 #ifdef BHND_NV_INVARIANTS
380 	if (prev != NULL &&
381 	    bhnd_nvram_data_getvar_order(nv, prev, *cookiep) > 0)
382 	{
383 		BHND_NV_PANIC("%s: returned out-of-order entry", __FUNCTION__);
384 	}
385 #endif
386 
387 	return (name);
388 }
389 
390 /**
391  * Search @p nv for a named variable, returning the variable's opaque reference
392  * if found, or NULL if unavailable.
393  *
394  * The BHND_NVRAM_DATA_CAP_INDEXED capability flag will be returned by
395  * bhnd_nvram_data_caps() if @p nv supports effecient name-based
396  * lookups.
397  *
398  * @param	nv	The NVRAM data to search.
399  * @param	name	The name to search for.
400  *
401  * @retval non-NULL	If @p name is found, the opaque cookie value will be
402  *			returned.
403  * @retval NULL		If @p name is not found.
404  */
405 void *
406 bhnd_nvram_data_find(struct bhnd_nvram_data *nv, const char *name)
407 {
408 	return (nv->cls->op_find(nv, name));
409 }
410 
411 /**
412  * A generic implementation of bhnd_nvram_data_find().
413  *
414  * This implementation will use bhnd_nvram_data_next() to perform a
415  * simple O(n) case-insensitve search for @p name.
416  */
417 void *
418 bhnd_nvram_data_generic_find(struct bhnd_nvram_data *nv, const char *name)
419 {
420 	const char	*next;
421 	void		*cookiep;
422 
423 	cookiep = NULL;
424 	while ((next = bhnd_nvram_data_next(nv, &cookiep))) {
425 		if (strcmp(name, next) == 0)
426 			return (cookiep);
427 	}
428 
429 	/* Not found */
430 	return (NULL);
431 }
432 
433 /**
434  * Compare the declaration order of two NVRAM variables.
435  *
436  * Variable declaration order is used to determine the current order of
437  * the variables in the source data, as well as to determine the precedence
438  * of variable declarations in data sources that define duplicate names.
439  *
440  * The comparison order will match the order of variables returned via
441  * bhnd_nvstore_path_data_next().
442  *
443  * @param		nv		The NVRAM data.
444  * @param		cookiep1	An NVRAM variable cookie previously
445  *					returned via bhnd_nvram_data_next() or
446  *					bhnd_nvram_data_find().
447  * @param		cookiep2	An NVRAM variable cookie previously
448  *					returned via bhnd_nvram_data_next() or
449  *					bhnd_nvram_data_find().
450  *
451  * @retval <= -1	If @p cookiep1 has an earlier declaration order than
452  *			@p cookiep2.
453  * @retval 0		If @p cookiep1 and @p cookiep2 are identical.
454  * @retval >= 1		If @p cookiep has a later declaration order than
455  *			@p cookiep2.
456  */
457 int
458 bhnd_nvram_data_getvar_order(struct bhnd_nvram_data *nv, void *cookiep1,
459     void *cookiep2)
460 {
461 	return (nv->cls->op_getvar_order(nv, cookiep1, cookiep2));
462 }
463 
464 /**
465  * Read a variable and decode as @p type.
466  *
467  * @param		nv	The NVRAM data.
468  * @param		cookiep	An NVRAM variable cookie previously returned
469  *				via bhnd_nvram_data_next() or
470  *				bhnd_nvram_data_find().
471  * @param[out]		buf	On success, the requested value will be written
472  *				to this buffer. This argment may be NULL if
473  *				the value is not desired.
474  * @param[in,out]	len	The capacity of @p buf. On success, will be set
475  *				to the actual size of the requested value.
476  * @param		type	The data type to be written to @p buf.
477  *
478  * @retval 0		success
479  * @retval ENOMEM	If @p buf is non-NULL and a buffer of @p len is too
480  *			small to hold the requested value.
481  * @retval EFTYPE	If the variable data cannot be coerced to @p type.
482  * @retval ERANGE	If value coercion would overflow @p type.
483  */
484 int
485 bhnd_nvram_data_getvar(struct bhnd_nvram_data *nv, void *cookiep, void *buf,
486     size_t *len, bhnd_nvram_type type)
487 {
488 	return (nv->cls->op_getvar(nv, cookiep, buf, len, type));
489 }
490 
491 /*
492  * Common bhnd_nvram_data_getvar_ptr() wrapper used by
493  * bhnd_nvram_data_generic_rp_getvar() and
494  * bhnd_nvram_data_generic_rp_copy_val().
495  *
496  * If a variable definition for the requested variable is found via
497  * bhnd_nvram_find_vardefn(), the definition will be used to populate fmt.
498  */
499 static const void *
500 bhnd_nvram_data_getvar_ptr_info(struct bhnd_nvram_data *nv, void *cookiep,
501     size_t *len, bhnd_nvram_type *type, const bhnd_nvram_val_fmt **fmt)
502 {
503 	const struct bhnd_nvram_vardefn	*vdefn;
504 	const char			*name;
505 	const void			*vptr;
506 
507 	BHND_NV_ASSERT(bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_READ_PTR,
508 	    ("instance does not advertise READ_PTR support"));
509 
510 	/* Fetch pointer to variable data */
511 	vptr = bhnd_nvram_data_getvar_ptr(nv, cookiep, len, type);
512 	if (vptr == NULL)
513 		return (NULL);
514 
515 	/* Select a default value format implementation */
516 
517 
518 	/* Fetch the reference variable name */
519 	name = bhnd_nvram_data_getvar_name(nv, cookiep);
520 
521 	/* Trim path prefix, if any; the Broadcom NVRAM format assumes a global
522 	 * namespace for all variable definitions */
523 	if (bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_DEVPATHS)
524 		name = bhnd_nvram_trim_path_name(name);
525 
526 	/* Check the variable definition table for a matching entry; if
527 	 * it exists, use it to populate the value format. */
528 	vdefn = bhnd_nvram_find_vardefn(name);
529 	if (vdefn != NULL) {
530 		BHND_NV_ASSERT(vdefn->fmt != NULL,
531 		    ("NULL format for %s", name));
532 		*fmt = vdefn->fmt;
533 	} else if (*type == BHND_NVRAM_TYPE_STRING) {
534 		/* Default to Broadcom-specific string interpretation */
535 		*fmt = &bhnd_nvram_val_bcm_string_fmt;
536 	} else {
537 		/* Fall back on native formatting */
538 		*fmt = bhnd_nvram_val_default_fmt(*type);
539 	}
540 
541 	return (vptr);
542 }
543 
544 /**
545  * A generic implementation of bhnd_nvram_data_getvar().
546  *
547  * This implementation will call bhnd_nvram_data_getvar_ptr() to fetch
548  * a pointer to the variable data and perform data coercion on behalf
549  * of the caller.
550  *
551  * If a variable definition for the requested variable is available via
552  * bhnd_nvram_find_vardefn(), the definition will be used to provide a
553  * formatting instance to bhnd_nvram_val_init().
554  */
555 int
556 bhnd_nvram_data_generic_rp_getvar(struct bhnd_nvram_data *nv, void *cookiep,
557     void *outp, size_t *olen, bhnd_nvram_type otype)
558 {
559 	bhnd_nvram_val			 val;
560 	const bhnd_nvram_val_fmt	*fmt;
561 	const void			*vptr;
562 	bhnd_nvram_type			 vtype;
563 	size_t				 vlen;
564 	int				 error;
565 
566 	BHND_NV_ASSERT(bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_READ_PTR,
567 	    ("instance does not advertise READ_PTR support"));
568 
569 	/* Fetch variable data and value format*/
570 	vptr = bhnd_nvram_data_getvar_ptr_info(nv, cookiep, &vlen, &vtype,
571 	    &fmt);
572 	if (vptr == NULL)
573 		return (EINVAL);
574 
575 	/* Attempt value coercion */
576 	error = bhnd_nvram_val_init(&val, fmt, vptr, vlen, vtype,
577 	    BHND_NVRAM_VAL_BORROW_DATA);
578 	if (error)
579 		return (error);
580 
581 	error = bhnd_nvram_val_encode(&val, outp, olen, otype);
582 
583 	/* Clean up */
584 	bhnd_nvram_val_release(&val);
585 	return (error);
586 }
587 
588 /**
589  * Return a caller-owned copy of an NVRAM entry's variable data.
590  *
591  * The caller is responsible for deallocating the returned value via
592  * bhnd_nvram_val_release().
593  *
594  * @param	nv	The NVRAM data.
595  * @param	cookiep	An NVRAM variable cookie previously returned
596  *			via bhnd_nvram_data_next() or bhnd_nvram_data_find().
597  * @param[out]	value	On success, the caller-owned value instance.
598  *
599  * @retval 0		success
600  * @retval ENOMEM	If allocation fails.
601  * @retval non-zero	If initialization of the value otherwise fails, a
602  *			regular unix error code will be returned.
603  */
604 int
605 bhnd_nvram_data_copy_val(struct bhnd_nvram_data *nv, void *cookiep,
606     bhnd_nvram_val **value)
607 {
608 	return (nv->cls->op_copy_val(nv, cookiep, value));
609 }
610 
611 /**
612  * A generic implementation of bhnd_nvram_data_copy_val().
613  *
614  * This implementation will call bhnd_nvram_data_getvar_ptr() to fetch
615  * a pointer to the variable data and perform data coercion on behalf
616  * of the caller.
617  *
618  * If a variable definition for the requested variable is available via
619  * bhnd_nvram_find_vardefn(), the definition will be used to provide a
620  * formatting instance to bhnd_nvram_val_init().
621  */
622 int
623 bhnd_nvram_data_generic_rp_copy_val(struct bhnd_nvram_data *nv,
624     void *cookiep, bhnd_nvram_val **value)
625 {
626 	const bhnd_nvram_val_fmt	*fmt;
627 	const void			*vptr;
628 	bhnd_nvram_type			 vtype;
629 	size_t				 vlen;
630 
631 	BHND_NV_ASSERT(bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_READ_PTR,
632 	    ("instance does not advertise READ_PTR support"));
633 
634 	/* Fetch variable data and value format*/
635 	vptr = bhnd_nvram_data_getvar_ptr_info(nv, cookiep, &vlen, &vtype,
636 	    &fmt);
637 	if (vptr == NULL)
638 		return (EINVAL);
639 
640 	/* Allocate and return the new value instance */
641 	return (bhnd_nvram_val_new(value, fmt, vptr, vlen, vtype,
642 	    BHND_NVRAM_VAL_DYNAMIC));
643 }
644 
645 /**
646  * If available and supported by the NVRAM data instance, return a reference
647  * to the internal buffer containing an entry's variable data,
648  *
649  * Note that string values may not be NUL terminated.
650  *
651  * @param		nv	The NVRAM data.
652  * @param		cookiep	An NVRAM variable cookie previously returned
653  *				via bhnd_nvram_data_next() or
654  *				bhnd_nvram_data_find().
655  * @param[out]		len	On success, will be set to the actual size of
656  *				the requested value.
657  * @param[out]		type	The data type of the entry data.
658  *
659  * @retval non-NULL	success
660  * @retval NULL		if direct data access is unsupported by @p nv, or
661  *			unavailable for @p cookiep.
662  */
663 const void *
664 bhnd_nvram_data_getvar_ptr(struct bhnd_nvram_data *nv, void *cookiep,
665     size_t *len, bhnd_nvram_type *type)
666 {
667 	return (nv->cls->op_getvar_ptr(nv, cookiep, len, type));
668 }
669 
670 
671 /**
672  * Return the variable name associated with a given @p cookiep.
673  * @param		nv	The NVRAM data to be iterated.
674  * @param[in,out]	cookiep	A pointer to a cookiep value previously returned
675  *				via bhnd_nvram_data_next() or
676  *				bhnd_nvram_data_find().
677  *
678  * @return Returns the variable's name.
679  */
680 const char *
681 bhnd_nvram_data_getvar_name(struct bhnd_nvram_data *nv, void *cookiep)
682 {
683 	return (nv->cls->op_getvar_name(nv, cookiep));
684 }
685 
686 /**
687  * Filter a request to set variable @p name with @p value.
688  *
689  * On success, the caller owns a reference to @p result, and must release
690  * any held resources via bhnd_nvram_val_release().
691  *
692  * @param	nv	The NVRAM data instance.
693  * @param	name	The name of the variable to be set.
694  * @param	value	The proposed value to be set.
695  * @param[out]	result	On success, a caller-owned reference to the filtered
696  *			value to be set.
697  *
698  * @retval	0	success
699  * @retval	ENOENT	if @p name is unrecognized by @p nv.
700  * @retval	EINVAL	if @p name is read-only.
701  * @retval	EINVAL	if @p value cannot be converted to the required value
702  *			type.
703  */
704 int
705 bhnd_nvram_data_filter_setvar(struct bhnd_nvram_data *nv, const char *name,
706     bhnd_nvram_val *value, bhnd_nvram_val **result)
707 {
708 	return (nv->cls->op_filter_setvar(nv, name, value, result));
709 }
710 
711 /**
712  * Filter a request to delete variable @p name.
713  *
714  * @param	nv	The NVRAM data instance.
715  * @param	name	The name of the variable to be deleted.
716  *
717  * @retval	0	success
718  * @retval	ENOENT	if @p name is unrecognized by @p nv.
719  * @retval	EINVAL	if @p name is read-only.
720  */
721 int
722 bhnd_nvram_data_filter_unsetvar(struct bhnd_nvram_data *nv, const char *name)
723 {
724 	return (nv->cls->op_filter_unsetvar(nv, name));
725 }
726