xref: /freebsd/sbin/hastd/nv.c (revision 32e86a82)
132115b10SPawel Jakub Dawidek /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
432115b10SPawel Jakub Dawidek  * Copyright (c) 2009-2010 The FreeBSD Foundation
532115b10SPawel Jakub Dawidek  * All rights reserved.
632115b10SPawel Jakub Dawidek  *
732115b10SPawel Jakub Dawidek  * This software was developed by Pawel Jakub Dawidek under sponsorship from
832115b10SPawel Jakub Dawidek  * the FreeBSD Foundation.
932115b10SPawel Jakub Dawidek  *
1032115b10SPawel Jakub Dawidek  * Redistribution and use in source and binary forms, with or without
1132115b10SPawel Jakub Dawidek  * modification, are permitted provided that the following conditions
1232115b10SPawel Jakub Dawidek  * are met:
1332115b10SPawel Jakub Dawidek  * 1. Redistributions of source code must retain the above copyright
1432115b10SPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer.
1532115b10SPawel Jakub Dawidek  * 2. Redistributions in binary form must reproduce the above copyright
1632115b10SPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer in the
1732115b10SPawel Jakub Dawidek  *    documentation and/or other materials provided with the distribution.
1832115b10SPawel Jakub Dawidek  *
1932115b10SPawel Jakub Dawidek  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
2032115b10SPawel Jakub Dawidek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2132115b10SPawel Jakub Dawidek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2232115b10SPawel Jakub Dawidek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
2332115b10SPawel Jakub Dawidek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2432115b10SPawel Jakub Dawidek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2532115b10SPawel Jakub Dawidek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2632115b10SPawel Jakub Dawidek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2732115b10SPawel Jakub Dawidek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2832115b10SPawel Jakub Dawidek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2932115b10SPawel Jakub Dawidek  * SUCH DAMAGE.
3032115b10SPawel Jakub Dawidek  */
3132115b10SPawel Jakub Dawidek 
3232115b10SPawel Jakub Dawidek #include <sys/param.h>
3332115b10SPawel Jakub Dawidek #include <sys/endian.h>
3432115b10SPawel Jakub Dawidek 
3532115b10SPawel Jakub Dawidek #include <bitstring.h>
3632115b10SPawel Jakub Dawidek #include <errno.h>
3732115b10SPawel Jakub Dawidek #include <stdarg.h>
3832115b10SPawel Jakub Dawidek #include <stdbool.h>
3932115b10SPawel Jakub Dawidek #include <stdint.h>
4032115b10SPawel Jakub Dawidek #include <stdlib.h>
4132115b10SPawel Jakub Dawidek #include <string.h>
4232115b10SPawel Jakub Dawidek #include <unistd.h>
4332115b10SPawel Jakub Dawidek 
4432115b10SPawel Jakub Dawidek #include <ebuf.h>
45adf8002bSPawel Jakub Dawidek #include <pjdlog.h>
46adf8002bSPawel Jakub Dawidek 
47adf8002bSPawel Jakub Dawidek #include "nv.h"
48adf8002bSPawel Jakub Dawidek 
49adf8002bSPawel Jakub Dawidek #ifndef	PJDLOG_ASSERT
50adf8002bSPawel Jakub Dawidek #include <assert.h>
51adf8002bSPawel Jakub Dawidek #define	PJDLOG_ASSERT(...)	assert(__VA_ARGS__)
52adf8002bSPawel Jakub Dawidek #endif
53adf8002bSPawel Jakub Dawidek #ifndef	PJDLOG_ABORT
54adf8002bSPawel Jakub Dawidek #define	PJDLOG_ABORT(...)	abort()
55adf8002bSPawel Jakub Dawidek #endif
5632115b10SPawel Jakub Dawidek 
57b9ffbb0aSPawel Jakub Dawidek #define	NV_TYPE_NONE		0
58b9ffbb0aSPawel Jakub Dawidek 
593dea75d2SPawel Jakub Dawidek #define	NV_TYPE_INT8		1
603dea75d2SPawel Jakub Dawidek #define	NV_TYPE_UINT8		2
613dea75d2SPawel Jakub Dawidek #define	NV_TYPE_INT16		3
623dea75d2SPawel Jakub Dawidek #define	NV_TYPE_UINT16		4
633dea75d2SPawel Jakub Dawidek #define	NV_TYPE_INT32		5
643dea75d2SPawel Jakub Dawidek #define	NV_TYPE_UINT32		6
653dea75d2SPawel Jakub Dawidek #define	NV_TYPE_INT64		7
663dea75d2SPawel Jakub Dawidek #define	NV_TYPE_UINT64		8
673dea75d2SPawel Jakub Dawidek #define	NV_TYPE_INT8_ARRAY	9
683dea75d2SPawel Jakub Dawidek #define	NV_TYPE_UINT8_ARRAY	10
693dea75d2SPawel Jakub Dawidek #define	NV_TYPE_INT16_ARRAY	11
703dea75d2SPawel Jakub Dawidek #define	NV_TYPE_UINT16_ARRAY	12
713dea75d2SPawel Jakub Dawidek #define	NV_TYPE_INT32_ARRAY	13
723dea75d2SPawel Jakub Dawidek #define	NV_TYPE_UINT32_ARRAY	14
733dea75d2SPawel Jakub Dawidek #define	NV_TYPE_INT64_ARRAY	15
743dea75d2SPawel Jakub Dawidek #define	NV_TYPE_UINT64_ARRAY	16
753dea75d2SPawel Jakub Dawidek #define	NV_TYPE_STRING		17
763dea75d2SPawel Jakub Dawidek 
773dea75d2SPawel Jakub Dawidek #define	NV_TYPE_MASK		0x7f
783dea75d2SPawel Jakub Dawidek #define	NV_TYPE_FIRST		NV_TYPE_INT8
793dea75d2SPawel Jakub Dawidek #define	NV_TYPE_LAST		NV_TYPE_STRING
803dea75d2SPawel Jakub Dawidek 
813dea75d2SPawel Jakub Dawidek #define	NV_ORDER_NETWORK	0x00
823dea75d2SPawel Jakub Dawidek #define	NV_ORDER_HOST		0x80
833dea75d2SPawel Jakub Dawidek 
843dea75d2SPawel Jakub Dawidek #define	NV_ORDER_MASK		0x80
853dea75d2SPawel Jakub Dawidek 
8632115b10SPawel Jakub Dawidek #define	NV_MAGIC	0xaea1e
8732115b10SPawel Jakub Dawidek struct nv {
8832115b10SPawel Jakub Dawidek 	int	nv_magic;
8932115b10SPawel Jakub Dawidek 	int	nv_error;
9032115b10SPawel Jakub Dawidek 	struct ebuf *nv_ebuf;
9132115b10SPawel Jakub Dawidek };
9232115b10SPawel Jakub Dawidek 
9332115b10SPawel Jakub Dawidek struct nvhdr {
9432115b10SPawel Jakub Dawidek 	uint8_t		nvh_type;
9532115b10SPawel Jakub Dawidek 	uint8_t		nvh_namesize;
9632115b10SPawel Jakub Dawidek 	uint32_t	nvh_dsize;
9732115b10SPawel Jakub Dawidek 	char		nvh_name[0];
9832115b10SPawel Jakub Dawidek } __packed;
9932115b10SPawel Jakub Dawidek #define	NVH_DATA(nvh)	((unsigned char *)nvh + NVH_HSIZE(nvh))
10032115b10SPawel Jakub Dawidek #define	NVH_HSIZE(nvh)	\
10132115b10SPawel Jakub Dawidek 	(sizeof(struct nvhdr) + roundup2((nvh)->nvh_namesize, 8))
10232115b10SPawel Jakub Dawidek #define	NVH_DSIZE(nvh)	\
10332115b10SPawel Jakub Dawidek 	(((nvh)->nvh_type & NV_ORDER_MASK) == NV_ORDER_HOST ?		\
10432115b10SPawel Jakub Dawidek 	(nvh)->nvh_dsize :						\
10532115b10SPawel Jakub Dawidek 	le32toh((nvh)->nvh_dsize))
10632115b10SPawel Jakub Dawidek #define	NVH_SIZE(nvh)	(NVH_HSIZE(nvh) + roundup2(NVH_DSIZE(nvh), 8))
10732115b10SPawel Jakub Dawidek 
10832115b10SPawel Jakub Dawidek #define	NV_CHECK(nv)	do {						\
109adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT((nv) != NULL);					\
110adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT((nv)->nv_magic == NV_MAGIC);			\
11132115b10SPawel Jakub Dawidek } while (0)
11232115b10SPawel Jakub Dawidek 
11332115b10SPawel Jakub Dawidek static void nv_add(struct nv *nv, const unsigned char *value, size_t vsize,
11432115b10SPawel Jakub Dawidek     int type, const char *name);
11532115b10SPawel Jakub Dawidek static void nv_addv(struct nv *nv, const unsigned char *value, size_t vsize,
11632115b10SPawel Jakub Dawidek     int type, const char *namefmt, va_list nameap);
11732115b10SPawel Jakub Dawidek static struct nvhdr *nv_find(struct nv *nv, int type, const char *namefmt,
11832115b10SPawel Jakub Dawidek     va_list nameap);
11932115b10SPawel Jakub Dawidek static void nv_swap(struct nvhdr *nvh, bool tohost);
12032115b10SPawel Jakub Dawidek 
12132115b10SPawel Jakub Dawidek /*
12232115b10SPawel Jakub Dawidek  * Allocate and initialize new nv structure.
12332115b10SPawel Jakub Dawidek  * Return NULL in case of malloc(3) failure.
12432115b10SPawel Jakub Dawidek  */
12532115b10SPawel Jakub Dawidek struct nv *
nv_alloc(void)12632115b10SPawel Jakub Dawidek nv_alloc(void)
12732115b10SPawel Jakub Dawidek {
12832115b10SPawel Jakub Dawidek 	struct nv *nv;
12932115b10SPawel Jakub Dawidek 
13032115b10SPawel Jakub Dawidek 	nv = malloc(sizeof(*nv));
13132115b10SPawel Jakub Dawidek 	if (nv == NULL)
13232115b10SPawel Jakub Dawidek 		return (NULL);
13332115b10SPawel Jakub Dawidek 	nv->nv_ebuf = ebuf_alloc(0);
13432115b10SPawel Jakub Dawidek 	if (nv->nv_ebuf == NULL) {
13532115b10SPawel Jakub Dawidek 		free(nv);
13632115b10SPawel Jakub Dawidek 		return (NULL);
13732115b10SPawel Jakub Dawidek 	}
13832115b10SPawel Jakub Dawidek 	nv->nv_error = 0;
13932115b10SPawel Jakub Dawidek 	nv->nv_magic = NV_MAGIC;
14032115b10SPawel Jakub Dawidek 	return (nv);
14132115b10SPawel Jakub Dawidek }
14232115b10SPawel Jakub Dawidek 
14332115b10SPawel Jakub Dawidek /*
14432115b10SPawel Jakub Dawidek  * Free the given nv structure.
14532115b10SPawel Jakub Dawidek  */
14632115b10SPawel Jakub Dawidek void
nv_free(struct nv * nv)14732115b10SPawel Jakub Dawidek nv_free(struct nv *nv)
14832115b10SPawel Jakub Dawidek {
14932115b10SPawel Jakub Dawidek 
15032115b10SPawel Jakub Dawidek 	if (nv == NULL)
15132115b10SPawel Jakub Dawidek 		return;
15232115b10SPawel Jakub Dawidek 
15332115b10SPawel Jakub Dawidek 	NV_CHECK(nv);
15432115b10SPawel Jakub Dawidek 
15532115b10SPawel Jakub Dawidek 	nv->nv_magic = 0;
15632115b10SPawel Jakub Dawidek 	ebuf_free(nv->nv_ebuf);
15732115b10SPawel Jakub Dawidek 	free(nv);
15832115b10SPawel Jakub Dawidek }
15932115b10SPawel Jakub Dawidek 
16032115b10SPawel Jakub Dawidek /*
16132115b10SPawel Jakub Dawidek  * Return error for the given nv structure.
16232115b10SPawel Jakub Dawidek  */
16332115b10SPawel Jakub Dawidek int
nv_error(const struct nv * nv)16432115b10SPawel Jakub Dawidek nv_error(const struct nv *nv)
16532115b10SPawel Jakub Dawidek {
16632115b10SPawel Jakub Dawidek 
16732115b10SPawel Jakub Dawidek 	if (nv == NULL)
16832115b10SPawel Jakub Dawidek 		return (ENOMEM);
16932115b10SPawel Jakub Dawidek 
17032115b10SPawel Jakub Dawidek 	NV_CHECK(nv);
17132115b10SPawel Jakub Dawidek 
17232115b10SPawel Jakub Dawidek 	return (nv->nv_error);
17332115b10SPawel Jakub Dawidek }
17432115b10SPawel Jakub Dawidek 
17532115b10SPawel Jakub Dawidek /*
17632115b10SPawel Jakub Dawidek  * Set error for the given nv structure and return previous error.
17732115b10SPawel Jakub Dawidek  */
17832115b10SPawel Jakub Dawidek int
nv_set_error(struct nv * nv,int error)17932115b10SPawel Jakub Dawidek nv_set_error(struct nv *nv, int error)
18032115b10SPawel Jakub Dawidek {
18132115b10SPawel Jakub Dawidek 	int preverr;
18232115b10SPawel Jakub Dawidek 
18332115b10SPawel Jakub Dawidek 	if (nv == NULL)
18432115b10SPawel Jakub Dawidek 		return (ENOMEM);
18532115b10SPawel Jakub Dawidek 
18632115b10SPawel Jakub Dawidek 	NV_CHECK(nv);
18732115b10SPawel Jakub Dawidek 
18832115b10SPawel Jakub Dawidek 	preverr = nv->nv_error;
18932115b10SPawel Jakub Dawidek 	nv->nv_error = error;
19032115b10SPawel Jakub Dawidek 	return (preverr);
19132115b10SPawel Jakub Dawidek }
19232115b10SPawel Jakub Dawidek 
19332115b10SPawel Jakub Dawidek /*
19432115b10SPawel Jakub Dawidek  * Validate correctness of the entire nv structure and all its elements.
19532115b10SPawel Jakub Dawidek  * If extrap is not NULL, store number of extra bytes at the end of the buffer.
19632115b10SPawel Jakub Dawidek  */
19732115b10SPawel Jakub Dawidek int
nv_validate(struct nv * nv,size_t * extrap)19832115b10SPawel Jakub Dawidek nv_validate(struct nv *nv, size_t *extrap)
19932115b10SPawel Jakub Dawidek {
20032115b10SPawel Jakub Dawidek 	struct nvhdr *nvh;
20132115b10SPawel Jakub Dawidek 	unsigned char *data, *ptr;
20232115b10SPawel Jakub Dawidek 	size_t dsize, size, vsize;
20332115b10SPawel Jakub Dawidek 	int error;
20432115b10SPawel Jakub Dawidek 
20532115b10SPawel Jakub Dawidek 	if (nv == NULL) {
20632115b10SPawel Jakub Dawidek 		errno = ENOMEM;
20732115b10SPawel Jakub Dawidek 		return (-1);
20832115b10SPawel Jakub Dawidek 	}
20932115b10SPawel Jakub Dawidek 
21032115b10SPawel Jakub Dawidek 	NV_CHECK(nv);
211adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(nv->nv_error == 0);
21232115b10SPawel Jakub Dawidek 
21332115b10SPawel Jakub Dawidek 	/* TODO: Check that names are unique? */
21432115b10SPawel Jakub Dawidek 
21532115b10SPawel Jakub Dawidek 	error = 0;
21632115b10SPawel Jakub Dawidek 	ptr = ebuf_data(nv->nv_ebuf, &size);
21732115b10SPawel Jakub Dawidek 	while (size > 0) {
21832115b10SPawel Jakub Dawidek 		/*
21932115b10SPawel Jakub Dawidek 		 * Zeros at the end of the buffer are acceptable.
22032115b10SPawel Jakub Dawidek 		 */
22132115b10SPawel Jakub Dawidek 		if (ptr[0] == '\0')
22232115b10SPawel Jakub Dawidek 			break;
22332115b10SPawel Jakub Dawidek 		/*
22432115b10SPawel Jakub Dawidek 		 * Minimum size at this point is size of nvhdr structure, one
22532115b10SPawel Jakub Dawidek 		 * character long name plus terminating '\0'.
22632115b10SPawel Jakub Dawidek 		 */
22732115b10SPawel Jakub Dawidek 		if (size < sizeof(*nvh) + 2) {
22832115b10SPawel Jakub Dawidek 			error = EINVAL;
22932115b10SPawel Jakub Dawidek 			break;
23032115b10SPawel Jakub Dawidek 		}
23132115b10SPawel Jakub Dawidek 		nvh = (struct nvhdr *)ptr;
23232115b10SPawel Jakub Dawidek 		if (size < NVH_HSIZE(nvh)) {
23332115b10SPawel Jakub Dawidek 			error = EINVAL;
23432115b10SPawel Jakub Dawidek 			break;
23532115b10SPawel Jakub Dawidek 		}
23632115b10SPawel Jakub Dawidek 		if (nvh->nvh_name[nvh->nvh_namesize - 1] != '\0') {
23732115b10SPawel Jakub Dawidek 			error = EINVAL;
23832115b10SPawel Jakub Dawidek 			break;
23932115b10SPawel Jakub Dawidek 		}
24032115b10SPawel Jakub Dawidek 		if (strlen(nvh->nvh_name) !=
24132115b10SPawel Jakub Dawidek 		    (size_t)(nvh->nvh_namesize - 1)) {
24232115b10SPawel Jakub Dawidek 			error = EINVAL;
24332115b10SPawel Jakub Dawidek 			break;
24432115b10SPawel Jakub Dawidek 		}
24532115b10SPawel Jakub Dawidek 		if ((nvh->nvh_type & NV_TYPE_MASK) < NV_TYPE_FIRST ||
24632115b10SPawel Jakub Dawidek 		    (nvh->nvh_type & NV_TYPE_MASK) > NV_TYPE_LAST) {
24732115b10SPawel Jakub Dawidek 			error = EINVAL;
24832115b10SPawel Jakub Dawidek 			break;
24932115b10SPawel Jakub Dawidek 		}
25032115b10SPawel Jakub Dawidek 		dsize = NVH_DSIZE(nvh);
25132115b10SPawel Jakub Dawidek 		if (dsize == 0) {
25232115b10SPawel Jakub Dawidek 			error = EINVAL;
25332115b10SPawel Jakub Dawidek 			break;
25432115b10SPawel Jakub Dawidek 		}
25532115b10SPawel Jakub Dawidek 		if (size < NVH_SIZE(nvh)) {
25632115b10SPawel Jakub Dawidek 			error = EINVAL;
25732115b10SPawel Jakub Dawidek 			break;
25832115b10SPawel Jakub Dawidek 		}
25932115b10SPawel Jakub Dawidek 		vsize = 0;
26032115b10SPawel Jakub Dawidek 		switch (nvh->nvh_type & NV_TYPE_MASK) {
26132115b10SPawel Jakub Dawidek 		case NV_TYPE_INT8:
26232115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT8:
26332115b10SPawel Jakub Dawidek 			if (vsize == 0)
26432115b10SPawel Jakub Dawidek 				vsize = 1;
265f9c5a09cSMikolaj Golub 			/* FALLTHROUGH */
26632115b10SPawel Jakub Dawidek 		case NV_TYPE_INT16:
26732115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT16:
26832115b10SPawel Jakub Dawidek 			if (vsize == 0)
26932115b10SPawel Jakub Dawidek 				vsize = 2;
270f9c5a09cSMikolaj Golub 			/* FALLTHROUGH */
27132115b10SPawel Jakub Dawidek 		case NV_TYPE_INT32:
27232115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT32:
27332115b10SPawel Jakub Dawidek 			if (vsize == 0)
27432115b10SPawel Jakub Dawidek 				vsize = 4;
275f9c5a09cSMikolaj Golub 			/* FALLTHROUGH */
27632115b10SPawel Jakub Dawidek 		case NV_TYPE_INT64:
27732115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT64:
27832115b10SPawel Jakub Dawidek 			if (vsize == 0)
27932115b10SPawel Jakub Dawidek 				vsize = 8;
28032115b10SPawel Jakub Dawidek 			if (dsize != vsize) {
28132115b10SPawel Jakub Dawidek 				error = EINVAL;
28232115b10SPawel Jakub Dawidek 				break;
28332115b10SPawel Jakub Dawidek 			}
28432115b10SPawel Jakub Dawidek 			break;
28532115b10SPawel Jakub Dawidek 		case NV_TYPE_INT8_ARRAY:
28632115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT8_ARRAY:
28732115b10SPawel Jakub Dawidek 			break;
28832115b10SPawel Jakub Dawidek 		case NV_TYPE_INT16_ARRAY:
28932115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT16_ARRAY:
29032115b10SPawel Jakub Dawidek 			if (vsize == 0)
29132115b10SPawel Jakub Dawidek 				vsize = 2;
292f9c5a09cSMikolaj Golub 			/* FALLTHROUGH */
29332115b10SPawel Jakub Dawidek 		case NV_TYPE_INT32_ARRAY:
29432115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT32_ARRAY:
29532115b10SPawel Jakub Dawidek 			if (vsize == 0)
29632115b10SPawel Jakub Dawidek 				vsize = 4;
297f9c5a09cSMikolaj Golub 			/* FALLTHROUGH */
29832115b10SPawel Jakub Dawidek 		case NV_TYPE_INT64_ARRAY:
29932115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT64_ARRAY:
30032115b10SPawel Jakub Dawidek 			if (vsize == 0)
30132115b10SPawel Jakub Dawidek 				vsize = 8;
30232115b10SPawel Jakub Dawidek 			if ((dsize % vsize) != 0) {
30332115b10SPawel Jakub Dawidek 				error = EINVAL;
30432115b10SPawel Jakub Dawidek 				break;
30532115b10SPawel Jakub Dawidek 			}
30632115b10SPawel Jakub Dawidek 			break;
30732115b10SPawel Jakub Dawidek 		case NV_TYPE_STRING:
30832115b10SPawel Jakub Dawidek 			data = NVH_DATA(nvh);
30932115b10SPawel Jakub Dawidek 			if (data[dsize - 1] != '\0') {
31032115b10SPawel Jakub Dawidek 				error = EINVAL;
31132115b10SPawel Jakub Dawidek 				break;
31232115b10SPawel Jakub Dawidek 			}
31332115b10SPawel Jakub Dawidek 			if (strlen((char *)data) != dsize - 1) {
31432115b10SPawel Jakub Dawidek 				error = EINVAL;
31532115b10SPawel Jakub Dawidek 				break;
31632115b10SPawel Jakub Dawidek 			}
31732115b10SPawel Jakub Dawidek 			break;
31832115b10SPawel Jakub Dawidek 		default:
319adf8002bSPawel Jakub Dawidek 			PJDLOG_ABORT("invalid condition");
32032115b10SPawel Jakub Dawidek 		}
32132115b10SPawel Jakub Dawidek 		if (error != 0)
32232115b10SPawel Jakub Dawidek 			break;
32332115b10SPawel Jakub Dawidek 		ptr += NVH_SIZE(nvh);
32432115b10SPawel Jakub Dawidek 		size -= NVH_SIZE(nvh);
32532115b10SPawel Jakub Dawidek 	}
32632115b10SPawel Jakub Dawidek 	if (error != 0) {
32732115b10SPawel Jakub Dawidek 		errno = error;
32832115b10SPawel Jakub Dawidek 		if (nv->nv_error == 0)
32932115b10SPawel Jakub Dawidek 			nv->nv_error = error;
33032115b10SPawel Jakub Dawidek 		return (-1);
33132115b10SPawel Jakub Dawidek 	}
33232115b10SPawel Jakub Dawidek 	if (extrap != NULL)
33332115b10SPawel Jakub Dawidek 		*extrap = size;
33432115b10SPawel Jakub Dawidek 	return (0);
33532115b10SPawel Jakub Dawidek }
33632115b10SPawel Jakub Dawidek 
33732115b10SPawel Jakub Dawidek /*
33832115b10SPawel Jakub Dawidek  * Convert the given nv structure to network byte order and return ebuf
33932115b10SPawel Jakub Dawidek  * structure.
34032115b10SPawel Jakub Dawidek  */
34132115b10SPawel Jakub Dawidek struct ebuf *
nv_hton(struct nv * nv)34232115b10SPawel Jakub Dawidek nv_hton(struct nv *nv)
34332115b10SPawel Jakub Dawidek {
34432115b10SPawel Jakub Dawidek 	struct nvhdr *nvh;
34532115b10SPawel Jakub Dawidek 	unsigned char *ptr;
34632115b10SPawel Jakub Dawidek 	size_t size;
34732115b10SPawel Jakub Dawidek 
34832115b10SPawel Jakub Dawidek 	NV_CHECK(nv);
349adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(nv->nv_error == 0);
35032115b10SPawel Jakub Dawidek 
35132115b10SPawel Jakub Dawidek 	ptr = ebuf_data(nv->nv_ebuf, &size);
35232115b10SPawel Jakub Dawidek 	while (size > 0) {
35332115b10SPawel Jakub Dawidek 		/*
35432115b10SPawel Jakub Dawidek 		 * Minimum size at this point is size of nvhdr structure,
35532115b10SPawel Jakub Dawidek 		 * one character long name plus terminating '\0'.
35632115b10SPawel Jakub Dawidek 		 */
357adf8002bSPawel Jakub Dawidek 		PJDLOG_ASSERT(size >= sizeof(*nvh) + 2);
35832115b10SPawel Jakub Dawidek 		nvh = (struct nvhdr *)ptr;
359adf8002bSPawel Jakub Dawidek 		PJDLOG_ASSERT(NVH_SIZE(nvh) <= size);
36032115b10SPawel Jakub Dawidek 		nv_swap(nvh, false);
36132115b10SPawel Jakub Dawidek 		ptr += NVH_SIZE(nvh);
36232115b10SPawel Jakub Dawidek 		size -= NVH_SIZE(nvh);
36332115b10SPawel Jakub Dawidek 	}
36432115b10SPawel Jakub Dawidek 
36532115b10SPawel Jakub Dawidek 	return (nv->nv_ebuf);
36632115b10SPawel Jakub Dawidek }
36732115b10SPawel Jakub Dawidek 
36832115b10SPawel Jakub Dawidek /*
36932115b10SPawel Jakub Dawidek  * Create nv structure based on ebuf received from the network.
37032115b10SPawel Jakub Dawidek  */
37132115b10SPawel Jakub Dawidek struct nv *
nv_ntoh(struct ebuf * eb)37232115b10SPawel Jakub Dawidek nv_ntoh(struct ebuf *eb)
37332115b10SPawel Jakub Dawidek {
37432115b10SPawel Jakub Dawidek 	struct nv *nv;
37532115b10SPawel Jakub Dawidek 	size_t extra;
37632115b10SPawel Jakub Dawidek 	int rerrno;
37732115b10SPawel Jakub Dawidek 
378adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(eb != NULL);
37932115b10SPawel Jakub Dawidek 
38032115b10SPawel Jakub Dawidek 	nv = malloc(sizeof(*nv));
38132115b10SPawel Jakub Dawidek 	if (nv == NULL)
38232115b10SPawel Jakub Dawidek 		return (NULL);
38332115b10SPawel Jakub Dawidek 	nv->nv_error = 0;
38432115b10SPawel Jakub Dawidek 	nv->nv_ebuf = eb;
38532115b10SPawel Jakub Dawidek 	nv->nv_magic = NV_MAGIC;
38632115b10SPawel Jakub Dawidek 
3872b1b224dSPawel Jakub Dawidek 	if (nv_validate(nv, &extra) == -1) {
38832115b10SPawel Jakub Dawidek 		rerrno = errno;
38932115b10SPawel Jakub Dawidek 		nv->nv_magic = 0;
39032115b10SPawel Jakub Dawidek 		free(nv);
39132115b10SPawel Jakub Dawidek 		errno = rerrno;
39232115b10SPawel Jakub Dawidek 		return (NULL);
39332115b10SPawel Jakub Dawidek 	}
39432115b10SPawel Jakub Dawidek 	/*
39532115b10SPawel Jakub Dawidek 	 * Remove extra zeros at the end of the buffer.
39632115b10SPawel Jakub Dawidek 	 */
39732115b10SPawel Jakub Dawidek 	ebuf_del_tail(eb, extra);
39832115b10SPawel Jakub Dawidek 
39932115b10SPawel Jakub Dawidek 	return (nv);
40032115b10SPawel Jakub Dawidek }
40132115b10SPawel Jakub Dawidek 
40232115b10SPawel Jakub Dawidek #define	NV_DEFINE_ADD(type, TYPE)					\
40332115b10SPawel Jakub Dawidek void									\
40432115b10SPawel Jakub Dawidek nv_add_##type(struct nv *nv, type##_t value, const char *namefmt, ...)	\
40532115b10SPawel Jakub Dawidek {									\
40632115b10SPawel Jakub Dawidek 	va_list nameap;							\
40732115b10SPawel Jakub Dawidek 									\
40832115b10SPawel Jakub Dawidek 	va_start(nameap, namefmt);					\
40932115b10SPawel Jakub Dawidek 	nv_addv(nv, (unsigned char *)&value, sizeof(value),		\
41032115b10SPawel Jakub Dawidek 	    NV_TYPE_##TYPE, namefmt, nameap);				\
41132115b10SPawel Jakub Dawidek 	va_end(nameap);							\
41232115b10SPawel Jakub Dawidek }
41332115b10SPawel Jakub Dawidek 
NV_DEFINE_ADD(int8,INT8)41432115b10SPawel Jakub Dawidek NV_DEFINE_ADD(int8, INT8)
41532115b10SPawel Jakub Dawidek NV_DEFINE_ADD(uint8, UINT8)
41632115b10SPawel Jakub Dawidek NV_DEFINE_ADD(int16, INT16)
41732115b10SPawel Jakub Dawidek NV_DEFINE_ADD(uint16, UINT16)
41832115b10SPawel Jakub Dawidek NV_DEFINE_ADD(int32, INT32)
41932115b10SPawel Jakub Dawidek NV_DEFINE_ADD(uint32, UINT32)
42032115b10SPawel Jakub Dawidek NV_DEFINE_ADD(int64, INT64)
42132115b10SPawel Jakub Dawidek NV_DEFINE_ADD(uint64, UINT64)
42232115b10SPawel Jakub Dawidek 
42332115b10SPawel Jakub Dawidek #undef	NV_DEFINE_ADD
42432115b10SPawel Jakub Dawidek 
42532115b10SPawel Jakub Dawidek #define	NV_DEFINE_ADD_ARRAY(type, TYPE)					\
42632115b10SPawel Jakub Dawidek void									\
42732115b10SPawel Jakub Dawidek nv_add_##type##_array(struct nv *nv, const type##_t *value,		\
42832115b10SPawel Jakub Dawidek     size_t nsize, const char *namefmt, ...)				\
42932115b10SPawel Jakub Dawidek {									\
43032115b10SPawel Jakub Dawidek 	va_list nameap;							\
43132115b10SPawel Jakub Dawidek 									\
43232115b10SPawel Jakub Dawidek 	va_start(nameap, namefmt);					\
43332115b10SPawel Jakub Dawidek 	nv_addv(nv, (const unsigned char *)value,			\
43432115b10SPawel Jakub Dawidek 	    sizeof(value[0]) * nsize, NV_TYPE_##TYPE##_ARRAY, namefmt,	\
43532115b10SPawel Jakub Dawidek 	    nameap);							\
43632115b10SPawel Jakub Dawidek 	va_end(nameap);							\
43732115b10SPawel Jakub Dawidek }
43832115b10SPawel Jakub Dawidek 
43932115b10SPawel Jakub Dawidek NV_DEFINE_ADD_ARRAY(int8, INT8)
44032115b10SPawel Jakub Dawidek NV_DEFINE_ADD_ARRAY(uint8, UINT8)
44132115b10SPawel Jakub Dawidek NV_DEFINE_ADD_ARRAY(int16, INT16)
44232115b10SPawel Jakub Dawidek NV_DEFINE_ADD_ARRAY(uint16, UINT16)
44332115b10SPawel Jakub Dawidek NV_DEFINE_ADD_ARRAY(int32, INT32)
44432115b10SPawel Jakub Dawidek NV_DEFINE_ADD_ARRAY(uint32, UINT32)
44532115b10SPawel Jakub Dawidek NV_DEFINE_ADD_ARRAY(int64, INT64)
44632115b10SPawel Jakub Dawidek NV_DEFINE_ADD_ARRAY(uint64, UINT64)
44732115b10SPawel Jakub Dawidek 
44832115b10SPawel Jakub Dawidek #undef	NV_DEFINE_ADD_ARRAY
44932115b10SPawel Jakub Dawidek 
45032115b10SPawel Jakub Dawidek void
45132115b10SPawel Jakub Dawidek nv_add_string(struct nv *nv, const char *value, const char *namefmt, ...)
45232115b10SPawel Jakub Dawidek {
45332115b10SPawel Jakub Dawidek 	va_list nameap;
45432115b10SPawel Jakub Dawidek 	size_t size;
45532115b10SPawel Jakub Dawidek 
45632115b10SPawel Jakub Dawidek 	size = strlen(value) + 1;
45732115b10SPawel Jakub Dawidek 
45832115b10SPawel Jakub Dawidek 	va_start(nameap, namefmt);
45932115b10SPawel Jakub Dawidek 	nv_addv(nv, (const unsigned char *)value, size, NV_TYPE_STRING,
46032115b10SPawel Jakub Dawidek 	    namefmt, nameap);
46132115b10SPawel Jakub Dawidek 	va_end(nameap);
46232115b10SPawel Jakub Dawidek }
46332115b10SPawel Jakub Dawidek 
46432115b10SPawel Jakub Dawidek void
nv_add_stringf(struct nv * nv,const char * name,const char * valuefmt,...)46532115b10SPawel Jakub Dawidek nv_add_stringf(struct nv *nv, const char *name, const char *valuefmt, ...)
46632115b10SPawel Jakub Dawidek {
46732115b10SPawel Jakub Dawidek 	va_list valueap;
46832115b10SPawel Jakub Dawidek 
46932115b10SPawel Jakub Dawidek 	va_start(valueap, valuefmt);
47032115b10SPawel Jakub Dawidek 	nv_add_stringv(nv, name, valuefmt, valueap);
47132115b10SPawel Jakub Dawidek 	va_end(valueap);
47232115b10SPawel Jakub Dawidek }
47332115b10SPawel Jakub Dawidek 
47432115b10SPawel Jakub Dawidek void
nv_add_stringv(struct nv * nv,const char * name,const char * valuefmt,va_list valueap)47532115b10SPawel Jakub Dawidek nv_add_stringv(struct nv *nv, const char *name, const char *valuefmt,
47632115b10SPawel Jakub Dawidek     va_list valueap)
47732115b10SPawel Jakub Dawidek {
47832115b10SPawel Jakub Dawidek 	char *value;
47932115b10SPawel Jakub Dawidek 	ssize_t size;
48032115b10SPawel Jakub Dawidek 
48132115b10SPawel Jakub Dawidek 	size = vasprintf(&value, valuefmt, valueap);
4822b1b224dSPawel Jakub Dawidek 	if (size == -1) {
48332115b10SPawel Jakub Dawidek 		if (nv->nv_error == 0)
48432115b10SPawel Jakub Dawidek 			nv->nv_error = ENOMEM;
48532115b10SPawel Jakub Dawidek 		return;
48632115b10SPawel Jakub Dawidek 	}
48732115b10SPawel Jakub Dawidek 	size++;
48832115b10SPawel Jakub Dawidek 	nv_add(nv, (const unsigned char *)value, size, NV_TYPE_STRING, name);
48932115b10SPawel Jakub Dawidek 	free(value);
49032115b10SPawel Jakub Dawidek }
49132115b10SPawel Jakub Dawidek 
49232115b10SPawel Jakub Dawidek #define	NV_DEFINE_GET(type, TYPE)					\
49332115b10SPawel Jakub Dawidek type##_t								\
49432115b10SPawel Jakub Dawidek nv_get_##type(struct nv *nv, const char *namefmt, ...)			\
49532115b10SPawel Jakub Dawidek {									\
49632115b10SPawel Jakub Dawidek 	struct nvhdr *nvh;						\
49732115b10SPawel Jakub Dawidek 	va_list nameap;							\
49832115b10SPawel Jakub Dawidek 	type##_t value;							\
49932115b10SPawel Jakub Dawidek 									\
50032115b10SPawel Jakub Dawidek 	va_start(nameap, namefmt);					\
50132115b10SPawel Jakub Dawidek 	nvh = nv_find(nv, NV_TYPE_##TYPE, namefmt, nameap);		\
50232115b10SPawel Jakub Dawidek 	va_end(nameap);							\
50332115b10SPawel Jakub Dawidek 	if (nvh == NULL)						\
50432115b10SPawel Jakub Dawidek 		return (0);						\
505adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT((nvh->nvh_type & NV_ORDER_MASK) == NV_ORDER_HOST);\
506adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(sizeof(value) == nvh->nvh_dsize);			\
50732115b10SPawel Jakub Dawidek 	bcopy(NVH_DATA(nvh), &value, sizeof(value));			\
50832115b10SPawel Jakub Dawidek 									\
50932115b10SPawel Jakub Dawidek 	return (value);							\
51032115b10SPawel Jakub Dawidek }
51132115b10SPawel Jakub Dawidek 
NV_DEFINE_GET(int8,INT8)51232115b10SPawel Jakub Dawidek NV_DEFINE_GET(int8, INT8)
51332115b10SPawel Jakub Dawidek NV_DEFINE_GET(uint8, UINT8)
51432115b10SPawel Jakub Dawidek NV_DEFINE_GET(int16, INT16)
51532115b10SPawel Jakub Dawidek NV_DEFINE_GET(uint16, UINT16)
51632115b10SPawel Jakub Dawidek NV_DEFINE_GET(int32, INT32)
51732115b10SPawel Jakub Dawidek NV_DEFINE_GET(uint32, UINT32)
51832115b10SPawel Jakub Dawidek NV_DEFINE_GET(int64, INT64)
51932115b10SPawel Jakub Dawidek NV_DEFINE_GET(uint64, UINT64)
52032115b10SPawel Jakub Dawidek 
52132115b10SPawel Jakub Dawidek #undef	NV_DEFINE_GET
52232115b10SPawel Jakub Dawidek 
52332115b10SPawel Jakub Dawidek #define	NV_DEFINE_GET_ARRAY(type, TYPE)					\
52432115b10SPawel Jakub Dawidek const type##_t *							\
52532115b10SPawel Jakub Dawidek nv_get_##type##_array(struct nv *nv, size_t *sizep,			\
52632115b10SPawel Jakub Dawidek     const char *namefmt, ...)						\
52732115b10SPawel Jakub Dawidek {									\
52832115b10SPawel Jakub Dawidek 	struct nvhdr *nvh;						\
52932115b10SPawel Jakub Dawidek 	va_list nameap;							\
53032115b10SPawel Jakub Dawidek 									\
53132115b10SPawel Jakub Dawidek 	va_start(nameap, namefmt);					\
53232115b10SPawel Jakub Dawidek 	nvh = nv_find(nv, NV_TYPE_##TYPE##_ARRAY, namefmt, nameap);	\
53332115b10SPawel Jakub Dawidek 	va_end(nameap);							\
53432115b10SPawel Jakub Dawidek 	if (nvh == NULL)						\
53532115b10SPawel Jakub Dawidek 		return (NULL);						\
536adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT((nvh->nvh_type & NV_ORDER_MASK) == NV_ORDER_HOST);\
537adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT((nvh->nvh_dsize % sizeof(type##_t)) == 0);	\
53832115b10SPawel Jakub Dawidek 	if (sizep != NULL)						\
53932115b10SPawel Jakub Dawidek 		*sizep = nvh->nvh_dsize / sizeof(type##_t);		\
54032115b10SPawel Jakub Dawidek 	return ((type##_t *)(void *)NVH_DATA(nvh));			\
54132115b10SPawel Jakub Dawidek }
54232115b10SPawel Jakub Dawidek 
54332115b10SPawel Jakub Dawidek NV_DEFINE_GET_ARRAY(int8, INT8)
54432115b10SPawel Jakub Dawidek NV_DEFINE_GET_ARRAY(uint8, UINT8)
54532115b10SPawel Jakub Dawidek NV_DEFINE_GET_ARRAY(int16, INT16)
54632115b10SPawel Jakub Dawidek NV_DEFINE_GET_ARRAY(uint16, UINT16)
54732115b10SPawel Jakub Dawidek NV_DEFINE_GET_ARRAY(int32, INT32)
54832115b10SPawel Jakub Dawidek NV_DEFINE_GET_ARRAY(uint32, UINT32)
54932115b10SPawel Jakub Dawidek NV_DEFINE_GET_ARRAY(int64, INT64)
55032115b10SPawel Jakub Dawidek NV_DEFINE_GET_ARRAY(uint64, UINT64)
55132115b10SPawel Jakub Dawidek 
55232115b10SPawel Jakub Dawidek #undef	NV_DEFINE_GET_ARRAY
55332115b10SPawel Jakub Dawidek 
55432115b10SPawel Jakub Dawidek const char *
55532115b10SPawel Jakub Dawidek nv_get_string(struct nv *nv, const char *namefmt, ...)
55632115b10SPawel Jakub Dawidek {
55732115b10SPawel Jakub Dawidek 	struct nvhdr *nvh;
55832115b10SPawel Jakub Dawidek 	va_list nameap;
55932115b10SPawel Jakub Dawidek 	char *str;
56032115b10SPawel Jakub Dawidek 
56132115b10SPawel Jakub Dawidek 	va_start(nameap, namefmt);
56232115b10SPawel Jakub Dawidek 	nvh = nv_find(nv, NV_TYPE_STRING, namefmt, nameap);
56332115b10SPawel Jakub Dawidek 	va_end(nameap);
56432115b10SPawel Jakub Dawidek 	if (nvh == NULL)
56532115b10SPawel Jakub Dawidek 		return (NULL);
566adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT((nvh->nvh_type & NV_ORDER_MASK) == NV_ORDER_HOST);
567adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(nvh->nvh_dsize >= 1);
5684d70e06fSMikolaj Golub 	str = (char *)NVH_DATA(nvh);
569adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(str[nvh->nvh_dsize - 1] == '\0');
570adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(strlen(str) == nvh->nvh_dsize - 1);
57132115b10SPawel Jakub Dawidek 	return (str);
57232115b10SPawel Jakub Dawidek }
57332115b10SPawel Jakub Dawidek 
574eed4e65fSPawel Jakub Dawidek static bool
nv_vexists(struct nv * nv,const char * namefmt,va_list nameap)575eed4e65fSPawel Jakub Dawidek nv_vexists(struct nv *nv, const char *namefmt, va_list nameap)
576b9ffbb0aSPawel Jakub Dawidek {
577b9ffbb0aSPawel Jakub Dawidek 	struct nvhdr *nvh;
578b9ffbb0aSPawel Jakub Dawidek 	int snverror, serrno;
579b9ffbb0aSPawel Jakub Dawidek 
580b9ffbb0aSPawel Jakub Dawidek 	if (nv == NULL)
581b9ffbb0aSPawel Jakub Dawidek 		return (false);
582b9ffbb0aSPawel Jakub Dawidek 
583b9ffbb0aSPawel Jakub Dawidek 	serrno = errno;
584b9ffbb0aSPawel Jakub Dawidek 	snverror = nv->nv_error;
585b9ffbb0aSPawel Jakub Dawidek 
586b9ffbb0aSPawel Jakub Dawidek 	nvh = nv_find(nv, NV_TYPE_NONE, namefmt, nameap);
587b9ffbb0aSPawel Jakub Dawidek 
588b9ffbb0aSPawel Jakub Dawidek 	errno = serrno;
589b9ffbb0aSPawel Jakub Dawidek 	nv->nv_error = snverror;
590b9ffbb0aSPawel Jakub Dawidek 
591b9ffbb0aSPawel Jakub Dawidek 	return (nvh != NULL);
592b9ffbb0aSPawel Jakub Dawidek }
593b9ffbb0aSPawel Jakub Dawidek 
594eed4e65fSPawel Jakub Dawidek bool
nv_exists(struct nv * nv,const char * namefmt,...)595eed4e65fSPawel Jakub Dawidek nv_exists(struct nv *nv, const char *namefmt, ...)
596eed4e65fSPawel Jakub Dawidek {
597eed4e65fSPawel Jakub Dawidek 	va_list nameap;
598eed4e65fSPawel Jakub Dawidek 	bool ret;
599eed4e65fSPawel Jakub Dawidek 
600eed4e65fSPawel Jakub Dawidek 	va_start(nameap, namefmt);
601eed4e65fSPawel Jakub Dawidek 	ret = nv_vexists(nv, namefmt, nameap);
602eed4e65fSPawel Jakub Dawidek 	va_end(nameap);
603eed4e65fSPawel Jakub Dawidek 
604eed4e65fSPawel Jakub Dawidek 	return (ret);
605eed4e65fSPawel Jakub Dawidek }
606eed4e65fSPawel Jakub Dawidek 
607eed4e65fSPawel Jakub Dawidek void
nv_assert(struct nv * nv,const char * namefmt,...)608eed4e65fSPawel Jakub Dawidek nv_assert(struct nv *nv, const char *namefmt, ...)
609eed4e65fSPawel Jakub Dawidek {
610eed4e65fSPawel Jakub Dawidek 	va_list nameap;
611eed4e65fSPawel Jakub Dawidek 
612eed4e65fSPawel Jakub Dawidek 	va_start(nameap, namefmt);
613adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(nv_vexists(nv, namefmt, nameap));
614eed4e65fSPawel Jakub Dawidek 	va_end(nameap);
615eed4e65fSPawel Jakub Dawidek }
616eed4e65fSPawel Jakub Dawidek 
61732115b10SPawel Jakub Dawidek /*
61832115b10SPawel Jakub Dawidek  * Dump content of the nv structure.
61932115b10SPawel Jakub Dawidek  */
62032115b10SPawel Jakub Dawidek void
nv_dump(struct nv * nv)62132115b10SPawel Jakub Dawidek nv_dump(struct nv *nv)
62232115b10SPawel Jakub Dawidek {
62332115b10SPawel Jakub Dawidek 	struct nvhdr *nvh;
62432115b10SPawel Jakub Dawidek 	unsigned char *data, *ptr;
62532115b10SPawel Jakub Dawidek 	size_t dsize, size;
62632115b10SPawel Jakub Dawidek 	unsigned int ii;
62732115b10SPawel Jakub Dawidek 	bool swap;
62832115b10SPawel Jakub Dawidek 
6292b1b224dSPawel Jakub Dawidek 	if (nv_validate(nv, NULL) == -1) {
63032115b10SPawel Jakub Dawidek 		printf("error: %d\n", errno);
63132115b10SPawel Jakub Dawidek 		return;
63232115b10SPawel Jakub Dawidek 	}
63332115b10SPawel Jakub Dawidek 
63432115b10SPawel Jakub Dawidek 	NV_CHECK(nv);
635adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(nv->nv_error == 0);
63632115b10SPawel Jakub Dawidek 
63732115b10SPawel Jakub Dawidek 	ptr = ebuf_data(nv->nv_ebuf, &size);
63832115b10SPawel Jakub Dawidek 	while (size > 0) {
639adf8002bSPawel Jakub Dawidek 		PJDLOG_ASSERT(size >= sizeof(*nvh) + 2);
64032115b10SPawel Jakub Dawidek 		nvh = (struct nvhdr *)ptr;
641adf8002bSPawel Jakub Dawidek 		PJDLOG_ASSERT(size >= NVH_SIZE(nvh));
64232115b10SPawel Jakub Dawidek 		swap = ((nvh->nvh_type & NV_ORDER_MASK) == NV_ORDER_NETWORK);
64332115b10SPawel Jakub Dawidek 		dsize = NVH_DSIZE(nvh);
64432115b10SPawel Jakub Dawidek 		data = NVH_DATA(nvh);
64532115b10SPawel Jakub Dawidek 		printf("  %s", nvh->nvh_name);
64632115b10SPawel Jakub Dawidek 		switch (nvh->nvh_type & NV_TYPE_MASK) {
64732115b10SPawel Jakub Dawidek 		case NV_TYPE_INT8:
64832115b10SPawel Jakub Dawidek 			printf("(int8): %jd", (intmax_t)(*(int8_t *)data));
64932115b10SPawel Jakub Dawidek 			break;
65032115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT8:
65132115b10SPawel Jakub Dawidek 			printf("(uint8): %ju", (uintmax_t)(*(uint8_t *)data));
65232115b10SPawel Jakub Dawidek 			break;
65332115b10SPawel Jakub Dawidek 		case NV_TYPE_INT16:
65432115b10SPawel Jakub Dawidek 			printf("(int16): %jd", swap ?
65532115b10SPawel Jakub Dawidek 			    (intmax_t)le16toh(*(int16_t *)(void *)data) :
65632115b10SPawel Jakub Dawidek 			    (intmax_t)*(int16_t *)(void *)data);
65732115b10SPawel Jakub Dawidek 			break;
65832115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT16:
65932115b10SPawel Jakub Dawidek 			printf("(uint16): %ju", swap ?
66032115b10SPawel Jakub Dawidek 			    (uintmax_t)le16toh(*(uint16_t *)(void *)data) :
66132115b10SPawel Jakub Dawidek 			    (uintmax_t)*(uint16_t *)(void *)data);
66232115b10SPawel Jakub Dawidek 			break;
66332115b10SPawel Jakub Dawidek 		case NV_TYPE_INT32:
66432115b10SPawel Jakub Dawidek 			printf("(int32): %jd", swap ?
66532115b10SPawel Jakub Dawidek 			    (intmax_t)le32toh(*(int32_t *)(void *)data) :
66632115b10SPawel Jakub Dawidek 			    (intmax_t)*(int32_t *)(void *)data);
66732115b10SPawel Jakub Dawidek 			break;
66832115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT32:
66932115b10SPawel Jakub Dawidek 			printf("(uint32): %ju", swap ?
67032115b10SPawel Jakub Dawidek 			    (uintmax_t)le32toh(*(uint32_t *)(void *)data) :
67132115b10SPawel Jakub Dawidek 			    (uintmax_t)*(uint32_t *)(void *)data);
67232115b10SPawel Jakub Dawidek 			break;
67332115b10SPawel Jakub Dawidek 		case NV_TYPE_INT64:
67432115b10SPawel Jakub Dawidek 			printf("(int64): %jd", swap ?
67532115b10SPawel Jakub Dawidek 			    (intmax_t)le64toh(*(int64_t *)(void *)data) :
67632115b10SPawel Jakub Dawidek 			    (intmax_t)*(int64_t *)(void *)data);
67732115b10SPawel Jakub Dawidek 			break;
67832115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT64:
67932115b10SPawel Jakub Dawidek 			printf("(uint64): %ju", swap ?
68032115b10SPawel Jakub Dawidek 			    (uintmax_t)le64toh(*(uint64_t *)(void *)data) :
68132115b10SPawel Jakub Dawidek 			    (uintmax_t)*(uint64_t *)(void *)data);
68232115b10SPawel Jakub Dawidek 			break;
68332115b10SPawel Jakub Dawidek 		case NV_TYPE_INT8_ARRAY:
68432115b10SPawel Jakub Dawidek 			printf("(int8 array):");
68532115b10SPawel Jakub Dawidek 			for (ii = 0; ii < dsize; ii++)
68632115b10SPawel Jakub Dawidek 				printf(" %jd", (intmax_t)((int8_t *)data)[ii]);
68732115b10SPawel Jakub Dawidek 			break;
68832115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT8_ARRAY:
68932115b10SPawel Jakub Dawidek 			printf("(uint8 array):");
69032115b10SPawel Jakub Dawidek 			for (ii = 0; ii < dsize; ii++)
69132115b10SPawel Jakub Dawidek 				printf(" %ju", (uintmax_t)((uint8_t *)data)[ii]);
69232115b10SPawel Jakub Dawidek 			break;
69332115b10SPawel Jakub Dawidek 		case NV_TYPE_INT16_ARRAY:
69432115b10SPawel Jakub Dawidek 			printf("(int16 array):");
69532115b10SPawel Jakub Dawidek 			for (ii = 0; ii < dsize / 2; ii++) {
69632115b10SPawel Jakub Dawidek 				printf(" %jd", swap ?
69732115b10SPawel Jakub Dawidek 				    (intmax_t)le16toh(((int16_t *)(void *)data)[ii]) :
69832115b10SPawel Jakub Dawidek 				    (intmax_t)((int16_t *)(void *)data)[ii]);
69932115b10SPawel Jakub Dawidek 			}
70032115b10SPawel Jakub Dawidek 			break;
70132115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT16_ARRAY:
70232115b10SPawel Jakub Dawidek 			printf("(uint16 array):");
70332115b10SPawel Jakub Dawidek 			for (ii = 0; ii < dsize / 2; ii++) {
70432115b10SPawel Jakub Dawidek 				printf(" %ju", swap ?
70532115b10SPawel Jakub Dawidek 				    (uintmax_t)le16toh(((uint16_t *)(void *)data)[ii]) :
70632115b10SPawel Jakub Dawidek 				    (uintmax_t)((uint16_t *)(void *)data)[ii]);
70732115b10SPawel Jakub Dawidek 			}
70832115b10SPawel Jakub Dawidek 			break;
70932115b10SPawel Jakub Dawidek 		case NV_TYPE_INT32_ARRAY:
71032115b10SPawel Jakub Dawidek 			printf("(int32 array):");
71132115b10SPawel Jakub Dawidek 			for (ii = 0; ii < dsize / 4; ii++) {
71232115b10SPawel Jakub Dawidek 				printf(" %jd", swap ?
71332115b10SPawel Jakub Dawidek 				    (intmax_t)le32toh(((int32_t *)(void *)data)[ii]) :
71432115b10SPawel Jakub Dawidek 				    (intmax_t)((int32_t *)(void *)data)[ii]);
71532115b10SPawel Jakub Dawidek 			}
71632115b10SPawel Jakub Dawidek 			break;
71732115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT32_ARRAY:
71832115b10SPawel Jakub Dawidek 			printf("(uint32 array):");
71932115b10SPawel Jakub Dawidek 			for (ii = 0; ii < dsize / 4; ii++) {
72032115b10SPawel Jakub Dawidek 				printf(" %ju", swap ?
72132115b10SPawel Jakub Dawidek 				    (uintmax_t)le32toh(((uint32_t *)(void *)data)[ii]) :
72232115b10SPawel Jakub Dawidek 				    (uintmax_t)((uint32_t *)(void *)data)[ii]);
72332115b10SPawel Jakub Dawidek 			}
72432115b10SPawel Jakub Dawidek 			break;
72532115b10SPawel Jakub Dawidek 		case NV_TYPE_INT64_ARRAY:
72632115b10SPawel Jakub Dawidek 			printf("(int64 array):");
72732115b10SPawel Jakub Dawidek 			for (ii = 0; ii < dsize / 8; ii++) {
72832115b10SPawel Jakub Dawidek 				printf(" %ju", swap ?
72932115b10SPawel Jakub Dawidek 				    (uintmax_t)le64toh(((uint64_t *)(void *)data)[ii]) :
73032115b10SPawel Jakub Dawidek 				    (uintmax_t)((uint64_t *)(void *)data)[ii]);
73132115b10SPawel Jakub Dawidek 			}
73232115b10SPawel Jakub Dawidek 			break;
73332115b10SPawel Jakub Dawidek 		case NV_TYPE_UINT64_ARRAY:
73432115b10SPawel Jakub Dawidek 			printf("(uint64 array):");
73532115b10SPawel Jakub Dawidek 			for (ii = 0; ii < dsize / 8; ii++) {
73632115b10SPawel Jakub Dawidek 				printf(" %ju", swap ?
73732115b10SPawel Jakub Dawidek 				    (uintmax_t)le64toh(((uint64_t *)(void *)data)[ii]) :
73832115b10SPawel Jakub Dawidek 				    (uintmax_t)((uint64_t *)(void *)data)[ii]);
73932115b10SPawel Jakub Dawidek 			}
74032115b10SPawel Jakub Dawidek 			break;
74132115b10SPawel Jakub Dawidek 		case NV_TYPE_STRING:
74232115b10SPawel Jakub Dawidek 			printf("(string): %s", (char *)data);
74332115b10SPawel Jakub Dawidek 			break;
74432115b10SPawel Jakub Dawidek 		default:
745adf8002bSPawel Jakub Dawidek 			PJDLOG_ABORT("invalid condition");
74632115b10SPawel Jakub Dawidek 		}
74732115b10SPawel Jakub Dawidek 		printf("\n");
74832115b10SPawel Jakub Dawidek 		ptr += NVH_SIZE(nvh);
74932115b10SPawel Jakub Dawidek 		size -= NVH_SIZE(nvh);
75032115b10SPawel Jakub Dawidek 	}
75132115b10SPawel Jakub Dawidek }
75232115b10SPawel Jakub Dawidek 
75332115b10SPawel Jakub Dawidek /*
75432115b10SPawel Jakub Dawidek  * Local routines below.
75532115b10SPawel Jakub Dawidek  */
75632115b10SPawel Jakub Dawidek 
75732115b10SPawel Jakub Dawidek static void
nv_add(struct nv * nv,const unsigned char * value,size_t vsize,int type,const char * name)75832115b10SPawel Jakub Dawidek nv_add(struct nv *nv, const unsigned char *value, size_t vsize, int type,
75932115b10SPawel Jakub Dawidek     const char *name)
76032115b10SPawel Jakub Dawidek {
76132115b10SPawel Jakub Dawidek 	static unsigned char align[7];
76232115b10SPawel Jakub Dawidek 	struct nvhdr *nvh;
76332115b10SPawel Jakub Dawidek 	size_t namesize;
76432115b10SPawel Jakub Dawidek 
76532115b10SPawel Jakub Dawidek 	if (nv == NULL) {
76632115b10SPawel Jakub Dawidek 		errno = ENOMEM;
76732115b10SPawel Jakub Dawidek 		return;
76832115b10SPawel Jakub Dawidek 	}
76932115b10SPawel Jakub Dawidek 
77032115b10SPawel Jakub Dawidek 	NV_CHECK(nv);
77132115b10SPawel Jakub Dawidek 
77232115b10SPawel Jakub Dawidek 	namesize = strlen(name) + 1;
77332115b10SPawel Jakub Dawidek 
77432115b10SPawel Jakub Dawidek 	nvh = malloc(sizeof(*nvh) + roundup2(namesize, 8));
77532115b10SPawel Jakub Dawidek 	if (nvh == NULL) {
77632115b10SPawel Jakub Dawidek 		if (nv->nv_error == 0)
77732115b10SPawel Jakub Dawidek 			nv->nv_error = ENOMEM;
77832115b10SPawel Jakub Dawidek 		return;
77932115b10SPawel Jakub Dawidek 	}
78032115b10SPawel Jakub Dawidek 	nvh->nvh_type = NV_ORDER_HOST | type;
78132115b10SPawel Jakub Dawidek 	nvh->nvh_namesize = (uint8_t)namesize;
78232115b10SPawel Jakub Dawidek 	nvh->nvh_dsize = (uint32_t)vsize;
78332115b10SPawel Jakub Dawidek 	bcopy(name, nvh->nvh_name, namesize);
78432115b10SPawel Jakub Dawidek 
78532115b10SPawel Jakub Dawidek 	/* Add header first. */
7862b1b224dSPawel Jakub Dawidek 	if (ebuf_add_tail(nv->nv_ebuf, nvh, NVH_HSIZE(nvh)) == -1) {
787adf8002bSPawel Jakub Dawidek 		PJDLOG_ASSERT(errno != 0);
78832115b10SPawel Jakub Dawidek 		if (nv->nv_error == 0)
78932115b10SPawel Jakub Dawidek 			nv->nv_error = errno;
7909f31eddbSPawel Jakub Dawidek 		free(nvh);
79132115b10SPawel Jakub Dawidek 		return;
79232115b10SPawel Jakub Dawidek 	}
7939f31eddbSPawel Jakub Dawidek 	free(nvh);
79432115b10SPawel Jakub Dawidek 	/* Add the actual data. */
7952b1b224dSPawel Jakub Dawidek 	if (ebuf_add_tail(nv->nv_ebuf, value, vsize) == -1) {
796adf8002bSPawel Jakub Dawidek 		PJDLOG_ASSERT(errno != 0);
79732115b10SPawel Jakub Dawidek 		if (nv->nv_error == 0)
79832115b10SPawel Jakub Dawidek 			nv->nv_error = errno;
79932115b10SPawel Jakub Dawidek 		return;
80032115b10SPawel Jakub Dawidek 	}
80132115b10SPawel Jakub Dawidek 	/* Align the data (if needed). */
80232115b10SPawel Jakub Dawidek 	vsize = roundup2(vsize, 8) - vsize;
80332115b10SPawel Jakub Dawidek 	if (vsize == 0)
80432115b10SPawel Jakub Dawidek 		return;
805adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(vsize > 0 && vsize <= sizeof(align));
8062b1b224dSPawel Jakub Dawidek 	if (ebuf_add_tail(nv->nv_ebuf, align, vsize) == -1) {
807adf8002bSPawel Jakub Dawidek 		PJDLOG_ASSERT(errno != 0);
80832115b10SPawel Jakub Dawidek 		if (nv->nv_error == 0)
80932115b10SPawel Jakub Dawidek 			nv->nv_error = errno;
81032115b10SPawel Jakub Dawidek 		return;
81132115b10SPawel Jakub Dawidek 	}
81232115b10SPawel Jakub Dawidek }
81332115b10SPawel Jakub Dawidek 
81432115b10SPawel Jakub Dawidek static void
nv_addv(struct nv * nv,const unsigned char * value,size_t vsize,int type,const char * namefmt,va_list nameap)81532115b10SPawel Jakub Dawidek nv_addv(struct nv *nv, const unsigned char *value, size_t vsize, int type,
81632115b10SPawel Jakub Dawidek     const char *namefmt, va_list nameap)
81732115b10SPawel Jakub Dawidek {
81832115b10SPawel Jakub Dawidek 	char name[255];
81932115b10SPawel Jakub Dawidek 	size_t namesize;
82032115b10SPawel Jakub Dawidek 
82132115b10SPawel Jakub Dawidek 	namesize = vsnprintf(name, sizeof(name), namefmt, nameap);
822adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(namesize > 0 && namesize < sizeof(name));
82332115b10SPawel Jakub Dawidek 
82432115b10SPawel Jakub Dawidek 	nv_add(nv, value, vsize, type, name);
82532115b10SPawel Jakub Dawidek }
82632115b10SPawel Jakub Dawidek 
82732115b10SPawel Jakub Dawidek static struct nvhdr *
nv_find(struct nv * nv,int type,const char * namefmt,va_list nameap)82832115b10SPawel Jakub Dawidek nv_find(struct nv *nv, int type, const char *namefmt, va_list nameap)
82932115b10SPawel Jakub Dawidek {
83032115b10SPawel Jakub Dawidek 	char name[255];
83132115b10SPawel Jakub Dawidek 	struct nvhdr *nvh;
83232115b10SPawel Jakub Dawidek 	unsigned char *ptr;
83332115b10SPawel Jakub Dawidek 	size_t size, namesize;
83432115b10SPawel Jakub Dawidek 
83532115b10SPawel Jakub Dawidek 	if (nv == NULL) {
83632115b10SPawel Jakub Dawidek 		errno = ENOMEM;
83732115b10SPawel Jakub Dawidek 		return (NULL);
83832115b10SPawel Jakub Dawidek 	}
83932115b10SPawel Jakub Dawidek 
84032115b10SPawel Jakub Dawidek 	NV_CHECK(nv);
84132115b10SPawel Jakub Dawidek 
84232115b10SPawel Jakub Dawidek 	namesize = vsnprintf(name, sizeof(name), namefmt, nameap);
843adf8002bSPawel Jakub Dawidek 	PJDLOG_ASSERT(namesize > 0 && namesize < sizeof(name));
84432115b10SPawel Jakub Dawidek 	namesize++;
84532115b10SPawel Jakub Dawidek 
84632115b10SPawel Jakub Dawidek 	ptr = ebuf_data(nv->nv_ebuf, &size);
84732115b10SPawel Jakub Dawidek 	while (size > 0) {
848adf8002bSPawel Jakub Dawidek 		PJDLOG_ASSERT(size >= sizeof(*nvh) + 2);
84932115b10SPawel Jakub Dawidek 		nvh = (struct nvhdr *)ptr;
850adf8002bSPawel Jakub Dawidek 		PJDLOG_ASSERT(size >= NVH_SIZE(nvh));
85132115b10SPawel Jakub Dawidek 		nv_swap(nvh, true);
85232115b10SPawel Jakub Dawidek 		if (strcmp(nvh->nvh_name, name) == 0) {
853b9ffbb0aSPawel Jakub Dawidek 			if (type != NV_TYPE_NONE &&
854b9ffbb0aSPawel Jakub Dawidek 			    (nvh->nvh_type & NV_TYPE_MASK) != type) {
85532115b10SPawel Jakub Dawidek 				errno = EINVAL;
85632115b10SPawel Jakub Dawidek 				if (nv->nv_error == 0)
85732115b10SPawel Jakub Dawidek 					nv->nv_error = EINVAL;
85832115b10SPawel Jakub Dawidek 				return (NULL);
85932115b10SPawel Jakub Dawidek 			}
86032115b10SPawel Jakub Dawidek 			return (nvh);
86132115b10SPawel Jakub Dawidek 		}
86232115b10SPawel Jakub Dawidek 		ptr += NVH_SIZE(nvh);
86332115b10SPawel Jakub Dawidek 		size -= NVH_SIZE(nvh);
86432115b10SPawel Jakub Dawidek 	}
86532115b10SPawel Jakub Dawidek 	errno = ENOENT;
86632115b10SPawel Jakub Dawidek 	if (nv->nv_error == 0)
86732115b10SPawel Jakub Dawidek 		nv->nv_error = ENOENT;
86832115b10SPawel Jakub Dawidek 	return (NULL);
86932115b10SPawel Jakub Dawidek }
87032115b10SPawel Jakub Dawidek 
87132115b10SPawel Jakub Dawidek static void
nv_swap(struct nvhdr * nvh,bool tohost)87232115b10SPawel Jakub Dawidek nv_swap(struct nvhdr *nvh, bool tohost)
87332115b10SPawel Jakub Dawidek {
87432115b10SPawel Jakub Dawidek 	unsigned char *data, *end, *p;
87532115b10SPawel Jakub Dawidek 	size_t vsize;
87632115b10SPawel Jakub Dawidek 
87732115b10SPawel Jakub Dawidek 	data = NVH_DATA(nvh);
87832115b10SPawel Jakub Dawidek 	if (tohost) {
87932115b10SPawel Jakub Dawidek 		if ((nvh->nvh_type & NV_ORDER_MASK) == NV_ORDER_HOST)
88032115b10SPawel Jakub Dawidek 			return;
88132115b10SPawel Jakub Dawidek 		nvh->nvh_dsize = le32toh(nvh->nvh_dsize);
88232115b10SPawel Jakub Dawidek 		end = data + nvh->nvh_dsize;
88332115b10SPawel Jakub Dawidek 		nvh->nvh_type &= ~NV_ORDER_MASK;
88432115b10SPawel Jakub Dawidek 		nvh->nvh_type |= NV_ORDER_HOST;
88532115b10SPawel Jakub Dawidek 	} else {
88632115b10SPawel Jakub Dawidek 		if ((nvh->nvh_type & NV_ORDER_MASK) == NV_ORDER_NETWORK)
88732115b10SPawel Jakub Dawidek 			return;
88832115b10SPawel Jakub Dawidek 		end = data + nvh->nvh_dsize;
88932115b10SPawel Jakub Dawidek 		nvh->nvh_dsize = htole32(nvh->nvh_dsize);
89032115b10SPawel Jakub Dawidek 		nvh->nvh_type &= ~NV_ORDER_MASK;
89132115b10SPawel Jakub Dawidek 		nvh->nvh_type |= NV_ORDER_NETWORK;
89232115b10SPawel Jakub Dawidek 	}
89332115b10SPawel Jakub Dawidek 
89432115b10SPawel Jakub Dawidek 	vsize = 0;
89532115b10SPawel Jakub Dawidek 
89632115b10SPawel Jakub Dawidek 	switch (nvh->nvh_type & NV_TYPE_MASK) {
89732115b10SPawel Jakub Dawidek 	case NV_TYPE_INT8:
89832115b10SPawel Jakub Dawidek 	case NV_TYPE_UINT8:
89932115b10SPawel Jakub Dawidek 	case NV_TYPE_INT8_ARRAY:
90032115b10SPawel Jakub Dawidek 	case NV_TYPE_UINT8_ARRAY:
90132115b10SPawel Jakub Dawidek 		break;
90232115b10SPawel Jakub Dawidek 	case NV_TYPE_INT16:
90332115b10SPawel Jakub Dawidek 	case NV_TYPE_UINT16:
90432115b10SPawel Jakub Dawidek 	case NV_TYPE_INT16_ARRAY:
90532115b10SPawel Jakub Dawidek 	case NV_TYPE_UINT16_ARRAY:
90632115b10SPawel Jakub Dawidek 		if (vsize == 0)
90732115b10SPawel Jakub Dawidek 			vsize = 2;
908f9c5a09cSMikolaj Golub 		/* FALLTHROUGH */
90932115b10SPawel Jakub Dawidek 	case NV_TYPE_INT32:
91032115b10SPawel Jakub Dawidek 	case NV_TYPE_UINT32:
91132115b10SPawel Jakub Dawidek 	case NV_TYPE_INT32_ARRAY:
91232115b10SPawel Jakub Dawidek 	case NV_TYPE_UINT32_ARRAY:
91332115b10SPawel Jakub Dawidek 		if (vsize == 0)
91432115b10SPawel Jakub Dawidek 			vsize = 4;
915f9c5a09cSMikolaj Golub 		/* FALLTHROUGH */
91632115b10SPawel Jakub Dawidek 	case NV_TYPE_INT64:
91732115b10SPawel Jakub Dawidek 	case NV_TYPE_UINT64:
91832115b10SPawel Jakub Dawidek 	case NV_TYPE_INT64_ARRAY:
91932115b10SPawel Jakub Dawidek 	case NV_TYPE_UINT64_ARRAY:
92032115b10SPawel Jakub Dawidek 		if (vsize == 0)
92132115b10SPawel Jakub Dawidek 			vsize = 8;
92232115b10SPawel Jakub Dawidek 		for (p = data; p < end; p += vsize) {
92332115b10SPawel Jakub Dawidek 			if (tohost) {
92432115b10SPawel Jakub Dawidek 				switch (vsize) {
92532115b10SPawel Jakub Dawidek 				case 2:
92632115b10SPawel Jakub Dawidek 					*(uint16_t *)(void *)p =
92732115b10SPawel Jakub Dawidek 					    le16toh(*(uint16_t *)(void *)p);
92832115b10SPawel Jakub Dawidek 					break;
92932115b10SPawel Jakub Dawidek 				case 4:
93032115b10SPawel Jakub Dawidek 					*(uint32_t *)(void *)p =
93132115b10SPawel Jakub Dawidek 					    le32toh(*(uint32_t *)(void *)p);
93232115b10SPawel Jakub Dawidek 					break;
93332115b10SPawel Jakub Dawidek 				case 8:
93432115b10SPawel Jakub Dawidek 					*(uint64_t *)(void *)p =
93532115b10SPawel Jakub Dawidek 					    le64toh(*(uint64_t *)(void *)p);
93632115b10SPawel Jakub Dawidek 					break;
93732115b10SPawel Jakub Dawidek 				default:
938adf8002bSPawel Jakub Dawidek 					PJDLOG_ABORT("invalid condition");
93932115b10SPawel Jakub Dawidek 				}
94032115b10SPawel Jakub Dawidek 			} else {
94132115b10SPawel Jakub Dawidek 				switch (vsize) {
94232115b10SPawel Jakub Dawidek 				case 2:
94332115b10SPawel Jakub Dawidek 					*(uint16_t *)(void *)p =
94432115b10SPawel Jakub Dawidek 					    htole16(*(uint16_t *)(void *)p);
94532115b10SPawel Jakub Dawidek 					break;
94632115b10SPawel Jakub Dawidek 				case 4:
94732115b10SPawel Jakub Dawidek 					*(uint32_t *)(void *)p =
94832115b10SPawel Jakub Dawidek 					    htole32(*(uint32_t *)(void *)p);
94932115b10SPawel Jakub Dawidek 					break;
95032115b10SPawel Jakub Dawidek 				case 8:
95132115b10SPawel Jakub Dawidek 					*(uint64_t *)(void *)p =
95232115b10SPawel Jakub Dawidek 					    htole64(*(uint64_t *)(void *)p);
95332115b10SPawel Jakub Dawidek 					break;
95432115b10SPawel Jakub Dawidek 				default:
955adf8002bSPawel Jakub Dawidek 					PJDLOG_ABORT("invalid condition");
95632115b10SPawel Jakub Dawidek 				}
95732115b10SPawel Jakub Dawidek 			}
95832115b10SPawel Jakub Dawidek 		}
95932115b10SPawel Jakub Dawidek 		break;
96032115b10SPawel Jakub Dawidek 	case NV_TYPE_STRING:
96132115b10SPawel Jakub Dawidek 		break;
96232115b10SPawel Jakub Dawidek 	default:
963adf8002bSPawel Jakub Dawidek 		PJDLOG_ABORT("unrecognized type");
96432115b10SPawel Jakub Dawidek 	}
96532115b10SPawel Jakub Dawidek }
966