1 /* SPDX-License-Identifier: GPL-2.0-only */
5 #include <console/console.h>
6 #include <device/mmio.h>
11 #define MAX_BLOCK_NUM 4
15 #define MIN_LEN_XIB 0x201
16 #define NEXT_OFFSET_HIB 0x1dc
17 #define NEXT_OFFSET_SIB 0x104
18 #define NEXT_OFFSET_EIB 0x0b0
19 #define NEXT_OFFSET_XIB 0x014
20 #define LEN_UNIQUEL_NUM 0x010
21 #define LEN_HW_REV 0x002
22 #define LEN_MAC_ADDRESS 0x006
24 #define LEN_EDID 0x080
25 #define LEN_OFFSET 0x00c
26 #define EIB_FEATRUE_OFFSET 0x00e
27 #define LEN_MAGIC_NUM 0x007
28 #define BLOCK_MAGIC "H1W2M3I"
29 #define HWI_MAX_NAME_LEN 32
31 /* Define all supported block types. */
39 /* This structure holds a valid position for a given field
40 * Every field can have multiple positions of which the first available
41 * will be taken by the library.
44 uint8_t blk_type
; /* Valid for a specific block type */
45 uint32_t offset
; /* Offset in given block */
46 size_t len
; /* Length for the field in this block */
49 /* This structure holds all the needed information for a given field type
50 * and a pointer to a function which is able to extract the desired data.
53 struct param_pos pos
[MAX_BLOCK_NUM
];
56 size_t (*get_field
)(const struct param_info
*param
, uint8_t *dst
, size_t dstsize
);
59 /* Storage for pointers to the different blocks. The contents will be filled
60 * in hwilib_find_blocks().
62 static uint8_t *all_blocks
[MAX_BLOCK_NUM
];
64 /* As the length of extended block is variable, save all length to a global
65 * variable so that they can be used later to check boundaries.
67 static uint16_t all_blk_size
[MAX_BLOCK_NUM
];
69 /* Storage for the cbfs file name of the currently open hwi file. */
70 static char current_hwi
[HWI_MAX_NAME_LEN
];
72 static size_t hwilib_read_bytes(const struct param_info
*param
, uint8_t *dst
, size_t dstsize
);
74 /* Add all supported fields to this variable. It is important to use the
75 * field type of a given field as the array index so that all the information
76 * is on the appropriate place inside the array. In this way one do not need
77 * to search for fields but can simply use an index into the array.
79 static const struct param_info params
[] = {
81 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x8, .len
= 4},
82 .get_field
= hwilib_read_bytes
},
84 .pos
[0] = {.blk_type
= BLK_SIB
, .offset
= 0x8, .len
= 4},
85 .get_field
= hwilib_read_bytes
},
87 .pos
[0] = {.blk_type
= BLK_EIB
, .offset
= 0x8, .len
= 4},
88 .get_field
= hwilib_read_bytes
},
90 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x8, .len
= 4},
91 .get_field
= hwilib_read_bytes
},
93 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xbe, .len
= 2},
94 .get_field
= hwilib_read_bytes
},
96 .pos
[0] = {.blk_type
= BLK_SIB
, .offset
= 0xc8, .len
= 2},
97 .get_field
= hwilib_read_bytes
},
99 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x1a8, .len
= 4},
100 .pos
[1] = {.blk_type
= BLK_SIB
, .offset
= 0xd0, .len
= 4},
101 .get_field
= hwilib_read_bytes
},
103 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xa2, .len
= 10},
104 .pos
[1] = {.blk_type
= BLK_SIB
, .offset
= 0xa2, .len
= 10},
105 .get_field
= hwilib_read_bytes
},
107 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xc0, .len
= 6},
108 .get_field
= hwilib_read_bytes
},
110 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xc6, .len
= 1},
111 .get_field
= hwilib_read_bytes
},
113 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xc8, .len
= 6},
114 .get_field
= hwilib_read_bytes
},
116 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xce, .len
= 1},
117 .get_field
= hwilib_read_bytes
},
119 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xd0, .len
= 6},
120 .get_field
= hwilib_read_bytes
},
122 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xd6, .len
= 1},
123 .get_field
= hwilib_read_bytes
},
125 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xd8, .len
= 6},
126 .get_field
= hwilib_read_bytes
},
128 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xde, .len
= 1},
129 .get_field
= hwilib_read_bytes
},
131 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0xe0, .len
= 0x80},
132 .get_field
= hwilib_read_bytes
},
134 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x1b8, .len
= 1},
137 .get_field
= hwilib_read_bytes
},
139 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x1b9, .len
= 1},
142 .get_field
= hwilib_read_bytes
},
143 [NvramVirtTimeDsaveReset
] = {
144 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x1be, .len
= 2},
145 .get_field
= hwilib_read_bytes
},
147 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x1c0, .len
= 4},
148 .get_field
= hwilib_read_bytes
},
150 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x1cc, .len
= 4},
151 .get_field
= hwilib_read_bytes
},
153 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x1d0, .len
= 4},
154 .get_field
= hwilib_read_bytes
},
156 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x1d4, .len
= 4},
157 .get_field
= hwilib_read_bytes
},
159 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x1d8, .len
= 4},
160 .get_field
= hwilib_read_bytes
},
162 .pos
[0] = {.blk_type
= BLK_HIB
, .offset
= 0x1e8, .len
= 1},
163 .get_field
= hwilib_read_bytes
},
165 .pos
[0] = {.blk_type
= BLK_SIB
, .offset
= 0xd8, .len
= 1},
166 .get_field
= hwilib_read_bytes
},
168 .pos
[0] = {.blk_type
= BLK_SIB
, .offset
= 0xe7, .len
= 1},
169 .get_field
= hwilib_read_bytes
},
171 .pos
[0] = {.blk_type
= BLK_SIB
, .offset
= 0xea, .len
= 1},
174 .get_field
= hwilib_read_bytes
},
176 .pos
[0] = {.blk_type
= BLK_SIB
, .offset
= 0xe3, .len
= 1},
177 .get_field
= hwilib_read_bytes
},
179 .pos
[0] = {.blk_type
= BLK_SIB
, .offset
= 0xf2, .len
= 1},
180 .get_field
= hwilib_read_bytes
},
182 .pos
[0] = {.blk_type
= BLK_EIB
, .offset
= 0x10, .len
= 0x80},
183 .get_field
= hwilib_read_bytes
},
185 .pos
[0] = {.blk_type
= BLK_EIB
, .offset
= 0x90, .len
= 2},
186 .get_field
= hwilib_read_bytes
},
188 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0xfc, .len
= 6},
189 .get_field
= hwilib_read_bytes
},
191 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x102, .len
= 1},
192 .get_field
= hwilib_read_bytes
},
194 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x114, .len
= 6},
195 .get_field
= hwilib_read_bytes
},
197 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x11a, .len
= 1},
198 .get_field
= hwilib_read_bytes
},
200 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x12c, .len
= 6},
201 .get_field
= hwilib_read_bytes
},
203 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x132, .len
= 1},
204 .get_field
= hwilib_read_bytes
},
206 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x144, .len
= 6},
207 .get_field
= hwilib_read_bytes
},
209 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x14a, .len
= 1},
210 .get_field
= hwilib_read_bytes
},
212 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x15c, .len
= 6},
213 .get_field
= hwilib_read_bytes
},
215 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x162, .len
= 1},
216 .get_field
= hwilib_read_bytes
},
218 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x174, .len
= 6},
219 .get_field
= hwilib_read_bytes
},
221 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x17a, .len
= 1},
222 .get_field
= hwilib_read_bytes
},
224 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x18c, .len
= 6},
225 .get_field
= hwilib_read_bytes
},
227 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x192, .len
= 1},
228 .get_field
= hwilib_read_bytes
},
230 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1a4, .len
= 6},
231 .get_field
= hwilib_read_bytes
},
233 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1aa, .len
= 1},
234 .get_field
= hwilib_read_bytes
},
236 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1bc, .len
= 6},
237 .get_field
= hwilib_read_bytes
},
239 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1c2, .len
= 1},
240 .get_field
= hwilib_read_bytes
},
242 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1d4, .len
= 6},
243 .get_field
= hwilib_read_bytes
},
245 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1da, .len
= 1},
246 .get_field
= hwilib_read_bytes
},
248 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0xec, .len
= 16},
249 .get_field
= hwilib_read_bytes
},
251 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x104, .len
= 16},
252 .get_field
= hwilib_read_bytes
},
254 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x11c, .len
= 16},
255 .get_field
= hwilib_read_bytes
},
257 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x134, .len
= 16},
258 .get_field
= hwilib_read_bytes
},
260 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x14c, .len
= 16},
261 .get_field
= hwilib_read_bytes
},
263 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x164, .len
= 16},
264 .get_field
= hwilib_read_bytes
},
266 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x17c, .len
= 16},
267 .get_field
= hwilib_read_bytes
},
269 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x194, .len
= 16},
270 .get_field
= hwilib_read_bytes
},
272 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1ac, .len
= 16},
273 .get_field
= hwilib_read_bytes
},
275 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1c4, .len
= 16},
276 .get_field
= hwilib_read_bytes
},
278 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x103, .len
= 1},
279 .get_field
= hwilib_read_bytes
},
281 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x11b, .len
= 1},
282 .get_field
= hwilib_read_bytes
},
284 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x133, .len
= 1},
285 .get_field
= hwilib_read_bytes
},
287 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x14b, .len
= 1},
288 .get_field
= hwilib_read_bytes
},
290 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x163, .len
= 1},
291 .get_field
= hwilib_read_bytes
},
293 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x17b, .len
= 1},
294 .get_field
= hwilib_read_bytes
},
296 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x193, .len
= 1},
297 .get_field
= hwilib_read_bytes
},
299 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1ab, .len
= 1},
300 .get_field
= hwilib_read_bytes
},
302 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1c3, .len
= 1},
303 .get_field
= hwilib_read_bytes
},
305 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1db, .len
= 1},
306 .get_field
= hwilib_read_bytes
},
308 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x18, .len
= 4},
309 .get_field
= hwilib_read_bytes
},
311 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x1c, .len
= 4},
312 .get_field
= hwilib_read_bytes
},
313 [FANSamplingTime
] = {
314 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x20, .len
= 4},
315 .get_field
= hwilib_read_bytes
},
317 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x24, .len
= 4},
318 .get_field
= hwilib_read_bytes
},
320 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x28, .len
= 4},
321 .get_field
= hwilib_read_bytes
},
323 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x2c, .len
= 4},
324 .get_field
= hwilib_read_bytes
},
326 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x30, .len
= 4},
327 .get_field
= hwilib_read_bytes
},
329 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x34, .len
= 4},
330 .get_field
= hwilib_read_bytes
},
331 [FANHystThreshold
] = {
332 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x38, .len
= 4},
333 .get_field
= hwilib_read_bytes
},
335 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x3c, .len
= 4},
336 .get_field
= hwilib_read_bytes
},
338 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x40, .len
= 2},
339 .get_field
= hwilib_read_bytes
},
341 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x42, .len
= 2},
342 .get_field
= hwilib_read_bytes
},
344 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x44, .len
= 4},
345 .get_field
= hwilib_read_bytes
},
347 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x48, .len
= 1},
348 .get_field
= hwilib_read_bytes
},
349 [FANSensorSelect
] = {
350 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x49, .len
= 1},
351 .get_field
= hwilib_read_bytes
},
353 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x4c, .len
= 20},
354 .get_field
= hwilib_read_bytes
},
356 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x60, .len
= 20},
357 .get_field
= hwilib_read_bytes
},
359 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x74, .len
= 20},
360 .get_field
= hwilib_read_bytes
},
362 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x88, .len
= 20},
363 .get_field
= hwilib_read_bytes
},
365 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x9c, .len
= 20},
366 .get_field
= hwilib_read_bytes
},
368 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0xb0, .len
= 20},
369 .get_field
= hwilib_read_bytes
},
371 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0xc4, .len
= 20},
372 .get_field
= hwilib_read_bytes
},
374 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0xd8, .len
= 20},
375 .get_field
= hwilib_read_bytes
},
377 .pos
[0] = {.blk_type
= BLK_XIB
, .offset
= 0x20c, .len
= 4},
378 .get_field
= hwilib_read_bytes
},
381 /** \brief This functions reads the given field from the first valid hwinfo
383 * @param *param Parameter to read from hwinfo
384 * @param *dst Pointer to memory where the data will be stored in
385 * @param dstsize Size of the memory passed in via the *dst pointer
386 * @return Number of copied bytes on success, 0 on error
388 static size_t hwilib_read_bytes(const struct param_info
*param
, uint8_t *dst
, size_t dstsize
)
390 uint8_t i
= 0, *blk
= NULL
;
394 /* Take the first valid block to get the parameter from */
396 if ((param
->pos
[i
].len
) && (param
->pos
[i
].offset
) &&
397 (all_blocks
[param
->pos
[i
].blk_type
])) {
398 blk
= all_blocks
[param
->pos
[i
].blk_type
];
402 } while (i
< MAX_BLOCK_NUM
);
404 /* Ensure there is a valid block available for this parameter and
405 * the length of the parameter does not exceed dstsize or block len.
407 if ((!blk
) || (param
->pos
[i
].len
> dstsize
) ||
408 (param
->pos
[i
].len
+ param
->pos
[i
].offset
>
409 all_blk_size
[param
->pos
[i
].blk_type
]))
411 /* We can now copy the wanted data. */
412 memcpy(dst
, (blk
+ param
->pos
[i
].offset
), param
->pos
[i
].len
);
413 /* If there is a mask given, apply it only for parameters with a
414 * length of 1, 2, 4 or 8 bytes.
417 switch (param
->pos
[i
].len
) {
419 /* Apply a mask on a 8 bit value */
420 *dst
&= (param
->mask
& 0xff);
421 *dst
>>= (param
->mask_offset
);
424 /* Apply mask on a 16 bit value */
425 *((uint16_t *)(dst
)) &= (param
->mask
& 0xffff);
426 *((uint16_t *)(dst
)) >>= (param
->mask_offset
);
429 /* Apply mask on a 32 bit value */
430 *((uint32_t *)(dst
)) &= (param
->mask
& 0xffffffff);
431 *((uint32_t *)(dst
)) >>= (param
->mask_offset
);
434 /* Apply mask on a 64 bit value */
435 *((uint64_t *)(dst
)) &= (param
->mask
);
436 *((uint64_t *)(dst
)) >>= (param
->mask_offset
);
439 /* Warn if there is a mask for an invalid length. */
441 "HWILIB: Invalid field length for given mask.\n");
445 return param
->pos
[i
].len
;
448 /** \brief This function finds all available block types in a given cbfs file.
449 * @param *hwi_filename Name of the cbfs-file to use.
450 * @return CB_SUCCESS when no error, otherwise error code
452 enum cb_err
hwilib_find_blocks(const char *hwi_filename
)
454 uint8_t *ptr
= NULL
, *base
= NULL
;
455 uint32_t next_offset
= 1;
458 /* Check for a valid parameter */
461 /* Check if this file is already open. If yes, just leave as there is
462 nothing left to do here. */
463 if (!strncmp(current_hwi
, hwi_filename
, HWI_MAX_NAME_LEN
)) {
464 printk(BIOS_SPEW
, "HWILIB: File \"%s\" already open.\n",
469 ptr
= cbfs_map(hwi_filename
, &filesize
);
471 printk(BIOS_ERR
,"HWILIB: Missing file \"%s\" in cbfs.\n",
475 /* Ensure the block has the right magic */
476 if (strncmp((char*)ptr
, BLOCK_MAGIC
, LEN_MAGIC_NUM
)) {
477 printk(BIOS_ERR
, "HWILIB: Bad magic at start of block!\n");
480 /* Reset all static pointers to blocks as they might have been set
481 * in prior calls to this function.
482 * This way the caller do not need to "close" already opened blocks.
484 memset(all_blocks
, 0, (MAX_BLOCK_NUM
* sizeof (uint8_t *)));
485 /* Check which blocks are available by examining the length field. */
487 /* Fill in sizes of all fixed length blocks. */
488 all_blk_size
[BLK_HIB
] = LEN_HIB
;
489 all_blk_size
[BLK_SIB
] = LEN_SIB
;
490 all_blk_size
[BLK_EIB
] = LEN_EIB
;
491 /* Length of BLK_XIB is variable and will be filled if block is found */
492 all_blk_size
[BLK_XIB
] = 0;
493 while(!(strncmp((char *)ptr
, BLOCK_MAGIC
, LEN_MAGIC_NUM
)) &&
495 uint16_t len
= read16(ptr
+ LEN_OFFSET
);
496 /* Ensure file size boundaries for a given block. */
497 if ((ptr
- base
+ len
) > filesize
)
499 if (len
== LEN_HIB
) {
500 all_blocks
[BLK_HIB
] = ptr
;
501 next_offset
= read32(ptr
+ NEXT_OFFSET_HIB
);
503 ptr
= base
+ next_offset
;
504 } else if (len
== LEN_SIB
) {
505 all_blocks
[BLK_SIB
] = ptr
;
506 next_offset
= read32(ptr
+ NEXT_OFFSET_SIB
);
508 ptr
= base
+ next_offset
;
509 } else if (len
== LEN_EIB
) {
510 /* Skip preliminary blocks */
511 if (!(read16(ptr
+ EIB_FEATRUE_OFFSET
) & 0x01))
512 all_blocks
[BLK_EIB
] = ptr
;
513 next_offset
= read32(ptr
+ NEXT_OFFSET_EIB
);
515 ptr
= base
+ next_offset
;
516 } else if (len
>= MIN_LEN_XIB
) {
517 all_blocks
[BLK_XIB
] = ptr
;
518 next_offset
= read32(ptr
+ NEXT_OFFSET_XIB
);
519 all_blk_size
[BLK_XIB
] = len
;
521 ptr
= base
+ next_offset
;
526 /* We should have found at least one valid block */
527 if (all_blocks
[BLK_HIB
] || all_blocks
[BLK_SIB
] || all_blocks
[BLK_EIB
] ||
528 all_blocks
[BLK_XIB
]) {
529 /* Save currently opened hwi filename. */
530 strncpy(current_hwi
, hwi_filename
, HWI_MAX_NAME_LEN
);
537 /** \brief This functions is used from caller to get a specific field from
539 * @param field Field type to read from hwinfo
540 * @param *dst Pointer to memory where the data will be stored in
541 * @param dstsize Size of the memory passed in via the *dst pointer
542 * @return Number of copied bytes on success, 0 on error
544 size_t hwilib_get_field(hwinfo_field_t field
, uint8_t *dst
, size_t dstsize
)
546 /* Check the boundaries of params-variable */
547 if ((uint32_t)field
< ARRAY_SIZE(params
))
548 return params
[field
].get_field(¶ms
[field
], dst
, dstsize
);