1 /*
2  * lfs utility functions
3  *
4  * Copyright (c) 2017, Arm Limited. All rights reserved.
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 #ifndef LFS_UTIL_H
8 #define LFS_UTIL_H
9 
10 // Users can override lfs_util.h with their own configuration by defining
11 // LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
12 //
13 // If LFS_CONFIG is used, none of the default utils will be emitted and must be
14 // provided by the config file. To start, I would suggest copying lfs_util.h
15 // and modifying as needed.
16 #ifdef LFS_CONFIG
17 #define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
18 #define LFS_STRINGIZE2(x) #x
19 #include LFS_STRINGIZE(LFS_CONFIG)
20 #else
21 
22 // System includes
23 #include <stdint.h>
24 #include <stdbool.h>
25 #include <string.h>
26 #include <inttypes.h>
27 
28 #ifndef LFS_NO_MALLOC
29 #include <stdlib.h>
30 #endif
31 #ifndef LFS_NO_ASSERT
32 #ifdef __ZEPHYR__
33 #include <sys/__assert.h>
34 #else  /* __ZEPHYR__ */
35 #include <assert.h>
36 #endif  /* __ZEPHYR__ */
37 #endif
38 
39 #if !defined(LFS_NO_DEBUG) || \
40         !defined(LFS_NO_WARN) || \
41         !defined(LFS_NO_ERROR) || \
42         defined(LFS_YES_TRACE)
43 
44 #ifdef __ZEPHYR__
45 #include <logging/log.h>
46 
47 #ifdef LFS_LOG_REGISTER
48 LOG_MODULE_REGISTER(littlefs, CONFIG_FS_LOG_LEVEL);
49 #else
50 LOG_MODULE_DECLARE(littlefs, CONFIG_FS_LOG_LEVEL);
51 #endif
52 
53 #endif  /* __ZEPHYR__ */
54 
55 #include <stdio.h>
56 #endif
57 
58 #ifdef __cplusplus
59 extern "C"
60 {
61 #endif
62 
63 
64 // Macros, may be replaced by system specific wrappers. Arguments to these
65 // macros must not have side-effects as the macros can be removed for a smaller
66 // code footprint
67 
68 // Logging functions
69 #ifdef LFS_YES_TRACE
70 #ifdef __ZEPHYR__
71 #define LFS_TRACE(fmt, ...) LOG_DBG("%s:%d:trace: " fmt, __FILE__, __LINE__, __VA_ARGS__)
72 #else /* __ZEPHYR__ */
73 #define LFS_TRACE_(fmt, ...) \
74     printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
75 #define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
76 #endif /* __ZEPHYR__ */
77 #else
78 #define LFS_TRACE(...)
79 #endif
80 
81 #ifndef LFS_NO_DEBUG
82 #ifdef __ZEPHYR__
83 #define LFS_DEBUG(fmt, ...) LOG_DBG("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__)
84 #else /* __ZEPHYR__ */
85 #define LFS_DEBUG_(fmt, ...) \
86     printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
87 #define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, "")
88 #endif /* __ZEPHYR__ */
89 #else
90 #define LFS_DEBUG(...)
91 #endif
92 
93 #ifndef LFS_NO_WARN
94 #ifdef __ZEPHYR__
95 #define LFS_WARN(fmt, ...) LOG_WRN("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__)
96 #else /* __ZEPHYR__ */
97 #define LFS_WARN_(fmt, ...) \
98     printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
99 #define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, "")
100 #endif /* __ZEPHYR__ */
101 #else
102 #define LFS_WARN(...)
103 #endif
104 
105 #ifndef LFS_NO_ERROR
106 #ifdef __ZEPHYR__
107 #define LFS_ERROR(fmt, ...) LOG_ERR("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__)
108 #else /* __ZEPHYR__ */
109 #define LFS_ERROR_(fmt, ...) \
110     printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
111 #define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "")
112 #endif /* __ZEPHYR__ */
113 #else
114 #define LFS_ERROR(...)
115 #endif
116 
117 // Runtime assertions
118 #ifndef LFS_NO_ASSERT
119 #ifdef __ZEPHYR__
120 #define LFS_ASSERT(test) __ASSERT_NO_MSG(test)
121 #else /* __ZEPHYR__ */
122 #define LFS_ASSERT(test) assert(test)
123 #endif /* __ZEPHYR__ */
124 #else
125 #define LFS_ASSERT(test)
126 #endif
127 
128 
129 // Builtin functions, these may be replaced by more efficient
130 // toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
131 // expensive basic C implementation for debugging purposes
132 
133 // Min/max functions for unsigned 32-bit numbers
lfs_max(uint32_t a,uint32_t b)134 static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
135     return (a > b) ? a : b;
136 }
137 
lfs_min(uint32_t a,uint32_t b)138 static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
139     return (a < b) ? a : b;
140 }
141 
142 // Align to nearest multiple of a size
lfs_aligndown(uint32_t a,uint32_t alignment)143 static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
144     return a - (a % alignment);
145 }
146 
lfs_alignup(uint32_t a,uint32_t alignment)147 static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
148     return lfs_aligndown(a + alignment-1, alignment);
149 }
150 
151 // Find the smallest power of 2 greater than or equal to a
lfs_npw2(uint32_t a)152 static inline uint32_t lfs_npw2(uint32_t a) {
153 #if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
154     return 32 - __builtin_clz(a-1);
155 #else
156     uint32_t r = 0;
157     uint32_t s;
158     a -= 1;
159     s = (a > 0xffff) << 4; a >>= s; r |= s;
160     s = (a > 0xff  ) << 3; a >>= s; r |= s;
161     s = (a > 0xf   ) << 2; a >>= s; r |= s;
162     s = (a > 0x3   ) << 1; a >>= s; r |= s;
163     return (r | (a >> 1)) + 1;
164 #endif
165 }
166 
167 // Count the number of trailing binary zeros in a
168 // lfs_ctz(0) may be undefined
lfs_ctz(uint32_t a)169 static inline uint32_t lfs_ctz(uint32_t a) {
170 #if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
171     return __builtin_ctz(a);
172 #else
173     return lfs_npw2((a & -a) + 1) - 1;
174 #endif
175 }
176 
177 // Count the number of binary ones in a
lfs_popc(uint32_t a)178 static inline uint32_t lfs_popc(uint32_t a) {
179 #if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
180     return __builtin_popcount(a);
181 #else
182     a = a - ((a >> 1) & 0x55555555);
183     a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
184     return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
185 #endif
186 }
187 
188 // Find the sequence comparison of a and b, this is the distance
189 // between a and b ignoring overflow
lfs_scmp(uint32_t a,uint32_t b)190 static inline int lfs_scmp(uint32_t a, uint32_t b) {
191     return (int)(unsigned)(a - b);
192 }
193 
194 // Convert between 32-bit little-endian and native order
lfs_fromle32(uint32_t a)195 static inline uint32_t lfs_fromle32(uint32_t a) {
196 #if !defined(LFS_NO_INTRINSICS) && ( \
197     (defined(  BYTE_ORDER  ) && defined(  ORDER_LITTLE_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_LITTLE_ENDIAN  ) || \
198     (defined(__BYTE_ORDER  ) && defined(__ORDER_LITTLE_ENDIAN  ) && __BYTE_ORDER   == __ORDER_LITTLE_ENDIAN  ) || \
199     (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
200     return a;
201 #elif !defined(LFS_NO_INTRINSICS) && ( \
202     (defined(  BYTE_ORDER  ) && defined(  ORDER_BIG_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_BIG_ENDIAN  ) || \
203     (defined(__BYTE_ORDER  ) && defined(__ORDER_BIG_ENDIAN  ) && __BYTE_ORDER   == __ORDER_BIG_ENDIAN  ) || \
204     (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
205     return __builtin_bswap32(a);
206 #else
207     return (((uint8_t*)&a)[0] <<  0) |
208            (((uint8_t*)&a)[1] <<  8) |
209            (((uint8_t*)&a)[2] << 16) |
210            (((uint8_t*)&a)[3] << 24);
211 #endif
212 }
213 
lfs_tole32(uint32_t a)214 static inline uint32_t lfs_tole32(uint32_t a) {
215     return lfs_fromle32(a);
216 }
217 
218 // Convert between 32-bit big-endian and native order
lfs_frombe32(uint32_t a)219 static inline uint32_t lfs_frombe32(uint32_t a) {
220 #if !defined(LFS_NO_INTRINSICS) && ( \
221     (defined(  BYTE_ORDER  ) && defined(  ORDER_LITTLE_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_LITTLE_ENDIAN  ) || \
222     (defined(__BYTE_ORDER  ) && defined(__ORDER_LITTLE_ENDIAN  ) && __BYTE_ORDER   == __ORDER_LITTLE_ENDIAN  ) || \
223     (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
224     return __builtin_bswap32(a);
225 #elif !defined(LFS_NO_INTRINSICS) && ( \
226     (defined(  BYTE_ORDER  ) && defined(  ORDER_BIG_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_BIG_ENDIAN  ) || \
227     (defined(__BYTE_ORDER  ) && defined(__ORDER_BIG_ENDIAN  ) && __BYTE_ORDER   == __ORDER_BIG_ENDIAN  ) || \
228     (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
229     return a;
230 #else
231     return (((uint8_t*)&a)[0] << 24) |
232            (((uint8_t*)&a)[1] << 16) |
233            (((uint8_t*)&a)[2] <<  8) |
234            (((uint8_t*)&a)[3] <<  0);
235 #endif
236 }
237 
lfs_tobe32(uint32_t a)238 static inline uint32_t lfs_tobe32(uint32_t a) {
239     return lfs_frombe32(a);
240 }
241 
242 // Calculate CRC-32 with polynomial = 0x04c11db7
243 uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
244 
245 // Allocate memory, only used if buffers are not provided to littlefs
246 // Note, memory must be 64-bit aligned
lfs_malloc(size_t size)247 static inline void *lfs_malloc(size_t size) {
248 #ifndef LFS_NO_MALLOC
249     return malloc(size);
250 #else
251     (void)size;
252     return NULL;
253 #endif
254 }
255 
256 // Deallocate memory, only used if buffers are not provided to littlefs
lfs_free(void * p)257 static inline void lfs_free(void *p) {
258 #ifndef LFS_NO_MALLOC
259     free(p);
260 #else
261     (void)p;
262 #endif
263 }
264 
265 
266 #ifdef __cplusplus
267 } /* extern "C" */
268 #endif
269 
270 #endif
271 #endif
272