Przeglądaj źródła

【同步】EasyFlash 至上游最新版。

Signed-off-by: armink <armink.ztl@gmail.com>
armink 6 lat temu
rodzic
commit
b96a1bc2ed
3 zmienionych plików z 220 dodań i 111 usunięć
  1. 4 55
      inc/easyflash.h
  2. 124 0
      inc/ef_def.h
  3. 92 56
      src/ef_env.c

+ 4 - 55
inc/easyflash.h

@@ -30,75 +30,24 @@
 #ifndef EASYFLASH_H_
 #define EASYFLASH_H_
 
-#include <ef_cfg.h>
 #include <stdint.h>
 #include <stddef.h>
 #include <stdbool.h>
+#include <ef_cfg.h>
+#include <ef_def.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-
-/* EasyFlash debug print function. Must be implement by user. */
-#ifdef PRINT_DEBUG
-#define EF_DEBUG(...) ef_log_debug(__FILE__, __LINE__, __VA_ARGS__)
-#else
-#define EF_DEBUG(...)
-#endif
-/* EasyFlash routine print function. Must be implement by user. */
-#define EF_INFO(...)  ef_log_info(__VA_ARGS__)
-/* EasyFlash assert for developer. */
-#define EF_ASSERT(EXPR)                                                       \
-if (!(EXPR))                                                                  \
-{                                                                             \
-    EF_DEBUG("(%s) has assert failed at %s.\n", #EXPR, __FUNCTION__);         \
-    while (1);                                                                \
-}
-
-/**
- * ENV version number defined by user.
- * Please change it when your firmware add a new ENV to default_env_set.
- */
-#ifndef EF_ENV_VER_NUM
-#define EF_ENV_VER_NUM                 0
-#endif
-
-/* EasyFlash software version number */
-#define EF_SW_VERSION                  "4.0.99"
-#define EF_SW_VERSION_NUM              0x40099
-
-typedef struct _ef_env {
-    char *key;
-    void *value;
-    size_t value_len;
-} ef_env, *ef_env_t;
-
-/* EasyFlash error code */
-typedef enum {
-    EF_NO_ERR,
-    EF_ERASE_ERR,
-    EF_READ_ERR,
-    EF_WRITE_ERR,
-    EF_ENV_NAME_ERR,
-    EF_ENV_NAME_EXIST,
-    EF_ENV_FULL,
-    EF_ENV_INIT_FAILED,
-} EfErrCode;
-
-/* the flash sector current status */
-typedef enum {
-    EF_SECTOR_EMPTY,
-    EF_SECTOR_USING,
-    EF_SECTOR_FULL,
-} EfSecrorStatus;
-
 /* easyflash.c */
 EfErrCode easyflash_init(void);
 
 #ifdef EF_USING_ENV
 /* only supported on ef_env.c */
 size_t ef_get_env_blob(const char *key, void *value_buf, size_t buf_len, size_t *saved_value_len);
+bool ef_get_env_obj(const char *key, env_node_obj_t env);
+size_t ef_read_env_value(env_node_obj_t env, uint8_t *value_buf, size_t buf_len);
 EfErrCode ef_set_env_blob(const char *key, const void *value_buf, size_t buf_len);
 
 /* ef_env.c, ef_env_legacy_wl.c and ef_env_legacy.c */

+ 124 - 0
inc/ef_def.h

@@ -0,0 +1,124 @@
+/*
+ * This file is part of the EasyFlash Library.
+ *
+ * Copyright (c) 2019, Armink, <armink.ztl@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * 'Software'), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Function: It is the definitions head file for this library.
+ * Created on: 2019-11-20
+ */
+
+#ifndef EF_DEF_H_
+#define EF_DEF_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* EasyFlash software version number */
+#define EF_SW_VERSION                  "4.0.99"
+#define EF_SW_VERSION_NUM              0x40099
+
+/*
+ * ENV version number defined by user.
+ * Please change it when your firmware add a new ENV to default_env_set.
+ */
+#ifndef EF_ENV_VER_NUM
+#define EF_ENV_VER_NUM                 0
+#endif
+
+/* the ENV max name length must less then it */
+#ifndef EF_ENV_NAME_MAX
+#define EF_ENV_NAME_MAX                          32
+#endif
+
+/* EasyFlash debug print function. Must be implement by user. */
+#ifdef PRINT_DEBUG
+#define EF_DEBUG(...) ef_log_debug(__FILE__, __LINE__, __VA_ARGS__)
+#else
+#define EF_DEBUG(...)
+#endif
+/* EasyFlash routine print function. Must be implement by user. */
+#define EF_INFO(...)  ef_log_info(__VA_ARGS__)
+/* EasyFlash assert for developer. */
+#define EF_ASSERT(EXPR)                                                       \
+if (!(EXPR))                                                                  \
+{                                                                             \
+    EF_DEBUG("(%s) has assert failed at %s.\n", #EXPR, __FUNCTION__);         \
+    while (1);                                                                \
+}
+
+typedef struct _ef_env {
+    char *key;
+    void *value;
+    size_t value_len;
+} ef_env, *ef_env_t;
+
+/* EasyFlash error code */
+typedef enum {
+    EF_NO_ERR,
+    EF_ERASE_ERR,
+    EF_READ_ERR,
+    EF_WRITE_ERR,
+    EF_ENV_NAME_ERR,
+    EF_ENV_NAME_EXIST,
+    EF_ENV_FULL,
+    EF_ENV_INIT_FAILED,
+} EfErrCode;
+
+/* the flash sector current status */
+typedef enum {
+    EF_SECTOR_EMPTY,
+    EF_SECTOR_USING,
+    EF_SECTOR_FULL,
+} EfSecrorStatus;
+
+enum env_status {
+    ENV_UNUSED,
+    ENV_PRE_WRITE,
+    ENV_WRITE,
+    ENV_PRE_DELETE,
+    ENV_DELETED,
+    ENV_ERR_HDR,
+    ENV_STATUS_NUM,
+};
+typedef enum env_status env_status_t;
+
+struct env_node_obj {
+    env_status_t status;                         /**< ENV node status, @see node_status_t */
+    bool crc_is_ok;                              /**< ENV node CRC32 check is OK */
+    uint8_t name_len;                            /**< name length */
+    uint32_t magic;                              /**< magic word(`K`, `V`, `4`, `0`) */
+    uint32_t len;                                /**< ENV node total length (header + name + value), must align by EF_WRITE_GRAN */
+    uint32_t value_len;                          /**< value length */
+    char name[EF_ENV_NAME_MAX];                  /**< name */
+    struct {
+        uint32_t start;                          /**< ENV node start address */
+        uint32_t value;                          /**< value start address */
+    } addr;
+};
+typedef struct env_node_obj *env_node_obj_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EF_DEF_H_ */

+ 92 - 56
src/ef_env.c

@@ -39,11 +39,6 @@
 #error "the write gran can be only setting as 1, 8, 32 and 64"
 #endif
 
-/* the ENV max name length must less then it */
-#ifndef EF_ENV_NAME_MAX
-#define EF_ENV_NAME_MAX                          32
-#endif
-
 /* magic word(`E`, `F`, `4`, `0`) */
 #define SECTOR_MAGIC_WORD                        0x30344645
 /* magic word(`K`, `V`, `4`, `0`) */
@@ -154,17 +149,6 @@ enum sector_dirty_status {
 };
 typedef enum sector_dirty_status sector_dirty_status_t;
 
-enum env_status {
-    ENV_UNUSED,
-    ENV_PRE_WRITE,
-    ENV_WRITE,
-    ENV_PRE_DELETE,
-    ENV_DELETED,
-    ENV_ERR_HDR,
-    ENV_STATUS_NUM,
-};
-typedef enum env_status env_status_t;
-
 struct sector_hdr_data {
     struct {
         uint8_t store[STORE_STATUS_TABLE_SIZE];  /**< sector store status @see sector_store_status_t */
@@ -200,21 +184,6 @@ struct env_hdr_data {
 };
 typedef struct env_hdr_data *env_hdr_data_t;
 
-struct env_meta_data {
-    env_status_t status;                         /**< ENV node status, @see node_status_t */
-    bool crc_is_ok;                              /**< ENV node CRC32 check is OK */
-    uint8_t name_len;                            /**< name length */
-    uint32_t magic;                              /**< magic word(`K`, `V`, `4`, `0`) */
-    uint32_t len;                                /**< ENV node total length (header + name + value), must align by EF_WRITE_GRAN */
-    uint32_t value_len;                          /**< value length */
-    char name[EF_ENV_NAME_MAX];                  /**< name */
-    struct {
-        uint32_t start;                          /**< ENV node start address */
-        uint32_t value;                          /**< value start address */
-    } addr;
-};
-typedef struct env_meta_data *env_meta_data_t;
-
 struct env_cache_node {
     uint16_t name_crc;                           /**< ENV name's CRC32 low 16bit value */
     uint16_t active;                             /**< ENV node access active degree */
@@ -502,7 +471,7 @@ static uint32_t find_next_env_addr(uint32_t start, uint32_t end)
         for (i = 0; i < sizeof(buf) - sizeof(uint32_t) && start + i < end; i++) {
 #ifndef EF_BIG_ENDIAN            /* Little Endian Order */
             magic = buf[i] + (buf[i + 1] << 8) + (buf[i + 2] << 16) + (buf[i + 3] << 24);
-#else                       // Big Endian Order
+#else                       /* Big Endian Order */
             magic = buf[i + 3] + (buf[i + 2] << 8) + (buf[i + 1] << 16) + (buf[i] << 24);
 #endif
             if (magic == ENV_MAGIC_WORD && (start + i - ENV_MAGIC_OFFSET) >= start_bak) {
@@ -514,7 +483,7 @@ static uint32_t find_next_env_addr(uint32_t start, uint32_t end)
     return FAILED_ADDR;
 }
 
-static uint32_t get_next_env_addr(sector_meta_data_t sector, env_meta_data_t pre_env)
+static uint32_t get_next_env_addr(sector_meta_data_t sector, env_node_obj_t pre_env)
 {
     uint32_t addr = FAILED_ADDR;
 
@@ -538,7 +507,7 @@ static uint32_t get_next_env_addr(sector_meta_data_t sector, env_meta_data_t pre
             addr = find_next_env_addr(addr, sector->addr + SECTOR_SIZE - SECTOR_HDR_DATA_SIZE);
 
             if (addr > sector->addr + SECTOR_SIZE || pre_env->len == 0) {
-                //TODO 鎵囧尯杩炵画妯″紡
+                //TODO 扇区连续模式
                 return FAILED_ADDR;
             }
         } else {
@@ -550,7 +519,7 @@ static uint32_t get_next_env_addr(sector_meta_data_t sector, env_meta_data_t pre
     return addr;
 }
 
-static EfErrCode read_env(env_meta_data_t env)
+static EfErrCode read_env(env_node_obj_t env)
 {
     struct env_hdr_data env_hdr;
     uint8_t buf[32];
@@ -573,7 +542,7 @@ static EfErrCode read_env(env_meta_data_t env)
         env->crc_is_ok = false;
         return EF_READ_ERR;
     } else if (env->len > SECTOR_SIZE - SECTOR_HDR_DATA_SIZE && env->len < ENV_AREA_SIZE) {
-        //TODO 鎵囧尯杩炵画妯″紡锛屾垨鑰呭啓鍏ラ暱搴︽病鏈夊啓鍏ュ畬鏁�
+        //TODO 扇区连续模式,或者写入长度没有写入完整
         EF_ASSERT(0);
     }
 
@@ -639,7 +608,7 @@ static EfErrCode read_sector_meta_data(uint32_t addr, sector_meta_data_t sector,
         if (sector->status.store == SECTOR_STORE_EMPTY) {
             sector->remain = SECTOR_SIZE - SECTOR_HDR_DATA_SIZE;
         } else if (sector->status.store == SECTOR_STORE_USING) {
-            struct env_meta_data env_meta;
+            struct env_node_obj env_meta;
 
 #ifdef EF_ENV_USING_CACHE
             if (get_sector_from_cache(addr, &sector->empty_env)) {
@@ -708,8 +677,8 @@ static uint32_t get_next_sector_addr(sector_meta_data_t pre_sec)
     }
 }
 
-static void env_iterator(env_meta_data_t env, void *arg1, void *arg2,
-        bool (*callback)(env_meta_data_t env, void *arg1, void *arg2))
+static void env_iterator(env_node_obj_t env, void *arg1, void *arg2,
+        bool (*callback)(env_node_obj_t env, void *arg1, void *arg2))
 {
     struct sector_meta_data sector;
     uint32_t sec_addr;
@@ -738,7 +707,7 @@ static void env_iterator(env_meta_data_t env, void *arg1, void *arg2,
     }
 }
 
-static bool find_env_cb(env_meta_data_t env, void *arg1, void *arg2)
+static bool find_env_cb(env_node_obj_t env, void *arg1, void *arg2)
 {
     const char *key = arg1;
     bool *find_ok = arg2;
@@ -755,7 +724,7 @@ static bool find_env_cb(env_meta_data_t env, void *arg1, void *arg2)
     return false;
 }
 
-static bool find_env_no_cache(const char *key, env_meta_data_t env)
+static bool find_env_no_cache(const char *key, env_node_obj_t env)
 {
     bool find_ok = false;
 
@@ -764,7 +733,7 @@ static bool find_env_no_cache(const char *key, env_meta_data_t env)
     return find_ok;
 }
 
-static bool find_env(const char *key, env_meta_data_t env)
+static bool find_env(const char *key, env_node_obj_t env)
 {
     bool find_ok = false;
 
@@ -803,7 +772,7 @@ static bool ef_is_str(uint8_t *value, size_t len)
 
 static size_t get_env(const char *key, void *value_buf, size_t buf_len, size_t *value_len)
 {
-    struct env_meta_data env;
+    struct env_node_obj env;
     size_t read_len = 0;
 
     if (find_env(key, &env)) {
@@ -823,6 +792,34 @@ static size_t get_env(const char *key, void *value_buf, size_t buf_len, size_t *
     return read_len;
 }
 
+/**
+ * Get a ENV object by key name
+ *
+ * @param key ENV name
+ * @param env ENV object
+ *
+ * @return TRUE: find the ENV is OK, else return false
+ */
+bool ef_get_env_obj(const char *key, env_node_obj_t env)
+{
+    bool find_ok = false;
+
+    if (!init_ok) {
+        EF_INFO("ENV isn't initialize OK.\n");
+        return 0;
+    }
+
+    /* lock the ENV cache */
+    ef_port_env_lock();
+
+    find_ok = find_env(key, env);
+
+    /* unlock the ENV cache */
+    ef_port_env_unlock();
+
+    return find_ok;
+}
+
 /**
  * Get a blob ENV value by key name.
  *
@@ -882,6 +879,45 @@ char *ef_get_env(const char *key)
     return NULL;
 }
 
+/**
+ * read the ENV value by ENV object
+ *
+ * @param env ENV object
+ * @param value_buf the buffer for store ENV value
+ * @param buf_len buffer length
+ *
+ * @return the actually read size on successful
+ */
+size_t ef_read_env_value(env_node_obj_t env, uint8_t *value_buf, size_t buf_len)
+{
+    size_t read_len = 0;
+
+    EF_ASSERT(env);
+    EF_ASSERT(value_buf);
+
+    if (!init_ok) {
+        EF_INFO("ENV isn't initialize OK.\n");
+        return 0;
+    }
+
+    if (env->crc_is_ok) {
+        /* lock the ENV cache */
+        ef_port_env_lock();
+
+        if (buf_len > env->value_len) {
+            read_len = env->value_len;
+        } else {
+            read_len = buf_len;
+        }
+
+        ef_port_read(env->addr.value, (uint32_t *) value_buf, read_len);
+        /* unlock the ENV cache */
+        ef_port_env_unlock();
+    }
+
+    return read_len;
+}
+
 static EfErrCode write_env_hdr(uint32_t addr, env_hdr_data_t env_hdr) {
     EfErrCode result = EF_NO_ERR;
     /* write the status will by write granularity */
@@ -1028,7 +1064,7 @@ static uint32_t alloc_env(sector_meta_data_t sector, size_t env_size)
     return empty_env;
 }
 
-static EfErrCode del_env(const char *key, env_meta_data_t old_env, bool complete_del) {
+static EfErrCode del_env(const char *key, env_node_obj_t old_env, bool complete_del) {
     EfErrCode result = EF_NO_ERR;
     uint32_t dirty_status_addr;
     static bool last_is_complete_del = false;
@@ -1041,7 +1077,7 @@ static EfErrCode del_env(const char *key, env_meta_data_t old_env, bool complete
 
     /* need find ENV */
     if (!old_env) {
-        struct env_meta_data env;
+        struct env_node_obj env;
         /* find ENV */
         if (find_env(key, &env)) {
             old_env = &env;
@@ -1080,7 +1116,7 @@ static EfErrCode del_env(const char *key, env_meta_data_t old_env, bool complete
 /*
  * move the ENV to new space
  */
-static EfErrCode move_env(env_meta_data_t env)
+static EfErrCode move_env(env_node_obj_t env)
 {
     EfErrCode result = EF_NO_ERR;
     uint8_t status_table[ENV_STATUS_TABLE_SIZE];
@@ -1094,7 +1130,7 @@ static EfErrCode move_env(env_meta_data_t env)
 
     if ((env_addr = alloc_env(&sector, env->len)) != FAILED_ADDR) {
         if (in_recovery_check) {
-            struct env_meta_data env_bak;
+            struct env_node_obj env_bak;
             char name[EF_ENV_NAME_MAX + 1] = { 0 };
             strncpy(name, env->name, env->name_len);
             /* check the ENV in flash is already create success */
@@ -1181,7 +1217,7 @@ static bool gc_check_cb(sector_meta_data_t sector, void *arg1, void *arg2)
 
 static bool do_gc(sector_meta_data_t sector, void *arg1, void *arg2)
 {
-    struct env_meta_data env;
+    struct env_node_obj env;
 
     if (sector->check_ok && (sector->status.dirty == SECTOR_DIRTY_TRUE || sector->status.dirty == SECTOR_DIRTY_GC)) {
         uint8_t status_table[DIRTY_STATUS_TABLE_SIZE];
@@ -1378,7 +1414,7 @@ EfErrCode ef_del_and_save_env(const char *key)
 static EfErrCode set_env(const char *key, const void *value_buf, size_t buf_len)
 {
     EfErrCode result = EF_NO_ERR;
-    static struct env_meta_data env;
+    static struct env_node_obj env;
     static struct sector_meta_data sector;
     bool env_is_found = false;
 
@@ -1529,7 +1565,7 @@ __exit:
     return result;
 }
 
-static bool print_env_cb(env_meta_data_t env, void *arg1, void *arg2)
+static bool print_env_cb(env_node_obj_t env, void *arg1, void *arg2)
 {
     bool value_is_str = true, print_value = false;
     size_t *using_size = arg1;
@@ -1582,7 +1618,7 @@ __reload:
  */
 void ef_print_env(void)
 {
-    struct env_meta_data env;
+    struct env_node_obj env;
     size_t using_size = 0;
 
     if (!init_ok) {
@@ -1614,7 +1650,7 @@ static void env_auto_update(void)
     if (get_env(VER_NUM_ENV_NAME, &saved_ver_num, sizeof(size_t), NULL) > 0) {
         /* check version number */
         if (saved_ver_num != setting_ver_num) {
-            struct env_meta_data env;
+            struct env_node_obj env;
             size_t i, value_len;
             struct sector_meta_data sector;
             EF_DEBUG("Update the ENV from version %d to %d.\n", saved_ver_num, setting_ver_num);
@@ -1667,7 +1703,7 @@ static bool check_and_recovery_gc_cb(sector_meta_data_t sector, void *arg1, void
     return false;
 }
 
-static bool check_and_recovery_env_cb(env_meta_data_t env, void *arg1, void *arg2)
+static bool check_and_recovery_env_cb(env_node_obj_t env, void *arg1, void *arg2)
 {
     /* recovery the prepare deleted ENV */
     if (env->crc_is_ok && env->status == ENV_PRE_DELETE) {
@@ -1682,7 +1718,7 @@ static bool check_and_recovery_env_cb(env_meta_data_t env, void *arg1, void *arg
     } else if (env->status == ENV_PRE_WRITE) {
         uint8_t status_table[ENV_STATUS_TABLE_SIZE];
         /* the ENV has not write finish, change the status to error */
-        //TODO 缁樺埗寮傚父澶勭悊鐨勭姸鎬佽�鎹㈠浘
+        //TODO 绘制异常处理的状态装换图
         write_status(env->addr.start, status_table, ENV_STATUS_NUM, ENV_ERR_HDR);
         return true;
     }
@@ -1698,7 +1734,7 @@ static bool check_and_recovery_env_cb(env_meta_data_t env, void *arg1, void *arg
 EfErrCode ef_load_env(void)
 {
     EfErrCode result = EF_NO_ERR;
-    struct env_meta_data env;
+    struct env_node_obj env;
     struct sector_meta_data sector;
     size_t check_failed_count = 0;
 
@@ -1710,7 +1746,7 @@ EfErrCode ef_load_env(void)
         EF_INFO("Warning: All sector header check failed. Set it to default.\n");
         ef_env_set_default();
     }
-    
+
     /* lock the ENV cache */
     ef_port_env_lock();
     /* check all sector header for recovery GC */