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/param.h>
3177cb4d3eSLandon J. Fuller
3277cb4d3eSLandon J. Fuller #ifdef _KERNEL
3377cb4d3eSLandon J. Fuller
3477cb4d3eSLandon J. Fuller #include <sys/ctype.h>
3577cb4d3eSLandon J. Fuller #include <sys/kernel.h>
3677cb4d3eSLandon J. Fuller #include <sys/limits.h>
3777cb4d3eSLandon J. Fuller #include <sys/malloc.h>
3877cb4d3eSLandon J. Fuller #include <sys/systm.h>
3977cb4d3eSLandon J. Fuller
4077cb4d3eSLandon J. Fuller #include <machine/_inttypes.h>
4177cb4d3eSLandon J. Fuller
4277cb4d3eSLandon J. Fuller #else /* !_KERNEL */
4377cb4d3eSLandon J. Fuller
4477cb4d3eSLandon J. Fuller #include <ctype.h>
4577cb4d3eSLandon J. Fuller #include <errno.h>
4677cb4d3eSLandon J. Fuller #include <inttypes.h>
4777cb4d3eSLandon J. Fuller #include <limits.h>
4877cb4d3eSLandon J. Fuller #include <stdbool.h>
4977cb4d3eSLandon J. Fuller #include <stdio.h>
5077cb4d3eSLandon J. Fuller #include <stdint.h>
5177cb4d3eSLandon J. Fuller #include <stdlib.h>
5277cb4d3eSLandon J. Fuller #include <string.h>
5377cb4d3eSLandon J. Fuller
5477cb4d3eSLandon J. Fuller #endif /* _KERNEL */
5577cb4d3eSLandon J. Fuller
5677cb4d3eSLandon J. Fuller #include "bhnd_nvram_io.h"
5777cb4d3eSLandon J. Fuller #include "bhnd_nvram_private.h"
5877cb4d3eSLandon J. Fuller #include "bhnd_nvram_value.h"
5977cb4d3eSLandon J. Fuller
6077cb4d3eSLandon J. Fuller #include "bhnd_nvram_map_data.h"
6177cb4d3eSLandon J. Fuller
6277cb4d3eSLandon J. Fuller /*
6377cb4d3eSLandon J. Fuller * Common NVRAM/SPROM support, including NVRAM variable map
6477cb4d3eSLandon J. Fuller * lookup.
6577cb4d3eSLandon J. Fuller */
6677cb4d3eSLandon J. Fuller
6777cb4d3eSLandon J. Fuller #ifdef _KERNEL
6877cb4d3eSLandon J. Fuller MALLOC_DEFINE(M_BHND_NVRAM, "bhnd_nvram", "bhnd nvram data");
6977cb4d3eSLandon J. Fuller #endif
7077cb4d3eSLandon J. Fuller
7177cb4d3eSLandon J. Fuller /*
7277cb4d3eSLandon J. Fuller * CRC-8 lookup table used to checksum SPROM and NVRAM data via
7377cb4d3eSLandon J. Fuller * bhnd_nvram_crc8().
7477cb4d3eSLandon J. Fuller *
7577cb4d3eSLandon J. Fuller * Generated with following parameters:
7677cb4d3eSLandon J. Fuller * polynomial: CRC-8 (x^8 + x^7 + x^6 + x^4 + x^2 + 1)
7777cb4d3eSLandon J. Fuller * reflected bits: false
7877cb4d3eSLandon J. Fuller * reversed: true
7977cb4d3eSLandon J. Fuller */
8077cb4d3eSLandon J. Fuller const uint8_t bhnd_nvram_crc8_tab[] = {
8177cb4d3eSLandon J. Fuller 0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b, 0x4a, 0xbd, 0xf3,
8277cb4d3eSLandon J. Fuller 0x04, 0x6f, 0x98, 0xd6, 0x21, 0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46,
8377cb4d3eSLandon J. Fuller 0x08, 0xff, 0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5, 0x7f,
8477cb4d3eSLandon J. Fuller 0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14, 0x35, 0xc2, 0x8c, 0x7b,
8577cb4d3eSLandon J. Fuller 0x10, 0xe7, 0xa9, 0x5e, 0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77,
8677cb4d3eSLandon J. Fuller 0x80, 0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca, 0xfe, 0x09,
8777cb4d3eSLandon J. Fuller 0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95, 0xb4, 0x43, 0x0d, 0xfa, 0x91,
8877cb4d3eSLandon J. Fuller 0x66, 0x28, 0xdf, 0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01,
8977cb4d3eSLandon J. Fuller 0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b, 0x81, 0x76, 0x38,
9077cb4d3eSLandon J. Fuller 0xcf, 0xa4, 0x53, 0x1d, 0xea, 0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19,
9177cb4d3eSLandon J. Fuller 0x57, 0xa0, 0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e, 0x5f,
9277cb4d3eSLandon J. Fuller 0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34, 0xab, 0x5c, 0x12, 0xe5,
9377cb4d3eSLandon J. Fuller 0x8e, 0x79, 0x37, 0xc0, 0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d,
9477cb4d3eSLandon J. Fuller 0x8a, 0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54, 0x75, 0x82,
9577cb4d3eSLandon J. Fuller 0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e, 0xd4, 0x23, 0x6d, 0x9a, 0xf1,
9677cb4d3eSLandon J. Fuller 0x06, 0x48, 0xbf, 0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5,
9777cb4d3eSLandon J. Fuller 0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b, 0x0a, 0xfd, 0xb3,
9877cb4d3eSLandon J. Fuller 0x44, 0x2f, 0xd8, 0x96, 0x61, 0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87,
9977cb4d3eSLandon J. Fuller 0xc9, 0x3e, 0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74, 0xc1,
10077cb4d3eSLandon J. Fuller 0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa, 0x8b, 0x7c, 0x32, 0xc5,
10177cb4d3eSLandon J. Fuller 0xae, 0x59, 0x17, 0xe0, 0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6,
10277cb4d3eSLandon J. Fuller 0x41, 0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b, 0xbe, 0x49,
10377cb4d3eSLandon J. Fuller 0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5, 0xf4, 0x03, 0x4d, 0xba, 0xd1,
10477cb4d3eSLandon J. Fuller 0x26, 0x68, 0x9f
10577cb4d3eSLandon J. Fuller };
10677cb4d3eSLandon J. Fuller
10777cb4d3eSLandon J. Fuller /**
10877cb4d3eSLandon J. Fuller * Return a human readable name for @p type.
10977cb4d3eSLandon J. Fuller *
11077cb4d3eSLandon J. Fuller * @param type The type to query.
11177cb4d3eSLandon J. Fuller */
11277cb4d3eSLandon J. Fuller const char *
bhnd_nvram_type_name(bhnd_nvram_type type)11377cb4d3eSLandon J. Fuller bhnd_nvram_type_name(bhnd_nvram_type type)
11477cb4d3eSLandon J. Fuller {
11577cb4d3eSLandon J. Fuller switch (type) {
11677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8:
11777cb4d3eSLandon J. Fuller return ("uint8");
11877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16:
11977cb4d3eSLandon J. Fuller return ("uint16");
12077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32:
12177cb4d3eSLandon J. Fuller return ("uint32");
12277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64:
12377cb4d3eSLandon J. Fuller return ("uint64");
12477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR:
12577cb4d3eSLandon J. Fuller return ("char");
12677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8:
12777cb4d3eSLandon J. Fuller return ("int8");
12877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16:
12977cb4d3eSLandon J. Fuller return ("int16");
13077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32:
13177cb4d3eSLandon J. Fuller return ("int32");
13277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64:
13377cb4d3eSLandon J. Fuller return ("int64");
13477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_STRING:
13577cb4d3eSLandon J. Fuller return ("string");
1366cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL:
1376cffadf0SLandon J. Fuller return ("bool");
1386cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_NULL:
1396cffadf0SLandon J. Fuller return ("null");
1406cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_DATA:
1416cffadf0SLandon J. Fuller return ("data");
14277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8_ARRAY:
14377cb4d3eSLandon J. Fuller return ("uint8[]");
14477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16_ARRAY:
14577cb4d3eSLandon J. Fuller return ("uint16[]");
14677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32_ARRAY:
14777cb4d3eSLandon J. Fuller return ("uint32[]");
14877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64_ARRAY:
14977cb4d3eSLandon J. Fuller return ("uint64[]");
15077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8_ARRAY:
15177cb4d3eSLandon J. Fuller return ("int8[]");
15277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16_ARRAY:
15377cb4d3eSLandon J. Fuller return ("int16[]");
15477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32_ARRAY:
15577cb4d3eSLandon J. Fuller return ("int32[]");
15677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64_ARRAY:
15777cb4d3eSLandon J. Fuller return ("int64[]");
15877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR_ARRAY:
15977cb4d3eSLandon J. Fuller return ("char[]");
16077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_STRING_ARRAY:
16177cb4d3eSLandon J. Fuller return ("string[]");
1626cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL_ARRAY:
1636cffadf0SLandon J. Fuller return ("bool[]");
16477cb4d3eSLandon J. Fuller }
16577cb4d3eSLandon J. Fuller
16677cb4d3eSLandon J. Fuller /* Quiesce gcc4.2 */
16777cb4d3eSLandon J. Fuller BHND_NV_PANIC("bhnd nvram type %u unknown", type);
16877cb4d3eSLandon J. Fuller }
16977cb4d3eSLandon J. Fuller
17077cb4d3eSLandon J. Fuller /**
17177cb4d3eSLandon J. Fuller * Return true if @p type is a signed integer type, false otherwise.
17277cb4d3eSLandon J. Fuller *
17377cb4d3eSLandon J. Fuller * Will return false for all array types.
17477cb4d3eSLandon J. Fuller *
17577cb4d3eSLandon J. Fuller * @param type The type to query.
17677cb4d3eSLandon J. Fuller */
17777cb4d3eSLandon J. Fuller bool
bhnd_nvram_is_signed_type(bhnd_nvram_type type)17877cb4d3eSLandon J. Fuller bhnd_nvram_is_signed_type(bhnd_nvram_type type)
17977cb4d3eSLandon J. Fuller {
18077cb4d3eSLandon J. Fuller switch (type) {
18177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8:
18277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16:
18377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32:
18477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64:
18577cb4d3eSLandon J. Fuller BHND_NV_ASSERT(bhnd_nvram_is_int_type(type), ("non-int type?"));
18677cb4d3eSLandon J. Fuller return (true);
18777cb4d3eSLandon J. Fuller
18877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR:
18977cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8:
19077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16:
19177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32:
19277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64:
19377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_STRING:
1946cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL:
1956cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_NULL:
1966cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_DATA:
19777cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8_ARRAY:
19877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16_ARRAY:
19977cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32_ARRAY:
20077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64_ARRAY:
20177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8_ARRAY:
20277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16_ARRAY:
20377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32_ARRAY:
20477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64_ARRAY:
20577cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR_ARRAY:
20677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_STRING_ARRAY:
2076cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL_ARRAY:
20877cb4d3eSLandon J. Fuller return (false);
20977cb4d3eSLandon J. Fuller }
21077cb4d3eSLandon J. Fuller
21177cb4d3eSLandon J. Fuller /* Quiesce gcc4.2 */
21277cb4d3eSLandon J. Fuller BHND_NV_PANIC("bhnd nvram type %u unknown", type);
21377cb4d3eSLandon J. Fuller }
21477cb4d3eSLandon J. Fuller
21577cb4d3eSLandon J. Fuller /**
21677cb4d3eSLandon J. Fuller * Return true if @p type is an unsigned integer type, false otherwise.
21777cb4d3eSLandon J. Fuller *
21877cb4d3eSLandon J. Fuller * @param type The type to query.
21977cb4d3eSLandon J. Fuller *
22077cb4d3eSLandon J. Fuller * @return Will return false for all array types.
22177cb4d3eSLandon J. Fuller * @return Will return true for BHND_NVRAM_TYPE_CHAR.
22277cb4d3eSLandon J. Fuller */
22377cb4d3eSLandon J. Fuller bool
bhnd_nvram_is_unsigned_type(bhnd_nvram_type type)22477cb4d3eSLandon J. Fuller bhnd_nvram_is_unsigned_type(bhnd_nvram_type type)
22577cb4d3eSLandon J. Fuller {
22677cb4d3eSLandon J. Fuller /* If an integer type, must be either signed or unsigned */
22777cb4d3eSLandon J. Fuller if (!bhnd_nvram_is_int_type(type))
22877cb4d3eSLandon J. Fuller return (false);
22977cb4d3eSLandon J. Fuller
23077cb4d3eSLandon J. Fuller return (!bhnd_nvram_is_signed_type(type));
23177cb4d3eSLandon J. Fuller }
23277cb4d3eSLandon J. Fuller
23377cb4d3eSLandon J. Fuller /**
23477cb4d3eSLandon J. Fuller * Return true if bhnd_nvram_is_signed_type() or bhnd_nvram_is_unsigned_type()
23577cb4d3eSLandon J. Fuller * returns true for @p type.
23677cb4d3eSLandon J. Fuller *
23777cb4d3eSLandon J. Fuller * @param type The type to query.
23877cb4d3eSLandon J. Fuller */
23977cb4d3eSLandon J. Fuller bool
bhnd_nvram_is_int_type(bhnd_nvram_type type)24077cb4d3eSLandon J. Fuller bhnd_nvram_is_int_type(bhnd_nvram_type type)
24177cb4d3eSLandon J. Fuller {
24277cb4d3eSLandon J. Fuller switch (type) {
24377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8:
24477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16:
24577cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32:
24677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64:
24777cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8:
24877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16:
24977cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32:
25077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64:
25177cb4d3eSLandon J. Fuller return (true);
25277cb4d3eSLandon J. Fuller
25377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR:
25477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_STRING:
2556cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL:
2566cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_NULL:
2576cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_DATA:
25877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8_ARRAY:
25977cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16_ARRAY:
26077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32_ARRAY:
26177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64_ARRAY:
26277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8_ARRAY:
26377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16_ARRAY:
26477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32_ARRAY:
26577cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64_ARRAY:
26677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR_ARRAY:
26777cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_STRING_ARRAY:
2686cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL_ARRAY:
26977cb4d3eSLandon J. Fuller return (false);
27077cb4d3eSLandon J. Fuller }
27177cb4d3eSLandon J. Fuller
27277cb4d3eSLandon J. Fuller /* Quiesce gcc4.2 */
27377cb4d3eSLandon J. Fuller BHND_NV_PANIC("bhnd nvram type %u unknown", type);
27477cb4d3eSLandon J. Fuller }
27577cb4d3eSLandon J. Fuller
27677cb4d3eSLandon J. Fuller /**
27777cb4d3eSLandon J. Fuller * Return true if @p type is an array type, false otherwise.
27877cb4d3eSLandon J. Fuller *
27977cb4d3eSLandon J. Fuller * @param type The type to query.
28077cb4d3eSLandon J. Fuller */
28177cb4d3eSLandon J. Fuller bool
bhnd_nvram_is_array_type(bhnd_nvram_type type)28277cb4d3eSLandon J. Fuller bhnd_nvram_is_array_type(bhnd_nvram_type type)
28377cb4d3eSLandon J. Fuller {
28477cb4d3eSLandon J. Fuller switch (type) {
28577cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8:
28677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16:
28777cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32:
28877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64:
28977cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8:
29077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16:
29177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32:
29277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64:
29377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR:
29477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_STRING:
2956cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL:
2966cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_NULL:
2976cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_DATA:
29877cb4d3eSLandon J. Fuller return (false);
29977cb4d3eSLandon J. Fuller
30077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8_ARRAY:
30177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16_ARRAY:
30277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32_ARRAY:
30377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64_ARRAY:
30477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8_ARRAY:
30577cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16_ARRAY:
30677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32_ARRAY:
30777cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64_ARRAY:
30877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR_ARRAY:
30977cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_STRING_ARRAY:
3106cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL_ARRAY:
31177cb4d3eSLandon J. Fuller return (true);
31277cb4d3eSLandon J. Fuller }
31377cb4d3eSLandon J. Fuller
31477cb4d3eSLandon J. Fuller /* Quiesce gcc4.2 */
31577cb4d3eSLandon J. Fuller BHND_NV_PANIC("bhnd nvram type %u unknown", type);
31677cb4d3eSLandon J. Fuller }
31777cb4d3eSLandon J. Fuller
31877cb4d3eSLandon J. Fuller /**
31977cb4d3eSLandon J. Fuller * If @p type is an array type, return the base element type. Otherwise,
32077cb4d3eSLandon J. Fuller * returns @p type.
32177cb4d3eSLandon J. Fuller *
32277cb4d3eSLandon J. Fuller * @param type The type to query.
32377cb4d3eSLandon J. Fuller */
32477cb4d3eSLandon J. Fuller bhnd_nvram_type
bhnd_nvram_base_type(bhnd_nvram_type type)32577cb4d3eSLandon J. Fuller bhnd_nvram_base_type(bhnd_nvram_type type)
32677cb4d3eSLandon J. Fuller {
32777cb4d3eSLandon J. Fuller switch (type) {
32877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8:
32977cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16:
33077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32:
33177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64:
33277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8:
33377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16:
33477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32:
33577cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64:
33677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR:
33777cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_STRING:
3386cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL:
3396cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_NULL:
3406cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_DATA:
34177cb4d3eSLandon J. Fuller return (type);
34277cb4d3eSLandon J. Fuller
34377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8_ARRAY: return (BHND_NVRAM_TYPE_UINT8);
34477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16_ARRAY: return (BHND_NVRAM_TYPE_UINT16);
34577cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32_ARRAY: return (BHND_NVRAM_TYPE_UINT32);
34677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64_ARRAY: return (BHND_NVRAM_TYPE_UINT64);
34777cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8_ARRAY: return (BHND_NVRAM_TYPE_INT8);
34877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16_ARRAY: return (BHND_NVRAM_TYPE_INT16);
34977cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32_ARRAY: return (BHND_NVRAM_TYPE_INT32);
35077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64_ARRAY: return (BHND_NVRAM_TYPE_INT64);
35177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR_ARRAY: return (BHND_NVRAM_TYPE_CHAR);
35277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_STRING_ARRAY: return (BHND_NVRAM_TYPE_STRING);
3536cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL_ARRAY: return (BHND_NVRAM_TYPE_BOOL);
3546cffadf0SLandon J. Fuller }
3556cffadf0SLandon J. Fuller
3566cffadf0SLandon J. Fuller /* Quiesce gcc4.2 */
3576cffadf0SLandon J. Fuller BHND_NV_PANIC("bhnd nvram type %u unknown", type);
3586cffadf0SLandon J. Fuller }
3596cffadf0SLandon J. Fuller
3606cffadf0SLandon J. Fuller /**
3616cffadf0SLandon J. Fuller * Return the raw data type used to represent values of @p type, or return
3626cffadf0SLandon J. Fuller * @p type is @p type is not a complex type.
3636cffadf0SLandon J. Fuller *
3646cffadf0SLandon J. Fuller * @param type The type to query.
3656cffadf0SLandon J. Fuller */
3666cffadf0SLandon J. Fuller bhnd_nvram_type
bhnd_nvram_raw_type(bhnd_nvram_type type)3676cffadf0SLandon J. Fuller bhnd_nvram_raw_type(bhnd_nvram_type type)
3686cffadf0SLandon J. Fuller {
3696cffadf0SLandon J. Fuller switch (type) {
3706cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_CHAR:
3716cffadf0SLandon J. Fuller return (BHND_NVRAM_TYPE_UINT8);
3726cffadf0SLandon J. Fuller
3736cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_CHAR_ARRAY:
3746cffadf0SLandon J. Fuller return (BHND_NVRAM_TYPE_UINT8_ARRAY);
3756cffadf0SLandon J. Fuller
3766cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL: {
3776cffadf0SLandon J. Fuller _Static_assert(sizeof(bhnd_nvram_bool_t) == sizeof(uint8_t),
3786cffadf0SLandon J. Fuller "bhnd_nvram_bool_t must be uint8-representable");
3796cffadf0SLandon J. Fuller return (BHND_NVRAM_TYPE_UINT8);
3806cffadf0SLandon J. Fuller }
3816cffadf0SLandon J. Fuller
3826cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL_ARRAY:
3836cffadf0SLandon J. Fuller return (BHND_NVRAM_TYPE_UINT8_ARRAY);
3846cffadf0SLandon J. Fuller
3856cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_DATA:
3866cffadf0SLandon J. Fuller return (BHND_NVRAM_TYPE_UINT8_ARRAY);
3876cffadf0SLandon J. Fuller
3886cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_STRING:
3896cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_STRING_ARRAY:
3906cffadf0SLandon J. Fuller return (BHND_NVRAM_TYPE_UINT8_ARRAY);
3916cffadf0SLandon J. Fuller
3926cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_UINT8:
3936cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_UINT16:
3946cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_UINT32:
3956cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_UINT64:
3966cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_INT8:
3976cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_INT16:
3986cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_INT32:
3996cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_INT64:
4006cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_NULL:
4016cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_UINT8_ARRAY:
4026cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_UINT16_ARRAY:
4036cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_UINT32_ARRAY:
4046cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_UINT64_ARRAY:
4056cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_INT8_ARRAY:
4066cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_INT16_ARRAY:
4076cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_INT32_ARRAY:
4086cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_INT64_ARRAY:
4096cffadf0SLandon J. Fuller return (type);
41077cb4d3eSLandon J. Fuller }
41177cb4d3eSLandon J. Fuller
41277cb4d3eSLandon J. Fuller /* Quiesce gcc4.2 */
41377cb4d3eSLandon J. Fuller BHND_NV_PANIC("bhnd nvram type %u unknown", type);
41477cb4d3eSLandon J. Fuller }
41577cb4d3eSLandon J. Fuller
41677cb4d3eSLandon J. Fuller /**
4179be0790dSLandon J. Fuller * Return the size, in bytes, of a single element of @p type, or 0
4189be0790dSLandon J. Fuller * if @p type is a variable-width type.
41977cb4d3eSLandon J. Fuller *
4209be0790dSLandon J. Fuller * @param type The type to query.
42177cb4d3eSLandon J. Fuller */
42277cb4d3eSLandon J. Fuller size_t
bhnd_nvram_type_width(bhnd_nvram_type type)4239be0790dSLandon J. Fuller bhnd_nvram_type_width(bhnd_nvram_type type)
42477cb4d3eSLandon J. Fuller {
42577cb4d3eSLandon J. Fuller switch (type) {
4269be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_STRING:
4279be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_STRING_ARRAY:
4286cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_DATA:
42977cb4d3eSLandon J. Fuller return (0);
43077cb4d3eSLandon J. Fuller
4316cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_NULL:
4326cffadf0SLandon J. Fuller return (0);
4336cffadf0SLandon J. Fuller
4346cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL:
4356cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL_ARRAY:
4366cffadf0SLandon J. Fuller return (sizeof(bhnd_nvram_bool_t));
4376cffadf0SLandon J. Fuller
43877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR:
4399be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR_ARRAY:
4409be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8:
4419be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8_ARRAY:
4429be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT8:
4439be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT8_ARRAY:
44477cb4d3eSLandon J. Fuller return (sizeof(uint8_t));
44577cb4d3eSLandon J. Fuller
44677cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16:
4479be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16_ARRAY:
4489be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT16:
4499be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT16_ARRAY:
45077cb4d3eSLandon J. Fuller return (sizeof(uint16_t));
45177cb4d3eSLandon J. Fuller
45277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32:
4539be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32_ARRAY:
4549be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT32:
4559be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT32_ARRAY:
45677cb4d3eSLandon J. Fuller return (sizeof(uint32_t));
45777cb4d3eSLandon J. Fuller
45877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64:
4599be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64_ARRAY:
46077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64:
4619be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT64_ARRAY:
46277cb4d3eSLandon J. Fuller return (sizeof(uint64_t));
46377cb4d3eSLandon J. Fuller }
46477cb4d3eSLandon J. Fuller
46577cb4d3eSLandon J. Fuller /* Quiesce gcc4.2 */
46677cb4d3eSLandon J. Fuller BHND_NV_PANIC("bhnd nvram type %u unknown", type);
46777cb4d3eSLandon J. Fuller }
46877cb4d3eSLandon J. Fuller
46977cb4d3eSLandon J. Fuller /**
4709be0790dSLandon J. Fuller * Return the native host alignment for values of @p type.
47177cb4d3eSLandon J. Fuller *
4729be0790dSLandon J. Fuller * @param type The type to query.
4739be0790dSLandon J. Fuller */
4749be0790dSLandon J. Fuller size_t
bhnd_nvram_type_host_align(bhnd_nvram_type type)4759be0790dSLandon J. Fuller bhnd_nvram_type_host_align(bhnd_nvram_type type)
4769be0790dSLandon J. Fuller {
4779be0790dSLandon J. Fuller switch (type) {
4789be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR:
4799be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR_ARRAY:
4806cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_DATA:
4819be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_STRING:
4829be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_STRING_ARRAY:
4839be0790dSLandon J. Fuller return (_Alignof(uint8_t));
4846cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL:
4856cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_BOOL_ARRAY: {
4866cffadf0SLandon J. Fuller _Static_assert(sizeof(bhnd_nvram_bool_t) == sizeof(uint8_t),
4876cffadf0SLandon J. Fuller "bhnd_nvram_bool_t must be uint8-representable");
4886cffadf0SLandon J. Fuller return (_Alignof(uint8_t));
4896cffadf0SLandon J. Fuller }
4906cffadf0SLandon J. Fuller case BHND_NVRAM_TYPE_NULL:
4916cffadf0SLandon J. Fuller return (1);
4929be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8:
4939be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8_ARRAY:
4949be0790dSLandon J. Fuller return (_Alignof(uint8_t));
4959be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16:
4969be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16_ARRAY:
4979be0790dSLandon J. Fuller return (_Alignof(uint16_t));
4989be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32:
4999be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32_ARRAY:
5009be0790dSLandon J. Fuller return (_Alignof(uint32_t));
5019be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64:
5029be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64_ARRAY:
5039be0790dSLandon J. Fuller return (_Alignof(uint64_t));
5049be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT8:
5059be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT8_ARRAY:
5069be0790dSLandon J. Fuller return (_Alignof(int8_t));
5079be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT16:
5089be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT16_ARRAY:
5099be0790dSLandon J. Fuller return (_Alignof(int16_t));
5109be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT32:
5119be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT32_ARRAY:
5129be0790dSLandon J. Fuller return (_Alignof(int32_t));
5139be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT64:
5149be0790dSLandon J. Fuller case BHND_NVRAM_TYPE_INT64_ARRAY:
5159be0790dSLandon J. Fuller return (_Alignof(int64_t));
5169be0790dSLandon J. Fuller }
5179be0790dSLandon J. Fuller
5189be0790dSLandon J. Fuller /* Quiesce gcc4.2 */
5199be0790dSLandon J. Fuller BHND_NV_PANIC("bhnd nvram type %u unknown", type);
5209be0790dSLandon J. Fuller }
5219be0790dSLandon J. Fuller
5229be0790dSLandon J. Fuller /**
523*05ed3f90SLandon J. Fuller * Iterate over all strings in the @p inp string array (see
524*05ed3f90SLandon J. Fuller * BHND_NVRAM_TYPE_STRING_ARRAY).
5259be0790dSLandon J. Fuller *
5269be0790dSLandon J. Fuller * @param inp The string array to be iterated. This must be a
5279be0790dSLandon J. Fuller * buffer of one or more NUL-terminated strings.
52877cb4d3eSLandon J. Fuller * @param ilen The size, in bytes, of @p inp, including any
52977cb4d3eSLandon J. Fuller * terminating NUL character(s).
5309be0790dSLandon J. Fuller * @param prev The pointer previously returned by
53177cb4d3eSLandon J. Fuller * bhnd_nvram_string_array_next(), or NULL to begin
53277cb4d3eSLandon J. Fuller * iteration.
5339be0790dSLandon J. Fuller * @param[in,out] olen If @p prev is non-NULL, @p olen must be a
5349be0790dSLandon J. Fuller * pointer to the length previously returned by
5359be0790dSLandon J. Fuller * bhnd_nvram_string_array_next(). On success, will
5369be0790dSLandon J. Fuller * be set to the next element's length, in bytes.
53777cb4d3eSLandon J. Fuller *
53877cb4d3eSLandon J. Fuller * @retval non-NULL A reference to the next NUL-terminated string
53977cb4d3eSLandon J. Fuller * @retval NULL If the end of the string array is reached.
540*05ed3f90SLandon J. Fuller *
541*05ed3f90SLandon J. Fuller * @see BHND_NVRAM_TYPE_STRING_ARRAY
54277cb4d3eSLandon J. Fuller */
54377cb4d3eSLandon J. Fuller const char *
bhnd_nvram_string_array_next(const char * inp,size_t ilen,const char * prev,size_t * olen)5449be0790dSLandon J. Fuller bhnd_nvram_string_array_next(const char *inp, size_t ilen, const char *prev,
5459be0790dSLandon J. Fuller size_t *olen)
54677cb4d3eSLandon J. Fuller {
5479be0790dSLandon J. Fuller return (bhnd_nvram_value_array_next(inp, ilen,
5489be0790dSLandon J. Fuller BHND_NVRAM_TYPE_STRING_ARRAY, prev, olen));
54977cb4d3eSLandon J. Fuller }
55077cb4d3eSLandon J. Fuller
55177cb4d3eSLandon J. Fuller /* used by bhnd_nvram_find_vardefn() */
55277cb4d3eSLandon J. Fuller static int
bhnd_nvram_find_vardefn_compare(const void * key,const void * rhs)55377cb4d3eSLandon J. Fuller bhnd_nvram_find_vardefn_compare(const void *key, const void *rhs)
55477cb4d3eSLandon J. Fuller {
55577cb4d3eSLandon J. Fuller const struct bhnd_nvram_vardefn *r = rhs;
55677cb4d3eSLandon J. Fuller
55777cb4d3eSLandon J. Fuller return (strcmp((const char *)key, r->name));
55877cb4d3eSLandon J. Fuller }
55977cb4d3eSLandon J. Fuller
56077cb4d3eSLandon J. Fuller /**
56177cb4d3eSLandon J. Fuller * Find and return the variable definition for @p varname, if any.
56277cb4d3eSLandon J. Fuller *
56377cb4d3eSLandon J. Fuller * @param varname variable name
56477cb4d3eSLandon J. Fuller *
56577cb4d3eSLandon J. Fuller * @retval bhnd_nvram_vardefn If a valid definition for @p varname is found.
56677cb4d3eSLandon J. Fuller * @retval NULL If no definition for @p varname is found.
56777cb4d3eSLandon J. Fuller */
56877cb4d3eSLandon J. Fuller const struct bhnd_nvram_vardefn *
bhnd_nvram_find_vardefn(const char * varname)56977cb4d3eSLandon J. Fuller bhnd_nvram_find_vardefn(const char *varname)
57077cb4d3eSLandon J. Fuller {
57177cb4d3eSLandon J. Fuller return (bsearch(varname, bhnd_nvram_vardefns, bhnd_nvram_num_vardefns,
57277cb4d3eSLandon J. Fuller sizeof(bhnd_nvram_vardefns[0]), bhnd_nvram_find_vardefn_compare));
57377cb4d3eSLandon J. Fuller }
57477cb4d3eSLandon J. Fuller
57577cb4d3eSLandon J. Fuller /**
57677cb4d3eSLandon J. Fuller * Return the variable ID for a variable definition.
57777cb4d3eSLandon J. Fuller *
57877cb4d3eSLandon J. Fuller * @param defn Variable definition previously returned by
57977cb4d3eSLandon J. Fuller * bhnd_nvram_find_vardefn() or bhnd_nvram_get_vardefn().
58077cb4d3eSLandon J. Fuller */
58177cb4d3eSLandon J. Fuller size_t
bhnd_nvram_get_vardefn_id(const struct bhnd_nvram_vardefn * defn)58277cb4d3eSLandon J. Fuller bhnd_nvram_get_vardefn_id(const struct bhnd_nvram_vardefn *defn)
58377cb4d3eSLandon J. Fuller {
58477cb4d3eSLandon J. Fuller BHND_NV_ASSERT(
58577cb4d3eSLandon J. Fuller defn >= bhnd_nvram_vardefns &&
58677cb4d3eSLandon J. Fuller defn <= &bhnd_nvram_vardefns[bhnd_nvram_num_vardefns-1],
58777cb4d3eSLandon J. Fuller ("invalid variable definition pointer %p", defn));
58877cb4d3eSLandon J. Fuller
58977cb4d3eSLandon J. Fuller return (defn - bhnd_nvram_vardefns);
59077cb4d3eSLandon J. Fuller }
59177cb4d3eSLandon J. Fuller
59277cb4d3eSLandon J. Fuller /**
59377cb4d3eSLandon J. Fuller * Return the variable definition with the given @p id, or NULL
59477cb4d3eSLandon J. Fuller * if no such variable ID is defined.
59577cb4d3eSLandon J. Fuller *
59677cb4d3eSLandon J. Fuller * @param id variable ID.
59777cb4d3eSLandon J. Fuller *
59877cb4d3eSLandon J. Fuller * @retval bhnd_nvram_vardefn If a valid definition for @p id is found.
59977cb4d3eSLandon J. Fuller * @retval NULL If no definition for @p id is found.
60077cb4d3eSLandon J. Fuller */
60177cb4d3eSLandon J. Fuller const struct bhnd_nvram_vardefn *
bhnd_nvram_get_vardefn(size_t id)60277cb4d3eSLandon J. Fuller bhnd_nvram_get_vardefn(size_t id)
60377cb4d3eSLandon J. Fuller {
60477cb4d3eSLandon J. Fuller if (id >= bhnd_nvram_num_vardefns)
60577cb4d3eSLandon J. Fuller return (NULL);
60677cb4d3eSLandon J. Fuller
60777cb4d3eSLandon J. Fuller return (&bhnd_nvram_vardefns[id]);
60877cb4d3eSLandon J. Fuller }
60977cb4d3eSLandon J. Fuller
61077cb4d3eSLandon J. Fuller /**
61177cb4d3eSLandon J. Fuller * Validate an NVRAM variable name.
61277cb4d3eSLandon J. Fuller *
61377cb4d3eSLandon J. Fuller * Scans for special characters (path delimiters, value delimiters, path
61477cb4d3eSLandon J. Fuller * alias prefixes), returning false if the given name cannot be used
61577cb4d3eSLandon J. Fuller * as a relative NVRAM key.
61677cb4d3eSLandon J. Fuller *
61777cb4d3eSLandon J. Fuller * @param name A relative NVRAM variable name to validate.
61877cb4d3eSLandon J. Fuller *
61977cb4d3eSLandon J. Fuller * @retval true If @p name is a valid relative NVRAM key.
62077cb4d3eSLandon J. Fuller * @retval false If @p name should not be used as a relative NVRAM key.
62177cb4d3eSLandon J. Fuller */
62277cb4d3eSLandon J. Fuller bool
bhnd_nvram_validate_name(const char * name)62319be09f3SLandon J. Fuller bhnd_nvram_validate_name(const char *name)
62477cb4d3eSLandon J. Fuller {
62519be09f3SLandon J. Fuller /* Reject path-prefixed variable names */
62619be09f3SLandon J. Fuller if (bhnd_nvram_trim_path_name(name) != name)
62777cb4d3eSLandon J. Fuller return (false);
62877cb4d3eSLandon J. Fuller
62919be09f3SLandon J. Fuller /* Reject device path alias declarations (devpath[1-9][0-9]*.*\0) */
63019be09f3SLandon J. Fuller if (strncmp(name, "devpath", strlen("devpath")) == 0) {
63119be09f3SLandon J. Fuller const char *p;
63219be09f3SLandon J. Fuller char *endp;
63319be09f3SLandon J. Fuller
63419be09f3SLandon J. Fuller /* Check for trailing [1-9][0-9]* */
63519be09f3SLandon J. Fuller p = name + strlen("devpath");
63619be09f3SLandon J. Fuller strtoul(p, &endp, 10);
63719be09f3SLandon J. Fuller if (endp != p)
63877cb4d3eSLandon J. Fuller return (false);
63977cb4d3eSLandon J. Fuller }
64077cb4d3eSLandon J. Fuller
64119be09f3SLandon J. Fuller /* Scan for [^A-Za-z_0-9] */
64219be09f3SLandon J. Fuller for (const char *p = name; *p != '\0'; p++) {
64377cb4d3eSLandon J. Fuller switch (*p) {
64419be09f3SLandon J. Fuller /* [0-9_] */
64519be09f3SLandon J. Fuller case '0': case '1': case '2': case '3': case '4':
64619be09f3SLandon J. Fuller case '5': case '6': case '7': case '8': case '9':
64719be09f3SLandon J. Fuller case '_':
64819be09f3SLandon J. Fuller break;
64977cb4d3eSLandon J. Fuller
65019be09f3SLandon J. Fuller /* [A-Za-z] */
65177cb4d3eSLandon J. Fuller default:
65219be09f3SLandon J. Fuller if (!bhnd_nv_isalpha(*p))
65377cb4d3eSLandon J. Fuller return (false);
65419be09f3SLandon J. Fuller break;
65577cb4d3eSLandon J. Fuller }
65677cb4d3eSLandon J. Fuller }
65777cb4d3eSLandon J. Fuller
65877cb4d3eSLandon J. Fuller return (true);
65977cb4d3eSLandon J. Fuller }
66077cb4d3eSLandon J. Fuller
66177cb4d3eSLandon J. Fuller /**
66277cb4d3eSLandon J. Fuller * Parses the string in the optionally NUL-terminated @p str to as an integer
66377cb4d3eSLandon J. Fuller * value of @p otype, accepting any integer format supported by the standard
66477cb4d3eSLandon J. Fuller * strtoul().
66577cb4d3eSLandon J. Fuller *
66677cb4d3eSLandon J. Fuller * - Any leading whitespace in @p str -- as defined by the equivalent of
66777cb4d3eSLandon J. Fuller * calling isspace_l() with an ASCII locale -- will be ignored.
66877cb4d3eSLandon J. Fuller * - A @p str may be prefixed with a single optional '+' or '-' sign denoting
66977cb4d3eSLandon J. Fuller * signedness.
67077cb4d3eSLandon J. Fuller * - A hexadecimal @p str may include an '0x' or '0X' prefix, denoting that a
67177cb4d3eSLandon J. Fuller * base 16 integer follows.
67277cb4d3eSLandon J. Fuller * - An octal @p str may include a '0' prefix, denoting that an octal integer
67377cb4d3eSLandon J. Fuller * follows.
67477cb4d3eSLandon J. Fuller *
67577cb4d3eSLandon J. Fuller * If a @p base of 0 is specified, the base will be determined according
67677cb4d3eSLandon J. Fuller * to the string's initial prefix, as per strtoul()'s documented behavior.
67777cb4d3eSLandon J. Fuller *
67877cb4d3eSLandon J. Fuller * When parsing a base 16 integer to a signed representation, if no explicit
67977cb4d3eSLandon J. Fuller * sign prefix is given, the string will be parsed as the raw two's complement
68077cb4d3eSLandon J. Fuller * representation of the signed integer value.
68177cb4d3eSLandon J. Fuller *
68277cb4d3eSLandon J. Fuller * @param str The string to be parsed.
68377cb4d3eSLandon J. Fuller * @param maxlen The maximum number of bytes to be read in
68477cb4d3eSLandon J. Fuller * @p str.
68577cb4d3eSLandon J. Fuller * @param base The input string's base (2-36), or 0.
68677cb4d3eSLandon J. Fuller * @param[out] nbytes On success or failure, will be set to the total
68777cb4d3eSLandon J. Fuller * number of parsed bytes. If the total number of
68877cb4d3eSLandon J. Fuller * bytes is not desired, a NULL pointer may be
68977cb4d3eSLandon J. Fuller * provided.
69077cb4d3eSLandon J. Fuller * @param[out] outp On success, the parsed integer value will be
69177cb4d3eSLandon J. Fuller * written to @p outp. This argment may be NULL if
69277cb4d3eSLandon J. Fuller * the value is not desired.
69377cb4d3eSLandon J. Fuller * @param[in,out] olen The capacity of @p outp. On success, will be set
69477cb4d3eSLandon J. Fuller * to the actual size of the requested value.
69577cb4d3eSLandon J. Fuller * @param otype The integer type to be parsed.
69677cb4d3eSLandon J. Fuller *
69777cb4d3eSLandon J. Fuller * @retval 0 success
69877cb4d3eSLandon J. Fuller * @retval EINVAL if an invalid @p base is specified.
69977cb4d3eSLandon J. Fuller * @retval EINVAL if an unsupported (or non-integer) @p otype is
70077cb4d3eSLandon J. Fuller * specified.
70177cb4d3eSLandon J. Fuller * @retval ENOMEM If @p outp is non-NULL and a buffer of @p olen is too
70277cb4d3eSLandon J. Fuller * small to hold the requested value.
70377cb4d3eSLandon J. Fuller * @retval EFTYPE if @p str cannot be parsed as an integer of @p base.
70477cb4d3eSLandon J. Fuller * @retval ERANGE If the integer parsed from @p str is too large to be
70577cb4d3eSLandon J. Fuller * represented as a value of @p otype.
70677cb4d3eSLandon J. Fuller */
70777cb4d3eSLandon J. Fuller int
bhnd_nvram_parse_int(const char * str,size_t maxlen,u_int base,size_t * nbytes,void * outp,size_t * olen,bhnd_nvram_type otype)70877cb4d3eSLandon J. Fuller bhnd_nvram_parse_int(const char *str, size_t maxlen, u_int base,
70977cb4d3eSLandon J. Fuller size_t *nbytes, void *outp, size_t *olen, bhnd_nvram_type otype)
71077cb4d3eSLandon J. Fuller {
71177cb4d3eSLandon J. Fuller uint64_t value;
71277cb4d3eSLandon J. Fuller uint64_t carry_max, value_max;
71377cb4d3eSLandon J. Fuller uint64_t type_max;
71477cb4d3eSLandon J. Fuller size_t limit, local_nbytes;
71577cb4d3eSLandon J. Fuller size_t ndigits;
71677cb4d3eSLandon J. Fuller bool negative, sign, twos_compl;
71777cb4d3eSLandon J. Fuller
71877cb4d3eSLandon J. Fuller /* Must be an integer type */
71977cb4d3eSLandon J. Fuller if (!bhnd_nvram_is_int_type(otype))
72077cb4d3eSLandon J. Fuller return (EINVAL);
72177cb4d3eSLandon J. Fuller
72277cb4d3eSLandon J. Fuller /* Determine output byte limit */
72377cb4d3eSLandon J. Fuller if (outp != NULL)
72477cb4d3eSLandon J. Fuller limit = *olen;
72577cb4d3eSLandon J. Fuller else
72677cb4d3eSLandon J. Fuller limit = 0;
72777cb4d3eSLandon J. Fuller
72877cb4d3eSLandon J. Fuller /* We always need a byte count. If the caller provides a NULL nbytes,
72977cb4d3eSLandon J. Fuller * track our position in a stack variable */
73077cb4d3eSLandon J. Fuller if (nbytes == NULL)
73177cb4d3eSLandon J. Fuller nbytes = &local_nbytes;
73277cb4d3eSLandon J. Fuller
73377cb4d3eSLandon J. Fuller value = 0;
73477cb4d3eSLandon J. Fuller ndigits = 0;
73577cb4d3eSLandon J. Fuller *nbytes = 0;
73677cb4d3eSLandon J. Fuller negative = false;
73777cb4d3eSLandon J. Fuller sign = false;
73877cb4d3eSLandon J. Fuller
73977cb4d3eSLandon J. Fuller /* Validate the specified base */
74077cb4d3eSLandon J. Fuller if (base != 0 && !(base >= 2 && base <= 36))
74177cb4d3eSLandon J. Fuller return (EINVAL);
74277cb4d3eSLandon J. Fuller
74377cb4d3eSLandon J. Fuller /* Skip any leading whitespace */
74477cb4d3eSLandon J. Fuller for (; *nbytes < maxlen; (*nbytes)++) {
74577cb4d3eSLandon J. Fuller if (!bhnd_nv_isspace(str[*nbytes]))
74677cb4d3eSLandon J. Fuller break;
74777cb4d3eSLandon J. Fuller }
74877cb4d3eSLandon J. Fuller
74977cb4d3eSLandon J. Fuller /* Empty string? */
75077cb4d3eSLandon J. Fuller if (*nbytes == maxlen)
75177cb4d3eSLandon J. Fuller return (EFTYPE);
75277cb4d3eSLandon J. Fuller
75377cb4d3eSLandon J. Fuller /* Parse and skip sign */
75477cb4d3eSLandon J. Fuller if (str[*nbytes] == '-') {
75577cb4d3eSLandon J. Fuller negative = true;
75677cb4d3eSLandon J. Fuller sign = true;
75777cb4d3eSLandon J. Fuller (*nbytes)++;
75877cb4d3eSLandon J. Fuller } else if (str[*nbytes] == '+') {
75977cb4d3eSLandon J. Fuller sign = true;
76077cb4d3eSLandon J. Fuller (*nbytes)++;
76177cb4d3eSLandon J. Fuller }
76277cb4d3eSLandon J. Fuller
76377cb4d3eSLandon J. Fuller /* Truncated after sign character? */
76477cb4d3eSLandon J. Fuller if (*nbytes == maxlen)
76577cb4d3eSLandon J. Fuller return (EFTYPE);
76677cb4d3eSLandon J. Fuller
76777cb4d3eSLandon J. Fuller /* Identify (or validate) hex base, skipping 0x/0X prefix */
76877cb4d3eSLandon J. Fuller if (base == 16 || base == 0) {
76977cb4d3eSLandon J. Fuller /* Check for (and skip) 0x/0X prefix */
77077cb4d3eSLandon J. Fuller if (maxlen - *nbytes >= 2 && str[*nbytes] == '0' &&
77177cb4d3eSLandon J. Fuller (str[*nbytes+1] == 'x' || str[*nbytes+1] == 'X'))
77277cb4d3eSLandon J. Fuller {
77377cb4d3eSLandon J. Fuller base = 16;
77477cb4d3eSLandon J. Fuller (*nbytes) += 2;
77577cb4d3eSLandon J. Fuller }
77677cb4d3eSLandon J. Fuller }
77777cb4d3eSLandon J. Fuller
77877cb4d3eSLandon J. Fuller /* Truncated after hex prefix? */
77977cb4d3eSLandon J. Fuller if (*nbytes == maxlen)
78077cb4d3eSLandon J. Fuller return (EFTYPE);
78177cb4d3eSLandon J. Fuller
78277cb4d3eSLandon J. Fuller /* Differentiate decimal/octal by looking for a leading 0 */
78377cb4d3eSLandon J. Fuller if (base == 0) {
78477cb4d3eSLandon J. Fuller if (str[*nbytes] == '0') {
78577cb4d3eSLandon J. Fuller base = 8;
78677cb4d3eSLandon J. Fuller } else {
78777cb4d3eSLandon J. Fuller base = 10;
78877cb4d3eSLandon J. Fuller }
78977cb4d3eSLandon J. Fuller }
79077cb4d3eSLandon J. Fuller
79177cb4d3eSLandon J. Fuller /* Only enable twos-compliment signed integer parsing enabled if the
79277cb4d3eSLandon J. Fuller * input is base 16, and no explicit sign prefix was provided */
79377cb4d3eSLandon J. Fuller if (!sign && base == 16)
79477cb4d3eSLandon J. Fuller twos_compl = true;
79577cb4d3eSLandon J. Fuller else
79677cb4d3eSLandon J. Fuller twos_compl = false;
79777cb4d3eSLandon J. Fuller
79877cb4d3eSLandon J. Fuller /* Determine the maximum value representable by the requested type */
79977cb4d3eSLandon J. Fuller switch (otype) {
80077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR:
80177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8:
80277cb4d3eSLandon J. Fuller type_max = (uint64_t)UINT8_MAX;
80377cb4d3eSLandon J. Fuller break;
80477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16:
80577cb4d3eSLandon J. Fuller type_max = (uint64_t)UINT16_MAX;
80677cb4d3eSLandon J. Fuller break;
80777cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32:
80877cb4d3eSLandon J. Fuller type_max = (uint64_t)UINT32_MAX;
80977cb4d3eSLandon J. Fuller break;
81077cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64:
81177cb4d3eSLandon J. Fuller type_max = (uint64_t)UINT64_MAX;
81277cb4d3eSLandon J. Fuller break;
81377cb4d3eSLandon J. Fuller
81477cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8:
81577cb4d3eSLandon J. Fuller if (twos_compl)
81677cb4d3eSLandon J. Fuller type_max = (uint64_t)UINT8_MAX;
81777cb4d3eSLandon J. Fuller else if (negative)
81877cb4d3eSLandon J. Fuller type_max = -(uint64_t)INT8_MIN;
81977cb4d3eSLandon J. Fuller else
82077cb4d3eSLandon J. Fuller type_max = (uint64_t)INT8_MAX;
82177cb4d3eSLandon J. Fuller break;
82277cb4d3eSLandon J. Fuller
82377cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16:
82477cb4d3eSLandon J. Fuller if (twos_compl)
82577cb4d3eSLandon J. Fuller type_max = (uint64_t)UINT16_MAX;
82677cb4d3eSLandon J. Fuller else if (negative)
82777cb4d3eSLandon J. Fuller type_max = -(uint64_t)INT16_MIN;
82877cb4d3eSLandon J. Fuller else
82977cb4d3eSLandon J. Fuller type_max = (uint64_t)INT16_MAX;
83077cb4d3eSLandon J. Fuller break;
83177cb4d3eSLandon J. Fuller
83277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32:
83377cb4d3eSLandon J. Fuller if (twos_compl)
83477cb4d3eSLandon J. Fuller type_max = (uint64_t)UINT32_MAX;
83577cb4d3eSLandon J. Fuller else if (negative)
83677cb4d3eSLandon J. Fuller type_max = -(uint64_t)INT32_MIN;
83777cb4d3eSLandon J. Fuller else
83877cb4d3eSLandon J. Fuller type_max = (uint64_t)INT32_MAX;
83977cb4d3eSLandon J. Fuller break;
84077cb4d3eSLandon J. Fuller
84177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64:
84277cb4d3eSLandon J. Fuller if (twos_compl)
84377cb4d3eSLandon J. Fuller type_max = (uint64_t)UINT64_MAX;
84477cb4d3eSLandon J. Fuller else if (negative)
84577cb4d3eSLandon J. Fuller type_max = -(uint64_t)INT64_MIN;
84677cb4d3eSLandon J. Fuller else
84777cb4d3eSLandon J. Fuller type_max = (uint64_t)INT64_MAX;
84877cb4d3eSLandon J. Fuller break;
84977cb4d3eSLandon J. Fuller
85077cb4d3eSLandon J. Fuller default:
85177cb4d3eSLandon J. Fuller BHND_NV_LOG("unsupported integer type: %d\n", otype);
85277cb4d3eSLandon J. Fuller return (EINVAL);
85377cb4d3eSLandon J. Fuller }
85477cb4d3eSLandon J. Fuller
85577cb4d3eSLandon J. Fuller /* The maximum value after which an additional carry would overflow */
85677cb4d3eSLandon J. Fuller value_max = type_max / (uint64_t)base;
85777cb4d3eSLandon J. Fuller
85877cb4d3eSLandon J. Fuller /* The maximum carry value given a value equal to value_max */
85977cb4d3eSLandon J. Fuller carry_max = type_max % (uint64_t)base;
86077cb4d3eSLandon J. Fuller
86177cb4d3eSLandon J. Fuller /* Consume input until we hit maxlen or a non-digit character */
86277cb4d3eSLandon J. Fuller for (; *nbytes < maxlen; (*nbytes)++) {
86377cb4d3eSLandon J. Fuller u_long carry;
86477cb4d3eSLandon J. Fuller char c;
86577cb4d3eSLandon J. Fuller
86677cb4d3eSLandon J. Fuller /* Parse carry value */
86777cb4d3eSLandon J. Fuller c = str[*nbytes];
86877cb4d3eSLandon J. Fuller if (bhnd_nv_isdigit(c)) {
86977cb4d3eSLandon J. Fuller carry = c - '0';
87077cb4d3eSLandon J. Fuller } else if (bhnd_nv_isxdigit(c)) {
87177cb4d3eSLandon J. Fuller if (bhnd_nv_isupper(c))
87277cb4d3eSLandon J. Fuller carry = (c - 'A') + 10;
87377cb4d3eSLandon J. Fuller else
87477cb4d3eSLandon J. Fuller carry = (c - 'a') + 10;
87577cb4d3eSLandon J. Fuller } else {
87677cb4d3eSLandon J. Fuller /* Hit first non-digit character */
87777cb4d3eSLandon J. Fuller break;
87877cb4d3eSLandon J. Fuller }
87977cb4d3eSLandon J. Fuller
88077cb4d3eSLandon J. Fuller /* If carry is outside the base, it's not a valid digit
88177cb4d3eSLandon J. Fuller * in the current parse context; consider it a non-digit
88277cb4d3eSLandon J. Fuller * character */
88377cb4d3eSLandon J. Fuller if (carry >= (uint64_t)base)
88477cb4d3eSLandon J. Fuller break;
88577cb4d3eSLandon J. Fuller
88677cb4d3eSLandon J. Fuller /* Increment count of parsed digits */
88777cb4d3eSLandon J. Fuller ndigits++;
88877cb4d3eSLandon J. Fuller
88977cb4d3eSLandon J. Fuller if (value > value_max) {
89077cb4d3eSLandon J. Fuller /* -Any- carry value would overflow */
89177cb4d3eSLandon J. Fuller return (ERANGE);
89277cb4d3eSLandon J. Fuller } else if (value == value_max && carry > carry_max) {
89377cb4d3eSLandon J. Fuller /* -This- carry value would overflow */
89477cb4d3eSLandon J. Fuller return (ERANGE);
89577cb4d3eSLandon J. Fuller }
89677cb4d3eSLandon J. Fuller
89777cb4d3eSLandon J. Fuller value *= (uint64_t)base;
89877cb4d3eSLandon J. Fuller value += carry;
89977cb4d3eSLandon J. Fuller }
90077cb4d3eSLandon J. Fuller
90177cb4d3eSLandon J. Fuller /* If we hit a non-digit character before parsing the first digit,
90277cb4d3eSLandon J. Fuller * we hit an empty integer string. */
90377cb4d3eSLandon J. Fuller if (ndigits == 0)
90477cb4d3eSLandon J. Fuller return (EFTYPE);
90577cb4d3eSLandon J. Fuller
90677cb4d3eSLandon J. Fuller if (negative)
90777cb4d3eSLandon J. Fuller value = -value;
90877cb4d3eSLandon J. Fuller
90977cb4d3eSLandon J. Fuller /* Provide (and verify) required length */
9109be0790dSLandon J. Fuller *olen = bhnd_nvram_type_width(otype);
91177cb4d3eSLandon J. Fuller if (outp == NULL)
91277cb4d3eSLandon J. Fuller return (0);
91377cb4d3eSLandon J. Fuller else if (limit < *olen)
91477cb4d3eSLandon J. Fuller return (ENOMEM);
91577cb4d3eSLandon J. Fuller
91677cb4d3eSLandon J. Fuller /* Provide result */
91777cb4d3eSLandon J. Fuller switch (otype) {
91877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_CHAR:
91977cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT8:
92077cb4d3eSLandon J. Fuller *(uint8_t *)outp = (uint8_t)value;
92177cb4d3eSLandon J. Fuller break;
92277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT16:
92377cb4d3eSLandon J. Fuller *(uint16_t *)outp = (uint16_t)value;
92477cb4d3eSLandon J. Fuller break;
92577cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT32:
92677cb4d3eSLandon J. Fuller *(uint32_t *)outp = (uint32_t)value;
92777cb4d3eSLandon J. Fuller break;
92877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_UINT64:
92977cb4d3eSLandon J. Fuller *(uint64_t *)outp = (uint64_t)value;
93077cb4d3eSLandon J. Fuller break;
93177cb4d3eSLandon J. Fuller
93277cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT8:
93377cb4d3eSLandon J. Fuller *(int8_t *)outp = (int8_t)(int64_t)value;
93477cb4d3eSLandon J. Fuller break;
93577cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT16:
93677cb4d3eSLandon J. Fuller *(int16_t *)outp = (int16_t)(int64_t)value;
93777cb4d3eSLandon J. Fuller break;
93877cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT32:
93977cb4d3eSLandon J. Fuller *(int32_t *)outp = (int32_t)(int64_t)value;
94077cb4d3eSLandon J. Fuller break;
94177cb4d3eSLandon J. Fuller case BHND_NVRAM_TYPE_INT64:
94277cb4d3eSLandon J. Fuller *(int64_t *)outp = (int64_t)value;
94377cb4d3eSLandon J. Fuller break;
94477cb4d3eSLandon J. Fuller default:
94577cb4d3eSLandon J. Fuller /* unreachable */
94677cb4d3eSLandon J. Fuller BHND_NV_PANIC("unhandled type %d\n", otype);
94777cb4d3eSLandon J. Fuller }
94877cb4d3eSLandon J. Fuller
94977cb4d3eSLandon J. Fuller return (0);
95077cb4d3eSLandon J. Fuller }
95177cb4d3eSLandon J. Fuller
95277cb4d3eSLandon J. Fuller /**
95319be09f3SLandon J. Fuller * Trim leading path (pci/1/1) or path alias (0:) prefix from @p name, if any,
95419be09f3SLandon J. Fuller * returning a pointer to the start of the relative variable name.
95519be09f3SLandon J. Fuller *
95619be09f3SLandon J. Fuller * @par Examples
95719be09f3SLandon J. Fuller *
95819be09f3SLandon J. Fuller * - "/foo" -> "foo"
95919be09f3SLandon J. Fuller * - "dev/pci/foo" -> "foo"
96019be09f3SLandon J. Fuller * - "0:foo" -> "foo"
96119be09f3SLandon J. Fuller * - "foo" -> "foo"
96219be09f3SLandon J. Fuller *
96319be09f3SLandon J. Fuller * @param name The string to be trimmed.
96419be09f3SLandon J. Fuller *
96519be09f3SLandon J. Fuller * @return A pointer to the start of the relative variable name in @p name.
96619be09f3SLandon J. Fuller */
96719be09f3SLandon J. Fuller const char *
bhnd_nvram_trim_path_name(const char * name)96819be09f3SLandon J. Fuller bhnd_nvram_trim_path_name(const char *name)
96919be09f3SLandon J. Fuller {
97019be09f3SLandon J. Fuller char *endp;
97119be09f3SLandon J. Fuller
97219be09f3SLandon J. Fuller /* path alias prefix? (0:varname) */
97319be09f3SLandon J. Fuller if (bhnd_nv_isdigit(*name)) {
97419be09f3SLandon J. Fuller /* Parse '0...:' alias prefix, if it exists */
97519be09f3SLandon J. Fuller strtoul(name, &endp, 10);
97619be09f3SLandon J. Fuller if (endp != name && *endp == ':') {
97719be09f3SLandon J. Fuller /* Variable name follows 0: prefix */
97819be09f3SLandon J. Fuller return (endp+1);
97919be09f3SLandon J. Fuller }
98019be09f3SLandon J. Fuller }
98119be09f3SLandon J. Fuller
98219be09f3SLandon J. Fuller /* device path prefix? (pci/1/1/varname) */
98319be09f3SLandon J. Fuller if ((endp = strrchr(name, '/')) != NULL) {
98419be09f3SLandon J. Fuller /* Variable name follows the final path separator '/' */
98519be09f3SLandon J. Fuller return (endp+1);
98619be09f3SLandon J. Fuller }
98719be09f3SLandon J. Fuller
98819be09f3SLandon J. Fuller /* variable name is not prefixed */
98919be09f3SLandon J. Fuller return (name);
99019be09f3SLandon J. Fuller }
99119be09f3SLandon J. Fuller
99219be09f3SLandon J. Fuller /**
99377cb4d3eSLandon J. Fuller * Parse a 'name=value' string.
99477cb4d3eSLandon J. Fuller *
99577cb4d3eSLandon J. Fuller * @param env The string to be parsed.
99677cb4d3eSLandon J. Fuller * @param env_len The length of @p envp.
99777cb4d3eSLandon J. Fuller * @param delim The delimiter used in @p envp. This will generally be '='.
99877cb4d3eSLandon J. Fuller * @param[out] name If not NULL, a pointer to the name string. This argument
99977cb4d3eSLandon J. Fuller * may be NULL.
100077cb4d3eSLandon J. Fuller * @param[out] name_len On success, the length of the name substring. This
100177cb4d3eSLandon J. Fuller * argument may be NULL.
100277cb4d3eSLandon J. Fuller * @param[out] value On success, a pointer to the value substring. This argument
100377cb4d3eSLandon J. Fuller * may be NULL.
100477cb4d3eSLandon J. Fuller * @param[out] value_len On success, the length of the value substring. This
100577cb4d3eSLandon J. Fuller * argument may be NULL.
100677cb4d3eSLandon J. Fuller *
100777cb4d3eSLandon J. Fuller * @retval 0 success
100877cb4d3eSLandon J. Fuller * @retval EINVAL if parsing @p envp fails.
100977cb4d3eSLandon J. Fuller */
101077cb4d3eSLandon J. Fuller int
bhnd_nvram_parse_env(const char * env,size_t env_len,char delim,const char ** name,size_t * name_len,const char ** value,size_t * value_len)101177cb4d3eSLandon J. Fuller bhnd_nvram_parse_env(const char *env, size_t env_len, char delim,
101277cb4d3eSLandon J. Fuller const char **name, size_t *name_len, const char **value, size_t *value_len)
101377cb4d3eSLandon J. Fuller {
101477cb4d3eSLandon J. Fuller const char *p;
101577cb4d3eSLandon J. Fuller
101677cb4d3eSLandon J. Fuller /* Name */
101777cb4d3eSLandon J. Fuller if ((p = memchr(env, delim, env_len)) == NULL) {
101877cb4d3eSLandon J. Fuller BHND_NV_LOG("delimiter '%c' not found in '%.*s'\n", delim,
101977cb4d3eSLandon J. Fuller BHND_NV_PRINT_WIDTH(env_len), env);
102077cb4d3eSLandon J. Fuller return (EINVAL);
102177cb4d3eSLandon J. Fuller }
102277cb4d3eSLandon J. Fuller
102377cb4d3eSLandon J. Fuller /* Name */
102477cb4d3eSLandon J. Fuller if (name != NULL)
102577cb4d3eSLandon J. Fuller *name = env;
102677cb4d3eSLandon J. Fuller if (name_len != NULL)
102777cb4d3eSLandon J. Fuller *name_len = p - env;
102877cb4d3eSLandon J. Fuller
102977cb4d3eSLandon J. Fuller /* Skip delim */
103077cb4d3eSLandon J. Fuller p++;
103177cb4d3eSLandon J. Fuller
103277cb4d3eSLandon J. Fuller /* Value */
103377cb4d3eSLandon J. Fuller if (value != NULL)
103477cb4d3eSLandon J. Fuller *value = p;
103577cb4d3eSLandon J. Fuller if (value_len != NULL)
103677cb4d3eSLandon J. Fuller *value_len = env_len - (p - env);
103777cb4d3eSLandon J. Fuller
103877cb4d3eSLandon J. Fuller return (0);
103977cb4d3eSLandon J. Fuller }
104077cb4d3eSLandon J. Fuller
104177cb4d3eSLandon J. Fuller /**
104277cb4d3eSLandon J. Fuller * Parse a field value, returning the actual pointer to the first
104377cb4d3eSLandon J. Fuller * non-whitespace character and the total size of the field.
104477cb4d3eSLandon J. Fuller *
104577cb4d3eSLandon J. Fuller * @param[in,out] inp The field string to parse. Will be updated to point
104677cb4d3eSLandon J. Fuller * at the first non-whitespace character found.
104777cb4d3eSLandon J. Fuller * @param ilen The length of @p inp, in bytes.
104877cb4d3eSLandon J. Fuller * @param delim The field delimiter to search for.
104977cb4d3eSLandon J. Fuller *
105077cb4d3eSLandon J. Fuller * @return Returns the actual size of the field data.
105177cb4d3eSLandon J. Fuller */
105277cb4d3eSLandon J. Fuller size_t
bhnd_nvram_parse_field(const char ** inp,size_t ilen,char delim)105377cb4d3eSLandon J. Fuller bhnd_nvram_parse_field(const char **inp, size_t ilen, char delim)
105477cb4d3eSLandon J. Fuller {
105577cb4d3eSLandon J. Fuller const char *p, *sp;
105677cb4d3eSLandon J. Fuller
105777cb4d3eSLandon J. Fuller /* Skip any leading whitespace */
105877cb4d3eSLandon J. Fuller for (sp = *inp; (size_t)(sp-*inp) < ilen && bhnd_nv_isspace(*sp); sp++)
105977cb4d3eSLandon J. Fuller continue;
106077cb4d3eSLandon J. Fuller
106177cb4d3eSLandon J. Fuller *inp = sp;
106277cb4d3eSLandon J. Fuller
106377cb4d3eSLandon J. Fuller /* Find the last field character */
106477cb4d3eSLandon J. Fuller for (p = *inp; (size_t)(p - *inp) < ilen; p++) {
106577cb4d3eSLandon J. Fuller if (*p == delim || *p == '\0')
106677cb4d3eSLandon J. Fuller break;
106777cb4d3eSLandon J. Fuller }
106877cb4d3eSLandon J. Fuller
106977cb4d3eSLandon J. Fuller return (p - *inp);
107077cb4d3eSLandon J. Fuller }
107177cb4d3eSLandon J. Fuller
107277cb4d3eSLandon J. Fuller /**
107377cb4d3eSLandon J. Fuller * Parse a field value, returning the actual pointer to the first
107477cb4d3eSLandon J. Fuller * non-whitespace character and the total size of the field, minus
107577cb4d3eSLandon J. Fuller * any trailing whitespace.
107677cb4d3eSLandon J. Fuller *
107777cb4d3eSLandon J. Fuller * @param[in,out] inp The field string to parse. Will be updated to point
107877cb4d3eSLandon J. Fuller * at the first non-whitespace character found.
107977cb4d3eSLandon J. Fuller * @param ilen The length of the parsed field, in bytes, excluding the
108077cb4d3eSLandon J. Fuller * field elimiter and any trailing whitespace.
108177cb4d3eSLandon J. Fuller * @param delim The field delimiter to search for.
108277cb4d3eSLandon J. Fuller *
108377cb4d3eSLandon J. Fuller * @return Returns the actual size of the field data.
108477cb4d3eSLandon J. Fuller */
108577cb4d3eSLandon J. Fuller size_t
bhnd_nvram_trim_field(const char ** inp,size_t ilen,char delim)108677cb4d3eSLandon J. Fuller bhnd_nvram_trim_field(const char **inp, size_t ilen, char delim)
108777cb4d3eSLandon J. Fuller {
108877cb4d3eSLandon J. Fuller const char *sp;
108977cb4d3eSLandon J. Fuller size_t plen;
109077cb4d3eSLandon J. Fuller
109177cb4d3eSLandon J. Fuller plen = bhnd_nvram_parse_field(inp, ilen, delim);
109277cb4d3eSLandon J. Fuller
109377cb4d3eSLandon J. Fuller /* Trim trailing whitespace */
109477cb4d3eSLandon J. Fuller sp = *inp;
109577cb4d3eSLandon J. Fuller while (plen > 0) {
109677cb4d3eSLandon J. Fuller if (!bhnd_nv_isspace(*(sp + plen - 1)))
109777cb4d3eSLandon J. Fuller break;
109877cb4d3eSLandon J. Fuller
109977cb4d3eSLandon J. Fuller plen--;
110077cb4d3eSLandon J. Fuller }
110177cb4d3eSLandon J. Fuller
110277cb4d3eSLandon J. Fuller return (plen);
110377cb4d3eSLandon J. Fuller }
1104