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_SPROMVAR_H_
33 #define _BHND_NVRAM_BHND_NVRAM_SPROMVAR_H_
34 
35 #ifdef _KERNEL
36 #include <sys/bitstring.h>
37 #else
38 #include <bitstring.h>
39 #endif
40 
41 #include "bhnd_nvram_private.h"
42 
43 #include "bhnd_nvram_datavar.h"
44 #include "bhnd_nvram_io.h"
45 
46 /** The maximum number of array elements encoded in a single SPROM variable */
47 #define	BHND_SPROM_ARRAY_MAXLEN	12
48 
49 typedef struct bhnd_sprom_opcode_state		bhnd_sprom_opcode_state;
50 typedef struct bhnd_sprom_opcode_bind		bhnd_sprom_opcode_bind;
51 typedef struct bhnd_sprom_opcode_var		bhnd_sprom_opcode_var;
52 typedef struct bhnd_sprom_opcode_idx_entry	bhnd_sprom_opcode_idx_entry;
53 
54 int				 bhnd_sprom_opcode_init(
55 				     bhnd_sprom_opcode_state *state,
56 				     const bhnd_sprom_layout *layout);
57 void				 bhnd_sprom_opcode_fini(
58 				     bhnd_sprom_opcode_state *state);
59 
60 bhnd_sprom_opcode_idx_entry	*bhnd_sprom_opcode_index_find(
61 				     bhnd_sprom_opcode_state *state,
62 				     const char *name);
63 bhnd_sprom_opcode_idx_entry	*bhnd_sprom_opcode_index_next(
64 				     bhnd_sprom_opcode_state *state,
65 				     bhnd_sprom_opcode_idx_entry *prev);
66 
67 int				 bhnd_sprom_opcode_init_entry(
68 				     bhnd_sprom_opcode_state *state,
69 				     bhnd_sprom_opcode_idx_entry *entry);
70 
71 int				 bhnd_sprom_opcode_eval_var(
72 				     bhnd_sprom_opcode_state *state,
73 				     bhnd_sprom_opcode_idx_entry *entry);
74 
75 int				 bhnd_sprom_opcode_seek(
76 				     bhnd_sprom_opcode_state *state,
77 				     bhnd_sprom_opcode_idx_entry *entry);
78 int				 bhnd_sprom_opcode_next_var(
79 				     bhnd_sprom_opcode_state *state);
80 int				 bhnd_sprom_opcode_next_binding(
81 				     bhnd_sprom_opcode_state *state);
82 int				 bhnd_sprom_opcode_apply_scale(
83 				     bhnd_sprom_opcode_state *state,
84 				      uint32_t *value);
85 
86 /**
87  * SPROM opcode per-bind evaluation state.
88  */
89 struct bhnd_sprom_opcode_bind {
90 	uint8_t		count;
91 	uint32_t	skip_in;		/**< input element skips */
92 	bool		skip_in_negative;	/**< skip_in should be subtracted */
93 	uint32_t	skip_out;		/**< output element skip */
94 };
95 
96 /**
97  * SPROM opcode per-variable evaluation state.
98  */
99 struct bhnd_sprom_opcode_var {
100 	uint8_t			nelem;		/**< variable array length */
101 	uint32_t		mask;		/**< current bind input mask */
102 	int8_t			shift;		/**< current bind input shift */
103 	bhnd_nvram_type		base_type;	/**< current bind input type */
104 	uint32_t		scale;		/**< current scale to apply to scaled encodings */
105 	bhnd_sprom_opcode_bind	bind;		/**< current bind state */
106 	bool			have_bind;	/**< if bind state is defined */
107 	size_t			bind_total;	/**< total count of bind operations performed */
108 };
109 
110 /**
111  * SPROM opcode variable definition states.
112  *
113  * Ordered to support inequality comparisons
114  * (e.g. >= SPROM_OPCODE_VAR_STATE_OPEN)
115  */
116 typedef enum {
117 	SPROM_OPCODE_VAR_STATE_NONE	= 1,	/**< no variable entry available */
118 	SPROM_OPCODE_VAR_STATE_OPEN	= 2,	/**< currently parsing a variable entry */
119 	SPROM_OPCODE_VAR_STATE_DONE	= 3	/**< full variable entry has been parsed */
120 } bhnd_sprom_opcode_var_state;
121 
122 /**
123  * SPROM opcode evaluation state
124  */
125 struct bhnd_sprom_opcode_state {
126 	const bhnd_sprom_layout		*layout;	/**< SPROM layout */
127 
128 	bhnd_sprom_opcode_idx_entry	*idx;		/**< variable index (NULL during initialization) */
129 	size_t				 num_idx;	/**< variable index entry count */
130 
131 	/** Current SPROM revision range */
132 	bitstr_t			 bit_decl(revs, SPROM_OP_REV_MAX);
133 
134 	const uint8_t			*input;		/**< opcode input position */
135 
136 	/* State preserved across variable definitions */
137 	uint32_t			 offset;	/**< SPROM offset */
138 	size_t				 vid;		/**< Variable ID */
139 
140 	/* State reset after end of each variable definition */
141 	bhnd_sprom_opcode_var		 var;		/**< variable record (if any) */
142 	bhnd_sprom_opcode_var_state	 var_state;	/**< variable record state */
143 };
144 
145 /**
146  * SPROM opcode variable index entry
147  */
148 struct bhnd_sprom_opcode_idx_entry {
149 	uint16_t	vid;		/**< SPROM variable ID */
150 	uint16_t	offset;		/**< SPROM input offset */
151 	uint16_t	opcodes;	/**< SPROM opcode offset */
152 };
153 
154 /**
155  * SPROM value storage.
156  *
157  * Sufficient for representing the native encoding of any defined SPROM
158  * variable.
159  */
160 union bhnd_nvram_sprom_storage {
161 	uint8_t		u8[BHND_SPROM_ARRAY_MAXLEN];
162 	uint16_t	u16[BHND_SPROM_ARRAY_MAXLEN];
163 	uint32_t	u32[BHND_SPROM_ARRAY_MAXLEN];
164 	int8_t		i8[BHND_SPROM_ARRAY_MAXLEN];
165 	int16_t		i16[BHND_SPROM_ARRAY_MAXLEN];
166 	int32_t		i32[BHND_SPROM_ARRAY_MAXLEN];
167 	char		ch[BHND_SPROM_ARRAY_MAXLEN];
168 };
169 
170 /**
171  * SPROM data class instance state.
172  */
173 struct bhnd_nvram_sprom {
174 	struct bhnd_nvram_data	 nv;		/**< common instance state */
175 	struct bhnd_nvram_io	*data;		/**< backing SPROM image */
176 	const bhnd_sprom_layout	*layout;	/**< layout definition */
177 	bhnd_sprom_opcode_state	 state;		/**< opcode eval state */
178 };
179 
180 #endif /* _BHND_NVRAM_BHND_NVRAM_SPROMVAR_H_ */
181