119ea8026Sopenharmony_ci/*
219ea8026Sopenharmony_ci * lfs utility functions
319ea8026Sopenharmony_ci *
419ea8026Sopenharmony_ci * Copyright (c) 2022, The littlefs authors.
519ea8026Sopenharmony_ci * Copyright (c) 2017, Arm Limited. All rights reserved.
619ea8026Sopenharmony_ci * SPDX-License-Identifier: BSD-3-Clause
719ea8026Sopenharmony_ci */
819ea8026Sopenharmony_ci#ifndef LFS_UTIL_H
919ea8026Sopenharmony_ci#define LFS_UTIL_H
1019ea8026Sopenharmony_ci
1119ea8026Sopenharmony_ci// Users can override lfs_util.h with their own configuration by defining
1219ea8026Sopenharmony_ci// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
1319ea8026Sopenharmony_ci//
1419ea8026Sopenharmony_ci// If LFS_CONFIG is used, none of the default utils will be emitted and must be
1519ea8026Sopenharmony_ci// provided by the config file. To start, I would suggest copying lfs_util.h
1619ea8026Sopenharmony_ci// and modifying as needed.
1719ea8026Sopenharmony_ci#ifdef LFS_CONFIG
1819ea8026Sopenharmony_ci#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
1919ea8026Sopenharmony_ci#define LFS_STRINGIZE2(x) #x
2019ea8026Sopenharmony_ci#include LFS_STRINGIZE(LFS_CONFIG)
2119ea8026Sopenharmony_ci#else
2219ea8026Sopenharmony_ci
2319ea8026Sopenharmony_ci// System includes
2419ea8026Sopenharmony_ci#include <stdint.h>
2519ea8026Sopenharmony_ci#include <stdbool.h>
2619ea8026Sopenharmony_ci#include <string.h>
2719ea8026Sopenharmony_ci#include <inttypes.h>
2819ea8026Sopenharmony_ci
2919ea8026Sopenharmony_ci#ifndef LFS_NO_MALLOC
3019ea8026Sopenharmony_ci#include <stdlib.h>
3119ea8026Sopenharmony_ci#endif
3219ea8026Sopenharmony_ci#ifndef LFS_NO_ASSERT
3319ea8026Sopenharmony_ci#include <assert.h>
3419ea8026Sopenharmony_ci#endif
3519ea8026Sopenharmony_ci#if !defined(LFS_NO_DEBUG) || \
3619ea8026Sopenharmony_ci        !defined(LFS_NO_WARN) || \
3719ea8026Sopenharmony_ci        !defined(LFS_NO_ERROR) || \
3819ea8026Sopenharmony_ci        defined(LFS_YES_TRACE)
3919ea8026Sopenharmony_ci#include <stdio.h>
4019ea8026Sopenharmony_ci#endif
4119ea8026Sopenharmony_ci
4219ea8026Sopenharmony_ci#ifdef __cplusplus
4319ea8026Sopenharmony_ciextern "C"
4419ea8026Sopenharmony_ci{
4519ea8026Sopenharmony_ci#endif
4619ea8026Sopenharmony_ci
4719ea8026Sopenharmony_ci
4819ea8026Sopenharmony_ci// Macros, may be replaced by system specific wrappers. Arguments to these
4919ea8026Sopenharmony_ci// macros must not have side-effects as the macros can be removed for a smaller
5019ea8026Sopenharmony_ci// code footprint
5119ea8026Sopenharmony_ci
5219ea8026Sopenharmony_ci// Logging functions
5319ea8026Sopenharmony_ci#ifndef LFS_TRACE
5419ea8026Sopenharmony_ci#ifdef LFS_YES_TRACE
5519ea8026Sopenharmony_ci#define LFS_TRACE_(fmt, ...) \
5619ea8026Sopenharmony_ci    printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
5719ea8026Sopenharmony_ci#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
5819ea8026Sopenharmony_ci#else
5919ea8026Sopenharmony_ci#define LFS_TRACE(...)
6019ea8026Sopenharmony_ci#endif
6119ea8026Sopenharmony_ci#endif
6219ea8026Sopenharmony_ci
6319ea8026Sopenharmony_ci#ifndef LFS_DEBUG
6419ea8026Sopenharmony_ci#ifndef LFS_NO_DEBUG
6519ea8026Sopenharmony_ci#define LFS_DEBUG_(fmt, ...) \
6619ea8026Sopenharmony_ci    printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
6719ea8026Sopenharmony_ci#define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, "")
6819ea8026Sopenharmony_ci#else
6919ea8026Sopenharmony_ci#define LFS_DEBUG(...)
7019ea8026Sopenharmony_ci#endif
7119ea8026Sopenharmony_ci#endif
7219ea8026Sopenharmony_ci
7319ea8026Sopenharmony_ci#ifndef LFS_WARN
7419ea8026Sopenharmony_ci#ifndef LFS_NO_WARN
7519ea8026Sopenharmony_ci#define LFS_WARN_(fmt, ...) \
7619ea8026Sopenharmony_ci    printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
7719ea8026Sopenharmony_ci#define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, "")
7819ea8026Sopenharmony_ci#else
7919ea8026Sopenharmony_ci#define LFS_WARN(...)
8019ea8026Sopenharmony_ci#endif
8119ea8026Sopenharmony_ci#endif
8219ea8026Sopenharmony_ci
8319ea8026Sopenharmony_ci#ifndef LFS_ERROR
8419ea8026Sopenharmony_ci#ifndef LFS_NO_ERROR
8519ea8026Sopenharmony_ci#define LFS_ERROR_(fmt, ...) \
8619ea8026Sopenharmony_ci    printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
8719ea8026Sopenharmony_ci#define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "")
8819ea8026Sopenharmony_ci#else
8919ea8026Sopenharmony_ci#define LFS_ERROR(...)
9019ea8026Sopenharmony_ci#endif
9119ea8026Sopenharmony_ci#endif
9219ea8026Sopenharmony_ci
9319ea8026Sopenharmony_ci// Runtime assertions
9419ea8026Sopenharmony_ci#ifndef LFS_ASSERT
9519ea8026Sopenharmony_ci#ifndef LFS_NO_ASSERT
9619ea8026Sopenharmony_ci#define LFS_ASSERT(test) assert(test)
9719ea8026Sopenharmony_ci#else
9819ea8026Sopenharmony_ci#define LFS_ASSERT(test)
9919ea8026Sopenharmony_ci#endif
10019ea8026Sopenharmony_ci#endif
10119ea8026Sopenharmony_ci
10219ea8026Sopenharmony_ci
10319ea8026Sopenharmony_ci// Builtin functions, these may be replaced by more efficient
10419ea8026Sopenharmony_ci// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
10519ea8026Sopenharmony_ci// expensive basic C implementation for debugging purposes
10619ea8026Sopenharmony_ci
10719ea8026Sopenharmony_ci// Min/max functions for unsigned 32-bit numbers
10819ea8026Sopenharmony_cistatic inline uint32_t lfs_max(uint32_t a, uint32_t b) {
10919ea8026Sopenharmony_ci    return (a > b) ? a : b;
11019ea8026Sopenharmony_ci}
11119ea8026Sopenharmony_ci
11219ea8026Sopenharmony_cistatic inline uint32_t lfs_min(uint32_t a, uint32_t b) {
11319ea8026Sopenharmony_ci    return (a < b) ? a : b;
11419ea8026Sopenharmony_ci}
11519ea8026Sopenharmony_ci
11619ea8026Sopenharmony_ci// Align to nearest multiple of a size
11719ea8026Sopenharmony_cistatic inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
11819ea8026Sopenharmony_ci    return a - (a % alignment);
11919ea8026Sopenharmony_ci}
12019ea8026Sopenharmony_ci
12119ea8026Sopenharmony_cistatic inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
12219ea8026Sopenharmony_ci    return lfs_aligndown(a + alignment-1, alignment);
12319ea8026Sopenharmony_ci}
12419ea8026Sopenharmony_ci
12519ea8026Sopenharmony_ci// Find the smallest power of 2 greater than or equal to a
12619ea8026Sopenharmony_cistatic inline uint32_t lfs_npw2(uint32_t a) {
12719ea8026Sopenharmony_ci#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
12819ea8026Sopenharmony_ci    return 32 - __builtin_clz(a-1);
12919ea8026Sopenharmony_ci#else
13019ea8026Sopenharmony_ci    uint32_t r = 0;
13119ea8026Sopenharmony_ci    uint32_t s;
13219ea8026Sopenharmony_ci    a -= 1;
13319ea8026Sopenharmony_ci    s = (a > 0xffff) << 4; a >>= s; r |= s;
13419ea8026Sopenharmony_ci    s = (a > 0xff  ) << 3; a >>= s; r |= s;
13519ea8026Sopenharmony_ci    s = (a > 0xf   ) << 2; a >>= s; r |= s;
13619ea8026Sopenharmony_ci    s = (a > 0x3   ) << 1; a >>= s; r |= s;
13719ea8026Sopenharmony_ci    return (r | (a >> 1)) + 1;
13819ea8026Sopenharmony_ci#endif
13919ea8026Sopenharmony_ci}
14019ea8026Sopenharmony_ci
14119ea8026Sopenharmony_ci// Count the number of trailing binary zeros in a
14219ea8026Sopenharmony_ci// lfs_ctz(0) may be undefined
14319ea8026Sopenharmony_cistatic inline uint32_t lfs_ctz(uint32_t a) {
14419ea8026Sopenharmony_ci#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
14519ea8026Sopenharmony_ci    return __builtin_ctz(a);
14619ea8026Sopenharmony_ci#else
14719ea8026Sopenharmony_ci    return lfs_npw2((a & -a) + 1) - 1;
14819ea8026Sopenharmony_ci#endif
14919ea8026Sopenharmony_ci}
15019ea8026Sopenharmony_ci
15119ea8026Sopenharmony_ci// Count the number of binary ones in a
15219ea8026Sopenharmony_cistatic inline uint32_t lfs_popc(uint32_t a) {
15319ea8026Sopenharmony_ci#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
15419ea8026Sopenharmony_ci    return __builtin_popcount(a);
15519ea8026Sopenharmony_ci#else
15619ea8026Sopenharmony_ci    a = a - ((a >> 1) & 0x55555555);
15719ea8026Sopenharmony_ci    a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
15819ea8026Sopenharmony_ci    return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
15919ea8026Sopenharmony_ci#endif
16019ea8026Sopenharmony_ci}
16119ea8026Sopenharmony_ci
16219ea8026Sopenharmony_ci// Find the sequence comparison of a and b, this is the distance
16319ea8026Sopenharmony_ci// between a and b ignoring overflow
16419ea8026Sopenharmony_cistatic inline int lfs_scmp(uint32_t a, uint32_t b) {
16519ea8026Sopenharmony_ci    return (int)(unsigned)(a - b);
16619ea8026Sopenharmony_ci}
16719ea8026Sopenharmony_ci
16819ea8026Sopenharmony_ci// Convert between 32-bit little-endian and native order
16919ea8026Sopenharmony_cistatic inline uint32_t lfs_fromle32(uint32_t a) {
17019ea8026Sopenharmony_ci#if (defined(  BYTE_ORDER  ) && defined(  ORDER_LITTLE_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_LITTLE_ENDIAN  ) || \
17119ea8026Sopenharmony_ci    (defined(__BYTE_ORDER  ) && defined(__ORDER_LITTLE_ENDIAN  ) && __BYTE_ORDER   == __ORDER_LITTLE_ENDIAN  ) || \
17219ea8026Sopenharmony_ci    (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
17319ea8026Sopenharmony_ci    return a;
17419ea8026Sopenharmony_ci#elif !defined(LFS_NO_INTRINSICS) && ( \
17519ea8026Sopenharmony_ci    (defined(  BYTE_ORDER  ) && defined(  ORDER_BIG_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_BIG_ENDIAN  ) || \
17619ea8026Sopenharmony_ci    (defined(__BYTE_ORDER  ) && defined(__ORDER_BIG_ENDIAN  ) && __BYTE_ORDER   == __ORDER_BIG_ENDIAN  ) || \
17719ea8026Sopenharmony_ci    (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
17819ea8026Sopenharmony_ci    return __builtin_bswap32(a);
17919ea8026Sopenharmony_ci#else
18019ea8026Sopenharmony_ci    return (((uint8_t*)&a)[0] <<  0) |
18119ea8026Sopenharmony_ci           (((uint8_t*)&a)[1] <<  8) |
18219ea8026Sopenharmony_ci           (((uint8_t*)&a)[2] << 16) |
18319ea8026Sopenharmony_ci           (((uint8_t*)&a)[3] << 24);
18419ea8026Sopenharmony_ci#endif
18519ea8026Sopenharmony_ci}
18619ea8026Sopenharmony_ci
18719ea8026Sopenharmony_cistatic inline uint32_t lfs_tole32(uint32_t a) {
18819ea8026Sopenharmony_ci    return lfs_fromle32(a);
18919ea8026Sopenharmony_ci}
19019ea8026Sopenharmony_ci
19119ea8026Sopenharmony_ci// Convert between 32-bit big-endian and native order
19219ea8026Sopenharmony_cistatic inline uint32_t lfs_frombe32(uint32_t a) {
19319ea8026Sopenharmony_ci#if !defined(LFS_NO_INTRINSICS) && ( \
19419ea8026Sopenharmony_ci    (defined(  BYTE_ORDER  ) && defined(  ORDER_LITTLE_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_LITTLE_ENDIAN  ) || \
19519ea8026Sopenharmony_ci    (defined(__BYTE_ORDER  ) && defined(__ORDER_LITTLE_ENDIAN  ) && __BYTE_ORDER   == __ORDER_LITTLE_ENDIAN  ) || \
19619ea8026Sopenharmony_ci    (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
19719ea8026Sopenharmony_ci    return __builtin_bswap32(a);
19819ea8026Sopenharmony_ci#elif (defined(  BYTE_ORDER  ) && defined(  ORDER_BIG_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_BIG_ENDIAN  ) || \
19919ea8026Sopenharmony_ci    (defined(__BYTE_ORDER  ) && defined(__ORDER_BIG_ENDIAN  ) && __BYTE_ORDER   == __ORDER_BIG_ENDIAN  ) || \
20019ea8026Sopenharmony_ci    (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
20119ea8026Sopenharmony_ci    return a;
20219ea8026Sopenharmony_ci#else
20319ea8026Sopenharmony_ci    return (((uint8_t*)&a)[0] << 24) |
20419ea8026Sopenharmony_ci           (((uint8_t*)&a)[1] << 16) |
20519ea8026Sopenharmony_ci           (((uint8_t*)&a)[2] <<  8) |
20619ea8026Sopenharmony_ci           (((uint8_t*)&a)[3] <<  0);
20719ea8026Sopenharmony_ci#endif
20819ea8026Sopenharmony_ci}
20919ea8026Sopenharmony_ci
21019ea8026Sopenharmony_cistatic inline uint32_t lfs_tobe32(uint32_t a) {
21119ea8026Sopenharmony_ci    return lfs_frombe32(a);
21219ea8026Sopenharmony_ci}
21319ea8026Sopenharmony_ci
21419ea8026Sopenharmony_ci// Calculate CRC-32 with polynomial = 0x04c11db7
21519ea8026Sopenharmony_ciuint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
21619ea8026Sopenharmony_ci
21719ea8026Sopenharmony_ci// Allocate memory, only used if buffers are not provided to littlefs
21819ea8026Sopenharmony_ci// Note, memory must be 64-bit aligned
21919ea8026Sopenharmony_cistatic inline void *lfs_malloc(size_t size) {
22019ea8026Sopenharmony_ci#ifndef LFS_NO_MALLOC
22119ea8026Sopenharmony_ci    return malloc(size);
22219ea8026Sopenharmony_ci#else
22319ea8026Sopenharmony_ci    (void)size;
22419ea8026Sopenharmony_ci    return NULL;
22519ea8026Sopenharmony_ci#endif
22619ea8026Sopenharmony_ci}
22719ea8026Sopenharmony_ci
22819ea8026Sopenharmony_ci// Deallocate memory, only used if buffers are not provided to littlefs
22919ea8026Sopenharmony_cistatic inline void lfs_free(void *p) {
23019ea8026Sopenharmony_ci#ifndef LFS_NO_MALLOC
23119ea8026Sopenharmony_ci    free(p);
23219ea8026Sopenharmony_ci#else
23319ea8026Sopenharmony_ci    (void)p;
23419ea8026Sopenharmony_ci#endif
23519ea8026Sopenharmony_ci}
23619ea8026Sopenharmony_ci
23719ea8026Sopenharmony_ci
23819ea8026Sopenharmony_ci#ifdef __cplusplus
23919ea8026Sopenharmony_ci} /* extern "C" */
24019ea8026Sopenharmony_ci#endif
24119ea8026Sopenharmony_ci
24219ea8026Sopenharmony_ci#endif
24319ea8026Sopenharmony_ci#endif
244