Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/bhnd/nvram/bhnd_nvram_private.h
39536 views
1
/*-
2
* Copyright (c) 2015-2016 Landon Fuller <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer,
10
* without modification.
11
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
12
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13
* redistribution must be conditioned upon including a substantially
14
* similar Disclaimer requirement for further binary redistribution.
15
*
16
* NO WARRANTY
17
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27
* THE POSSIBILITY OF SUCH DAMAGES.
28
*
29
*/
30
31
#ifndef _BHND_NVRAM_BHND_NVRAM_PRIVATE_H_
32
#define _BHND_NVRAM_BHND_NVRAM_PRIVATE_H_
33
34
/*
35
* Private BHND NVRAM definitions.
36
*/
37
38
#include <sys/param.h>
39
40
#ifdef _KERNEL
41
#include <sys/malloc.h>
42
#include <sys/stdarg.h>
43
#else
44
#include <stdarg.h>
45
#include <stdbool.h>
46
#include <stdint.h>
47
#include <stdlib.h>
48
#endif
49
50
#include "bhnd_nvram.h"
51
#include "bhnd_nvram_value.h"
52
53
/*
54
* bhnd_nvram_crc8() lookup table.
55
*/
56
extern const uint8_t bhnd_nvram_crc8_tab[];
57
58
/* Forward declarations */
59
struct bhnd_nvram_vardefn;
60
61
#ifdef _KERNEL
62
63
MALLOC_DECLARE(M_BHND_NVRAM);
64
65
#define bhnd_nv_isupper(c) isupper(c)
66
#define bhnd_nv_islower(c) islower(c)
67
#define bhnd_nv_isalpha(c) isalpha(c)
68
#define bhnd_nv_isprint(c) isprint(c)
69
#define bhnd_nv_isspace(c) isspace(c)
70
#define bhnd_nv_isdigit(c) isdigit(c)
71
#define bhnd_nv_isxdigit(c) isxdigit(c)
72
#define bhnd_nv_toupper(c) toupper(c)
73
74
#define bhnd_nv_malloc(size) malloc((size), M_BHND_NVRAM, M_NOWAIT)
75
#define bhnd_nv_calloc(n, size) mallocarray((n), (size), M_BHND_NVRAM, \
76
M_NOWAIT | M_ZERO)
77
#define bhnd_nv_reallocf(buf, size) reallocf((buf), (size), M_BHND_NVRAM, \
78
M_NOWAIT)
79
#define bhnd_nv_free(buf) free((buf), M_BHND_NVRAM)
80
#define bhnd_nv_asprintf(buf, fmt, ...) asprintf((buf), M_BHND_NVRAM, \
81
fmt, ## __VA_ARGS__)
82
83
/* We need our own strdup() implementation to pass required M_NOWAIT */
84
static inline char *
85
bhnd_nv_strdup(const char *str)
86
{
87
char *dest;
88
size_t len;
89
90
len = strlen(str);
91
dest = malloc(len + 1, M_BHND_NVRAM, M_NOWAIT);
92
if (dest == NULL)
93
return (NULL);
94
95
memcpy(dest, str, len);
96
dest[len] = '\0';
97
98
return (dest);
99
}
100
101
/* We need our own strndup() implementation to pass required M_NOWAIT */
102
static inline char *
103
bhnd_nv_strndup(const char *str, size_t len)
104
{
105
char *dest;
106
107
len = strnlen(str, len);
108
dest = malloc(len + 1, M_BHND_NVRAM, M_NOWAIT);
109
if (dest == NULL)
110
return (NULL);
111
112
memcpy(dest, str, len);
113
dest[len] = '\0';
114
115
return (dest);
116
}
117
118
#ifdef INVARIANTS
119
#define BHND_NV_INVARIANTS
120
#endif
121
122
#define BHND_NV_ASSERT(expr, ...) KASSERT(expr, __VA_ARGS__)
123
124
#define BHND_NV_VERBOSE (bootverbose)
125
#define BHND_NV_PANIC(...) panic(__VA_ARGS__)
126
#define BHND_NV_LOG(fmt, ...) \
127
printf("%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
128
129
#define bhnd_nv_ummax(a, b) ummax((a), (b))
130
#define bhnd_nv_ummin(a, b) ummin((a), (b))
131
132
#else /* !_KERNEL */
133
134
#include <assert.h>
135
#include <stdint.h>
136
#include <stdio.h>
137
#include <stdlib.h>
138
139
/* ASCII-specific ctype variants that work consistently regardless
140
* of current locale */
141
#define bhnd_nv_isupper(c) ((c) >= 'A' && (c) <= 'Z')
142
#define bhnd_nv_islower(c) ((c) >= 'a' && (c) <= 'z')
143
#define bhnd_nv_isalpha(c) (bhnd_nv_isupper(c) || bhnd_nv_islower(c))
144
#define bhnd_nv_isprint(c) ((c) >= ' ' && (c) <= '~')
145
#define bhnd_nv_isspace(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r'))
146
#define bhnd_nv_isdigit(c) isdigit(c)
147
#define bhnd_nv_isxdigit(c) isxdigit(c)
148
#define bhnd_nv_toupper(c) ((c) - \
149
(('a' - 'A') * ((c) >= 'a' && (c) <= 'z')))
150
151
#define bhnd_nv_malloc(size) malloc((size))
152
#define bhnd_nv_calloc(n, size) calloc((n), (size))
153
#define bhnd_nv_reallocf(buf, size) reallocf((buf), (size))
154
#define bhnd_nv_free(buf) free((buf))
155
#define bhnd_nv_strdup(str) strdup(str)
156
#define bhnd_nv_strndup(str, len) strndup(str, len)
157
#define bhnd_nv_asprintf(buf, fmt, ...) asprintf((buf), fmt, ## __VA_ARGS__)
158
159
#ifndef NDEBUG
160
#define BHND_NV_INVARIANTS
161
#endif
162
163
#ifdef BHND_NV_INVARIANTS
164
165
#define BHND_NV_ASSERT(expr, msg) do { \
166
if (!(expr)) { \
167
fprintf(stderr, "Assertion failed: %s, function %s, " \
168
"file %s, line %u\n", __STRING(expr), __FUNCTION__, \
169
__FILE__, __LINE__); \
170
BHND_NV_PANIC msg; \
171
} \
172
} while(0)
173
174
#else /* !BHND_NV_INVARIANTS */
175
176
#define BHND_NV_ASSERT(expr, msg)
177
178
#endif /* BHND_NV_INVARIANTS */
179
180
#define BHND_NV_VERBOSE (0)
181
#define BHND_NV_PANIC(fmt, ...) do { \
182
fprintf(stderr, "panic: " fmt "\n", ##__VA_ARGS__); \
183
abort(); \
184
} while(0)
185
#define BHND_NV_LOG(fmt, ...) \
186
fprintf(stderr, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
187
188
static inline uintmax_t
189
bhnd_nv_ummax(uintmax_t a, uintmax_t b)
190
{
191
return (a > b ? a : b);
192
}
193
194
static inline uintmax_t
195
bhnd_nv_ummin(uintmax_t a, uintmax_t b)
196
{
197
198
return (a < b ? a : b);
199
}
200
201
#endif /* _KERNEL */
202
203
#ifdef BHND_NV_VERBOSE
204
#define BHND_NV_DEBUG(...) BHND_NV_LOG(__VA_ARGS__)
205
#else /* !BHND_NV_VERBOSE */
206
#define BHND_NV_DEBUG(...)
207
#endif /* BHND_NV_VERBOSE */
208
209
/* Limit a size_t value to a suitable range for use as a printf string field
210
* width */
211
#define BHND_NV_PRINT_WIDTH(_len) \
212
((_len) > (INT_MAX) ? (INT_MAX) : (int)(_len))
213
214
int bhnd_nvram_value_coerce(const void *inp,
215
size_t ilen, bhnd_nvram_type itype,
216
void *outp, size_t *olen,
217
bhnd_nvram_type otype);
218
219
int bhnd_nvram_value_check_aligned(const void *inp,
220
size_t ilen, bhnd_nvram_type itype);
221
222
int bhnd_nvram_value_nelem(const void *inp,
223
size_t ilen, bhnd_nvram_type itype,
224
size_t *nelem);
225
226
size_t bhnd_nvram_value_size(const void *inp,
227
size_t ilen, bhnd_nvram_type itype,
228
size_t nelem);
229
230
int bhnd_nvram_value_printf(const char *fmt,
231
const void *inp, size_t ilen,
232
bhnd_nvram_type itype, char *outp,
233
size_t *olen, ...);
234
int bhnd_nvram_value_vprintf(const char *fmt,
235
const void *inp, size_t ilen,
236
bhnd_nvram_type itype, char *outp,
237
size_t *olen, va_list ap);
238
239
const void *bhnd_nvram_value_array_next(const void *inp,
240
size_t ilen, bhnd_nvram_type itype,
241
const void *prev, size_t *olen);
242
243
const struct bhnd_nvram_vardefn *bhnd_nvram_find_vardefn(const char *varname);
244
const struct bhnd_nvram_vardefn *bhnd_nvram_get_vardefn(size_t id);
245
size_t bhnd_nvram_get_vardefn_id(
246
const struct bhnd_nvram_vardefn *defn);
247
248
int bhnd_nvram_parse_int(const char *s,
249
size_t maxlen, u_int base, size_t *nbytes,
250
void *outp, size_t *olen,
251
bhnd_nvram_type otype);
252
253
int bhnd_nvram_parse_env(const char *env,
254
size_t env_len, char delim,
255
const char **name, size_t *name_len,
256
const char **value, size_t *value_len);
257
258
size_t bhnd_nvram_parse_field(const char **inp,
259
size_t ilen, char delim);
260
size_t bhnd_nvram_trim_field(const char **inp,
261
size_t ilen, char delim);
262
263
const char *bhnd_nvram_trim_path_name(const char *name);
264
265
bool bhnd_nvram_validate_name(const char *name);
266
267
/**
268
* Calculate CRC-8 over @p buf using the Broadcom SPROM/NVRAM CRC-8
269
* polynomial.
270
*
271
* @param buf input buffer
272
* @param size buffer size
273
* @param crc last computed crc, or BHND_NVRAM_CRC8_INITIAL
274
*/
275
static inline uint8_t
276
bhnd_nvram_crc8(const void *buf, size_t size, uint8_t crc)
277
{
278
const uint8_t *p = (const uint8_t *)buf;
279
while (size--)
280
crc = bhnd_nvram_crc8_tab[(crc ^ *p++)];
281
282
return (crc);
283
}
284
285
#define BHND_NVRAM_CRC8_INITIAL 0xFF /**< Initial bhnd_nvram_crc8 value */
286
#define BHND_NVRAM_CRC8_VALID 0x9F /**< Valid CRC-8 checksum */
287
288
/** NVRAM variable flags */
289
enum {
290
BHND_NVRAM_VF_MFGINT = 1<<0, /**< mfg-internal variable; should not
291
be externally visible */
292
BHND_NVRAM_VF_IGNALL1 = 1<<1 /**< hide variable if its value has all
293
bits set. */
294
};
295
296
/**
297
* SPROM layout flags
298
*/
299
enum {
300
/**
301
* SPROM layout does not have magic identification value.
302
*
303
* This applies to SPROM revisions 1-3, where the actual
304
* layout must be determined by looking for a matching sromrev
305
* at the expected offset, and then verifying the CRC to ensure
306
* that the match was not a false positive.
307
*/
308
SPROM_LAYOUT_MAGIC_NONE = (1<<0),
309
};
310
311
/** NVRAM variable definition */
312
struct bhnd_nvram_vardefn {
313
const char *name; /**< variable name */
314
const char *desc; /**< human readable description,
315
or NULL */
316
const char *help; /**< human readable help text,
317
or NULL */
318
bhnd_nvram_type type; /**< variable type */
319
uint8_t nelem; /**< element count, or 1 if not
320
an array-typed variable */
321
const bhnd_nvram_val_fmt *fmt; /**< value format */
322
uint32_t flags; /**< flags (BHND_NVRAM_VF_*) */
323
};
324
325
/*
326
* NVRAM variable definitions generated from nvram_map.
327
*/
328
extern const struct bhnd_nvram_vardefn bhnd_nvram_vardefns[];
329
extern const size_t bhnd_nvram_num_vardefns;
330
331
/**
332
* SPROM layout descriptor.
333
*/
334
typedef struct bhnd_sprom_layout {
335
size_t size; /**< SPROM image size, in bytes */
336
uint8_t rev; /**< SPROM revision */
337
uint8_t flags; /**< layout flags (SPROM_LAYOUT_*) */
338
size_t srev_offset; /**< offset to SROM revision */
339
size_t magic_offset; /**< offset to magic value */
340
uint16_t magic_value; /**< expected magic value */
341
size_t crc_offset; /**< offset to crc8 value */
342
const uint8_t *bindings; /**< SPROM binding opcode table */
343
size_t bindings_size; /**< SPROM binding opcode table size */
344
uint16_t num_vars; /**< total number of variables defined
345
for this layout by the binding
346
table */
347
} bhnd_sprom_layout;
348
349
/*
350
* SPROM layout descriptions generated from nvram_map.
351
*/
352
extern const struct bhnd_sprom_layout bhnd_sprom_layouts[];
353
extern const size_t bhnd_sprom_num_layouts;
354
355
/*
356
* SPROM binding opcodes.
357
*
358
* Most opcodes are provided with two variants:
359
*
360
* - Standard: The opcode's data directly follows the opcode. The data type
361
* (SPROM_OPCODE_DATA_*) is encoded in the opcode immediate (IMM).
362
* - Immediate: The opcode's data is encoded directly in the opcode immediate
363
* (IMM).
364
*/
365
#define SPROM_OPC_MASK 0xF0 /**< operation mask */
366
#define SPROM_IMM_MASK 0x0F /**< immediate value mask */
367
#define SPROM_IMM_MAX SPROM_IMM_MASK
368
#define SPROM_OP_DATA_U8 0x00 /**< data is u8 */
369
#define SPROM_OP_DATA_U8_SCALED 0x01 /**< data is u8; multiply by
370
type width */
371
#define SPROM_OP_DATA_U16 0x02 /**< data is u16-le */
372
#define SPROM_OP_DATA_U32 0x03 /**< data is u32-le */
373
#define SPROM_OP_DATA_I8 0x04 /**< data is i8 */
374
#define SPROM_OPCODE_EXT 0x00 /**< extended opcodes defined
375
in IMM */
376
#define SPROM_OPCODE_EOF 0x00 /**< marks end of opcode
377
stream */
378
#define SPROM_OPCODE_NELEM 0x01 /**< variable array element
379
count follows as U8 */
380
#define SPROM_OPCODE_VAR_END 0x02 /**< marks end of variable
381
definition */
382
#define SPROM_OPCODE_TYPE 0x03 /**< input type follows as U8
383
(see BHND_NVRAM_TYPE_*) */
384
#define SPROM_OPCODE_VAR_IMM 0x10 /**< variable ID (imm) */
385
#define SPROM_OPCODE_VAR_REL_IMM 0x20 /**< relative variable ID
386
(last ID + imm) */
387
#define SPROM_OPCODE_VAR 0x30 /**< variable ID */
388
#define SPROM_OPCODE_REV_IMM 0x40 /**< revision range (imm) */
389
#define SPROM_OPCODE_REV_RANGE 0x50 /**< revision range (8-bit range)*/
390
#define SPROM_OP_REV_RANGE_MAX 0x0F /**< maximum representable SROM
391
revision */
392
#define SPROM_OP_REV_START_MASK 0xF0
393
#define SPROM_OP_REV_START_SHIFT 4
394
#define SPROM_OP_REV_END_MASK 0x0F
395
#define SPROM_OP_REV_END_SHIFT 0
396
#define SPROM_OPCODE_MASK_IMM 0x60 /**< value mask (imm) */
397
#define SPROM_OPCODE_MASK 0x70 /**< value mask */
398
#define SPROM_OPCODE_SHIFT_IMM 0x80 /**< value shift (unsigned
399
imm, multipled by 2) */
400
#define SPROM_OPCODE_SHIFT 0x90 /**< value shift */
401
#define SPROM_OPCODE_OFFSET_REL_IMM 0xA0 /**< relative input offset
402
(last offset +
403
(imm * type width)) */
404
#define SPROM_OPCODE_OFFSET 0xB0 /**< input offset */
405
#define SPROM_OPCODE_TYPE_IMM 0xC0 /**< input type (imm,
406
see BHND_NVRAM_TYPE_*) */
407
#define SPROM_OPCODE_DO_BIND 0xD0 /**< bind current value,
408
advance input/output
409
offsets as per IMM */
410
#define SPROM_OP_BIND_SKIP_IN_MASK 0x03 /**< the number of input
411
elements to advance after
412
the bind */
413
#define SPROM_OP_BIND_SKIP_IN_SHIFT 0
414
#define SPROM_OP_BIND_SKIP_IN_SIGN (1<<2) /**< SKIP_IN sign bit */
415
#define SPROM_OP_BIND_SKIP_OUT_MASK 0x08 /**< the number of output
416
elements to advance after
417
the bind */
418
#define SPROM_OP_BIND_SKIP_OUT_SHIFT 3
419
#define SPROM_OPCODE_DO_BINDN_IMM 0xE0 /**< bind IMM times, advancing
420
input/output offsets by one
421
element each time */
422
#define SPROM_OPCODE_DO_BINDN 0xF0 /**< bind N times, advancing
423
input/output offsets as per
424
SPROM_OP_BIND_SKIP_IN/SPROM_OP_BIND_SKIP_OUT
425
IMM values. The U8 element
426
count follows. */
427
428
/** Evaluates to true if opcode is an extended opcode */
429
#define SPROM_OPCODE_IS_EXT(_opcode) \
430
(((_opcode) & SPROM_OPC_MASK) == SPROM_OPCODE_EXT)
431
432
/** Return the opcode constant for a simple or extended opcode */
433
#define SPROM_OPCODE_OP(_opcode) \
434
(SPROM_OPCODE_IS_EXT(_opcode) ? (_opcode) : ((_opcode) & SPROM_OPC_MASK))
435
436
/** Return the opcode immediate for a simple opcode, or zero if this is
437
* an extended opcode */
438
#define SPROM_OPCODE_IMM(_opcode) \
439
(SPROM_OPCODE_IS_EXT(_opcode) ? 0 : ((_opcode) & SPROM_IMM_MASK))
440
441
/** Evaluates to true if the given opcode produces an implicit
442
* SPROM_OPCODE_VAR_END instruction for any open variable */
443
#define SPROM_OP_IS_IMPLICIT_VAR_END(_opcode) \
444
(((_opcode) == SPROM_OPCODE_VAR_IMM) || \
445
((_opcode) == SPROM_OPCODE_VAR_REL_IMM) || \
446
((_opcode) == SPROM_OPCODE_VAR) || \
447
((_opcode) == SPROM_OPCODE_REV_IMM) || \
448
((_opcode) == SPROM_OPCODE_REV_RANGE))
449
450
/** Evaluates to true if the given opcode is either an explicit
451
* SPROM_OPCODE_VAR_END instruction, or is an opcode that produces an
452
* implicit terminatation of any open variable */
453
#define SPROM_OP_IS_VAR_END(_opcode) \
454
(((_opcode) == SPROM_OPCODE_VAR_END) || \
455
SPROM_OP_IS_IMPLICIT_VAR_END(_opcode))
456
457
/** maximum representable immediate value */
458
#define SPROM_OP_IMM_MAX SPROM_IMM_MASK
459
460
/** maximum representable SROM revision */
461
#define SPROM_OP_REV_MAX MAX(SPROM_OP_REV_RANGE_MAX, SPROM_IMM_MAX)
462
463
#endif /* _BHND_NVRAM_BHND_NVRAM_PRIVATE_H_ */
464
465