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