xref: /freebsd/sys/dev/bhnd/nvram/bhnd_nvram_data.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
177cb4d3eSLandon J. Fuller /*-
277cb4d3eSLandon J. Fuller  * Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
377cb4d3eSLandon J. Fuller  * All rights reserved.
477cb4d3eSLandon J. Fuller  *
577cb4d3eSLandon J. Fuller  * Redistribution and use in source and binary forms, with or without
677cb4d3eSLandon J. Fuller  * modification, are permitted provided that the following conditions
777cb4d3eSLandon J. Fuller  * are met:
877cb4d3eSLandon J. Fuller  * 1. Redistributions of source code must retain the above copyright
977cb4d3eSLandon J. Fuller  *    notice, this list of conditions and the following disclaimer,
1077cb4d3eSLandon J. Fuller  *    without modification.
1177cb4d3eSLandon J. Fuller  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1277cb4d3eSLandon J. Fuller  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
1377cb4d3eSLandon J. Fuller  *    redistribution must be conditioned upon including a substantially
1477cb4d3eSLandon J. Fuller  *    similar Disclaimer requirement for further binary redistribution.
1577cb4d3eSLandon J. Fuller  *
1677cb4d3eSLandon J. Fuller  * NO WARRANTY
1777cb4d3eSLandon J. Fuller  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1877cb4d3eSLandon J. Fuller  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1977cb4d3eSLandon J. Fuller  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
2077cb4d3eSLandon J. Fuller  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
2177cb4d3eSLandon J. Fuller  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
2277cb4d3eSLandon J. Fuller  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2377cb4d3eSLandon J. Fuller  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2477cb4d3eSLandon J. Fuller  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2577cb4d3eSLandon J. Fuller  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2677cb4d3eSLandon J. Fuller  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2777cb4d3eSLandon J. Fuller  * THE POSSIBILITY OF SUCH DAMAGES.
2877cb4d3eSLandon J. Fuller  */
2977cb4d3eSLandon J. Fuller 
3077cb4d3eSLandon J. Fuller #include <sys/cdefs.h>
3177cb4d3eSLandon J. Fuller #ifdef _KERNEL
3277cb4d3eSLandon J. Fuller 
3377cb4d3eSLandon J. Fuller #include <sys/param.h>
3477cb4d3eSLandon J. Fuller #include <sys/systm.h>
3577cb4d3eSLandon J. Fuller 
3677cb4d3eSLandon J. Fuller #include <machine/_inttypes.h>
3777cb4d3eSLandon J. Fuller 
3877cb4d3eSLandon J. Fuller #else /* !_KERNEL */
3977cb4d3eSLandon J. Fuller 
4077cb4d3eSLandon J. Fuller #include <errno.h>
4177cb4d3eSLandon J. Fuller #include <stdint.h>
4277cb4d3eSLandon J. Fuller #include <stdlib.h>
4377cb4d3eSLandon J. Fuller #include <string.h>
4477cb4d3eSLandon J. Fuller 
4577cb4d3eSLandon J. Fuller #endif /* _KERNEL */
4677cb4d3eSLandon J. Fuller 
4777cb4d3eSLandon J. Fuller #include "bhnd_nvram_private.h"
4877cb4d3eSLandon J. Fuller #include "bhnd_nvram_io.h"
4977cb4d3eSLandon J. Fuller 
5077cb4d3eSLandon J. Fuller #include "bhnd_nvram_datavar.h"
5177cb4d3eSLandon J. Fuller #include "bhnd_nvram_data.h"
5277cb4d3eSLandon J. Fuller 
5377cb4d3eSLandon J. Fuller /**
5477cb4d3eSLandon J. Fuller  * Return a human-readable description for the given NVRAM data class.
5577cb4d3eSLandon J. Fuller  *
5677cb4d3eSLandon J. Fuller  * @param cls The NVRAM class.
5777cb4d3eSLandon J. Fuller  */
5877cb4d3eSLandon J. Fuller const char *
bhnd_nvram_data_class_desc(bhnd_nvram_data_class * cls)5958efe686SLandon J. Fuller bhnd_nvram_data_class_desc(bhnd_nvram_data_class *cls)
6077cb4d3eSLandon J. Fuller {
6177cb4d3eSLandon J. Fuller 	return (cls->desc);
6277cb4d3eSLandon J. Fuller }
6377cb4d3eSLandon J. Fuller 
6477cb4d3eSLandon J. Fuller /**
65c283839dSLandon J. Fuller  * Return the class-level capability flags (@see BHND_NVRAM_DATA_CAP_*) for
66c283839dSLandon J. Fuller  * of @p cls.
67c283839dSLandon J. Fuller  *
68c283839dSLandon J. Fuller  * @param cls The NVRAM class.
69c283839dSLandon J. Fuller  */
70c283839dSLandon J. Fuller uint32_t
bhnd_nvram_data_class_caps(bhnd_nvram_data_class * cls)71c283839dSLandon J. Fuller bhnd_nvram_data_class_caps(bhnd_nvram_data_class *cls)
72c283839dSLandon J. Fuller {
73c283839dSLandon J. Fuller 	return (cls->caps);
74c283839dSLandon J. Fuller }
75c283839dSLandon J. Fuller 
76c283839dSLandon J. Fuller /**
77c283839dSLandon J. Fuller  * Serialize all NVRAM properties in @p plist using @p cls's NVRAM data
78c283839dSLandon J. Fuller  * format, writing the result to @p outp.
79c283839dSLandon J. Fuller  *
80c283839dSLandon J. Fuller  * @param		cls	The NVRAM data class to be used to perform
81c283839dSLandon J. Fuller  *				serialization.
82c283839dSLandon J. Fuller  * @param		props	The raw property values to be serialized to
83c283839dSLandon J. Fuller  *				@p outp, in serialization order.
84c283839dSLandon J. Fuller  * @param		options	Serialization options for @p cls, or NULL.
85c283839dSLandon J. Fuller  * @param[out]		outp	On success, the serialed NVRAM data will be
86c283839dSLandon J. Fuller  *				written to this buffer. This argment may be
87c283839dSLandon J. Fuller  *				NULL if the value is not desired.
88c283839dSLandon J. Fuller  * @param[in,out]	olen	The capacity of @p buf. On success, will be set
89c283839dSLandon J. Fuller  *				to the actual length of the serialized data.
90c283839dSLandon J. Fuller  *
91c283839dSLandon J. Fuller  * @retval 0		success
92c283839dSLandon J. Fuller  *
93c283839dSLandon J. Fuller  * @retval ENOMEM	If @p outp is non-NULL and a buffer of @p olen is too
94c283839dSLandon J. Fuller  *			small to hold the serialized data.
95c283839dSLandon J. Fuller  * @retval EINVAL	If a property value required by @p cls is not found in
96c283839dSLandon J. Fuller  *			@p plist.
97c283839dSLandon J. Fuller  * @retval EFTYPE	If a property value in @p plist cannot be represented
98c283839dSLandon J. Fuller  *			as the data type required by @p cls.
99c283839dSLandon J. Fuller  * @retval ERANGE	If a property value in @p plist would would overflow
100c283839dSLandon J. Fuller  *			(or underflow) the data type required by @p cls.
101c283839dSLandon J. Fuller  * @retval non-zero	If serialization otherwise fails, a regular unix error
102c283839dSLandon J. Fuller  *			code will be returned.
103c283839dSLandon J. Fuller  */
104c283839dSLandon J. Fuller int
bhnd_nvram_data_serialize(bhnd_nvram_data_class * cls,bhnd_nvram_plist * props,bhnd_nvram_plist * options,void * outp,size_t * olen)105c283839dSLandon J. Fuller bhnd_nvram_data_serialize(bhnd_nvram_data_class *cls,
106c283839dSLandon J. Fuller     bhnd_nvram_plist *props, bhnd_nvram_plist *options, void *outp,
107c283839dSLandon J. Fuller     size_t *olen)
108c283839dSLandon J. Fuller {
109c283839dSLandon J. Fuller 	return (cls->op_serialize(cls, props, options, outp, olen));
110c283839dSLandon J. Fuller }
111c283839dSLandon J. Fuller 
112c283839dSLandon J. Fuller /**
11377cb4d3eSLandon J. Fuller  * Probe to see if this NVRAM data class class supports the data mapped by the
11477cb4d3eSLandon J. Fuller  * given I/O context, returning a BHND_NVRAM_DATA_PROBE probe result.
11577cb4d3eSLandon J. Fuller  *
11677cb4d3eSLandon J. Fuller  * @param cls The NVRAM class.
11777cb4d3eSLandon J. Fuller  * @param io An I/O context mapping the NVRAM data.
11877cb4d3eSLandon J. Fuller  *
11977cb4d3eSLandon J. Fuller  * @retval 0 if this is the only possible NVRAM data class for @p io.
12077cb4d3eSLandon J. Fuller  * @retval negative if the probe succeeds, a negative value should be returned;
12177cb4d3eSLandon J. Fuller  * the class returning the highest negative value should be selected to handle
12277cb4d3eSLandon J. Fuller  * NVRAM parsing.
12377cb4d3eSLandon J. Fuller  * @retval ENXIO If the NVRAM format is not handled by @p cls.
12477cb4d3eSLandon J. Fuller  * @retval positive if an error occurs during probing, a regular unix error
12577cb4d3eSLandon J. Fuller  * code should be returned.
12677cb4d3eSLandon J. Fuller  */
12777cb4d3eSLandon J. Fuller int
bhnd_nvram_data_probe(bhnd_nvram_data_class * cls,struct bhnd_nvram_io * io)12858efe686SLandon J. Fuller bhnd_nvram_data_probe(bhnd_nvram_data_class *cls, struct bhnd_nvram_io *io)
12977cb4d3eSLandon J. Fuller {
13077cb4d3eSLandon J. Fuller 	return (cls->op_probe(io));
13177cb4d3eSLandon J. Fuller }
13277cb4d3eSLandon J. Fuller 
13377cb4d3eSLandon J. Fuller /**
13477cb4d3eSLandon J. Fuller  * Probe to see if an NVRAM data class in @p classes supports parsing
13577cb4d3eSLandon J. Fuller  * of the data mapped by @p io, returning the parsed data in @p data.
13677cb4d3eSLandon J. Fuller  *
13777cb4d3eSLandon J. Fuller  * The caller is responsible for deallocating the returned instance via
13877cb4d3eSLandon J. Fuller  * bhnd_nvram_data_release().
13977cb4d3eSLandon J. Fuller  *
14077cb4d3eSLandon J. Fuller  * @param[out] data On success, the parsed NVRAM data instance.
14177cb4d3eSLandon J. Fuller  * @param io An I/O context mapping the NVRAM data to be copied and parsed.
14277cb4d3eSLandon J. Fuller  * @param classes An array of NVRAM data classes to be probed, or NULL to
14377cb4d3eSLandon J. Fuller  * probe the default supported set.
14477cb4d3eSLandon J. Fuller  * @param num_classes The number of NVRAM data classes in @p classes.
14577cb4d3eSLandon J. Fuller  *
14677cb4d3eSLandon J. Fuller  * @retval 0 success
14777cb4d3eSLandon J. Fuller  * @retval ENXIO if no class is found capable of parsing @p io.
14877cb4d3eSLandon J. Fuller  * @retval non-zero if an error otherwise occurs during allocation,
14977cb4d3eSLandon J. Fuller  * initialization, or parsing of the NVRAM data, a regular unix error code
15077cb4d3eSLandon J. Fuller  * will be returned.
15177cb4d3eSLandon J. Fuller  */
15277cb4d3eSLandon J. Fuller int
bhnd_nvram_data_probe_classes(struct bhnd_nvram_data ** data,struct bhnd_nvram_io * io,bhnd_nvram_data_class * classes[],size_t num_classes)15377cb4d3eSLandon J. Fuller bhnd_nvram_data_probe_classes(struct bhnd_nvram_data **data,
15458efe686SLandon J. Fuller     struct bhnd_nvram_io *io, bhnd_nvram_data_class *classes[],
15577cb4d3eSLandon J. Fuller     size_t num_classes)
15677cb4d3eSLandon J. Fuller {
15758efe686SLandon J. Fuller 	bhnd_nvram_data_class	*cls;
15877cb4d3eSLandon J. Fuller 	int			 error, prio, result;
15977cb4d3eSLandon J. Fuller 
16077cb4d3eSLandon J. Fuller 	cls = NULL;
16177cb4d3eSLandon J. Fuller 	prio = 0;
16277cb4d3eSLandon J. Fuller 	*data = NULL;
16377cb4d3eSLandon J. Fuller 
16477cb4d3eSLandon J. Fuller 	/* If class array is NULL, default to our linker set */
16577cb4d3eSLandon J. Fuller 	if (classes == NULL) {
16677cb4d3eSLandon J. Fuller 		classes = SET_BEGIN(bhnd_nvram_data_class_set);
16777cb4d3eSLandon J. Fuller 		num_classes = SET_COUNT(bhnd_nvram_data_class_set);
16877cb4d3eSLandon J. Fuller 	}
16977cb4d3eSLandon J. Fuller 
17077cb4d3eSLandon J. Fuller 	/* Try to find the best data class capable of parsing io */
17177cb4d3eSLandon J. Fuller 	for (size_t i = 0; i < num_classes; i++) {
17258efe686SLandon J. Fuller 		bhnd_nvram_data_class *next_cls;
17377cb4d3eSLandon J. Fuller 
17477cb4d3eSLandon J. Fuller 		next_cls = classes[i];
17577cb4d3eSLandon J. Fuller 
17677cb4d3eSLandon J. Fuller 		/* Try to probe */
17777cb4d3eSLandon J. Fuller 		result = bhnd_nvram_data_probe(next_cls, io);
17877cb4d3eSLandon J. Fuller 
17977cb4d3eSLandon J. Fuller 		/* The parser did not match if an error was returned */
18077cb4d3eSLandon J. Fuller 		if (result > 0)
18177cb4d3eSLandon J. Fuller 			continue;
18277cb4d3eSLandon J. Fuller 
18377cb4d3eSLandon J. Fuller 		/* Lower priority than previous match; keep
18477cb4d3eSLandon J. Fuller 		 * searching */
18577cb4d3eSLandon J. Fuller 		if (cls != NULL && result <= prio)
18677cb4d3eSLandon J. Fuller 			continue;
18777cb4d3eSLandon J. Fuller 
18877cb4d3eSLandon J. Fuller 		/* Drop any previously parsed data */
18977cb4d3eSLandon J. Fuller 		if (*data != NULL) {
19077cb4d3eSLandon J. Fuller 			bhnd_nvram_data_release(*data);
19177cb4d3eSLandon J. Fuller 			*data = NULL;
19277cb4d3eSLandon J. Fuller 		}
19377cb4d3eSLandon J. Fuller 
19477cb4d3eSLandon J. Fuller 		/* If this is a 'maybe' match, attempt actual parsing to
19577cb4d3eSLandon J. Fuller 		 * verify that this does in fact match */
19677cb4d3eSLandon J. Fuller 		if (result <= BHND_NVRAM_DATA_PROBE_MAYBE) {
19777cb4d3eSLandon J. Fuller 			/* If parsing fails, keep searching */
19877cb4d3eSLandon J. Fuller 			error = bhnd_nvram_data_new(next_cls, data, io);
19977cb4d3eSLandon J. Fuller 			if (error)
20077cb4d3eSLandon J. Fuller 				continue;
20177cb4d3eSLandon J. Fuller 		}
20277cb4d3eSLandon J. Fuller 
20377cb4d3eSLandon J. Fuller 		/* Record best new match */
20477cb4d3eSLandon J. Fuller 		prio = result;
20577cb4d3eSLandon J. Fuller 		cls = next_cls;
20677cb4d3eSLandon J. Fuller 
20777cb4d3eSLandon J. Fuller 		/* Terminate search immediately on
20877cb4d3eSLandon J. Fuller 		 * BHND_NVRAM_DATA_PROBE_SPECIFIC */
20977cb4d3eSLandon J. Fuller 		if (result == BHND_NVRAM_DATA_PROBE_SPECIFIC)
21077cb4d3eSLandon J. Fuller 			break;
21177cb4d3eSLandon J. Fuller 	}
21277cb4d3eSLandon J. Fuller 
21377cb4d3eSLandon J. Fuller 	/* If no match, return error */
21477cb4d3eSLandon J. Fuller 	if (cls == NULL)
21577cb4d3eSLandon J. Fuller 		return (ENXIO);
21677cb4d3eSLandon J. Fuller 
21777cb4d3eSLandon J. Fuller 	/* If the NVRAM data was not parsed above, do so now */
21877cb4d3eSLandon J. Fuller 	if (*data == NULL) {
21977cb4d3eSLandon J. Fuller 		if ((error = bhnd_nvram_data_new(cls, data, io)))
22077cb4d3eSLandon J. Fuller 			return (error);
22177cb4d3eSLandon J. Fuller 	}
22277cb4d3eSLandon J. Fuller 
22377cb4d3eSLandon J. Fuller 	return (0);
22477cb4d3eSLandon J. Fuller }
22577cb4d3eSLandon J. Fuller 
22677cb4d3eSLandon J. Fuller /**
227*591e79bcSLandon J. Fuller  * Read a variable directly from @p io and decode as @p type.
228*591e79bcSLandon J. Fuller  *
229*591e79bcSLandon J. Fuller  * This may be used to perform reading of NVRAM variables during the very
230*591e79bcSLandon J. Fuller  * early boot process, prior to the availability of the kernel allocator.
231*591e79bcSLandon J. Fuller  *
232*591e79bcSLandon J. Fuller  * @param		cls	An NVRAM class capable of parsing @p io.
233*591e79bcSLandon J. Fuller  * @param		io	NVRAM data to be parsed.
234*591e79bcSLandon J. Fuller  * @param		name	The raw name of the variable to be fetched,
235*591e79bcSLandon J. Fuller  *				including any device path (/pci/1/1/varname) or
236*591e79bcSLandon J. Fuller  *				alias prefix (0:varname).
237*591e79bcSLandon J. Fuller  * @param[out]		buf	On success, the requested value will be written
238*591e79bcSLandon J. Fuller  *				to this buffer. This argment may be NULL if
239*591e79bcSLandon J. Fuller  *				the value is not desired.
240*591e79bcSLandon J. Fuller  * @param[in,out]	len	The capacity of @p buf. On success, will be set
241*591e79bcSLandon J. Fuller  *				to the actual size of the requested value.
242*591e79bcSLandon J. Fuller  * @param		type	The data type to be written to @p buf.
243*591e79bcSLandon J. Fuller  *
244*591e79bcSLandon J. Fuller  * @retval 0		success
245*591e79bcSLandon J. Fuller  * @retval ENOMEM	If @p buf is non-NULL and a buffer of @p len is too
246*591e79bcSLandon J. Fuller  *			small to hold the requested value.
247*591e79bcSLandon J. Fuller  * @retval ENOENT	If @p name is not found in @p io.
248*591e79bcSLandon J. Fuller  * @retval EFTYPE	If the variable data cannot be coerced to @p type.
249*591e79bcSLandon J. Fuller  * @retval ERANGE	If value coercion would overflow @p type.
250*591e79bcSLandon J. Fuller  * @retval non-zero	If parsing @p io otherwise fails, a regular unix error
251*591e79bcSLandon J. Fuller  *			code will be returned.
252*591e79bcSLandon J. Fuller  */
253*591e79bcSLandon J. Fuller int
bhnd_nvram_data_getvar_direct(bhnd_nvram_data_class * cls,struct bhnd_nvram_io * io,const char * name,void * buf,size_t * len,bhnd_nvram_type type)254*591e79bcSLandon J. Fuller bhnd_nvram_data_getvar_direct(bhnd_nvram_data_class *cls,
255*591e79bcSLandon J. Fuller     struct bhnd_nvram_io *io, const char *name, void *buf, size_t *len,
256*591e79bcSLandon J. Fuller     bhnd_nvram_type type)
257*591e79bcSLandon J. Fuller {
258*591e79bcSLandon J. Fuller 	return (cls->op_getvar_direct(io, name, buf, len, type));
259*591e79bcSLandon J. Fuller }
260*591e79bcSLandon J. Fuller 
261*591e79bcSLandon J. Fuller /**
26277cb4d3eSLandon J. Fuller  * Allocate and initialize a new instance of data class @p cls, copying and
26377cb4d3eSLandon J. Fuller  * parsing NVRAM data from @p io.
26477cb4d3eSLandon J. Fuller  *
26577cb4d3eSLandon J. Fuller  * The caller is responsible for releasing the returned parser instance
26677cb4d3eSLandon J. Fuller  * reference via bhnd_nvram_data_release().
26777cb4d3eSLandon J. Fuller  *
26877cb4d3eSLandon J. Fuller  * @param cls If non-NULL, the data class to be allocated. If NULL,
26977cb4d3eSLandon J. Fuller  * bhnd_nvram_data_probe_classes() will be used to determine the data format.
27077cb4d3eSLandon J. Fuller  * @param[out] nv On success, a pointer to the newly allocated NVRAM data instance.
27177cb4d3eSLandon J. Fuller  * @param io An I/O context mapping the NVRAM data to be copied and parsed.
27277cb4d3eSLandon J. Fuller  *
27377cb4d3eSLandon J. Fuller  * @retval 0 success
27477cb4d3eSLandon J. Fuller  * @retval non-zero if an error occurs during allocation or initialization, a
27577cb4d3eSLandon J. Fuller  * regular unix error code will be returned.
27677cb4d3eSLandon J. Fuller  */
27777cb4d3eSLandon J. Fuller int
bhnd_nvram_data_new(bhnd_nvram_data_class * cls,struct bhnd_nvram_data ** nv,struct bhnd_nvram_io * io)27858efe686SLandon J. Fuller bhnd_nvram_data_new(bhnd_nvram_data_class *cls, struct bhnd_nvram_data **nv,
27958efe686SLandon J. Fuller     struct bhnd_nvram_io *io)
28077cb4d3eSLandon J. Fuller {
28177cb4d3eSLandon J. Fuller 	struct bhnd_nvram_data	*data;
28277cb4d3eSLandon J. Fuller 	int			 error;
28377cb4d3eSLandon J. Fuller 
28477cb4d3eSLandon J. Fuller 	/* If NULL, try to identify the appropriate class */
28577cb4d3eSLandon J. Fuller 	if (cls == NULL)
28677cb4d3eSLandon J. Fuller 		return (bhnd_nvram_data_probe_classes(nv, io, NULL, 0));
28777cb4d3eSLandon J. Fuller 
28877cb4d3eSLandon J. Fuller 	/* Allocate new instance */
28977cb4d3eSLandon J. Fuller 	BHND_NV_ASSERT(sizeof(struct bhnd_nvram_data) <= cls->size,
29077cb4d3eSLandon J. Fuller 	    ("instance size %zu less than minimum %zu", cls->size,
29177cb4d3eSLandon J. Fuller 	     sizeof(struct bhnd_nvram_data)));
29277cb4d3eSLandon J. Fuller 
29377cb4d3eSLandon J. Fuller 	data = bhnd_nv_calloc(1, cls->size);
29477cb4d3eSLandon J. Fuller 	data->cls = cls;
29577cb4d3eSLandon J. Fuller 	refcount_init(&data->refs, 1);
29677cb4d3eSLandon J. Fuller 
29777cb4d3eSLandon J. Fuller 	/* Let the class handle initialization */
29877cb4d3eSLandon J. Fuller 	if ((error = cls->op_new(data, io))) {
29977cb4d3eSLandon J. Fuller 		bhnd_nv_free(data);
30077cb4d3eSLandon J. Fuller 		return (error);
30177cb4d3eSLandon J. Fuller 	}
30277cb4d3eSLandon J. Fuller 
30377cb4d3eSLandon J. Fuller 	*nv = data;
30477cb4d3eSLandon J. Fuller 	return (0);
30577cb4d3eSLandon J. Fuller }
30677cb4d3eSLandon J. Fuller 
30777cb4d3eSLandon J. Fuller /**
30877cb4d3eSLandon J. Fuller  * Retain and return a reference to the given data instance.
30977cb4d3eSLandon J. Fuller  *
31077cb4d3eSLandon J. Fuller  * @param nv The reference to be retained.
31177cb4d3eSLandon J. Fuller  */
31277cb4d3eSLandon J. Fuller struct bhnd_nvram_data *
bhnd_nvram_data_retain(struct bhnd_nvram_data * nv)31377cb4d3eSLandon J. Fuller bhnd_nvram_data_retain(struct bhnd_nvram_data *nv)
31477cb4d3eSLandon J. Fuller {
31577cb4d3eSLandon J. Fuller 	refcount_acquire(&nv->refs);
31677cb4d3eSLandon J. Fuller 	return (nv);
31777cb4d3eSLandon J. Fuller }
31877cb4d3eSLandon J. Fuller 
31977cb4d3eSLandon J. Fuller /**
32077cb4d3eSLandon J. Fuller  * Release a reference to the given data instance.
32177cb4d3eSLandon J. Fuller  *
32277cb4d3eSLandon J. Fuller  * If this is the last reference, the data instance and its associated
32377cb4d3eSLandon J. Fuller  * resources will be freed.
32477cb4d3eSLandon J. Fuller  *
32577cb4d3eSLandon J. Fuller  * @param nv The reference to be released.
32677cb4d3eSLandon J. Fuller  */
32777cb4d3eSLandon J. Fuller void
bhnd_nvram_data_release(struct bhnd_nvram_data * nv)32877cb4d3eSLandon J. Fuller bhnd_nvram_data_release(struct bhnd_nvram_data *nv)
32977cb4d3eSLandon J. Fuller {
33077cb4d3eSLandon J. Fuller 	if (!refcount_release(&nv->refs))
33177cb4d3eSLandon J. Fuller 		return;
33277cb4d3eSLandon J. Fuller 
33377cb4d3eSLandon J. Fuller 	/* Free any internal resources */
33477cb4d3eSLandon J. Fuller 	nv->cls->op_free(nv);
33577cb4d3eSLandon J. Fuller 
33677cb4d3eSLandon J. Fuller 	/* Free the instance allocation */
33777cb4d3eSLandon J. Fuller 	bhnd_nv_free(nv);
33877cb4d3eSLandon J. Fuller }
33977cb4d3eSLandon J. Fuller 
34077cb4d3eSLandon J. Fuller /**
34177cb4d3eSLandon J. Fuller  * Return a pointer to @p nv's data class.
34277cb4d3eSLandon J. Fuller  *
34377cb4d3eSLandon J. Fuller  * @param nv The NVRAM data instance to be queried.
34477cb4d3eSLandon J. Fuller  */
34558efe686SLandon J. Fuller bhnd_nvram_data_class *
bhnd_nvram_data_get_class(struct bhnd_nvram_data * nv)34658efe686SLandon J. Fuller bhnd_nvram_data_get_class(struct bhnd_nvram_data *nv)
34777cb4d3eSLandon J. Fuller {
34877cb4d3eSLandon J. Fuller 	return (nv->cls);
34977cb4d3eSLandon J. Fuller }
35077cb4d3eSLandon J. Fuller 
35177cb4d3eSLandon J. Fuller /**
35277cb4d3eSLandon J. Fuller  * Return the number of variables in @p nv.
35377cb4d3eSLandon J. Fuller  *
35477cb4d3eSLandon J. Fuller  * @param nv The NVRAM data to be queried.
35577cb4d3eSLandon J. Fuller  */
35677cb4d3eSLandon J. Fuller size_t
bhnd_nvram_data_count(struct bhnd_nvram_data * nv)35777cb4d3eSLandon J. Fuller bhnd_nvram_data_count(struct bhnd_nvram_data *nv)
35877cb4d3eSLandon J. Fuller {
35977cb4d3eSLandon J. Fuller 	return (nv->cls->op_count(nv));
36077cb4d3eSLandon J. Fuller }
36177cb4d3eSLandon J. Fuller 
36277cb4d3eSLandon J. Fuller /**
363a7c43ebdSLandon J. Fuller  * Return a borrowed reference to the serialization options for @p nv,
364a7c43ebdSLandon J. Fuller  * suitable for use with bhnd_nvram_data_serialize(), or NULL if none.
365a7c43ebdSLandon J. Fuller  *
366a7c43ebdSLandon J. Fuller  * @param nv The NVRAM data to be queried.
367a7c43ebdSLandon J. Fuller  */
368a7c43ebdSLandon J. Fuller bhnd_nvram_plist *
bhnd_nvram_data_options(struct bhnd_nvram_data * nv)369a7c43ebdSLandon J. Fuller bhnd_nvram_data_options(struct bhnd_nvram_data *nv)
370a7c43ebdSLandon J. Fuller {
371a7c43ebdSLandon J. Fuller 	return (nv->cls->op_options(nv));
372a7c43ebdSLandon J. Fuller }
373a7c43ebdSLandon J. Fuller 
374a7c43ebdSLandon J. Fuller /**
37577cb4d3eSLandon J. Fuller  * Return the capability flags (@see BHND_NVRAM_DATA_CAP_*) for @p nv.
37677cb4d3eSLandon J. Fuller  *
37777cb4d3eSLandon J. Fuller  * @param	nv	The NVRAM data to be queried.
37877cb4d3eSLandon J. Fuller  */
37977cb4d3eSLandon J. Fuller uint32_t
bhnd_nvram_data_caps(struct bhnd_nvram_data * nv)38077cb4d3eSLandon J. Fuller bhnd_nvram_data_caps(struct bhnd_nvram_data *nv)
38177cb4d3eSLandon J. Fuller {
38277cb4d3eSLandon J. Fuller 	return (nv->cls->op_caps(nv));
38377cb4d3eSLandon J. Fuller }
38477cb4d3eSLandon J. Fuller 
38577cb4d3eSLandon J. Fuller /**
38677cb4d3eSLandon J. Fuller  * Iterate over @p nv, returning the names of subsequent variables.
38777cb4d3eSLandon J. Fuller  *
38877cb4d3eSLandon J. Fuller  * @param		nv	The NVRAM data to be iterated.
38977cb4d3eSLandon J. Fuller  * @param[in,out]	cookiep	A pointer to a cookiep value previously returned
39077cb4d3eSLandon J. Fuller  *				by bhnd_nvram_data_next(), or a NULL value to
39177cb4d3eSLandon J. Fuller  *				begin iteration.
39277cb4d3eSLandon J. Fuller  *
39377cb4d3eSLandon J. Fuller  * @return Returns the next variable name, or NULL if there are no more
39477cb4d3eSLandon J. Fuller  * variables defined in @p nv.
39577cb4d3eSLandon J. Fuller  */
39677cb4d3eSLandon J. Fuller const char *
bhnd_nvram_data_next(struct bhnd_nvram_data * nv,void ** cookiep)39777cb4d3eSLandon J. Fuller bhnd_nvram_data_next(struct bhnd_nvram_data *nv, void **cookiep)
39877cb4d3eSLandon J. Fuller {
39919be09f3SLandon J. Fuller 	const char	*name;
40019be09f3SLandon J. Fuller #ifdef BHND_NV_INVARIANTS
40119be09f3SLandon J. Fuller 	void		*prev = *cookiep;
40219be09f3SLandon J. Fuller #endif
40319be09f3SLandon J. Fuller 
40419be09f3SLandon J. Fuller 	/* Fetch next */
40519be09f3SLandon J. Fuller 	if ((name = nv->cls->op_next(nv, cookiep)) == NULL)
40619be09f3SLandon J. Fuller 		return (NULL);
40719be09f3SLandon J. Fuller 
40819be09f3SLandon J. Fuller 	/* Enforce precedence ordering invariant between bhnd_nvram_data_next()
40919be09f3SLandon J. Fuller 	 * and bhnd_nvram_data_getvar_order() */
41019be09f3SLandon J. Fuller #ifdef BHND_NV_INVARIANTS
41119be09f3SLandon J. Fuller 	if (prev != NULL &&
41219be09f3SLandon J. Fuller 	    bhnd_nvram_data_getvar_order(nv, prev, *cookiep) > 0)
41319be09f3SLandon J. Fuller 	{
41419be09f3SLandon J. Fuller 		BHND_NV_PANIC("%s: returned out-of-order entry", __FUNCTION__);
41519be09f3SLandon J. Fuller 	}
41619be09f3SLandon J. Fuller #endif
41719be09f3SLandon J. Fuller 
41819be09f3SLandon J. Fuller 	return (name);
41977cb4d3eSLandon J. Fuller }
42077cb4d3eSLandon J. Fuller 
42177cb4d3eSLandon J. Fuller /**
42277cb4d3eSLandon J. Fuller  * Search @p nv for a named variable, returning the variable's opaque reference
42377cb4d3eSLandon J. Fuller  * if found, or NULL if unavailable.
42477cb4d3eSLandon J. Fuller  *
42577cb4d3eSLandon J. Fuller  * The BHND_NVRAM_DATA_CAP_INDEXED capability flag will be returned by
42677cb4d3eSLandon J. Fuller  * bhnd_nvram_data_caps() if @p nv supports effecient name-based
42777cb4d3eSLandon J. Fuller  * lookups.
42877cb4d3eSLandon J. Fuller  *
42977cb4d3eSLandon J. Fuller  * @param	nv	The NVRAM data to search.
43077cb4d3eSLandon J. Fuller  * @param	name	The name to search for.
43177cb4d3eSLandon J. Fuller  *
43277cb4d3eSLandon J. Fuller  * @retval non-NULL	If @p name is found, the opaque cookie value will be
43377cb4d3eSLandon J. Fuller  *			returned.
43477cb4d3eSLandon J. Fuller  * @retval NULL		If @p name is not found.
43577cb4d3eSLandon J. Fuller  */
43677cb4d3eSLandon J. Fuller void *
bhnd_nvram_data_find(struct bhnd_nvram_data * nv,const char * name)43777cb4d3eSLandon J. Fuller bhnd_nvram_data_find(struct bhnd_nvram_data *nv, const char *name)
43877cb4d3eSLandon J. Fuller {
43977cb4d3eSLandon J. Fuller 	return (nv->cls->op_find(nv, name));
44077cb4d3eSLandon J. Fuller }
44177cb4d3eSLandon J. Fuller 
44277cb4d3eSLandon J. Fuller /**
44377cb4d3eSLandon J. Fuller  * A generic implementation of bhnd_nvram_data_find().
44477cb4d3eSLandon J. Fuller  *
44577cb4d3eSLandon J. Fuller  * This implementation will use bhnd_nvram_data_next() to perform a
44677cb4d3eSLandon J. Fuller  * simple O(n) case-insensitve search for @p name.
44777cb4d3eSLandon J. Fuller  */
44877cb4d3eSLandon J. Fuller void *
bhnd_nvram_data_generic_find(struct bhnd_nvram_data * nv,const char * name)44977cb4d3eSLandon J. Fuller bhnd_nvram_data_generic_find(struct bhnd_nvram_data *nv, const char *name)
45077cb4d3eSLandon J. Fuller {
45177cb4d3eSLandon J. Fuller 	const char	*next;
45277cb4d3eSLandon J. Fuller 	void		*cookiep;
45377cb4d3eSLandon J. Fuller 
45477cb4d3eSLandon J. Fuller 	cookiep = NULL;
45577cb4d3eSLandon J. Fuller 	while ((next = bhnd_nvram_data_next(nv, &cookiep))) {
45619be09f3SLandon J. Fuller 		if (strcmp(name, next) == 0)
45777cb4d3eSLandon J. Fuller 			return (cookiep);
45877cb4d3eSLandon J. Fuller 	}
45977cb4d3eSLandon J. Fuller 
46077cb4d3eSLandon J. Fuller 	/* Not found */
46177cb4d3eSLandon J. Fuller 	return (NULL);
46277cb4d3eSLandon J. Fuller }
46377cb4d3eSLandon J. Fuller 
46477cb4d3eSLandon J. Fuller /**
46519be09f3SLandon J. Fuller  * Compare the declaration order of two NVRAM variables.
46619be09f3SLandon J. Fuller  *
46719be09f3SLandon J. Fuller  * Variable declaration order is used to determine the current order of
46819be09f3SLandon J. Fuller  * the variables in the source data, as well as to determine the precedence
46919be09f3SLandon J. Fuller  * of variable declarations in data sources that define duplicate names.
47019be09f3SLandon J. Fuller  *
47119be09f3SLandon J. Fuller  * The comparison order will match the order of variables returned via
47219be09f3SLandon J. Fuller  * bhnd_nvstore_path_data_next().
47319be09f3SLandon J. Fuller  *
47419be09f3SLandon J. Fuller  * @param		nv		The NVRAM data.
47519be09f3SLandon J. Fuller  * @param		cookiep1	An NVRAM variable cookie previously
47619be09f3SLandon J. Fuller  *					returned via bhnd_nvram_data_next() or
47719be09f3SLandon J. Fuller  *					bhnd_nvram_data_find().
47819be09f3SLandon J. Fuller  * @param		cookiep2	An NVRAM variable cookie previously
47919be09f3SLandon J. Fuller  *					returned via bhnd_nvram_data_next() or
48019be09f3SLandon J. Fuller  *					bhnd_nvram_data_find().
48119be09f3SLandon J. Fuller  *
48219be09f3SLandon J. Fuller  * @retval <= -1	If @p cookiep1 has an earlier declaration order than
48319be09f3SLandon J. Fuller  *			@p cookiep2.
48419be09f3SLandon J. Fuller  * @retval 0		If @p cookiep1 and @p cookiep2 are identical.
48519be09f3SLandon J. Fuller  * @retval >= 1		If @p cookiep has a later declaration order than
48619be09f3SLandon J. Fuller  *			@p cookiep2.
48719be09f3SLandon J. Fuller  */
48819be09f3SLandon J. Fuller int
bhnd_nvram_data_getvar_order(struct bhnd_nvram_data * nv,void * cookiep1,void * cookiep2)48919be09f3SLandon J. Fuller bhnd_nvram_data_getvar_order(struct bhnd_nvram_data *nv, void *cookiep1,
49019be09f3SLandon J. Fuller     void *cookiep2)
49119be09f3SLandon J. Fuller {
49219be09f3SLandon J. Fuller 	return (nv->cls->op_getvar_order(nv, cookiep1, cookiep2));
49319be09f3SLandon J. Fuller }
49419be09f3SLandon J. Fuller 
49519be09f3SLandon J. Fuller /**
49677cb4d3eSLandon J. Fuller  * Read a variable and decode as @p type.
49777cb4d3eSLandon J. Fuller  *
49877cb4d3eSLandon J. Fuller  * @param		nv	The NVRAM data.
49977cb4d3eSLandon J. Fuller  * @param		cookiep	An NVRAM variable cookie previously returned
50077cb4d3eSLandon J. Fuller  *				via bhnd_nvram_data_next() or
50177cb4d3eSLandon J. Fuller  *				bhnd_nvram_data_find().
50277cb4d3eSLandon J. Fuller  * @param[out]		buf	On success, the requested value will be written
50377cb4d3eSLandon J. Fuller  *				to this buffer. This argment may be NULL if
50477cb4d3eSLandon J. Fuller  *				the value is not desired.
50577cb4d3eSLandon J. Fuller  * @param[in,out]	len	The capacity of @p buf. On success, will be set
50677cb4d3eSLandon J. Fuller  *				to the actual size of the requested value.
50777cb4d3eSLandon J. Fuller  * @param		type	The data type to be written to @p buf.
50877cb4d3eSLandon J. Fuller  *
50977cb4d3eSLandon J. Fuller  * @retval 0		success
51077cb4d3eSLandon J. Fuller  * @retval ENOMEM	If @p buf is non-NULL and a buffer of @p len is too
51177cb4d3eSLandon J. Fuller  *			small to hold the requested value.
51277cb4d3eSLandon J. Fuller  * @retval EFTYPE	If the variable data cannot be coerced to @p type.
51377cb4d3eSLandon J. Fuller  * @retval ERANGE	If value coercion would overflow @p type.
51477cb4d3eSLandon J. Fuller  */
51577cb4d3eSLandon J. Fuller int
bhnd_nvram_data_getvar(struct bhnd_nvram_data * nv,void * cookiep,void * buf,size_t * len,bhnd_nvram_type type)51677cb4d3eSLandon J. Fuller bhnd_nvram_data_getvar(struct bhnd_nvram_data *nv, void *cookiep, void *buf,
51777cb4d3eSLandon J. Fuller     size_t *len, bhnd_nvram_type type)
51877cb4d3eSLandon J. Fuller {
51977cb4d3eSLandon J. Fuller 	return (nv->cls->op_getvar(nv, cookiep, buf, len, type));
52077cb4d3eSLandon J. Fuller }
52177cb4d3eSLandon J. Fuller 
52219be09f3SLandon J. Fuller /*
52319be09f3SLandon J. Fuller  * Common bhnd_nvram_data_getvar_ptr() wrapper used by
52419be09f3SLandon J. Fuller  * bhnd_nvram_data_generic_rp_getvar() and
52519be09f3SLandon J. Fuller  * bhnd_nvram_data_generic_rp_copy_val().
52619be09f3SLandon J. Fuller  *
52719be09f3SLandon J. Fuller  * If a variable definition for the requested variable is found via
52819be09f3SLandon J. Fuller  * bhnd_nvram_find_vardefn(), the definition will be used to populate fmt.
52919be09f3SLandon J. Fuller  */
53019be09f3SLandon J. Fuller static const void *
bhnd_nvram_data_getvar_ptr_info(struct bhnd_nvram_data * nv,void * cookiep,size_t * len,bhnd_nvram_type * type,const bhnd_nvram_val_fmt ** fmt)53119be09f3SLandon J. Fuller bhnd_nvram_data_getvar_ptr_info(struct bhnd_nvram_data *nv, void *cookiep,
53219be09f3SLandon J. Fuller     size_t *len, bhnd_nvram_type *type, const bhnd_nvram_val_fmt **fmt)
53319be09f3SLandon J. Fuller {
53419be09f3SLandon J. Fuller 	const struct bhnd_nvram_vardefn	*vdefn;
53519be09f3SLandon J. Fuller 	const char			*name;
53619be09f3SLandon J. Fuller 	const void			*vptr;
53719be09f3SLandon J. Fuller 
53819be09f3SLandon J. Fuller 	BHND_NV_ASSERT(bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_READ_PTR,
53919be09f3SLandon J. Fuller 	    ("instance does not advertise READ_PTR support"));
54019be09f3SLandon J. Fuller 
54119be09f3SLandon J. Fuller 	/* Fetch pointer to variable data */
54219be09f3SLandon J. Fuller 	vptr = bhnd_nvram_data_getvar_ptr(nv, cookiep, len, type);
54319be09f3SLandon J. Fuller 	if (vptr == NULL)
54419be09f3SLandon J. Fuller 		return (NULL);
54519be09f3SLandon J. Fuller 
54619be09f3SLandon J. Fuller 	/* Select a default value format implementation */
54719be09f3SLandon J. Fuller 
54819be09f3SLandon J. Fuller 	/* Fetch the reference variable name */
54919be09f3SLandon J. Fuller 	name = bhnd_nvram_data_getvar_name(nv, cookiep);
55019be09f3SLandon J. Fuller 
55119be09f3SLandon J. Fuller 	/* Trim path prefix, if any; the Broadcom NVRAM format assumes a global
55219be09f3SLandon J. Fuller 	 * namespace for all variable definitions */
55319be09f3SLandon J. Fuller 	if (bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_DEVPATHS)
55419be09f3SLandon J. Fuller 		name = bhnd_nvram_trim_path_name(name);
55519be09f3SLandon J. Fuller 
55619be09f3SLandon J. Fuller 	/* Check the variable definition table for a matching entry; if
55719be09f3SLandon J. Fuller 	 * it exists, use it to populate the value format. */
55819be09f3SLandon J. Fuller 	vdefn = bhnd_nvram_find_vardefn(name);
55919be09f3SLandon J. Fuller 	if (vdefn != NULL) {
56019be09f3SLandon J. Fuller 		BHND_NV_ASSERT(vdefn->fmt != NULL,
56119be09f3SLandon J. Fuller 		    ("NULL format for %s", name));
56219be09f3SLandon J. Fuller 		*fmt = vdefn->fmt;
56319be09f3SLandon J. Fuller 	} else if (*type == BHND_NVRAM_TYPE_STRING) {
56419be09f3SLandon J. Fuller 		/* Default to Broadcom-specific string interpretation */
56519be09f3SLandon J. Fuller 		*fmt = &bhnd_nvram_val_bcm_string_fmt;
56619be09f3SLandon J. Fuller 	} else {
56719be09f3SLandon J. Fuller 		/* Fall back on native formatting */
56819be09f3SLandon J. Fuller 		*fmt = bhnd_nvram_val_default_fmt(*type);
56919be09f3SLandon J. Fuller 	}
57019be09f3SLandon J. Fuller 
57119be09f3SLandon J. Fuller 	return (vptr);
57219be09f3SLandon J. Fuller }
57358efe686SLandon J. Fuller 
57477cb4d3eSLandon J. Fuller /**
57577cb4d3eSLandon J. Fuller  * A generic implementation of bhnd_nvram_data_getvar().
57677cb4d3eSLandon J. Fuller  *
57777cb4d3eSLandon J. Fuller  * This implementation will call bhnd_nvram_data_getvar_ptr() to fetch
57877cb4d3eSLandon J. Fuller  * a pointer to the variable data and perform data coercion on behalf
57977cb4d3eSLandon J. Fuller  * of the caller.
58077cb4d3eSLandon J. Fuller  *
58177cb4d3eSLandon J. Fuller  * If a variable definition for the requested variable is available via
58219be09f3SLandon J. Fuller  * bhnd_nvram_find_vardefn(), the definition will be used to provide a
58319be09f3SLandon J. Fuller  * formatting instance to bhnd_nvram_val_init().
58477cb4d3eSLandon J. Fuller  */
58577cb4d3eSLandon J. Fuller int
bhnd_nvram_data_generic_rp_getvar(struct bhnd_nvram_data * nv,void * cookiep,void * outp,size_t * olen,bhnd_nvram_type otype)58677cb4d3eSLandon J. Fuller bhnd_nvram_data_generic_rp_getvar(struct bhnd_nvram_data *nv, void *cookiep,
58777cb4d3eSLandon J. Fuller     void *outp, size_t *olen, bhnd_nvram_type otype)
58877cb4d3eSLandon J. Fuller {
58958efe686SLandon J. Fuller 	bhnd_nvram_val			 val;
59058efe686SLandon J. Fuller 	const bhnd_nvram_val_fmt	*fmt;
59177cb4d3eSLandon J. Fuller 	const void			*vptr;
59277cb4d3eSLandon J. Fuller 	bhnd_nvram_type			 vtype;
59377cb4d3eSLandon J. Fuller 	size_t				 vlen;
59477cb4d3eSLandon J. Fuller 	int				 error;
59577cb4d3eSLandon J. Fuller 
59677cb4d3eSLandon J. Fuller 	BHND_NV_ASSERT(bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_READ_PTR,
59777cb4d3eSLandon J. Fuller 	    ("instance does not advertise READ_PTR support"));
59877cb4d3eSLandon J. Fuller 
59919be09f3SLandon J. Fuller 	/* Fetch variable data and value format*/
60019be09f3SLandon J. Fuller 	vptr = bhnd_nvram_data_getvar_ptr_info(nv, cookiep, &vlen, &vtype,
60119be09f3SLandon J. Fuller 	    &fmt);
60277cb4d3eSLandon J. Fuller 	if (vptr == NULL)
60377cb4d3eSLandon J. Fuller 		return (EINVAL);
60477cb4d3eSLandon J. Fuller 
60577cb4d3eSLandon J. Fuller 	/* Attempt value coercion */
60677cb4d3eSLandon J. Fuller 	error = bhnd_nvram_val_init(&val, fmt, vptr, vlen, vtype,
60777cb4d3eSLandon J. Fuller 	    BHND_NVRAM_VAL_BORROW_DATA);
60877cb4d3eSLandon J. Fuller 	if (error)
60977cb4d3eSLandon J. Fuller 		return (error);
61077cb4d3eSLandon J. Fuller 
61177cb4d3eSLandon J. Fuller 	error = bhnd_nvram_val_encode(&val, outp, olen, otype);
61277cb4d3eSLandon J. Fuller 
61377cb4d3eSLandon J. Fuller 	/* Clean up */
61477cb4d3eSLandon J. Fuller 	bhnd_nvram_val_release(&val);
61577cb4d3eSLandon J. Fuller 	return (error);
61677cb4d3eSLandon J. Fuller }
61777cb4d3eSLandon J. Fuller 
61877cb4d3eSLandon J. Fuller /**
61919be09f3SLandon J. Fuller  * Return a caller-owned copy of an NVRAM entry's variable data.
62019be09f3SLandon J. Fuller  *
62119be09f3SLandon J. Fuller  * The caller is responsible for deallocating the returned value via
62219be09f3SLandon J. Fuller  * bhnd_nvram_val_release().
62319be09f3SLandon J. Fuller  *
62419be09f3SLandon J. Fuller  * @param	nv	The NVRAM data.
62519be09f3SLandon J. Fuller  * @param	cookiep	An NVRAM variable cookie previously returned
62619be09f3SLandon J. Fuller  *			via bhnd_nvram_data_next() or bhnd_nvram_data_find().
62719be09f3SLandon J. Fuller  * @param[out]	value	On success, the caller-owned value instance.
62819be09f3SLandon J. Fuller  *
62919be09f3SLandon J. Fuller  * @retval 0		success
63019be09f3SLandon J. Fuller  * @retval ENOMEM	If allocation fails.
63119be09f3SLandon J. Fuller  * @retval non-zero	If initialization of the value otherwise fails, a
63219be09f3SLandon J. Fuller  *			regular unix error code will be returned.
63319be09f3SLandon J. Fuller  */
63419be09f3SLandon J. Fuller int
bhnd_nvram_data_copy_val(struct bhnd_nvram_data * nv,void * cookiep,bhnd_nvram_val ** value)63519be09f3SLandon J. Fuller bhnd_nvram_data_copy_val(struct bhnd_nvram_data *nv, void *cookiep,
63619be09f3SLandon J. Fuller     bhnd_nvram_val **value)
63719be09f3SLandon J. Fuller {
63819be09f3SLandon J. Fuller 	return (nv->cls->op_copy_val(nv, cookiep, value));
63919be09f3SLandon J. Fuller }
64019be09f3SLandon J. Fuller 
64119be09f3SLandon J. Fuller /**
64219be09f3SLandon J. Fuller  * A generic implementation of bhnd_nvram_data_copy_val().
64319be09f3SLandon J. Fuller  *
64419be09f3SLandon J. Fuller  * This implementation will call bhnd_nvram_data_getvar_ptr() to fetch
64519be09f3SLandon J. Fuller  * a pointer to the variable data and perform data coercion on behalf
64619be09f3SLandon J. Fuller  * of the caller.
64719be09f3SLandon J. Fuller  *
64819be09f3SLandon J. Fuller  * If a variable definition for the requested variable is available via
64919be09f3SLandon J. Fuller  * bhnd_nvram_find_vardefn(), the definition will be used to provide a
65019be09f3SLandon J. Fuller  * formatting instance to bhnd_nvram_val_init().
65119be09f3SLandon J. Fuller  */
65219be09f3SLandon J. Fuller int
bhnd_nvram_data_generic_rp_copy_val(struct bhnd_nvram_data * nv,void * cookiep,bhnd_nvram_val ** value)65319be09f3SLandon J. Fuller bhnd_nvram_data_generic_rp_copy_val(struct bhnd_nvram_data *nv,
65419be09f3SLandon J. Fuller     void *cookiep, bhnd_nvram_val **value)
65519be09f3SLandon J. Fuller {
65619be09f3SLandon J. Fuller 	const bhnd_nvram_val_fmt	*fmt;
65719be09f3SLandon J. Fuller 	const void			*vptr;
65819be09f3SLandon J. Fuller 	bhnd_nvram_type			 vtype;
65919be09f3SLandon J. Fuller 	size_t				 vlen;
66019be09f3SLandon J. Fuller 
66119be09f3SLandon J. Fuller 	BHND_NV_ASSERT(bhnd_nvram_data_caps(nv) & BHND_NVRAM_DATA_CAP_READ_PTR,
66219be09f3SLandon J. Fuller 	    ("instance does not advertise READ_PTR support"));
66319be09f3SLandon J. Fuller 
66419be09f3SLandon J. Fuller 	/* Fetch variable data and value format*/
66519be09f3SLandon J. Fuller 	vptr = bhnd_nvram_data_getvar_ptr_info(nv, cookiep, &vlen, &vtype,
66619be09f3SLandon J. Fuller 	    &fmt);
66719be09f3SLandon J. Fuller 	if (vptr == NULL)
66819be09f3SLandon J. Fuller 		return (EINVAL);
66919be09f3SLandon J. Fuller 
67019be09f3SLandon J. Fuller 	/* Allocate and return the new value instance */
67119be09f3SLandon J. Fuller 	return (bhnd_nvram_val_new(value, fmt, vptr, vlen, vtype,
67219be09f3SLandon J. Fuller 	    BHND_NVRAM_VAL_DYNAMIC));
67319be09f3SLandon J. Fuller }
67419be09f3SLandon J. Fuller 
67519be09f3SLandon J. Fuller /**
67677cb4d3eSLandon J. Fuller  * If available and supported by the NVRAM data instance, return a reference
67777cb4d3eSLandon J. Fuller  * to the internal buffer containing an entry's variable data,
67877cb4d3eSLandon J. Fuller  *
67977cb4d3eSLandon J. Fuller  * Note that string values may not be NUL terminated.
68077cb4d3eSLandon J. Fuller  *
68177cb4d3eSLandon J. Fuller  * @param		nv	The NVRAM data.
68277cb4d3eSLandon J. Fuller  * @param		cookiep	An NVRAM variable cookie previously returned
68377cb4d3eSLandon J. Fuller  *				via bhnd_nvram_data_next() or
68477cb4d3eSLandon J. Fuller  *				bhnd_nvram_data_find().
68577cb4d3eSLandon J. Fuller  * @param[out]		len	On success, will be set to the actual size of
68677cb4d3eSLandon J. Fuller  *				the requested value.
68777cb4d3eSLandon J. Fuller  * @param[out]		type	The data type of the entry data.
68877cb4d3eSLandon J. Fuller  *
68977cb4d3eSLandon J. Fuller  * @retval non-NULL	success
69077cb4d3eSLandon J. Fuller  * @retval NULL		if direct data access is unsupported by @p nv, or
69177cb4d3eSLandon J. Fuller  *			unavailable for @p cookiep.
69277cb4d3eSLandon J. Fuller  */
69377cb4d3eSLandon J. Fuller const void *
bhnd_nvram_data_getvar_ptr(struct bhnd_nvram_data * nv,void * cookiep,size_t * len,bhnd_nvram_type * type)69477cb4d3eSLandon J. Fuller bhnd_nvram_data_getvar_ptr(struct bhnd_nvram_data *nv, void *cookiep,
69577cb4d3eSLandon J. Fuller     size_t *len, bhnd_nvram_type *type)
69677cb4d3eSLandon J. Fuller {
69777cb4d3eSLandon J. Fuller 	return (nv->cls->op_getvar_ptr(nv, cookiep, len, type));
69877cb4d3eSLandon J. Fuller }
69977cb4d3eSLandon J. Fuller 
70077cb4d3eSLandon J. Fuller /**
70177cb4d3eSLandon J. Fuller  * Return the variable name associated with a given @p cookiep.
70277cb4d3eSLandon J. Fuller  * @param		nv	The NVRAM data to be iterated.
70377cb4d3eSLandon J. Fuller  * @param[in,out]	cookiep	A pointer to a cookiep value previously returned
70477cb4d3eSLandon J. Fuller  *				via bhnd_nvram_data_next() or
70577cb4d3eSLandon J. Fuller  *				bhnd_nvram_data_find().
70677cb4d3eSLandon J. Fuller  *
70777cb4d3eSLandon J. Fuller  * @return Returns the variable's name.
70877cb4d3eSLandon J. Fuller  */
70977cb4d3eSLandon J. Fuller const char *
bhnd_nvram_data_getvar_name(struct bhnd_nvram_data * nv,void * cookiep)71077cb4d3eSLandon J. Fuller bhnd_nvram_data_getvar_name(struct bhnd_nvram_data *nv, void *cookiep)
71177cb4d3eSLandon J. Fuller {
71277cb4d3eSLandon J. Fuller 	return (nv->cls->op_getvar_name(nv, cookiep));
71377cb4d3eSLandon J. Fuller }
71419be09f3SLandon J. Fuller 
71519be09f3SLandon J. Fuller /**
71619be09f3SLandon J. Fuller  * Filter a request to set variable @p name with @p value.
71719be09f3SLandon J. Fuller  *
71819be09f3SLandon J. Fuller  * On success, the caller owns a reference to @p result, and must release
71919be09f3SLandon J. Fuller  * any held resources via bhnd_nvram_val_release().
72019be09f3SLandon J. Fuller  *
72119be09f3SLandon J. Fuller  * @param	nv	The NVRAM data instance.
72219be09f3SLandon J. Fuller  * @param	name	The name of the variable to be set.
72319be09f3SLandon J. Fuller  * @param	value	The proposed value to be set.
72419be09f3SLandon J. Fuller  * @param[out]	result	On success, a caller-owned reference to the filtered
72519be09f3SLandon J. Fuller  *			value to be set.
72619be09f3SLandon J. Fuller  *
72719be09f3SLandon J. Fuller  * @retval	0	success
72819be09f3SLandon J. Fuller  * @retval	ENOENT	if @p name is unrecognized by @p nv.
72919be09f3SLandon J. Fuller  * @retval	EINVAL	if @p name is read-only.
73019be09f3SLandon J. Fuller  * @retval	EINVAL	if @p value cannot be converted to the required value
73119be09f3SLandon J. Fuller  *			type.
73219be09f3SLandon J. Fuller  */
73319be09f3SLandon J. Fuller int
bhnd_nvram_data_filter_setvar(struct bhnd_nvram_data * nv,const char * name,bhnd_nvram_val * value,bhnd_nvram_val ** result)73419be09f3SLandon J. Fuller bhnd_nvram_data_filter_setvar(struct bhnd_nvram_data *nv, const char *name,
73519be09f3SLandon J. Fuller     bhnd_nvram_val *value, bhnd_nvram_val **result)
73619be09f3SLandon J. Fuller {
73719be09f3SLandon J. Fuller 	return (nv->cls->op_filter_setvar(nv, name, value, result));
73819be09f3SLandon J. Fuller }
73919be09f3SLandon J. Fuller 
74019be09f3SLandon J. Fuller /**
74119be09f3SLandon J. Fuller  * Filter a request to delete variable @p name.
74219be09f3SLandon J. Fuller  *
74319be09f3SLandon J. Fuller  * @param	nv	The NVRAM data instance.
74419be09f3SLandon J. Fuller  * @param	name	The name of the variable to be deleted.
74519be09f3SLandon J. Fuller  *
74619be09f3SLandon J. Fuller  * @retval	0	success
74719be09f3SLandon J. Fuller  * @retval	ENOENT	if @p name is unrecognized by @p nv.
74819be09f3SLandon J. Fuller  * @retval	EINVAL	if @p name is read-only.
74919be09f3SLandon J. Fuller  */
75019be09f3SLandon J. Fuller int
bhnd_nvram_data_filter_unsetvar(struct bhnd_nvram_data * nv,const char * name)75119be09f3SLandon J. Fuller bhnd_nvram_data_filter_unsetvar(struct bhnd_nvram_data *nv, const char *name)
75219be09f3SLandon J. Fuller {
75319be09f3SLandon J. Fuller 	return (nv->cls->op_filter_unsetvar(nv, name));
75419be09f3SLandon J. Fuller }
755