forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmxtlv.c
....@@ -1,15 +1,16 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * Driver O/S-independent utility routines
43 *
5
- * Copyright (C) 1999-2019, Broadcom Corporation
6
- *
4
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
5
+ *
6
+ * Copyright (C) 1999-2017, Broadcom Corporation
7
+ *
78 * Unless you and Broadcom execute a separate written software license
89 * agreement governing use of this software, this software is licensed to you
910 * under the terms of the GNU General Public License version 2 (the "GPL"),
1011 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1112 * following added to such license:
12
- *
13
+ *
1314 * As a special exception, the copyright holders of this software give you
1415 * permission to link this software with independent modules, and to copy and
1516 * distribute the resulting executable under terms of your choice, provided that
....@@ -17,7 +18,7 @@
1718 * the license of that module. An independent module is a module which is not
1819 * derived from this software. The special exception does not apply to any
1920 * modifications of the software.
20
- *
21
+ *
2122 * Notwithstanding the above, under no circumstances may you combine this
2223 * software in any way with any other Broadcom software provided under a license
2324 * other than the GPL, without Broadcom's express prior written consent.
....@@ -25,7 +26,7 @@
2526 *
2627 * <<Broadcom-WL-IPTag/Open:>>
2728 *
28
- * $Id: bcmxtlv.c 603083 2015-11-30 23:40:43Z $
29
+ * $Id: bcmxtlv.c 700655 2017-05-20 06:09:06Z $
2930 */
3031
3132 #include <bcm_cfg.h>
....@@ -38,40 +39,110 @@
3839 #ifdef BCMDRIVER
3940 #include <osl.h>
4041 #else /* !BCMDRIVER */
41
- #include <stdlib.h> /* AS!!! */
4242 #include <stdio.h>
4343 #include <string.h>
4444 #include <stdlib.h>
4545 #ifndef ASSERT
4646 #define ASSERT(exp)
47
-#endif
48
-INLINE void* MALLOCZ(void *o, size_t s) { BCM_REFERENCE(o); return calloc(1, s); }
49
-INLINE void MFREE(void *o, void *p, size_t s) { BCM_REFERENCE(o); BCM_REFERENCE(s); free(p); }
47
+#endif // endif
5048 #endif /* !BCMDRIVER */
5149
50
+#include <bcmtlv.h>
5251 #include <bcmendian.h>
5352 #include <bcmutils.h>
5453
55
-static INLINE int bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts)
54
+int
55
+bcm_xtlv_hdr_size(bcm_xtlv_opts_t opts)
5656 {
57
- return ((opts & BCM_XTLV_OPTION_ALIGN32) ? ALIGN_SIZE(dlen + BCM_XTLV_HDR_SIZE, 4)
58
- : (dlen + BCM_XTLV_HDR_SIZE));
57
+ int len = (int)OFFSETOF(bcm_xtlv_t, data); /* nominal */
58
+ if (opts & BCM_XTLV_OPTION_LENU8) --len;
59
+ if (opts & BCM_XTLV_OPTION_IDU8) --len;
60
+
61
+ return len;
62
+}
63
+
64
+bool
65
+bcm_valid_xtlv(const bcm_xtlv_t *elt, int buf_len, bcm_xtlv_opts_t opts)
66
+{
67
+ return elt != NULL &&
68
+ buf_len >= bcm_xtlv_hdr_size(opts) &&
69
+ buf_len >= bcm_xtlv_size(elt, opts);
70
+}
71
+
72
+int
73
+bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts)
74
+{
75
+ int hsz;
76
+
77
+ hsz = bcm_xtlv_hdr_size(opts);
78
+ return ((opts & BCM_XTLV_OPTION_ALIGN32) ? ALIGN_SIZE(dlen + hsz, 4)
79
+ : (dlen + hsz));
80
+}
81
+
82
+int
83
+bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
84
+{
85
+ int size; /* size including header, data, and any pad */
86
+ int len; /* length wthout padding */
87
+
88
+ len = BCM_XTLV_LEN_EX(elt, opts);
89
+ size = bcm_xtlv_size_for_data(len, opts);
90
+ return size;
91
+}
92
+
93
+int
94
+bcm_xtlv_len(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
95
+{
96
+ const uint8 *lenp;
97
+ int len;
98
+
99
+ lenp = (const uint8 *)&elt->len; /* nominal */
100
+ if (opts & BCM_XTLV_OPTION_IDU8) {
101
+ --lenp;
102
+ }
103
+
104
+ if (opts & BCM_XTLV_OPTION_LENU8) {
105
+ len = *lenp;
106
+ } else if (opts & BCM_XTLV_OPTION_LENBE) {
107
+ len = (uint32)hton16(elt->len);
108
+ } else {
109
+ len = ltoh16_ua(lenp);
110
+ }
111
+
112
+ return len;
113
+}
114
+
115
+int
116
+bcm_xtlv_id(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
117
+{
118
+ int id = 0;
119
+ if (opts & BCM_XTLV_OPTION_IDU8) {
120
+ id = *(const uint8 *)elt;
121
+ } else if (opts & BCM_XTLV_OPTION_IDBE) {
122
+ id = (uint32)hton16(elt->id);
123
+ } else {
124
+ id = ltoh16_ua((const uint8 *)elt);
125
+ }
126
+
127
+ return id;
59128 }
60129
61130 bcm_xtlv_t *
62
-bcm_next_xtlv(bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts)
131
+bcm_next_xtlv(const bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts)
63132 {
64133 int sz;
65134 /* advance to next elt */
66
- sz = BCM_XTLV_SIZE(elt, opts);
67
- elt = (bcm_xtlv_t*)((uint8 *)elt + sz);
135
+ sz = BCM_XTLV_SIZE_EX(elt, opts);
136
+ elt = (const bcm_xtlv_t*)((const uint8 *)elt + sz);
68137 *buflen -= sz;
69138
70139 /* validate next elt */
71140 if (!bcm_valid_xtlv(elt, *buflen, opts))
72141 return NULL;
73142
74
- return elt;
143
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
144
+ return (bcm_xtlv_t *)(elt);
145
+ GCC_DIAGNOSTIC_POP();
75146 }
76147
77148 int
....@@ -90,99 +161,191 @@
90161 uint16
91162 bcm_xtlv_buf_len(bcm_xtlvbuf_t *tbuf)
92163 {
93
- if (tbuf == NULL) return 0;
94
- return (uint16)(tbuf->buf - tbuf->head);
164
+ uint16 len;
165
+
166
+ if (tbuf)
167
+ len = (uint16)(tbuf->buf - tbuf->head);
168
+ else
169
+ len = 0;
170
+
171
+ return len;
95172 }
173
+
96174 uint16
97175 bcm_xtlv_buf_rlen(bcm_xtlvbuf_t *tbuf)
98176 {
99
- if (tbuf == NULL) return 0;
100
- return tbuf->size - bcm_xtlv_buf_len(tbuf);
177
+ uint16 rlen;
178
+ if (tbuf)
179
+ rlen = tbuf->size - bcm_xtlv_buf_len(tbuf);
180
+ else
181
+ rlen = 0;
182
+
183
+ return rlen;
101184 }
185
+
102186 uint8 *
103187 bcm_xtlv_buf(bcm_xtlvbuf_t *tbuf)
104188 {
105
- if (tbuf == NULL) return NULL;
106
- return tbuf->buf;
189
+ return tbuf ? tbuf->buf : NULL;
107190 }
191
+
108192 uint8 *
109193 bcm_xtlv_head(bcm_xtlvbuf_t *tbuf)
110194 {
111
- if (tbuf == NULL) return NULL;
112
- return tbuf->head;
195
+ return tbuf ? tbuf->head : NULL;
113196 }
197
+
198
+void
199
+bcm_xtlv_pack_xtlv(bcm_xtlv_t *xtlv, uint16 type, uint16 len, const uint8 *data,
200
+ bcm_xtlv_opts_t opts)
201
+{
202
+ uint8 *data_buf;
203
+ bcm_xtlv_opts_t mask = BCM_XTLV_OPTION_IDU8 | BCM_XTLV_OPTION_LENU8;
204
+
205
+ if (!(opts & mask)) { /* default */
206
+ uint8 *idp = (uint8 *)xtlv;
207
+ uint8 *lenp = idp + sizeof(xtlv->id);
208
+ htol16_ua_store(type, idp);
209
+ htol16_ua_store(len, lenp);
210
+ data_buf = lenp + sizeof(uint16);
211
+ } else if ((opts & mask) == mask) { /* u8 id and u8 len */
212
+ uint8 *idp = (uint8 *)xtlv;
213
+ uint8 *lenp = idp + 1;
214
+ *idp = (uint8)type;
215
+ *lenp = (uint8)len;
216
+ data_buf = lenp + sizeof(uint8);
217
+ } else if (opts & BCM_XTLV_OPTION_IDU8) { /* u8 id, u16 len */
218
+ uint8 *idp = (uint8 *)xtlv;
219
+ uint8 *lenp = idp + 1;
220
+ *idp = (uint8)type;
221
+ htol16_ua_store(len, lenp);
222
+ data_buf = lenp + sizeof(uint16);
223
+ } else if (opts & BCM_XTLV_OPTION_LENU8) { /* u16 id, u8 len */
224
+ uint8 *idp = (uint8 *)xtlv;
225
+ uint8 *lenp = idp + sizeof(uint16);
226
+ htol16_ua_store(type, idp);
227
+ *lenp = (uint8)len;
228
+ data_buf = lenp + sizeof(uint8);
229
+ } else {
230
+ bool Unexpected_xtlv_option = TRUE;
231
+ BCM_REFERENCE(Unexpected_xtlv_option);
232
+ ASSERT(!Unexpected_xtlv_option);
233
+ return;
234
+ }
235
+
236
+ if (opts & BCM_XTLV_OPTION_LENU8) {
237
+ ASSERT(len <= 0x00ff);
238
+ len &= 0xff;
239
+ }
240
+
241
+ if (data != NULL)
242
+ memcpy(data_buf, data, len);
243
+}
244
+
245
+/* xtlv header is always packed in LE order */
246
+void
247
+bcm_xtlv_unpack_xtlv(const bcm_xtlv_t *xtlv, uint16 *type, uint16 *len,
248
+ const uint8 **data, bcm_xtlv_opts_t opts)
249
+{
250
+ if (type)
251
+ *type = (uint16)bcm_xtlv_id(xtlv, opts);
252
+ if (len)
253
+ *len = (uint16)bcm_xtlv_len(xtlv, opts);
254
+ if (data)
255
+ *data = (const uint8 *)xtlv + BCM_XTLV_HDR_SIZE_EX(opts);
256
+}
257
+
114258 int
115
-bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const void *data, uint16 dlen)
259
+bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n)
116260 {
117261 bcm_xtlv_t *xtlv;
118262 int size;
119263
120264 if (tbuf == NULL)
121265 return BCME_BADARG;
122
- size = bcm_xtlv_size_for_data(dlen, tbuf->opts);
266
+
267
+ size = bcm_xtlv_size_for_data(n, tbuf->opts);
123268 if (bcm_xtlv_buf_rlen(tbuf) < size)
124269 return BCME_NOMEM;
270
+
125271 xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
126
- xtlv->id = htol16(type);
127
- xtlv->len = htol16(dlen);
128
- memcpy(xtlv->data, data, dlen);
129
- tbuf->buf += size;
272
+ bcm_xtlv_pack_xtlv(xtlv, type, (uint16)n, data, tbuf->opts);
273
+ tbuf->buf += size; /* note: data may be NULL, reserves space */
130274 return BCME_OK;
131275 }
132
-int
133
-bcm_xtlv_put_8(bcm_xtlvbuf_t *tbuf, uint16 type, const int8 data)
276
+
277
+static int
278
+bcm_xtlv_put_int(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n, int int_sz)
134279 {
135280 bcm_xtlv_t *xtlv;
136
- int size;
281
+ int xtlv_len;
282
+ uint8 *xtlv_data;
283
+ int err = BCME_OK;
137284
138
- if (tbuf == NULL)
139
- return BCME_BADARG;
140
- size = bcm_xtlv_size_for_data(1, tbuf->opts);
141
- if (bcm_xtlv_buf_rlen(tbuf) < size)
142
- return BCME_NOMEM;
285
+ if (tbuf == NULL) {
286
+ err = BCME_BADARG;
287
+ goto done;
288
+ }
289
+
143290 xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
144
- xtlv->id = htol16(type);
145
- xtlv->len = htol16(sizeof(data));
146
- xtlv->data[0] = data;
147
- tbuf->buf += size;
148
- return BCME_OK;
291
+
292
+ /* put type and length in xtlv and reserve data space */
293
+ xtlv_len = n * int_sz;
294
+ err = bcm_xtlv_put_data(tbuf, type, NULL, xtlv_len);
295
+ if (err != BCME_OK)
296
+ goto done;
297
+
298
+ xtlv_data = (uint8 *)xtlv + bcm_xtlv_hdr_size(tbuf->opts);
299
+
300
+ /* write data w/ little-endianness into buffer - single loop, aligned access */
301
+ for (; n != 0; --n, xtlv_data += int_sz, data += int_sz) {
302
+ switch (int_sz) {
303
+ case sizeof(uint8):
304
+ break;
305
+ case sizeof(uint16):
306
+ {
307
+ uint16 v = load16_ua(data);
308
+ htol16_ua_store(v, xtlv_data);
309
+ break;
310
+ }
311
+ case sizeof(uint32):
312
+ {
313
+ uint32 v = load32_ua(data);
314
+ htol32_ua_store(v, xtlv_data);
315
+ break;
316
+ }
317
+ case sizeof(uint64):
318
+ {
319
+ uint64 v = load64_ua(data);
320
+ htol64_ua_store(v, xtlv_data);
321
+ break;
322
+ }
323
+ default:
324
+ err = BCME_UNSUPPORTED;
325
+ goto done;
326
+ }
327
+ }
328
+
329
+done:
330
+ return err;
149331 }
332
+
150333 int
151
-bcm_xtlv_put_16(bcm_xtlvbuf_t *tbuf, uint16 type, const int16 data)
334
+bcm_xtlv_put16(bcm_xtlvbuf_t *tbuf, uint16 type, const uint16 *data, int n)
152335 {
153
- bcm_xtlv_t *xtlv;
154
- int size;
155
-
156
- if (tbuf == NULL)
157
- return BCME_BADARG;
158
- size = bcm_xtlv_size_for_data(2, tbuf->opts);
159
- if (bcm_xtlv_buf_rlen(tbuf) < size)
160
- return BCME_NOMEM;
161
-
162
- xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
163
- xtlv->id = htol16(type);
164
- xtlv->len = htol16(sizeof(data));
165
- htol16_ua_store(data, xtlv->data);
166
- tbuf->buf += size;
167
- return BCME_OK;
336
+ return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint16));
168337 }
169
-int
170
-bcm_xtlv_put_32(bcm_xtlvbuf_t *tbuf, uint16 type, const int32 data)
171
-{
172
- bcm_xtlv_t *xtlv;
173
- int size;
174338
175
- if (tbuf == NULL)
176
- return BCME_BADARG;
177
- size = bcm_xtlv_size_for_data(4, tbuf->opts);
178
- if (bcm_xtlv_buf_rlen(tbuf) < size)
179
- return BCME_NOMEM;
180
- xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
181
- xtlv->id = htol16(type);
182
- xtlv->len = htol16(sizeof(data));
183
- htol32_ua_store(data, xtlv->data);
184
- tbuf->buf += size;
185
- return BCME_OK;
339
+int
340
+bcm_xtlv_put32(bcm_xtlvbuf_t *tbuf, uint16 type, const uint32 *data, int n)
341
+{
342
+ return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint32));
343
+}
344
+
345
+int
346
+bcm_xtlv_put64(bcm_xtlvbuf_t *tbuf, uint16 type, const uint64 *data, int n)
347
+{
348
+ return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint64));
186349 }
187350
188351 /*
....@@ -192,65 +355,51 @@
192355 * caller's resposible for dst space check
193356 */
194357 int
195
-bcm_unpack_xtlv_entry(uint8 **tlv_buf, uint16 xpct_type, uint16 xpct_len, void *dst,
196
- bcm_xtlv_opts_t opts)
358
+bcm_unpack_xtlv_entry(const uint8 **tlv_buf, uint16 xpct_type, uint16 xpct_len,
359
+ uint8 *dst_data, bcm_xtlv_opts_t opts)
197360 {
198
- bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf;
361
+ const bcm_xtlv_t *ptlv = (const bcm_xtlv_t *)*tlv_buf;
199362 uint16 len;
200363 uint16 type;
364
+ const uint8 *data;
201365
202366 ASSERT(ptlv);
203
- /* tlv headr is always packed in LE order */
204
- len = ltoh16(ptlv->len);
205
- type = ltoh16(ptlv->id);
206
- if (len == 0) {
207
- /* z-len tlv headers: allow, but don't process */
208
- printf("z-len, skip unpack\n");
209
- } else {
210
- if ((type != xpct_type) ||
211
- (len > xpct_len)) {
212
- printf("xtlv_unpack Error: found[type:%d,len:%d] != xpct[type:%d,len:%d]\n",
213
- type, len, xpct_type, xpct_len);
367
+
368
+ bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts);
369
+ if (len) {
370
+ if ((type != xpct_type) || (len > xpct_len))
214371 return BCME_BADARG;
215
- }
216
- /* copy tlv record to caller's buffer */
217
- memcpy(dst, ptlv->data, ptlv->len);
372
+ if (dst_data && data)
373
+ memcpy(dst_data, data, len); /* copy data to dst */
218374 }
219
- *tlv_buf += BCM_XTLV_SIZE(ptlv, opts);
375
+
376
+ *tlv_buf += BCM_XTLV_SIZE_EX(ptlv, opts);
220377 return BCME_OK;
221378 }
222379
223380 /*
224
- * packs user data into tlv record
225
- * advances tlv pointer to next xtlv slot
381
+ * packs user data into tlv record and advances tlv pointer to next xtlv slot
226382 * buflen is used for tlv_buf space check
227383 */
228384 int
229
-bcm_pack_xtlv_entry(uint8 **tlv_buf, uint16 *buflen, uint16 type, uint16 len, void *src,
230
- bcm_xtlv_opts_t opts)
385
+bcm_pack_xtlv_entry(uint8 **tlv_buf, uint16 *buflen, uint16 type, uint16 len,
386
+ const uint8 *src_data, bcm_xtlv_opts_t opts)
231387 {
232388 bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf;
233389 int size;
234390
235391 ASSERT(ptlv);
236
- ASSERT(src);
237392
238393 size = bcm_xtlv_size_for_data(len, opts);
239394
240395 /* copy data from tlv buffer to dst provided by user */
241
- if (size > *buflen) {
242
- printf("bcm_pack_xtlv_entry: no space tlv_buf: requested:%d, available:%d\n",
243
- size, *buflen);
396
+ if (size > *buflen)
244397 return BCME_BADLEN;
245
- }
246
- ptlv->id = htol16(type);
247
- ptlv->len = htol16(len);
248398
249
- /* copy callers data */
250
- memcpy(ptlv->data, src, len);
399
+ bcm_xtlv_pack_xtlv(ptlv, type, len, src_data, opts);
251400
252401 /* advance callers pointer to tlv buff */
253
- *tlv_buf += size;
402
+ *tlv_buf = (uint8*)(*tlv_buf) + size;
254403 /* decrement the len */
255404 *buflen -= (uint16)size;
256405 return BCME_OK;
....@@ -261,34 +410,33 @@
261410 * to set function one call per found tlv record
262411 */
263412 int
264
-bcm_unpack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
413
+bcm_unpack_xtlv_buf(void *ctx, const uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
265414 bcm_xtlv_unpack_cbfn_t *cbfn)
266415 {
267416 uint16 len;
268417 uint16 type;
269418 int res = BCME_OK;
270419 int size;
271
- bcm_xtlv_t *ptlv;
420
+ const bcm_xtlv_t *ptlv;
272421 int sbuflen = buflen;
422
+ const uint8 *data;
423
+ int hdr_size;
273424
274425 ASSERT(!buflen || tlv_buf);
275426 ASSERT(!buflen || cbfn);
276427
277
- while (sbuflen >= (int)BCM_XTLV_HDR_SIZE) {
278
- ptlv = (bcm_xtlv_t *)tlv_buf;
428
+ hdr_size = BCM_XTLV_HDR_SIZE_EX(opts);
429
+ while (sbuflen >= hdr_size) {
430
+ ptlv = (const bcm_xtlv_t *)tlv_buf;
279431
280
- /* tlv header is always packed in LE order */
281
- len = ltoh16(ptlv->len);
282
- type = ltoh16(ptlv->id);
283
-
432
+ bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts);
284433 size = bcm_xtlv_size_for_data(len, opts);
285434
286435 sbuflen -= size;
287
- /* check for possible buffer overrun */
288
- if (sbuflen < 0)
436
+ if (sbuflen < 0) /* check for buffer overrun */
289437 break;
290438
291
- if ((res = cbfn(ctx, ptlv->data, type, len)) != BCME_OK)
439
+ if ((res = cbfn(ctx, data, type, len)) != BCME_OK)
292440 break;
293441 tlv_buf += size;
294442 }
....@@ -296,7 +444,7 @@
296444 }
297445
298446 int
299
-bcm_pack_xtlv_buf(void *ctx, void *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
447
+bcm_pack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
300448 bcm_pack_xtlv_next_info_cbfn_t get_next, bcm_pack_xtlv_pack_next_cbfn_t pack_next,
301449 int *outlen)
302450 {
....@@ -308,24 +456,26 @@
308456 uint8 *buf;
309457 bool more;
310458 int size;
459
+ int hdr_size;
311460
312461 ASSERT(get_next && pack_next);
313462
314
- buf = (uint8 *)tlv_buf;
463
+ buf = tlv_buf;
315464 startp = buf;
316465 endp = (uint8 *)buf + buflen;
317466 more = TRUE;
467
+ hdr_size = BCM_XTLV_HDR_SIZE_EX(opts);
468
+
318469 while (more && (buf < endp)) {
319470 more = get_next(ctx, &tlv_id, &tlv_len);
320471 size = bcm_xtlv_size_for_data(tlv_len, opts);
321
- if ((buf + size) >= endp) {
472
+ if ((buf + size) > endp) {
322473 res = BCME_BUFTOOSHORT;
323474 goto done;
324475 }
325476
326
- htol16_ua_store(tlv_id, buf);
327
- htol16_ua_store(tlv_len, buf + sizeof(tlv_id));
328
- pack_next(ctx, tlv_id, tlv_len, buf + BCM_XTLV_HDR_SIZE);
477
+ bcm_xtlv_pack_xtlv((bcm_xtlv_t *)buf, tlv_id, tlv_len, NULL, opts);
478
+ pack_next(ctx, tlv_id, tlv_len, buf + hdr_size);
329479 buf += size;
330480 }
331481
....@@ -343,20 +493,22 @@
343493 * pack xtlv buffer from memory according to xtlv_desc_t
344494 */
345495 int
346
-bcm_pack_xtlv_buf_from_mem(void **tlv_buf, uint16 *buflen, xtlv_desc_t *items,
496
+bcm_pack_xtlv_buf_from_mem(uint8 **tlv_buf, uint16 *buflen, const xtlv_desc_t *items,
347497 bcm_xtlv_opts_t opts)
348498 {
349499 int res = BCME_OK;
350
- uint8 *ptlv = (uint8 *)*tlv_buf;
500
+ uint8 *ptlv = *tlv_buf;
351501
352502 while (items->type != 0) {
353
- if ((res = bcm_pack_xtlv_entry(&ptlv,
354
- buflen, items->type,
355
- items->len, items->ptr, opts) != BCME_OK)) {
356
- break;
503
+ if (items->len && items->ptr) {
504
+ res = bcm_pack_xtlv_entry(&ptlv, buflen, items->type,
505
+ items->len, items->ptr, opts);
506
+ if (res != BCME_OK)
507
+ break;
357508 }
358509 items++;
359510 }
511
+
360512 *tlv_buf = ptlv; /* update the external pointer */
361513 return res;
362514 }
....@@ -366,7 +518,8 @@
366518 *
367519 */
368520 int
369
-bcm_unpack_xtlv_buf_to_mem(void *tlv_buf, int *buflen, xtlv_desc_t *items, bcm_xtlv_opts_t opts)
521
+bcm_unpack_xtlv_buf_to_mem(uint8 *tlv_buf, int *buflen, xtlv_desc_t *items,
522
+ bcm_xtlv_opts_t opts)
370523 {
371524 int res = BCME_OK;
372525 bcm_xtlv_t *elt;
....@@ -380,14 +533,16 @@
380533 for (; elt != NULL && res == BCME_OK; elt = bcm_next_xtlv(elt, buflen, opts)) {
381534 /* find matches in desc_t items */
382535 xtlv_desc_t *dst_desc = items;
383
- uint16 len = ltoh16(elt->len);
536
+ uint16 len, type;
537
+ const uint8 *data;
384538
539
+ bcm_xtlv_unpack_xtlv(elt, &type, &len, &data, opts);
385540 while (dst_desc->type != 0) {
386
- if (ltoh16(elt->id) == dst_desc->type) {
541
+ if (type == dst_desc->type) {
387542 if (len != dst_desc->len) {
388543 res = BCME_BADLEN;
389544 } else {
390
- memcpy(dst_desc->ptr, elt->data, len);
545
+ memcpy(dst_desc->ptr, data, len);
391546 }
392547 break;
393548 }
....@@ -403,60 +558,67 @@
403558
404559 /*
405560 * return data pointer of a given ID from xtlv buffer.
406
- * If the specified xTLV ID is found, on return *data_len_out will contain
561
+ * If the specified xTLV ID is found, on return *datalen will contain
407562 * the the data length of the xTLV ID.
408563 */
409
-void *
410
-bcm_get_data_from_xtlv_buf(uint8 *tlv_buf, uint16 buflen, uint16 id,
411
- uint16 *datalen_out, bcm_xtlv_opts_t opts)
564
+const uint8*
565
+bcm_get_data_from_xtlv_buf(const uint8 *tlv_buf, uint16 buflen, uint16 id,
566
+ uint16 *datalen, bcm_xtlv_opts_t opts)
412567 {
413
- void *retptr = NULL;
568
+ const uint8 *retptr = NULL;
414569 uint16 type, len;
415570 int size;
416
- bcm_xtlv_t *ptlv;
571
+ const bcm_xtlv_t *ptlv;
417572 int sbuflen = buflen;
573
+ const uint8 *data;
574
+ int hdr_size;
575
+
576
+ hdr_size = BCM_XTLV_HDR_SIZE_EX(opts);
418577
419578 /* Init the datalength */
420
- if (datalen_out) {
421
- *datalen_out = 0;
579
+ if (datalen) {
580
+ *datalen = 0;
422581 }
423
- while (sbuflen >= (int)BCM_XTLV_HDR_SIZE) {
424
- ptlv = (bcm_xtlv_t *)tlv_buf;
582
+ while (sbuflen >= hdr_size) {
583
+ ptlv = (const bcm_xtlv_t *)tlv_buf;
584
+ bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts);
425585
426
- /* tlv header is always packed in LE order */
427
- type = ltoh16(ptlv->id);
428
- len = ltoh16(ptlv->len);
429586 size = bcm_xtlv_size_for_data(len, opts);
430
-
431587 sbuflen -= size;
432
- /* check for possible buffer overrun */
433
- if (sbuflen < 0) {
434
- printf("%s %d: Invalid sbuflen %d\n",
435
- __FUNCTION__, __LINE__, sbuflen);
588
+ if (sbuflen < 0) /* buffer overrun? */
436589 break;
437
- }
438590
439591 if (id == type) {
440
- retptr = ptlv->data;
441
- if (datalen_out) {
442
- *datalen_out = len;
443
- }
592
+ retptr = data;
593
+ if (datalen)
594
+ *datalen = len;
444595 break;
445596 }
597
+
446598 tlv_buf += size;
447599 }
448600
449601 return retptr;
450602 }
451603
452
-int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
604
+bcm_xtlv_t*
605
+bcm_xtlv_bcopy(const bcm_xtlv_t *src, bcm_xtlv_t *dst,
606
+ int src_buf_len, int dst_buf_len, bcm_xtlv_opts_t opts)
453607 {
454
- int size; /* entire size of the XTLV including header, data, and optional padding */
455
- int len; /* XTLV's value real length wthout padding */
608
+ bcm_xtlv_t *dst_next = NULL;
609
+ src = (src && bcm_valid_xtlv(src, src_buf_len, opts)) ? src : NULL;
610
+ if (src && dst) {
611
+ uint16 type;
612
+ uint16 len;
613
+ const uint8 *data;
614
+ int size;
615
+ bcm_xtlv_unpack_xtlv(src, &type, &len, &data, opts);
616
+ size = bcm_xtlv_size_for_data(len, opts);
617
+ if (size <= dst_buf_len) {
618
+ bcm_xtlv_pack_xtlv(dst, type, len, data, opts);
619
+ dst_next = (bcm_xtlv_t *)((uint8 *)dst + size);
620
+ }
621
+ }
456622
457
- len = BCM_XTLV_LEN(elt);
458
-
459
- size = bcm_xtlv_size_for_data(len, opts);
460
-
461
- return size;
623
+ return dst_next;
462624 }