1 /*
2 * Copyright 2008-2024 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 /*! \file wm_utils.h
9 * \brief Utility functions
10 *
11 * Collection of some common helper functions
12 */
13
14 #ifndef _UTIL_H_
15 #define _UTIL_H_
16
17 #include <wifi_config_default.h>
18 #include <wmtypes.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <ctype.h>
22 #include <zephyr/kernel.h>
23 #include <strings.h>
24
25 #ifndef PRINTF
26 #define PRINTF printk
27 #endif
28 #ifndef SDK_DEBUGCONSOLE
29 #define SDK_DEBUGCONSOLE CONFIG_WIFI_EXTRA_DEBUG
30 #endif
31
32 #define ffs __builtin_ffs
33
34 #ifdef __GNUC__
35 #define WARN_UNUSED_RET __attribute__((warn_unused_result))
36
37 #ifndef PACK_START
38 #define PACK_START
39 #endif
40 #ifndef PACK_END
41 #define PACK_END __attribute__((packed))
42 #endif
43 #define NORETURN __attribute__((noreturn))
44
45 /* alignment value should be a power of 2 */
46 #define ALIGN_X(num, align) WM_MASK(num, (typeof(num))align - 1)
47
48 #define ALIGN_2(num) ALIGN_X(num, 2)
49 #define ALIGN_4(num) ALIGN_X(num, 4)
50 #define ALIGN_8(num) ALIGN_X(num, 8)
51 #define ALIGN_16(num) ALIGN_X(num, 16)
52 #define ALIGN_32(num) ALIGN_X(num, 32)
53
54 #else /* __GNUC__ */
55
56 #define WARN_UNUSED_RET
57
58 #define PACK_START __packed
59 #define PACK_END
60 #define NORETURN
61
62 #endif /* __GNUC__ */
63
64 /* Weak function. */
65 #if defined(__GNUC__)
66 #define WEAK __attribute__((weak))
67 #elif defined(__ICCARM__)
68 #define WEAK __weak
69 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
70 #define WEAK __attribute__((weak))
71 #endif
72
73 /* alignment value should be a power of 2 */
74 #define __WM_ALIGN__(num, num_type, align) WM_MASK(num, (num_type)align - 1)
75 #define WM_MASK(num, mask) ((num + mask) & ~(mask))
76
77 NORETURN void wmpanic(void);
78
79 /**
80 * Convert a given hex string to a equivalent binary representation.
81 *
82 * E.g. If your input string of 4 bytes is {'F', 'F', 'F', 'F'} the output
83 * string will be of 2 bytes {255, 255} or to put the same in other way
84 * {0xFF, 0xFF}
85 *
86 * Note that hex2bin is not the same as strtoul as the latter will properly
87 * return the integer in the correct machine binary format viz. little
88 * endian. hex2bin however does only in-place like replacement of two ASCII
89 * characters to one binary number taking 1 byte in memory.
90 *
91 * @param[in] ibuf input buffer
92 * @param[out] obuf output buffer
93 * @param[in] max_olen Maximum output buffer length
94 *
95 * @return length of the binary string
96 */
wm_hex2bin(const uint8_t * ibuf,uint8_t * obuf,unsigned max_olen)97 static inline unsigned int wm_hex2bin(const uint8_t *ibuf, uint8_t *obuf, unsigned max_olen)
98 {
99 return hex2bin(ibuf, strlen(ibuf), obuf, max_olen);
100 }
101
102 /** Function prototype for a random entropy/seed generator
103 *
104 * \return a 32bit random number
105 */
106 typedef uint32_t (*random_hdlr_t)(void);
107
108 /** Register a random entropy generator handler
109 *
110 * This API allows applications to register their own random entropy
111 * generator handlers that will be internally used by get_random_sequence()
112 * to add even more randomization to the byte stream generated by it.
113 *
114 * \param[in] func Function pointer of type \ref random_hdlr_t
115 *
116 * \return WM_SUCCESS if successful
117 * \return -WM_E_NOSPC if there is no space available for additional handlers
118 */
119 int random_register_handler(random_hdlr_t func);
120
121 /** Un-register a random entropy generator handler
122 *
123 * This API can be used to un-register a handler registered using
124 * random_register_handler()
125 *
126 * \param[in] func Function pointer of type \ref random_hdlr_t used during
127 * registering
128 *
129 * \return WM_SUCCESS if successful
130 * \return -WM_E_INVAL if the passed pointer is invalid
131 */
132 int random_unregister_handler(random_hdlr_t func);
133
134 /** Register a random seed generator handler
135 *
136 * For getting better random numbers, the initial seed (ideally required only
137 * once on every boot) should also be random. This API allows applications to
138 * register their own seed generators. Applications can use any logic such
139 * that a different seed is generated every time. A sample seed generator which
140 * uses a combination of DAC (generating random noise) and ADC (that internally
141 * samples the random noise) along with the flash id has already been provided.
142 * Please have a look at sample_initialise_random_seed().
143 *
144 * The seed generator handler is called only once by the get_random_sequence()
145 * function. Applications can also explicitly initialize the seed by calling
146 * random_initialize_seed() after registering a handler.
147 *
148 * \param[in] func Function pointer of type \ref random_hdlr_t
149 *
150 * \return WM_SUCCESS if successful
151 * \return -WM_E_NOSPC if there is no space available for additional handlers
152 */
153 int random_register_seed_handler(random_hdlr_t func);
154
155 /** Un-register a random seed generator handler
156 *
157 * This API can be used to un-register a handler registered using
158 * random_register_seed_handler()
159 *
160 * \param[in] func Function pointer of type \ref random_hdlr_t used during
161 * registering
162 *
163 * \return WM_SUCCESS if successful
164 * \return -WM_E_INVAL if the passed pointer is invalid
165 */
166 int random_unregister_seed_handler(random_hdlr_t func);
167
168 /** Initialize the random number generator's seed
169 *
170 * The get_random_sequence() uses a random number generator that is
171 * initialized with a seed when get_random_sequence() is called for the first
172 * time. The handlers registered using random_register_seed_handler() are
173 * used to generate the seed. If an application wants to explicitly initialize
174 * the seed, this API can be used. The seed will then not be re-initialized
175 * in get_random_sequence().
176 */
177 void random_initialize_seed(void);
178
179 /** Sample random seed generator
180 *
181 * This is a sample random seed generator handler that can be registered using
182 * random_register_seed_handler() to generate a random seed. This uses a
183 * combination of DAC (generating random noise) and ADC (that internally
184 * samples the random noise) along with the flash id to generate a seed.
185 * It is recommended to register this handler and immediately call
186 * random_initialize_seed() before executing any other application code,
187 * especially if the application is going to use ADC/DAC for its own purpose.
188 *
189 * \return Random seed
190 */
191 uint32_t sample_initialise_random_seed(void);
192
193 /** Generate random sequence of bytes
194 *
195 * This function generates random sequence of bytes in the user provided buffer.
196 *
197 * @param[out] buf The buffer to be populated with random data
198 * @param[in] size The number of bytes of the random sequence required
199 *
200 */
201 void get_random_sequence(void *buf, unsigned int size);
202 #define DUMP_WRAPAROUND 16U
203
204 /** Dump buffer in hex format on console
205 *
206 * This function prints the received buffer in HEX format on the console
207 *
208 * \param[in] data Pointer to the data buffer
209 * \param[in] len Length of the data
210 */
dump_hex(const void * data,unsigned len)211 static inline void dump_hex(const void *data, unsigned len)
212 {
213 (void)PRINTF("**** Dump @ %p Len: %d ****\n\r", data, len);
214
215 unsigned int i = 0;
216 const char *data8 = (const char *)data;
217 while (i < len)
218 {
219 (void)PRINTF("%02x ", data8[i++]);
220 if (!(i % DUMP_WRAPAROUND))
221 {
222 (void)PRINTF("\n\r");
223 }
224 }
225
226 (void)PRINTF("\n\r******** End Dump *******\n\r");
227 }
228 /** Dump buffer in hex and ascii format on console
229 *
230 * This function prints the received buffer in HEX as well as ASCII
231 * format on the console
232 *
233 * \param[in] data Pointer to the data buffer
234 * \param[in] len Length of the data
235 */
236 void dump_hex_ascii(const void *data, unsigned len);
237 void dump_ascii(const void *data, unsigned len);
238 void print_ascii(const void *data, unsigned len);
239 void dump_json(const void *buffer, unsigned len);
240
241 /* Helper functions to print a float value. Some compilers have a problem
242 * interpreting %f
243 */
244
245 #define wm_int_part_of(x) ((int)(x))
wm_frac_part_of(float x,short precision)246 static inline int wm_frac_part_of(float x, short precision)
247 {
248 int scale = 1;
249
250 while ((precision--) != (short)0U)
251 {
252 scale *= 10;
253 }
254
255 return (x < 0 ? (int)(((int)x - x) * scale) : (int)((x - (int)x) * scale));
256 }
257
258 #ifndef __linux__
259 /** Returns a pointer to a new string which is a duplicate of the
260 * input string s.
261 * Memory for the new string is obtained allocated by the function.
262 *
263 * It is caller's responsibility to free the memory after its use.
264 *
265 * \param[in] s Pointer to string to be duplicated
266 *
267 * \return Pointer to newly allocated string which is duplicate of
268 * input string
269 * \return NULL on error
270 */
271 char *strdup(const char *s);
272 #endif /* ! __linux__ */
273
274 /** Calculate CRC32 using software algorithm
275 *
276 * @pre soft_crc32_init()
277 *
278 * soft_crc32() allows the user to calculate CRC32 values of arbitrary
279 * sized buffers across multiple calls.
280 *
281 * @param[in] data__ Input buffer over which CRC32 is calculated.
282 * @param[in] data_size Length of the input buffer.
283 * @param[in] crc Previous CRC32 value used as starting point for given
284 * buffer calculation.
285 *
286 * @return Calculated CRC32 value
287 */
288 uint32_t soft_crc32(const void *data__, int data_size, uint32_t crc);
289 float wm_strtof(const char *str, char **endptr);
290
291 /**
292 * Fill the given buffer with a sequential pattern starting from
293 * given byte.
294 *
295 * For example, if the 'first_byte' is 0x45 and buffer size of 5 then
296 * buffer will be set to {0x45, 0x46, 0x47, 0x48, 0x49}
297 * @param[in] buffer The pattern will be set to this buffer.
298 * @param[in] size Number of pattern bytes to the be written to the buffer.
299 * @param[in] first_byte This is the value of first byte in the sequential
300 * pattern.
301 *
302 */
303 void fill_sequential_pattern(void *buffer, int size, uint8_t first_byte);
304
305 /**
306 * Verify if the the given buffer has a sequential pattern starting from
307 * given byte.
308 *
309 * For example, if the 'first_byte' is 0x45 and buffer size of 5 then
310 * buffer will be verified for presence of {0x45, 0x46, 0x47, 0x48, 0x49}
311 * @param[in] buffer The pattern will be verified from this buffer.
312 * @param[in] size Number of pattern bytes to the be verified from the buffer.
313 * @param[in] first_byte This is the value of first byte in the sequential
314 * pattern.
315 *
316 * @return 'true' If verification successful.
317 * @return 'false' If verification fails.
318 */
319 bool verify_sequential_pattern(const void *buffer, int size, uint8_t first_byte);
320 #endif
321