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