xref: /OK3568_Linux_fs/external/rkwifibt/drivers/infineon/include/bcmtlv.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * TLV and XTLV support
3  *
4  * Portions of this code are copyright (c) 2021 Cypress Semiconductor Corporation
5  *
6  * Copyright (C) 1999-2017, Broadcom Corporation
7  *
8  *      Unless you and Broadcom execute a separate written software license
9  * agreement governing use of this software, this software is licensed to you
10  * under the terms of the GNU General Public License version 2 (the "GPL"),
11  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
12  * following added to such license:
13  *
14  *      As a special exception, the copyright holders of this software give you
15  * permission to link this software with independent modules, and to copy and
16  * distribute the resulting executable under terms of your choice, provided that
17  * you also meet, for each linked independent module, the terms and conditions of
18  * the license of that module.  An independent module is a module which is not
19  * derived from this software.  The special exception does not apply to any
20  * modifications of the software.
21  *
22  *      Notwithstanding the above, under no circumstances may you combine this
23  * software in any way with any other Broadcom software provided under a license
24  * other than the GPL, without Broadcom's express prior written consent.
25  *
26  * <<Broadcom-WL-IPTag/Open:>>
27  *
28  * $Id: $
29  */
30 
31 #ifndef	_bcmtlv_h_
32 #define	_bcmtlv_h_
33 
34 #include <typedefs.h>
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif /* __cplusplus */
39 
40 /* begin tlvs - used in 802.11 IEs etc. */
41 
42 /* type(aka id)/length/value buffer triple */
43 typedef struct bcm_tlv {
44 	uint8	id;
45 	uint8	len;
46 	uint8	data[1];
47 } bcm_tlv_t;
48 
49 /* size of tlv including data */
50 #define BCM_TLV_SIZE(_tlv) ((_tlv) ? (OFFSETOF(bcm_tlv_t, data) + (_tlv)->len) : 0)
51 
52 /* get next tlv - no length checks */
53 #define BCM_TLV_NEXT(_tlv) (bcm_tlv_t *)((uint8 *)(_tlv)+ BCM_TLV_SIZE(_tlv))
54 
55 /* tlv length is restricted to 1 byte */
56 #define BCM_TLV_MAX_DATA_SIZE (255)
57 
58 /* tlv header - two bytes */
59 #define BCM_TLV_HDR_SIZE (OFFSETOF(bcm_tlv_t, data))
60 
61 /* Check that bcm_tlv_t fits into the given buffer len */
62 #define bcm_valid_tlv(elt, buflen) (\
63 	 ((int)(buflen) >= (int)BCM_TLV_HDR_SIZE) && \
64 	 ((int)(buflen) >= (int)(BCM_TLV_HDR_SIZE + (elt)->len)))
65 
66 /* type(aka id)/length/ext/value buffer */
67 typedef struct bcm_tlv_ext {
68 	uint8	id;
69 	uint8	len;
70 	uint8	ext;
71 	uint8	data[1];
72 } bcm_tlv_ext_t;
73 
74 /* get next tlv_ext - no length checks */
75 #define BCM_TLV_EXT_NEXT(_tlv_ext) \
76 	(bcm_tlv_ext_t *)((uint8 *)(_tlv_ext)+ BCM_TLV_EXT_SIZE(_tlv_ext))
77 
78 /* tlv_ext length is restricted to 1 byte */
79 #define BCM_TLV_EXT_MAX_DATA_SIZE (254)
80 
81 /* tlv_ext header - three bytes */
82 #define BCM_TLV_EXT_HDR_SIZE (OFFSETOF(bcm_tlv_ext_t, data))
83 
84 /* size of tlv_ext including data */
85 #define BCM_TLV_EXT_SIZE(_tlv_ext) (BCM_TLV_EXT_HDR_SIZE + (_tlv_ext)->len)
86 
87 /* find the next tlv */
88 bcm_tlv_t *bcm_next_tlv(const  bcm_tlv_t *elt, uint *buflen);
89 
90 /* move buffer/buflen up to the given tlv, or set to NULL/0 on error */
91 void bcm_tlv_buffer_advance_to(const bcm_tlv_t *elt, const uint8 **buffer, uint *buflen);
92 
93 /* move buffer/buflen past the given tlv, or set to NULL/0 on error */
94 void bcm_tlv_buffer_advance_past(const bcm_tlv_t *elt, const uint8 **buffer, uint *buflen);
95 
96 /* find the tlv for a given id */
97 bcm_tlv_t *bcm_parse_tlvs(const  void *buf, uint buflen, uint key);
98 
99 /*
100  * Traverse tlvs and return pointer to the first tlv that
101  * matches the key. Return NULL if not found or tlv len < min_bodylen
102  */
103 bcm_tlv_t *bcm_parse_tlvs_min_bodylen(const  void *buf, int buflen, uint key, int min_bodylen);
104 
105 /* parse tlvs for dot11 - same as parse_tlvs but supports 802.11 id extension */
106 bcm_tlv_t *bcm_parse_tlvs_dot11(const  void *buf, int buflen, uint key, bool id_ext);
107 
108 /* same as parse_tlvs, but stops when found id > key */
109 const  bcm_tlv_t *bcm_parse_ordered_tlvs(const  void *buf, int buflen, uint key);
110 
111 /* find a tlv with DOT11_MNG_PROPR_ID as id, and the given oui and type */
112 	bcm_tlv_t *bcm_find_vendor_ie(const  void *tlvs, uint tlvs_len, const char *voui,
113 	                              uint8 *type, uint type_len);
114 
115 /* write tlv at dst and return next tlv ptr */
116 uint8 *bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst);
117 
118 /* write tlv_ext at dst and return next tlv ptr */
119 uint8 *bcm_write_tlv_ext(uint8 type, uint8 ext, const void *data, uint8 datalen, uint8 *dst);
120 
121 /* write tlv at dst if space permits and return next tlv ptr */
122 uint8 *bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst,
123 	int dst_maxlen);
124 
125 /* copy a tlv  and return next tlv ptr */
126 uint8 *bcm_copy_tlv(const void *src, uint8 *dst);
127 
128 /* copy a tlv if space permits and return next tlv ptr */
129 uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen);
130 
131 /* end tlvs */
132 
133 /* begin xtlv - used for iovars, nan attributes etc. */
134 
135 /* bcm type(id), length, value with w/16 bit id/len. The structure below
136  * is nominal, and is used to support variable length id and type. See
137  * xtlv options below.
138  */
139 typedef struct bcm_xtlv {
140 	uint16	id;
141 	uint16	len;
142 	uint8	data[1];
143 } bcm_xtlv_t;
144 
145 /* xtlv options */
146 #define BCM_XTLV_OPTION_NONE	0x0000
147 #define BCM_XTLV_OPTION_ALIGN32	0x0001 /* 32bit alignment of type.len.data */
148 #define BCM_XTLV_OPTION_IDU8	0x0002 /* shorter id */
149 #define BCM_XTLV_OPTION_LENU8	0x0004 /* shorted length */
150 #define BCM_XTLV_OPTION_IDBE	0x0008 /* big endian format id */
151 #define BCM_XTLV_OPTION_LENBE	0x0010 /* big endian format length */
152 typedef uint16 bcm_xtlv_opts_t;
153 
154 /* header size. depends on options. Macros names ending w/ _EX are where
155  * options are explcitly specified that may be less common. The ones
156  * without use default values that correspond to ...OPTION_NONE
157  */
158 
159 /* xtlv header size depends on options */
160 #define BCM_XTLV_HDR_SIZE 4
161 #define BCM_XTLV_HDR_SIZE_EX(_opts) bcm_xtlv_hdr_size(_opts)
162 
163 /* note: xtlv len only stores the value's length without padding */
164 #define BCM_XTLV_LEN(_elt) ltoh16_ua(&(_elt)->len)
165 #define BCM_XTLV_LEN_EX(_elt, _opts) bcm_xtlv_len(_elt, _opts)
166 
167 #define BCM_XTLV_ID(_elt) ltoh16_ua(&(_elt)->id)
168 #define BCM_XTLV_ID_EX(_elt, _opts) bcm_xtlv_id(_elt, _opts)
169 
170 /* entire size of the XTLV including header, data, and optional padding */
171 #define BCM_XTLV_SIZE(elt, opts) bcm_xtlv_size(elt, opts)
172 #define BCM_XTLV_SIZE_EX(_elt, _opts) bcm_xtlv_size(_elt, _opts)
173 
174 /* max xtlv data size */
175 #define BCM_XTLV_MAX_DATA_SIZE 65535
176 #define BCM_XTLV_MAX_DATA_SIZE_EX(_opts) ((_opts & BCM_XTLV_OPTION_LENU8) ? \
177 	255 : 65535)
178 
179 /* descriptor of xtlv data, packing(src) and unpacking(dst) support  */
180 typedef struct {
181 	uint16	type;
182 	uint16	len;
183 	void	*ptr; /* ptr to memory location */
184 } xtlv_desc_t;
185 
186 /* xtlv buffer - packing/unpacking support */
187 struct bcm_xtlvbuf {
188 	bcm_xtlv_opts_t opts;
189 	uint16 size;
190 	uint8 *head; /* point to head of buffer */
191 	uint8 *buf; /* current position of buffer */
192 	/* allocated buffer may follow, but not necessarily */
193 };
194 typedef struct bcm_xtlvbuf bcm_xtlvbuf_t;
195 
196 /* valid xtlv ? */
197 bool bcm_valid_xtlv(const bcm_xtlv_t *elt, int buf_len, bcm_xtlv_opts_t opts);
198 
199 /* return the next xtlv element, and update buffer len (remaining). Buffer length
200  * updated includes padding as specified by options
201  */
202 bcm_xtlv_t *bcm_next_xtlv(const bcm_xtlv_t *elt, int *buf_len, bcm_xtlv_opts_t opts);
203 
204 /* initialize an xtlv buffer. Use options specified for packing/unpacking using
205  * the buffer. Caller is responsible for allocating both buffers.
206  */
207 int bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len,
208 	bcm_xtlv_opts_t opts);
209 
210 /* length of data in the xtlv buffer */
211 uint16 bcm_xtlv_buf_len(struct bcm_xtlvbuf *tbuf);
212 
213 /* remaining space in the xtlv buffer */
214 uint16 bcm_xtlv_buf_rlen(struct bcm_xtlvbuf *tbuf);
215 
216 /* write ptr */
217 uint8 *bcm_xtlv_buf(struct bcm_xtlvbuf *tbuf);
218 
219 /* head */
220 uint8 *bcm_xtlv_head(struct bcm_xtlvbuf *tbuf);
221 
222 /* put a data buffer into xtlv */
223 int bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n);
224 
225 /* put one or more u16 elts into xtlv */
226 int bcm_xtlv_put16(bcm_xtlvbuf_t *tbuf, uint16 type, const uint16 *data, int n);
227 
228 /* put one or more u32 elts into xtlv */
229 int bcm_xtlv_put32(bcm_xtlvbuf_t *tbuf, uint16 type, const uint32 *data, int n);
230 
231 /* put one or more u64 elts into xtlv */
232 int bcm_xtlv_put64(bcm_xtlvbuf_t *tbuf, uint16 type, const uint64 *data, int n);
233 
234 /* note: there are no get equivalent of integer unpacking, becasuse bcmendian.h
235  * can be used directly using pointers returned in the buffer being processed.
236  */
237 
238 /* unpack a single xtlv entry, advances buffer and copies data to dst_data on match
239  * type and length match must be exact
240  */
241 int bcm_unpack_xtlv_entry(const uint8 **buf, uint16 expected_type, uint16 expected_len,
242 	uint8 *dst_data, bcm_xtlv_opts_t opts);
243 
244 /* packs an xtlv into buffer, and advances buffer, decreements buffer length.
245  * buffer length is checked and must be >= size of xtlv - otherwise BCME_BADLEN
246  */
247 int bcm_pack_xtlv_entry(uint8 **buf, uint16 *buflen, uint16 type, uint16 len,
248 	const uint8 *src_data, bcm_xtlv_opts_t opts);
249 
250 /* accessors and lengths for element given options */
251 int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
252 int bcm_xtlv_hdr_size(bcm_xtlv_opts_t opts);
253 int bcm_xtlv_len(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
254 int bcm_xtlv_id(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
255 int bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts);
256 
257 /* compute size needed for number of tlvs whose total data len is given */
258 #define BCM_XTLV_SIZE_FOR_TLVS(_data_len, _num_tlvs, _opts) (\
259 	bcm_xtlv_size_for_data(_data_len, _opts) + (\
260 	(_num_tlvs) * BCM_XTLV_HDR_SIZE_EX(_opts)))
261 
262 /* unsafe copy xtlv */
263 #define BCM_XTLV_BCOPY(_src, _dst, _opts) \
264 	bcm_xtlv_bcopy(_src, _dst, BCM_XTLV_MAX_DATA_SIZE_EX(_opts), \
265 		BCM_XTLV_MAX_DATA_SIZE_EX(_opts), _opts)
266 
267 /* copy xtlv - note: src->dst bcopy order - to be compatible w/ tlv version */
268 bcm_xtlv_t* bcm_xtlv_bcopy(const bcm_xtlv_t *src, bcm_xtlv_t *dst,
269 	int src_buf_len, int dst_buf_len, bcm_xtlv_opts_t opts);
270 
271 /* callback for unpacking xtlv from a buffer into context. */
272 typedef int (bcm_xtlv_unpack_cbfn_t)(void *ctx, const uint8 *buf,
273 	uint16 type, uint16 len);
274 
275 /* unpack a tlv buffer using buffer, options, and callback */
276 int bcm_unpack_xtlv_buf(void *ctx, const uint8 *buf, uint16 buflen,
277 	bcm_xtlv_opts_t opts, bcm_xtlv_unpack_cbfn_t *cbfn);
278 
279 /* unpack a set of tlvs from the buffer using provided xtlv descriptors */
280 int bcm_unpack_xtlv_buf_to_mem(uint8 *buf, int *buflen, xtlv_desc_t *items,
281 	bcm_xtlv_opts_t opts);
282 
283 /* pack a set of tlvs into buffer using provided xtlv descriptors */
284 int bcm_pack_xtlv_buf_from_mem(uint8 **buf, uint16 *buflen,
285 	const xtlv_desc_t *items, bcm_xtlv_opts_t opts);
286 
287 /* return data pointer and data length of a given id from xtlv buffer
288  * data_len may be NULL
289  */
290 const uint8* bcm_get_data_from_xtlv_buf(const uint8 *tlv_buf, uint16 buflen,
291 	uint16 id, uint16 *datalen, bcm_xtlv_opts_t opts);
292 
293 /* callback to return next tlv id and len to pack, if there is more tlvs to come and
294  * options e.g. alignment
295  */
296 typedef bool (*bcm_pack_xtlv_next_info_cbfn_t)(void *ctx, uint16 *tlv_id, uint16 *tlv_len);
297 
298 /* callback to pack the tlv into length validated buffer */
299 typedef void (*bcm_pack_xtlv_pack_next_cbfn_t)(void *ctx,
300 	uint16 tlv_id, uint16 tlv_len, uint8* buf);
301 
302 /* pack a set of tlvs into buffer using get_next to interate */
303 int bcm_pack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen,
304 	bcm_xtlv_opts_t opts, bcm_pack_xtlv_next_info_cbfn_t get_next,
305 	bcm_pack_xtlv_pack_next_cbfn_t pack_next, int *outlen);
306 
307 /* pack an xtlv. does not do any error checking. if data is not NULL
308  * data of given length is copied  to buffer (xtlv)
309  */
310 void bcm_xtlv_pack_xtlv(bcm_xtlv_t *xtlv, uint16 type, uint16 len,
311 	const uint8 *data, bcm_xtlv_opts_t opts);
312 
313 /* unpack an xtlv and return ptr to data, and data length */
314 void bcm_xtlv_unpack_xtlv(const bcm_xtlv_t *xtlv, uint16 *type, uint16 *len,
315 	const uint8 **data, bcm_xtlv_opts_t opts);
316 
317 /* end xtlvs */
318 
319 /* length value pairs */
320 struct bcm_xlv {
321 	uint16 len;
322 	uint8 data[1];
323 };
324 typedef struct bcm_xlv bcm_xlv_t;
325 
326 struct bcm_xlvp {
327 	uint16 len;
328 	uint8 *data;
329 };
330 typedef struct bcm_xlvp bcm_xlvp_t;
331 
332 struct bcm_const_xlvp {
333 	uint16 len;
334 	const uint8 *data;
335 };
336 typedef struct bcm_const_xlvp bcm_const_xlvp_t;
337 
338 /* end length value pairs */
339 
340 #ifdef __cplusplus
341 }
342 #endif /* __cplusplus */
343 
344 #endif	/* _bcmtlv_h_ */
345