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