Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers configuration_store.c Source File

configuration_store.c

Go to the documentation of this file.
00001 /** @file configuration_store.c
00002  *
00003  * mbed Microcontroller Library
00004  * Copyright (c) 2006-2016 ARM Limited
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *     http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 
00019 // This file is deprecated so deprecation warnings when building it are silenced
00020 #if   defined ( __CC_ARM )
00021 #pragma diag_suppress 1361  // Deprecated declaration
00022 #elif defined ( __GNUC__ )
00023 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
00024 #endif
00025 
00026 #include "cfstore_config.h"
00027 #include "cfstore_debug.h"
00028 #include "cfstore_list.h"
00029 #include "cfstore_fnmatch.h"
00030 #include "configuration_store.h"
00031 
00032 #if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
00033 #include <core-util/critical.h>
00034 #endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
00035 
00036 #ifdef YOTTA_CFG_CFSTORE_UVISOR
00037 #include "uvisor-lib/uvisor-lib.h"
00038 #endif /* YOTTA_CFG_CFSTORE_UVISOR */
00039 
00040 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
00041 #include "cfstore_svm.h"
00042 #include "flash_journal_strategy_sequential.h"
00043 #include "flash_journal.h"
00044 #include "Driver_Common.h"
00045 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
00046 
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050 #include <assert.h>
00051 #include <inttypes.h>
00052 
00053 
00054 #ifdef CFSTORE_DEBUG
00055 uint32_t cfstore_optDebug_g = 1;
00056 uint32_t cfstore_optLogLevel_g = CFSTORE_LOG_NONE; /*CFSTORE_LOG_NONE|CFSTORE_LOG_ERR|CFSTORE_LOG_DEBUG|CFSTORE_LOG_FENTRY */
00057 uint32_t cfstore_optLogTracepoint_g = CFSTORE_TP_NONE; /*CFSTORE_TP_NONE|CFSTORE_TP_CLOSE|CFSTORE_TP_CREATE|CFSTORE_TP_DELETE|CFSTORE_TP_FILE|CFSTORE_TP_FIND|CFSTORE_TP_FLUSH|CFSTORE_TP_INIT|CFSTORE_TP_OPEN|CFSTORE_TP_READ|CFSTORE_TP_WRITE|CFSTORE_TP_VERBOSE1|CFSTORE_TP_VERBOSE2|CFSTORE_TP_VERBOSE3|CFSTORE_TP_FENTRY; */
00058 #endif
00059 
00060 
00061 /*
00062  * Externs
00063  */
00064 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
00065 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_MTD_K64F;
00066 ARM_DRIVER_STORAGE *cfstore_storage_drv = &ARM_Driver_Storage_MTD_K64F;
00067 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
00068 
00069 struct _ARM_DRIVER_STORAGE cfstore_journal_mtd;
00070 
00071 /*
00072  * Defines
00073  *
00074  * CFSTORE_FLASH_STACK_BUF_SIZE
00075  *  when performing flush, if the program_unit <= CFSTORE_FLASH_STACK_BUF_SIZE octets then a
00076  *  stack buffer is used to perform the tail write. Otherwise a buffer is malloced
00077  *
00078  * CFSTORE_FLASH_AREA_SIZE_MIN
00079  *  valid sizes of areas should always be greater than the size of the header, and therefore
00080  *  greater than this value, which is defined as smaller than the header size
00081  *
00082  * CFSTORE_FLASH_NUMSLOTS
00083  *  number of flash journal slots
00084  *
00085  * ARM_DRIVER_OK_DONE
00086  *   value that indicates an operation has been done i.e. a value > 0
00087  */
00088 #define CFSTORE_KEY_NAME_CHARS_ACCEPTABLE           "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{}.-_@"
00089 #define CFSTORE_KEY_NAME_QUERY_CHARS_ACCEPTABLE     CFSTORE_KEY_NAME_CHARS_ACCEPTABLE"*"
00090 #define CFSTORE_HKVT_REFCOUNT_MAX                   0xff
00091 #define CFSTORE_LOCK_REFCOUNT_MAX                   0xffff
00092 #define CFSTORE_FILE_CREATE_MODE_DEFAULT            (ARM_CFSTORE_FMODE)0
00093 #define CFSTORE_FLASH_STACK_BUF_SIZE                64
00094 #define CFSTORE_FLASH_AREA_SIZE_MIN                 (sizeof(cfstore_area_header_t) - 1)
00095 #define CFSTORE_FLASH_NUMSLOTS                      4
00096 #define cfstore_fsm_null                            NULL
00097 #define CFSTORE_SENTINEL                            0x7fffffff
00098 #define CFSTORE_CALLBACK_RET_CODE_DEFAULT           0x1
00099 #define ARM_DRIVER_OK_DONE                          1
00100 
00101 /*
00102  * Simple Types
00103  */
00104 #define CFSTORE_LOCK uint32_t
00105 
00106 
00107 /*
00108  * Structures
00109  */
00110 
00111 /** @brief
00112  *
00113  * @param   key_permissions
00114  *          bottom 6 bits contain the ACLs-bits (owner read/write/execute,
00115  *           other read/write/execute). The remaining bits in this field are
00116  *          used for the Device Data Security Protection Features bit field,
00117  *          bits are low-active
00118  * @param   perm_owner_read
00119  *          if set => this KV is owner readable
00120  * @param   perm_owner_write
00121  *          if set => this KV is owner writable
00122  * @param   perm_owner_execute
00123  *          if set => this KV is owner executable
00124  * @param   perm_other_read
00125  *          if set => this KV is world readable
00126  * @param   perm_other_write
00127  *          if set => this KV is world writable
00128  * @param   perm_other_execute
00129  *          if set => this KV is world executable
00130  * @param   klength
00131  *          key name size including zero-padding
00132  * @param   vlength
00133  *          this value fragment length
00134  * @param   refcount
00135  *          Number of handles open on this hkvt
00136  *
00137  * @param   delete
00138  *          indicates this KV is being deleted
00139  */
00140 typedef struct cfstore_area_header_t 
00141 {
00142     uint32_t vlength;
00143     uint8_t klength;
00144     uint8_t perm_owner_read : 1;
00145     uint8_t perm_owner_write : 1;
00146     uint8_t perm_owner_execute : 1;
00147     uint8_t perm_other_read : 1;
00148     uint8_t perm_other_write : 1;
00149     uint8_t perm_other_execute : 1;
00150     uint8_t reserved : 2;
00151     uint8_t refcount;
00152     struct flags_t {
00153         uint8_t delete : 1;
00154         uint8_t reserved : 7;
00155     } flags ;
00156 } cfstore_area_header_t ;
00157 
00158 
00159 /* helper struct */
00160 typedef struct cfstore_area_hkvt_t
00161 {
00162     uint8_t *head;
00163     uint8_t *key;
00164     uint8_t *value;
00165     uint8_t *tail;
00166 } cfstore_area_hkvt_t;
00167 
00168 
00169 /* helper struct */
00170 typedef struct cfstore_client_notify_data_t
00171 {
00172     uint32_t opcode;
00173     int32_t status;
00174     ARM_CFSTORE_HANDLE  handle;
00175 } cfstore_client_notify_data_t;
00176 
00177 /* @brief  test fsm states and events */
00178 typedef enum cfstore_fsm_state_t {
00179     cfstore_fsm_state_stopped = 0,
00180     cfstore_fsm_state_initing,
00181     cfstore_fsm_state_reading,
00182     cfstore_fsm_state_logging,
00183     cfstore_fsm_state_committing,
00184     cfstore_fsm_state_resetting,
00185     cfstore_fsm_state_ready,        /* ready for next flash journal command to arise */
00186     cfstore_fsm_state_formatting,   /* flash formatting in progress */
00187     cfstore_fsm_state_max
00188 } cfstore_fsm_state_t;
00189 
00190 /* @brief  test fsm events */
00191 typedef enum cfstore_fsm_event_t {
00192     cfstore_fsm_event_init_done = 0,
00193     cfstore_fsm_event_read_done,
00194     cfstore_fsm_event_log_done,
00195     cfstore_fsm_event_commit_req,
00196     cfstore_fsm_event_commit_done,
00197     cfstore_fsm_event_reset_done,
00198     cfstore_fsm_event_format_done,
00199     cfstore_fsm_event_max,
00200 } cfstore_fsm_event_t;
00201 
00202 typedef int32_t (*cfstore_fsm_handler)(void* ctx);
00203 
00204 /* @brief   flash finite state machine helper function */
00205 typedef struct cfstore_fsm_t
00206 {
00207     cfstore_fsm_state_t state;
00208     cfstore_fsm_event_t event;
00209 } cfstore_fsm_t;
00210 
00211 
00212 #ifdef CFSTORE_DEBUG
00213 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
00214 /* strings used for debug trace */
00215 static const char* cfstore_flash_opcode_str[] =
00216 {
00217     "FLASH_JOURNAL_OPCODE_FORMAT",
00218     "FLASH_JOURNAL_OPCODE_INITIALIZE",
00219     "FLASH_JOURNAL_OPCODE_GET_INFO",
00220     "FLASH_JOURNAL_OPCODE_READ_BLOB",
00221     "FLASH_JOURNAL_OPCODE_LOG_BLOB",
00222     "FLASH_JOURNAL_OPCODE_COMMIT",
00223     "FLASH_JOURNAL_OPCODE_RESET",
00224 };
00225 
00226 static const char* cfstore_flash_state_str[] =
00227 {
00228     "stopped",
00229     "initializing",
00230     "reading",
00231     "logging",
00232     "committing",
00233     "resetting",
00234     "ready",
00235     "formatting",
00236     "unknown"
00237 };
00238 
00239 static const char* cfstore_flash_event_str[] =
00240 {
00241     "init_done",
00242     "read_done",
00243     "log_done",
00244     "commit_req",
00245     "commit_done",
00246     "reset_done",
00247     "format_done",
00248     "unknown"
00249 };
00250 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
00251 #endif /* CFSTORE_DEBUG */
00252 
00253 
00254 /*
00255  * Forward decl
00256  */
00257 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
00258 static int32_t cfstore_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_fsm_event_t event, void* context);
00259 static int32_t cfstore_fsm_state_set(cfstore_fsm_t* fsm, cfstore_fsm_state_t new_state, void* ctx);
00260 #endif  /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
00261 static int32_t cfstore_get_key_name_ex(cfstore_area_hkvt_t *hkvt, char* key_name, uint8_t *key_name_len);
00262 
00263 
00264 /* Walking Area HKVT's While Inserting   a New HKVT:
00265  * Implementation Note 1 [NOTE1]
00266  *
00267  * The implementation must address the following problem:
00268  * - client1 may be creating a new KV into area_0, which means inserting the
00269  *   header-key-value-tail data into area_0.
00270  * - concurrently, client2 (through a call to Find()) is walking KVs in area_0,
00271  *   and the walk has to be safe against the insertion of the new KV.
00272  *
00273  * This problem is addressed in the by using the cfstore_ctx_g.rw_lock to police
00274  * access to the area when making changes.
00275  * - Walking the KVs in area_0 is performed using the header structures,
00276  *   which contain key and value lengths required to find the start of the
00277  *   next hkvt. These must not change under the client.
00278  * - The Find() walk is terminated when the hkvt header pointer is found to
00279  *   point to cfstore_ctx_g.area_0_tail i.e. when this arises then the
00280  *   iterator knows its come to the end of the hkvt's in the area.
00281  *
00282  * Memory Management (todo: future support)
00283  * Implementation Note 2 [NOTE2]
00284  * CFSTORE supports using a client provisioned SRAM slab rather than using realloc() to allocated heap
00285  * memory. This has the following advantages:
00286  * - the client is in control of the memory allocation.
00287  * - realloc() cannot fail (e.g. due to memory leaks losing memory) as the sram has been preprovisioned.
00288  *   This makes the system more resilient.
00289  * The client specifes the sram slab in the following way:
00290  * - having target.json defined yotta_config.h symbol for CFSTORE_SRAM_START_ADDR, CFSTORE_SRAM_SIZE
00291  *   and #ifdef on these values to use that memory area for area_0 rather than using malloc.
00292  * - for the case where a client tries to create a KV which causes area_0 to exceed CFSTORE_SRAM_SIZE
00293  *   then the operation is failed.
00294  * - modify the API so that the client is responsible for allocating the memory the the CFSTORE internal
00295  *   data structures, with the size of the internal data structure exposed through a #define.
00296  *   The contents of the buffer are opaque to the client. The reasons for this are as follows:
00297  *   - to allow the cfstore implementation not to use malloc().
00298  *   - the memory allocation policy for allocating the memory of CFSTORE internal data structures
00299  *     can be decided and implemented by the client
00300  *   - for clients written in C++, its possible to have a static class with the memory for the
00301  *     internal context, and the static class memory area is given to CFSTORE for use, so it
00302  *     provides good C++ support.
00303  *   - The SRAM area can be allocated with the previous point, and the handle associated data
00304  *     structures i.e. cfstore_file_t, can be covered by the supplied buffers to those functions
00305  *     creating handles.
00306  * - currently neither target.json nor config.json allow a symbol in yotta_config.h to be defined
00307  *   for the current case of CFSTORE being a yotta module/library.
00308  *
00309  * UVISOR Integration (todo)
00310  * Implementation Note 3 [NOTE3]
00311  * Outstanding Questions:
00312  * - uvisor_ctx. Should all functions use this to access the global data context?
00313  *   - see cfstore_ctx_get() for an implementation
00314  *   - compile in cfstore_ctx_g only when not using uvisor
00315  * - how do you allocate heap memory objects with uvisor protections?
00316  *   - doesnt seem to be an api for this yet.
00317  *   - will be required for sram storage of KVs i.e. "the area".
00318  *   - will be required for file objects
00319  * - Q: is it safe to store the caller_box_id in the cfstore_file_t?
00320  *   A: no, because the cfstore_file_t is held in client controlled memory (opaque hkey)
00321  *      so the client can modify from under cfstore, breaching security if it was used
00322  *      by other cfstore methods.
00323  * - method for securing access:
00324  *   - create()/open() checks namespace etc, and then creates/opens cfstore_file_t
00325  *     and returns hkey (opaque cfstore_file_t) for subsequent use by api calls.
00326  *   - read/write/rseek etc check the kv pathname accessible via cfstore_file_t::head
00327  *     is within the callers namespace.
00328  *   - we are trusting the caller to be secure and not be malicious?
00329  *  - put "uvisor-lib" : "^2.0.0" in module.json. not necessary as mbed-drivers has this dep.
00330  *  - flash-journal change from using NVIC_Set/GetVector() to VIRQ_Set/GetVector()
00331  *
00332  */
00333 
00334 /*
00335  * @brief   CS global context that maintains state
00336  *
00337  * @param   area_0_start
00338  *          pointer to start of malloc-ed memory block for containing area_0
00339  *
00340  * @param   area_0_head
00341  *          pointer to area_0 header struct within the memblock.
00342  *          - ((cfstore_area_header_t*) area_0)->refcount is the number of
00343  *            open handles in the whole of area_0.
00344  *          - accessed in app & intr context; hence needs CS protection.
00345  *
00346  * @param   area_0_tail
00347  *          pointer to address in the sram after the last byte of the last
00348  *          KV. Note there can be padding after the area_0_tail to align the
00349  *          sram area with flash program_unit (or 1 if SRAM only version)
00350  *          to facilitate reading/writing to flash.
00351  *          - accessed in app & intr context; hence needs CS protection.
00352  *
00353  * @param   area_0_len
00354  *          length of the area used for storing KVs, including padding to
00355  *          round to nearest program unit
00356  *
00357  * @param   rw_area0_lock
00358  *          lock used to make CS re-entrant e.g. only 1 flush operation can be
00359  *          performed at a time while no readers/writers have handles open
00360  *          to KVs. The lock is to protect access to the following:
00361  *          - cfstore_ctx_g.area_0_head/cfstore_ctx_g.area_0_tail. Realloc()
00362  *            in Delete() and Create() can cause these pointers to change.
00363  *
00364  * @param   client_notify_data
00365  *          fsm handler functions set a flag for a client notification call
00366  *          to be made after fsm handler functions have been completed. This
00367  *          block holds the client notification status data for the callback.
00368  *
00369  * @param   area_dirty_flag
00370  *          flag indicating that the area has been written and therefore is
00371  *          dirty with respect to the data persisted to flash.
00372  *
00373  * @expected_blob_size  expected_blob_size = area_0_tail - area_0_head + pad
00374  *          In the case of reading from flash into sram, this will be be size
00375  *          of the flash blob (rounded to a multiple program_unit if not
00376  *          already so).
00377  *          In the case of writing to flash, this the size of all the KV's
00378  *          plus padding so the sram blob size is a multiple of flash
00379  *          program_unit.
00380  *          - accessed in app & intr context; hence needs CS protection.
00381  */
00382 typedef struct cfstore_ctx_t
00383 {
00384     cfstore_list_node_t file_list;
00385     int32_t init_ref_count;
00386     CFSTORE_LOCK rw_area0_lock;
00387     ARM_POWER_STATE power_state;
00388     uint8_t *area_0_head;
00389     uint8_t *area_0_tail;
00390     size_t area_0_len;
00391     cfstore_fsm_t fsm;
00392     int32_t status;
00393 
00394     /* client notification data */
00395     void* client_context;
00396     ARM_CFSTORE_CALLBACK client_callback;
00397     cfstore_client_notify_data_t client_notify_data;
00398 
00399     /* flags */
00400     uint32_t client_callback_notify_flag : 1;
00401     uint32_t area_dirty_flag : 1;
00402     uint32_t f_reserved0 : 30;
00403 
00404 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
00405     /* flash journal related data */
00406     FlashJournal_t jrnl;
00407     FlashJournal_Info_t info;
00408     FlashJournal_OpCode_t cmd_code;
00409     uint64_t expected_blob_size;
00410 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
00411 } cfstore_ctx_t;
00412 
00413 
00414 /*
00415  * @brief   file structure for KV, one per open file handle.
00416  *
00417  * @param   head
00418  *          pointer to head of KV
00419  *
00420  * @param   rlocation
00421  *          read location of rseek to move
00422  *
00423  * @param   read
00424  *          indicates file is readable,
00425  * @param   writable
00426  *          indicates file is readable,
00427  * @param   executable
00428  *          indicates file is readable,
00429  * @param   uvisor_client_box_id
00430  *          box id of caller using this file. set on create/open and thereafter used by other methods to check accesses.
00431  *          Q: is it safe to store this here? Is it of any value? i.e. a client can change the value
00432  *          after cfstore has set it so cfstore cant rely on it being secure.
00433  */
00434 typedef struct cfstore_file_t
00435 {
00436     cfstore_list_node_t node;
00437     uint32_t rlocation;
00438     uint32_t wlocation;
00439     uint8_t *head;
00440     ARM_CFSTORE_FMODE flags;
00441 #ifdef YOTTA_CFG_CFSTORE_UVISOR
00442     // todo: add this into mix.
00443     //int uvisor_client_box_id;
00444 #endif
00445 
00446 } cfstore_file_t;
00447 
00448 /* @brief   structure used to compose table for mapping flash journal error codes to cfstore error codes */
00449 typedef struct cfstore_flash_journal_error_code_node
00450 {
00451     int32_t flash_journal_error_code;
00452     int32_t cfstore_error_code;
00453 } cfstore_flash_journal_error_code_node;
00454 
00455 
00456 /*
00457  * Globals
00458  */
00459 #ifndef CFSTORE_STORAGE_DRIVER_CONFIG_HARDWARE_MTD_ASYNC_OPS
00460 static ARM_CFSTORE_CAPABILITIES cfstore_caps_g = { .asynchronous_ops = 1, .uvisor_support_enabled = 0 };
00461 #else
00462 static ARM_CFSTORE_CAPABILITIES cfstore_caps_g = { .asynchronous_ops = CFSTORE_STORAGE_DRIVER_CONFIG_HARDWARE_MTD_ASYNC_OPS, .uvisor_support_enabled = 0 };
00463 #endif /* CFSTORE_STORAGE_DRIVER_CONFIG_HARDWARE_MTD_ASYNC_OPS */
00464 
00465 static const ARM_DRIVER_VERSION cfstore_driver_version_g = { .api = ARM_CFSTORE_API_VERSION, .drv = ARM_CFSTORE_DRV_VERSION };
00466 
00467 #ifndef YOTTA_CFG_CFSTORE_UVISOR
00468 /* uvisor is not being used so instantiate a context */
00469 static cfstore_ctx_t cfstore_ctx_g = {
00470         .file_list.next = NULL,
00471         .file_list.prev = NULL,
00472         .init_ref_count = 0,
00473         .rw_area0_lock = 0,
00474         .power_state = ARM_POWER_FULL,
00475         .area_0_head = NULL,
00476         .area_0_tail = NULL,
00477         .client_callback = NULL,
00478         .client_context = NULL,
00479         .f_reserved0 = 0,
00480 };
00481 #endif /* YOTTA_CFG_CFSTORE_UVISOR */
00482 
00483 #ifdef YOTTA_CFG_CFSTORE_UVISOR
00484 
00485 /*
00486  * Configure the secure box compartment
00487  */
00488 static const char const cfstore_uvisor_namespace_root_g[] = "com.arm.mbed.";
00489 // UVISOR_BOX_NAMESPACE("com.arm.mbed.configuration-store");
00490 // macro: static const char *const __uvisor_box_namespace = box_namespace
00491 static const char *const __uvisor_box_namespace = "com.arm.mbed.configuration-store";
00492 
00493 /* although the descriptor is empty, the main box descriptor is inherited and added to whats here. */
00494 static const UvisorBoxAclItem cfstore_acl_list_g[] = {
00495     /* todo: this needs completing with correct data for the secure flash partition above the binary
00496      *
00497      0xabaadfood = start of secure flash in address map (flash journal partition
00498      0xbeefbeef = size in bytes of secure flash partition
00499      {(void *) 0xabaadfood, 0xbeefbeef, UVISOR_TACLDEF_PERIPH},
00500      */
00501      /* put reference to k64 subfamily reference manual and cmsis k64f target header as to where this comes from */
00502      {FTFE,    sizeof(*FTFE),    UVISOR_TACLDEF_PERIPH},
00503 };
00504 
00505 /* UVISOR_BOX_CONFIG_CTX(configuration_store, UVISOR_BOX_STACK_SIZE, cfstore_ctx_t);
00506  *
00507  * It would be better to use the following macro:
00508  *  UVISOR_BOX_CONFIG(configuration_store, cfstore_acl_list_g, UVISOR_BOX_STACK_SIZE, cfstore_ctx_t);
00509  * rather than the unpacked macro code that follows.
00510  *
00511  * #define __UVISOR_BOX_CONFIG(box_name, acl_list, acl_list_count, stack_size, context_size) \
00512  *     \
00513  *     uint8_t __attribute__((section(".keep.uvisor.bss.boxes"), aligned(32))) \
00514  *         box_name ## _reserved[UVISOR_STACK_SIZE_ROUND(((UVISOR_MIN_STACK(stack_size) + (context_size))*8)/6)]; \
00515  *     \
00516  *     static const __attribute__((section(".keep.uvisor.cfgtbl"), aligned(4))) UvisorBoxConfig box_name ## _cfg = { \
00517  *         UVISOR_BOX_MAGIC, \
00518  *         UVISOR_BOX_VERSION, \
00519  *         UVISOR_MIN_STACK(stack_size), \
00520  *         context_size, \
00521  *         __uvisor_box_namespace, \
00522  *         acl_list, \
00523  *         acl_list_count \
00524  *     }; \
00525  *     \
00526  *     extern const __attribute__((section(".keep.uvisor.cfgtbl_ptr"), aligned(4))) void * const box_name ## _cfg_ptr = &box_name ## _cfg;
00527  *
00528  * However, the macro currently generates warnings that need to be fixed i.e.
00529  * =====================================================================================================================================================================================
00530  * d:/datastore/public/jobs/yr2016/2247/sdh_dev_10/configuration-store/source/configuration_store.c:490:1: error: initializer element is not constant
00531  * UVISOR_BOX_CONFIG(configuration_store, cfstore_acl_list_g, UVISOR_BOX_STACK_SIZE, cfstore_ctx_t);
00532  * ^
00533  * d:/datastore/public/jobs/yr2016/2247/sdh_dev_10/configuration-store/source/configuration_store.c:490:1: error: (near initialization for 'configuration_store_cfg.box_namespace')
00534  * In file included from d:/datastore/public/jobs/yr2016/2247/sdh_dev_10/configuration-store/yotta_modules/uvisor-lib/uvisor-lib/uvisor-lib.h:38:0,
00535  *      from d:/datastore/public/jobs/yr2016/2247/sdh_dev_10/configuration-store/source/configuration_store.c:27:
00536  * d:/datastore/public/jobs/yr2016/2247/sdh_dev_10/configuration-store/source/configuration_store.c:490:19: warning: 'configuration_store_cfg_ptr' initialized and declared 'extern'
00537  * UVISOR_BOX_CONFIG(configuration_store, cfstore_acl_list_g, UVISOR_BOX_STACK_SIZE, cfstore_ctx_t);
00538  *                    ^
00539  * d:/datastore/public/jobs/yr2016/2247/sdh_dev_10/configuration-store/yotta_modules/uvisor-lib/uvisor-lib/box_config.h:74:95: note: in definition of macro '__UVISOR_BOX_CONFIG'
00540  *      extern const __attribute__((section(".keep.uvisor.cfgtbl_ptr"), aligned(4))) void * const box_name ## _cfg_ptr = &box_name ## _cfg;
00541  *                                                                                                     ^
00542  * d:/datastore/public/jobs/yr2016/2247/sdh_dev_10/configuration-store/yotta_modules/uvisor-lib/uvisor-lib/box_config.h:57:55: note: in expansion of macro '__UVISOR_BOX_CONFIG_CONTEXT'
00543  * #define __UVISOR_BOX_MACRO(_1, _2, _3, _4, NAME, ...) NAME
00544  *                                                        ^
00545  * d:/datastore/public/jobs/yr2016/2247/sdh_dev_10/configuration-store/yotta_modules/uvisor-lib/uvisor-lib/box_config.h:101:5: note: in expansion of macro 'UVISOR_BOX_CONFIG_ACL'
00546  *      UVISOR_BOX_CONFIG_ACL(__VA_ARGS__)
00547  *           ^
00548  * d:/datastore/public/jobs/yr2016/2247/sdh_dev_10/configuration-store/source/configuration_store.c:490:1: note: in expansion of macro 'UVISOR_BOX_CONFIG'
00549  * UVISOR_BOX_CONFIG(configuration_store, cfstore_acl_list_g, UVISOR_BOX_STACK_SIZE, cfstore_ctx_t);
00550  * ^
00551  * ninja: build stopped: subcommand failed.
00552  * error: command ['ninja'] failed
00553  * =====================================================================================================================================================================================
00554  * The UVISOR_BOX_CONFIG() macro expands to include the following:
00555  *      extern const __attribute__((section(".keep.uvisor.cfgtbl_ptr"), aligned(4))) void * const configuration_store_cfg_ptr = &configuration_store_cfg;
00556  * The extern at the beginning of the line creates a warning when in a c file, and so needs to be removed/fixed.
00557  * There are also many other warnings from the macro expansion which need to be investigated further.
00558  *
00559  * todo: possible investigation: move configuration_store.c -> configuration_store.cpp
00560  */
00561 uint8_t __attribute__((section(".keep.uvisor.bss.boxes"), aligned(32))) configuration_store_reserved[UVISOR_STACK_SIZE_ROUND(((UVISOR_MIN_STACK(UVISOR_BOX_STACK_SIZE) + (sizeof(cfstore_ctx_t)))*8)/6)];
00562 static const __attribute__((section(".keep.uvisor.cfgtbl"), aligned(4))) UvisorBoxConfig configuration_store_cfg = {
00563     UVISOR_BOX_MAGIC,
00564     UVISOR_BOX_VERSION,
00565     UVISOR_MIN_STACK(UVISOR_BOX_STACK_SIZE),
00566     sizeof(cfstore_ctx_t),
00567     "com.arm.mbed.configuration-store", //problem using__uvisor_box_namespace defined above so inserting string directly here
00568     cfstore_acl_list_g,
00569     UVISOR_ARRAY_COUNT(cfstore_acl_list_g)
00570 };
00571 
00572 const __attribute__((section(".keep.uvisor.cfgtbl_ptr"), aligned(4))) void * const configuration_store_cfg_ptr = &configuration_store_cfg;
00573 UVISOR_EXTERN cfstore_ctx_t * const uvisor_ctx;
00574 
00575 #endif /* YOTTA_CFG_CFSTORE_UVISOR */
00576 
00577 /*
00578  * client notifier helper function
00579  */
00580 static void cfstore_client_notify_data_init(cfstore_client_notify_data_t* data, uint32_t opcode, int32_t status, ARM_CFSTORE_HANDLE  handle)
00581 {
00582     memset(data, 0, sizeof(cfstore_client_notify_data_t));
00583     data->opcode = opcode;
00584     data->status = status;
00585     data->handle = handle;
00586 }
00587 
00588 /*
00589  * cfstore_ctx_t methods
00590  */
00591 
00592 /* @brief   helper function to report whether the initialisation flag has been set in the cfstore_ctx_g */
00593 static bool cfstore_ctx_is_initialised(cfstore_ctx_t* ctx)
00594 {
00595     CFSTORE_ASSERT(ctx!= NULL);
00596     return ctx->init_ref_count > 0 ? true : false;
00597 }
00598 
00599 /* @brief   helper function to return a pointer to the global cfstore context. */
00600 static inline cfstore_ctx_t* cfstore_ctx_get(void)
00601 {
00602 #ifdef YOTTA_CFG_CFSTORE_UVISOR
00603     /* use the secure cfstore_ctx_t struct allocated by uvisor for use */
00604     return (cfstore_ctx_t*) uvisor_ctx;
00605 #else
00606     /* use the insecure statically allocated data struct */
00607     return &cfstore_ctx_g;
00608 #endif
00609 }
00610 
00611 /** @brief   helper function to compute the total size of the KVs stored in the
00612  *           sram area in bytes.
00613  *
00614  * Note:
00615  *  - sram_area_size =  cfstore_ctx_get_kv_total_len() + padding
00616  *  - padding rounds up cfstore_ctx_get_kv_total_len() to
00617  *    be a multiple of flash program_unit size.
00618  */
00619 static ARM_CFSTORE_SIZE cfstore_ctx_get_kv_total_len(void)
00620 {
00621     ARM_CFSTORE_SIZE size = 0;
00622     cfstore_ctx_t* ctx = cfstore_ctx_get();
00623 
00624     size = (ARM_CFSTORE_SIZE) (ctx->area_0_tail - ctx->area_0_head);
00625     return size;
00626 }
00627 
00628 /* @brief   helper function to get the program_unit */
00629 static inline uint32_t cfstore_ctx_get_program_unit(cfstore_ctx_t* ctx)
00630 {
00631     CFSTORE_ASSERT(ctx!= NULL);
00632 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
00633     return ctx->info.program_unit;
00634 #else
00635     /* the program unit is 1 so byte aligned when no flash backend present */
00636     (void) ctx;
00637     return 1;
00638 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
00639 
00640 }
00641 
00642 static inline void cfstore_ctx_client_notify(cfstore_ctx_t* ctx, cfstore_client_notify_data_t* data)
00643 {
00644     CFSTORE_FENTRYLOG("%s:entered: ctx=%p, ctx->client_callback=%p, ctx->client_context=%p\n", __func__, ctx, ctx->client_callback, ctx->client_context);
00645     CFSTORE_TP(CFSTORE_TP_CALLBACK, "%s:data=%p, data->opcode=%d, data->status=%d, data->handle=%p\n", __func__, data, (int) data->opcode, (int) data->status, data->handle);
00646     if(ctx->client_callback){
00647         ctx->client_callback(data->status, (ARM_CFSTORE_OPCODE) data->opcode, ctx->client_context, data->handle);
00648     }
00649     return;
00650 }
00651 
00652 /*
00653  * CFSTORE_YOTTA_CFG_CFSTORE_SRAM_ADDR
00654  *  client can supply a SRAM slab address and size for
00655  *  CFSTORE internal use. This is a default addr
00656  *  for development use. Should be defined by client
00657  * CFSTORE_YOTTA_CFG_CFSTORE_SRAM_SIZE
00658  *  size of sram area. Should be define by client
00659  */
00660 #ifndef CFSTORE_YOTTA_CFG_CFSTORE_SRAM_ADDR
00661 /* if the client doesnt provide a memory slab then CFSTORE uses realloc internally*/
00662 
00663 #ifndef CFSTORE_DEBUG
00664 #define CFSTORE_FREE        free
00665 #define CFSTORE_MALLOC      malloc
00666 #define CFSTORE_REALLOC     realloc
00667 #else
00668 
00669 static uint32_t cfstore_malloc_size_g = 0;
00670 #define CFSTORE_MALLOC      malloc
00671 
00672 static void* CFSTORE_REALLOC(void *ptr, size_t size)
00673 {
00674     void* mem;
00675 
00676     mem = realloc(ptr, size);
00677     CFSTORE_TP(CFSTORE_TP_MEM, "%s:ptr=%p, mem=%p, old_size=%u, new_size=%u.\n", __func__, ptr, mem, (int) cfstore_malloc_size_g, (int) size);
00678     cfstore_malloc_size_g = size;
00679     return mem;
00680 }
00681 
00682 static void CFSTORE_FREE(void *ptr)
00683 {
00684     free(ptr);
00685     CFSTORE_TP(CFSTORE_TP_MEM, "%s:ptr=%p, old_size=%u, new_size=%u.\n", __func__, ptr, (int) cfstore_malloc_size_g, 0);
00686     cfstore_malloc_size_g = 0;
00687     return;
00688 }
00689 #endif /* CFSTORE_DEBUG */
00690 
00691 /* memory tracking */
00692 
00693 #else
00694 #define CFSTORE_FREE        CFSTORE_ASSERT(0)
00695 #define CFSTORE_MALLOC      CFSTORE_ASSERT(0)
00696 #define CFSTORE_REALLOC     cfstore_realloc
00697 
00698 
00699 
00700 /* function to realloc from a client provided memory slab
00701  * size = new size of area used by sram
00702  * ptr is always head of slab
00703  *
00704  * The cfstore_realloc() function changes the size of the memory
00705  * block pointed to by ptr to size bytes, backed by the client
00706  * provided memory slab. The contents will be unchanged in the
00707  * range from the start of the region up to the minimum of the
00708  * old and new sizes. If the new size is larger than the old size,
00709  * the added memory will not be initialized.
00710  *
00711  * ptr
00712  * ptr should be set to null on the first call to this function and
00713  * for size > 0 && size <= CFSTORE_YOTTA_CFG_CFSTORE_SRAM_SIZE
00714  * CFSTORE_YOTTA_CFG_CFSTORE_SRAM_ADDR will be returned.
00715  * On subsequent calls, ptr must have been returned by an earlier
00716  * call to this function.
00717  *
00718  * size
00719  * if size is equal to zero, and ptr is not NULL, then the call is
00720  * equivalent to reseting the memory area and NULL will be returned.
00721  */
00722 void *cfstore_realloc(void *ptr, ARM_CFSTORE_SIZE size)
00723 {
00724     static uint8_t *cfstore_sram_head = NULL;
00725     static uint8_t *cfstore_sram_tail = NULL;
00726 
00727     if(size > 0) {
00728         if(size <= CFSTORE_YOTTA_CFG_CFSTORE_SRAM_SIZE) {
00729             if(ptr == NULL) {
00730                 memset(CFSTORE_YOTTA_CFG_CFSTORE_SRAM_ADDR, 0, CFSTORE_YOTTA_CFG_CFSTORE_SRAM_SIZE);
00731                 cfstore_sram_head = CFSTORE_YOTTA_CFG_CFSTORE_SRAM_ADDR;
00732             }
00733             cfstore_sram_tail = cfstore_sram_head + size;
00734             return (void*) cfstore_sram_head;
00735         }
00736         /* requested size is too big so fail the operation by setting
00737          * head/tail to NULL */
00738     }
00739     /* size == 0 => reset */
00740     cfstore_sram_head = NULL;
00741     cfstore_sram_tail = NULL;
00742     return (void*) cfstore_sram_head;
00743 }
00744 
00745 #endif /* CFSTORE_YOTTA_CFG_CFSTORE_SRAM_ADDR */
00746 
00747 
00748 #ifdef CFSTORE_TARGET_LIKE_X86_LINUX_NATIVE
00749 static inline void cfstore_critical_section_lock(CFSTORE_LOCK* lock, const char* tag){ (void) tag; __sync_fetch_and_add(lock, 1); }
00750 static inline void cfstore_critical_section_unlock(CFSTORE_LOCK* lock, const char* tag){(void) tag;  __sync_fetch_and_sub(lock, 1); }
00751 
00752 static CFSTORE_INLINE int32_t cfstore_hkvt_refcount_dec(cfstore_area_hkvt_t* hkvt, uint8_t *refcount)
00753 {
00754     cfstore_area_header_t  *hdr = (cfstore_area_header_t *) hkvt->head;
00755     uint32_t __refcount;
00756 
00757     __refcount =__sync_fetch_and_sub(&hdr->refcount, 1);
00758     if(refcount) *refcount = __refcount;
00759     return ARM_DRIVER_OK;
00760 }
00761 
00762 static CFSTORE_INLINE int32_t cfstore_hkvt_refcount_inc(cfstore_area_hkvt_t* hkvt, uint8_t *refcount)
00763 {
00764     int32_t ret = ARM_CFSTORE_DRIVER_ERROR_HANDLE_COUNT_MAX;
00765     uint32_t __refcount;
00766     cfstore_area_header_t  *hdr = (cfstore_area_header_t *) hkvt->head;
00767 
00768     if( (__refcount = __sync_fetch_and_add(&hdr->refcount, 1)) < CFSTORE_LOCK_REFCOUNT_MAX) {
00769         if(refcount) *refcount = __refcount;
00770         ret = ARM_DRIVER_OK;
00771     } else {
00772         /* maximum count reach, back down and return error*/
00773         __sync_fetch_and_sub(&hdr->refcount, 1);
00774     }
00775     return ret;
00776 }
00777 
00778 
00779 #else
00780 
00781 /*
00782  * Platform Specific Function Implementations
00783  */
00784 
00785 static inline void cfstore_critical_section_unlock(CFSTORE_LOCK* lock, const char* tag)
00786 {
00787     (void) lock;
00788     (void) tag;
00789     CFSTORE_DBGLOG("%s:before critical_section_exit()(lock=%lu)\n", tag, *lock);
00790     (*lock)--;
00791     /* todo: put mbedosv3++ critical section exit here */
00792     CFSTORE_DBGLOG("%s:after critical_section_exit()(lock=%lu)\n", tag, *lock);
00793 }
00794 
00795 static inline void cfstore_critical_section_lock(CFSTORE_LOCK* lock, const char* tag)
00796 {
00797     (void) lock;
00798     (void) tag;
00799     CFSTORE_DBGLOG("%s:before critical_section_enter()(lock=%lu)\n", tag, *lock);
00800     /* todo: put mbedosv3++ critical section enter here */
00801     (*lock)++;
00802     CFSTORE_DBGLOG("%s:after critical_section_enter()(lock=%lu)\n", tag, *lock);
00803 }
00804 
00805 static CFSTORE_INLINE int32_t cfstore_hkvt_refcount_dec(cfstore_area_hkvt_t* hkvt, uint8_t *refcount)
00806 {
00807     cfstore_area_header_t  *hdr = (cfstore_area_header_t *) hkvt->head;
00808 
00809     /* todo: put mbedosv3++ critical section enter here */
00810     hdr->refcount--;
00811     if(refcount) *refcount = hdr->refcount;
00812     /* todo: put mbedosv3++ critical section exit here */
00813     return ARM_DRIVER_OK;
00814 }
00815 
00816 static CFSTORE_INLINE int32_t cfstore_hkvt_refcount_inc(cfstore_area_hkvt_t* hkvt, uint8_t *refcount)
00817 {
00818     int32_t ret = ARM_CFSTORE_DRIVER_ERROR_HANDLE_COUNT_MAX;
00819     cfstore_area_header_t  *hdr = (cfstore_area_header_t *) hkvt->head;
00820 
00821     /* todo: put mbedosv3++ critical section enter here */
00822     if(hdr->refcount < CFSTORE_HKVT_REFCOUNT_MAX)
00823     {
00824         hdr->refcount++;
00825         if(refcount) *refcount = hdr->refcount;
00826         ret = ARM_DRIVER_OK;
00827     }
00828     /* todo: put mbedosv3++ critical section exit here */
00829     return ret;
00830 }
00831 
00832 #endif /* CFSTORE_TARGET_LIKE_X86_LINUX_NATIVE */
00833 
00834 
00835 /*
00836  * security/permissions helper functions
00837  */
00838 
00839 #ifdef YOTTA_CFG_CFSTORE_UVISOR
00840 /**
00841  * @brief   check that a client (cfstore-uvisor client box) is the "owner" of the
00842  *          KV. Owner means the client that can create or created the KV. This is
00843  *          determined by the clients namespace and whether the KV path name falls
00844  *          within that name space
00845  * @param   key_name
00846  *          the name of the KV being created.
00847  *          the validation that the key_name is composed of permissible chars is
00848  *          carried out before this function is called.
00849  * @note
00850  * Conceptually, cfstore supports the following KV path namespaces:
00851  *  - com.arm.mbed.
00852  *  - guids of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx where x is a hex digit.
00853  *
00854  *  In the cfstore implementation, explicit checking of the structure of the
00855  *  namespace string is not required. Cfstore only need enforce that:
00856  *      the root of the KV pathname == cfstore client uvisor namespace.
00857  */
00858 static int32_t cfstore_uvisor_is_client_kv_owner(char* key_name, int32_t* cfstore_uvisor_box_id)
00859 {
00860     int32_t calling_box_id;
00861     int32_t ret;
00862     /* We store the calling_box_namespace on our stack, lest somebody else modify it. */
00863     char calling_box_namespace[UVISOR_MAX_BOX_NAMESPACE_LENGTH];
00864 
00865     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
00866     memset(calling_box_namespace, 0, sizeof(calling_box_namespace));
00867     /* Get the ID of the box that called this box through the most recent secure gateway. */
00868     calling_box_id = uvisor_box_id_caller();
00869     if(calling_box_id < 0){
00870         CFSTORE_ERRLOG("%s: Error: uvisor uvisor_box_id_caller() returned invalid id (calling_box_id=%d\n", __func__, (int) calling_box_id);
00871         return ARM_CFSTORE_DRIVER_ERROR_UVISOR_BOX_ID;
00872     }
00873     if(cfstore_uvisor_box_id){
00874         *cfstore_uvisor_box_id = calling_box_id;
00875     }
00876     if(calling_box_id == 0){
00877         /* the cfstore uvisor client is the main box.
00878          * main box is not allowed to create a key as a client is only permitted to create KVs in their namespace. */
00879         CFSTORE_ERRLOG("%s: Error: uvisor box id identifies cfstore client cannot create KVs (calling_box_id=%d\n", __func__, (int) calling_box_id);
00880         return ARM_CFSTORE_DRIVER_ERROR_UVISOR_BOX_ID;
00881     }
00882     /* Copy the name of the calling box to our stack. */
00883     ret = uvisor_box_namespace(calling_box_id, calling_box_namespace, sizeof(calling_box_namespace));
00884     if(ret < 0){
00885         /* error */
00886         CFSTORE_ERRLOG("%s: Error: unable to recover uvisor box namespace\n", __func__);
00887         return ARM_CFSTORE_DRIVER_ERROR_UVISOR_NAMESPACE;
00888     }
00889     /* check the cfstore client uvisor box namespace is non-trivial */
00890     if(strlen(calling_box_namespace) == 0){
00891         CFSTORE_ERRLOG("%s: Error: uvisor box namespace is zero length\n", __func__);
00892         return ARM_CFSTORE_DRIVER_ERROR_UVISOR_NAMESPACE;
00893     }
00894     /* check that the key name is within the root domain namespace */
00895     if(strncmp(calling_box_namespace, key_name, sizeof(calling_box_namespace)) != 0) {
00896         /* The key_name does not fall within the cfstore-uvisor client namespace and therefore the create is not allowed */
00897         CFSTORE_ERRLOG("%s: Error: key name (%s) is not permitted to be created within client uvisor box namespace (%s) of cfstore client\n", __func__, key_name, calling_box_namespace);
00898         return ARM_CFSTORE_DRIVER_ERROR_NO_PERMISSIONS;
00899     }
00900     /* We've passed all our checks, so we allow the calling box. */
00901     return ARM_DRIVER_OK;
00902 }
00903 #endif /* YOTTA_CFG_CFSTORE_UVISOR */
00904 
00905 /**
00906  * @brief   check that the cfstore client (caller, which is a uvisor box)
00907  *          is only trying to access its own namespace.
00908  *
00909  * @note    This function is the cfstore equivalent of "is_calling_box_allowed"
00910  */
00911 static int32_t cfstore_uvisor_security_context_prefix_check(const char* key_name)
00912 {
00913     /*todo: implement : A client uvisor security context should exist with
00914      *      a security_prefix_name that matches the first part of the
00915      *      key_name. Make sure this is the case. */
00916 
00917     // if the caller is the main box then deny access, as only secure uvisor boxes
00918     // are permitted to access cfstore.
00919 
00920     // get box_id of caller
00921     // get namespace of caller
00922     // if the keyname is in the namespace then permit, otherwise deny
00923 
00924     (void) key_name;
00925     return ARM_DRIVER_OK;
00926 }
00927 
00928 /* @brief   check that a client (cfstore-uvisor client box) is the "owner" of the
00929  *          KV (wrapper). see cfstore_uvisor_is_client_kv_owner() for more details.
00930  */
00931 static int32_t cfstore_is_client_kv_owner(const char* key_name, int32_t* cfstore_uvisor_box_id)
00932 {
00933     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
00934 /*
00935 #ifdef YOTTA_CFG_CFSTORE_UVISOR
00936     return cfstore_uvisor_is_client_kv_owner(key_name, cfstore_uvisor_box_id);
00937 #else
00938     return ARM_DRIVER_OK;
00939 #endif
00940 */
00941     (void) key_name;
00942     (void) cfstore_uvisor_box_id;
00943     return ARM_DRIVER_OK;
00944 }
00945 
00946 /* @brief   helper function to determine whether this client can close a given KV */
00947 static bool cfstore_is_kv_client_closable(cfstore_file_t* file)
00948 {
00949     /* todo: integrate with uvisor to get boxId (security prefix name)
00950      * - check the kv key_name prefix matches the security context to determine whether client is
00951      *   allowed to close the given key_name.
00952      */
00953     /* until can implement this functionality, assume client can close KV */
00954     (void) file;
00955     return true;
00956 }
00957 
00958 /* @brief   helper function to determine whether this client can delete a given KV */
00959 static bool cfstore_is_kv_client_deletable(cfstore_file_t* file)
00960 {
00961     /* todo: integrate with uvisor to get boxId (security prefix name)
00962      * - check the kv key_name prefix matches the security context to determine whether client is
00963      *   allowed to delete the given key_name.
00964      */
00965     /* until can implement this functionality, assume client can delete KV */
00966     (void) file;
00967     return true;
00968 }
00969 
00970 #ifdef YOTTA_CFG_CFSTORE_UVISOR
00971 /* @brief   helper function to determine whether this cfstore-uvisor client box can read a given KV */
00972 static bool cfstore_is_kv_client_readable(cfstore_area_hkvt_t* hkvt)
00973 {
00974     bool bret = false;
00975     int32_t ret = ARM_DRIVER_ERROR;
00976     char key_name[CFSTORE_KEY_NAME_MAX_LENGTH+1];
00977     uint8_t key_name_len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
00978     cfstore_area_header_t  *hdr = (cfstore_area_header_t *) hkvt->head;
00979 
00980 
00981     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
00982     memset(key_name, 0, key_name_len);
00983     ret = cfstore_get_key_name_ex(hkvt, key_name, &key_name_len);
00984     if(ret < ARM_DRIVER_OK){
00985         CFSTORE_ERRLOG("%s:Error: cfstore_get_key_name_ex() returned error.\n", __func__);
00986         return bret;
00987     }
00988     ret = cfstore_is_client_kv_owner(key_name, NULL);
00989     if(ret == ARM_DRIVER_OK){
00990         /* cfstore-usvisor client box is the "owner" of the key */
00991         bret = hdr->perm_owner_read;
00992     } else {
00993         /* cfstore-usvisor client box is not the "owner" of the key i.e. is the "other" */
00994         bret = hdr->perm_other_read;
00995     }
00996     return bret;
00997 }
00998 
00999 /* @brief   helper function to determine whether this client can write a given KV */
01000 static bool cfstore_is_kv_client_writable(cfstore_area_hkvt_t* hkvt)
01001 {
01002     bool bret = false;
01003     int32_t ret = ARM_DRIVER_ERROR;
01004     char key_name[CFSTORE_KEY_NAME_MAX_LENGTH+1];
01005     uint8_t key_name_len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
01006     cfstore_area_header_t  *hdr = (cfstore_area_header_t *) hkvt->head;
01007 
01008     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
01009     memset(key_name, 0, key_name_len);
01010     ret = cfstore_get_key_name_ex(hkvt, key_name, &key_name_len);
01011     if(ret < ARM_DRIVER_OK){
01012         CFSTORE_ERRLOG("%s:Error: cfstore_get_key_name_ex() returned error.\n", __func__);
01013         return bret;
01014     }
01015     ret = cfstore_is_client_kv_owner(key_name, NULL);
01016     if(ret == ARM_DRIVER_OK){
01017         /* cfstore-usvisor client box is the "owner" of the key */
01018         bret = hdr->perm_owner_write;
01019     } else {
01020         /* cfstore-usvisor client box is not the "owner" of the key i.e. is the "other" */
01021         bret = hdr->perm_other_write;
01022     }
01023     return bret;
01024 }
01025 
01026 /* @brief   helper function to determine whether this client can execute a given KV */
01027 static bool cfstore_is_kv_client_executable(cfstore_area_hkvt_t* hkvt)
01028 {
01029     bool bret = false;
01030     int32_t ret = ARM_DRIVER_ERROR;
01031     char key_name[CFSTORE_KEY_NAME_MAX_LENGTH+1];
01032     uint8_t key_name_len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
01033     cfstore_area_header_t  *hdr = (cfstore_area_header_t *) hkvt->head;
01034 
01035     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
01036     memset(key_name, 0, key_name_len);
01037     ret = cfstore_get_key_name_ex(hkvt, key_name, &key_name_len);
01038     if(ret < ARM_DRIVER_OK){
01039         CFSTORE_ERRLOG("%s:Error: cfstore_get_key_name_ex() returned error.\n", __func__);
01040         return bret;
01041     }
01042     ret = cfstore_is_client_kv_owner(key_name, NULL);
01043     if(ret == ARM_DRIVER_OK){
01044         /* cfstore-usvisor client box is the "owner" of the key */
01045         bret = hdr->perm_owner_execute;
01046     } else {
01047         /* cfstore-usvisor client box is not the "owner" of the key i.e. is the "other" */
01048         bret = hdr->perm_other_execute;
01049     }
01050     return bret;
01051 }
01052 #endif  /* YOTTA_CFG_CFSTORE_UVISOR */
01053 
01054 /* @brief   helper function to determine whether this client can read a given KV */
01055 static bool cfstore_is_kv_client_readable(cfstore_area_hkvt_t* hkvt)
01056 {
01057     /* todo: integrate with uvisor to get boxId (security prefix name)
01058      * - check the kv key_name prefix matches the security context to determine whether client is
01059      *   owner or other.
01060      * - if(owner)
01061      *   {
01062      *      // client is owner of kv
01063      *      if( ((cfstore_area_header_t*)(hkvt->head))->perm_owner_read == true) {
01064      *          return true;
01065      *      }
01066      *   } else {
01067      *      // client is other
01068      *      if( ((cfstore_area_header_t*)(hkvt->head))->perm_other_read == true) {
01069      *          return true;
01070      *   }
01071      *   return false;
01072      */
01073     /* until can implement this functionality, assume client has read access to KV */
01074     (void) hkvt;
01075     return true;
01076 }
01077 
01078 /* @brief   helper function to determine whether this client can write a given KV */
01079 static bool cfstore_is_kv_client_writable(cfstore_area_hkvt_t* hkvt)
01080 {
01081     cfstore_area_header_t  *hdr = (cfstore_area_header_t *) hkvt->head;
01082 
01083     /* todo: integrate with uvisor to get boxId (security prefix name)
01084      * - check the kv key_name prefix matches the security context to determine whether client is
01085      *   owner or other.
01086      * - if(owner)
01087      *   {
01088      *      // client is owner of kv
01089      *      if( ((cfstore_area_header_t*)(hkvt->head))->perm_owner_write == true) {
01090      *          return true;
01091      *      }
01092      *   } else {
01093      *      // client is other
01094      *      if( ((cfstore_area_header_t*)(hkvt->head))->perm_other_write == true) {
01095      *          return true;
01096      *   }
01097      *   return false;
01098      */
01099     /* until can implement this functionality, assume client has write access to KV */
01100 
01101     /* check that the owner has write permission */
01102     return hdr->perm_owner_write;
01103 }
01104 
01105 /* @brief   helper function to determine whether this client can execute a given KV */
01106 static bool cfstore_is_kv_client_executable(cfstore_area_hkvt_t* hkvt)
01107 {
01108     /* todo: integrate with uvisor to get boxId (security prefix name)
01109      * - check the kv key_name prefix matches the security context to determine whether client is
01110      *   owner or other.
01111      * - if(owner)
01112      *   {
01113      *      // client is owner of kv
01114      *      if( ((cfstore_area_header_t*)(hkvt->head))->perm_owner_execute == true) {
01115      *          return true;
01116      *      }
01117      *   } else {
01118      *      // client is other
01119      *      if( ((cfstore_area_header_t*)(hkvt->head))->perm_other_execute == true) {
01120      *          return true;
01121      *   }
01122      *   return false;
01123      */
01124     /* until can implement this functionality, assume client has execute access to KV */
01125     (void) hkvt;
01126     return true;
01127 }
01128 
01129 
01130 /*
01131  * flags helper function
01132  */
01133 static bool cfstore_acl_is_default(ARM_CFSTORE_ACCESS_CONTROL_LIST acl)
01134 {
01135     if(     acl.perm_owner_read == false                &&
01136             acl.perm_owner_write == false               &&
01137             acl.perm_owner_execute == false             &&
01138             acl.perm_other_read == false                &&
01139             acl.perm_other_write == false               &&
01140             acl.perm_other_execute == false             )
01141     {
01142         /* flags are set to indicate "adopt some meaningful default behaviour" */
01143         return true;
01144     }
01145     return false;
01146 }
01147 
01148 /*
01149  * flags helper function
01150  */
01151 static bool cfstore_flags_is_default(ARM_CFSTORE_FMODE flags)
01152 {
01153     if( flags.read == 0             &&
01154         flags.write == 0            &&
01155         flags.continuous == 0       &&
01156         flags.flush_on_close == 0   &&
01157         flags.lazy_flush == 0       &&
01158         flags.storage_detect == 0   )
01159     {
01160         /* flags are set to indicate "adopt some meaningful default behaviour" */
01161         return true;
01162     }
01163     return false;
01164 }
01165 
01166 static CFSTORE_INLINE bool cfstore_hkvt_get_flags_delete(cfstore_area_hkvt_t *hkvt)
01167 {
01168     return ((cfstore_area_header_t *) hkvt->head)->flags.delete;
01169 }
01170 
01171 static CFSTORE_INLINE void cfstore_hkvt_set_flags_delete(cfstore_area_hkvt_t *hkvt, bool flag)
01172 {
01173     CFSTORE_ASSERT(hkvt != NULL);
01174     ((cfstore_area_header_t *) hkvt->head)->flags.delete = flag;
01175 }
01176 
01177 
01178 /*
01179  * struct cfstore_area_hkvt_t helper operations
01180  */
01181 static CFSTORE_INLINE uint8_t cfstore_hkvt_get_key_len(cfstore_area_hkvt_t* hkvt)
01182 {
01183     cfstore_area_header_t  *header;
01184     CFSTORE_ASSERT(hkvt != NULL);
01185     header = (cfstore_area_header_t *) hkvt->head;
01186     return header->klength;
01187 }
01188 
01189 static CFSTORE_INLINE uint32_t cfstore_hkvt_get_value_len(cfstore_area_hkvt_t* hkvt)
01190 {
01191     cfstore_area_header_t  *header;
01192     CFSTORE_ASSERT(hkvt != NULL);
01193     header = (cfstore_area_header_t *) hkvt->head;
01194     return header->vlength;
01195 }
01196 
01197 static CFSTORE_INLINE ARM_CFSTORE_SIZE cfstore_hkvt_get_size(cfstore_area_hkvt_t* hkvt)
01198 {
01199     ARM_CFSTORE_SIZE kv_size = 0;
01200 
01201     kv_size += sizeof(cfstore_area_header_t );
01202     kv_size += cfstore_hkvt_get_key_len(hkvt);
01203     kv_size += cfstore_hkvt_get_value_len(hkvt);
01204     return kv_size;
01205 }
01206 
01207 static CFSTORE_INLINE void cfstore_hkvt_init(cfstore_area_hkvt_t* hkvt)
01208 {
01209     memset(hkvt, 0, sizeof(cfstore_area_hkvt_t));
01210 }
01211 
01212 
01213 static CFSTORE_INLINE bool cfstore_hkvt_is_valid(cfstore_area_hkvt_t *hkvt, uint8_t *area_0_tail)
01214 {
01215     if(hkvt->head && hkvt->head != area_0_tail && hkvt->key && hkvt->value && hkvt->tail) {
01216         return true;
01217     }
01218     return false;
01219 }
01220 
01221 static CFSTORE_INLINE uint32_t cfstore_hkvt_set_value_len(cfstore_area_hkvt_t* hkvt, uint32_t value_len)
01222 {
01223     uint32_t vlength;
01224     cfstore_area_header_t  *hdr;
01225     CFSTORE_ASSERT(hkvt != NULL);
01226     hdr = (cfstore_area_header_t *) hkvt->head;
01227     vlength = hdr->vlength;
01228     hdr->vlength = value_len;
01229     return vlength;
01230 }
01231 
01232 /* @brief   helper function to detect if there are any KV's stored in the sram area */
01233 static bool cfstore_area_has_hkvt(void)
01234 {
01235     cfstore_ctx_t* ctx = cfstore_ctx_get();
01236 
01237     /* head and tail pointer equal means there are no KVs stored */
01238     if(ctx->area_0_head == ctx->area_0_tail){
01239         /* there are no KV's stored*/
01240         return false;
01241     }
01242     return true;
01243 }
01244 
01245 
01246 /* @brief   helper function to get the first KV in the sram area */
01247 static cfstore_area_hkvt_t cfstore_get_hkvt_from_head_ptr(uint8_t* head)
01248 {
01249     cfstore_area_hkvt_t hkvt;
01250 
01251     CFSTORE_ASSERT(head != NULL);
01252     memset((void*) &hkvt, 0, sizeof(hkvt));
01253     hkvt.head = head;
01254     hkvt.key = hkvt.head + sizeof(cfstore_area_header_t );
01255     hkvt.value = hkvt.key + ((cfstore_area_header_t *) hkvt.head)->klength;
01256     hkvt.tail = hkvt.value + ((cfstore_area_header_t *) hkvt.head)->vlength;
01257     return hkvt;
01258 }
01259 
01260 
01261 /* @brief   helper function to convert a opaque handle to a struct cfstore_area_hkvt_t */
01262 static cfstore_area_hkvt_t cfstore_get_hkvt(ARM_CFSTORE_HANDLE  hkey)
01263 {
01264     cfstore_file_t* file = (cfstore_file_t*) hkey;
01265     return cfstore_get_hkvt_from_head_ptr((uint8_t*) file->head);
01266 }
01267 
01268 
01269 /* @brief   helper function to convert a opaque handle to a struct cfstore_area_hkvt_t */
01270 static int32_t cfstore_get_head_hkvt(cfstore_area_hkvt_t* hkvt)
01271 {
01272     cfstore_ctx_t* ctx = cfstore_ctx_get();
01273 
01274     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
01275     CFSTORE_ASSERT(hkvt != NULL);
01276     if(!cfstore_area_has_hkvt()){
01277         CFSTORE_TP(CFSTORE_TP_VERBOSE1, "%s:CFSTORE has no KVs\n", __func__);
01278         memset((void*) hkvt, 0, sizeof(cfstore_area_hkvt_t));
01279         return ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND;
01280     }
01281 
01282     CFSTORE_TP(CFSTORE_TP_VERBOSE1, "%s:CFSTORE has KVs\n", __func__);
01283     *hkvt = cfstore_get_hkvt_from_head_ptr(ctx->area_0_head);
01284     return ARM_DRIVER_OK;
01285 }
01286 
01287 
01288 /* @brief   helper function to walk the sram area from the previous hkvt to
01289  *          the next hkvt.
01290  * @param   prev
01291  *          pointer to previous hkvt. If null then the search is started
01292  *          from the beginning of the sram area.
01293  * @param   next
01294  *          pointer to next hkvt for which the pointers need calculating.
01295  */
01296 static int32_t cfstore_get_next_hkvt(cfstore_area_hkvt_t* prev, cfstore_area_hkvt_t* next)
01297 {
01298     cfstore_ctx_t* ctx = cfstore_ctx_get();
01299 
01300     CFSTORE_ASSERT(prev != NULL);
01301     CFSTORE_ASSERT(next != NULL);
01302     CFSTORE_ASSERT(prev->tail <= ctx->area_0_tail);
01303 
01304     if(prev->tail == ctx->area_0_tail){
01305         CFSTORE_TP(CFSTORE_TP_VERBOSE1, "%s:reached the end of the list. return NULL entry\n", __func__);
01306         memset((void*) next, 0, sizeof(cfstore_area_hkvt_t));
01307         return ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND;
01308     }
01309     /* use the prev tail pointer to find the next head pointer */
01310     *next = cfstore_get_hkvt_from_head_ptr((uint8_t*) prev->tail);
01311     return ARM_DRIVER_OK;
01312 }
01313 
01314 
01315 /*
01316  * Flash support functions
01317  */
01318 
01319 static CFSTORE_INLINE void cfstore_hkvt_dump(cfstore_area_hkvt_t* hkvt, const char* tag);
01320 
01321 /** @brief  Set the context tail pointer area_0_tail to point to the end of the
01322  *          last KV in the memory area.
01323  *
01324  * This function walks hkvt entries in the KV area to find the memory
01325  * address after the end of the last KV, and then sets the area tail pointer
01326  * area_0_tail to that address. The function therefore relies on the
01327  * head, key, value, tail fields being correct.
01328  *
01329  * Notes:
01330  * - This function should only be called after the memory area is loaded from
01331  *   flash and the area_0_tail pointer needs setting. The only way to do this
01332  *   (at the present time) is to walk the list of KVs, which is what this function
01333  *   does. The only other place the code sets area_0_tail is cfstore_realloc_ex(),
01334  *   and this state of affairs shouldnt change i.e. its unnecessary for
01335  *   other functions to change area_0_tail.
01336  * - When loading the area_0 image from falsh, cfstore_realloc_ex() is used
01337  *   to allocate the memory with ctx->expected_blob_size as the size. Thus
01338  *   area_0_tail will be initially set to
01339  *     area_0_tail = area_0_head + expected_blob_size       (1)
01340  *   and thereby may include padding used to align the area size to a
01341  *   flash program unit boundary. cfstore_flash_set_tail() is used to
01342  *   set area_0_tail correctly.
01343  */
01344 static int32_t cfstore_flash_set_tail(void)
01345 {
01346     int32_t ret = ARM_DRIVER_ERROR;
01347     uint8_t* ptr = NULL;
01348     cfstore_ctx_t* ctx = cfstore_ctx_get();
01349     uint8_t* tail = NULL;
01350     cfstore_area_hkvt_t hkvt;
01351 
01352     CFSTORE_FENTRYLOG("%s:entered: \n", __func__);
01353     CFSTORE_ASSERT(ctx != NULL);
01354     cfstore_hkvt_init(&hkvt);
01355 
01356     /* Check for cases where the tail pointer is already set correctly
01357      * e.g. where the area is of zero length */
01358     if(cfstore_ctx_get_kv_total_len() == 0) {
01359         /* tail pointer already set correctly */
01360         return ARM_DRIVER_OK;
01361     }
01362     ptr = ctx->area_0_head;
01363     tail = ctx->area_0_tail;
01364     while(ptr <= tail) {
01365         CFSTORE_FENTRYLOG("%s:ptr=%p, tail=%p: \n", __func__, ptr, tail);
01366         hkvt = cfstore_get_hkvt_from_head_ptr(ptr);
01367         if(cfstore_hkvt_is_valid(&hkvt, tail) == false) {
01368             CFSTORE_ERRLOG("%s:Error:found invalid hkvt entry in area\n", __func__);
01369             break;
01370         }
01371         cfstore_hkvt_dump(&hkvt, __func__);
01372         /* when the length between the hkvt.tail and tail
01373          * is less than the minimum KV length then we have found the last KV, and can set the
01374          * area_0_tail correctly to the end of the last KV. This works OK for the present support
01375          * (where flash_program_unit ~ sizeof(cfstore_area_header_t)) but may need
01376          * revisiting where flash_program_unit > sizeof(cfstore_area_header_t) */
01377         if((uint32_t)(tail - hkvt.tail) < sizeof(cfstore_area_header_t )){
01378             /* ptr is last KV in area as there isn't space for another header  */
01379             ctx->area_0_tail = hkvt.tail;
01380             ret = ARM_DRIVER_OK;
01381             break;
01382         }
01383         ptr = hkvt.tail;
01384     }
01385     return ret;
01386 }
01387 
01388 
01389 /** @brief  Function to realloc the SRAM area used to store KVs.
01390  *
01391  * This function consolidates the code needed to:
01392  * - realloc the memory
01393  * - when the start of the SRAM area moves, update data structures
01394  *   which point into SRAM area (e.g. open files cfstore_file_t head pointers).
01395  *
01396  * The function assumes:
01397  * - the cfstore_file_t::head pointers are valid i.e. point to the
01398  *   correct locations in the KV area for each file.
01399  *
01400  * @param   size
01401  * total KV size in bytes storage required. Note this does not include
01402  * padding to round up to the nearest multiple of flash program unit
01403  * as this is computed and added in this function.
01404  *
01405  * @param   allocated_size
01406  * total size in bytes that was allocated (value returned to caller).
01407  * This may be larger than the requested size due to rounding to align with a
01408  * flash program unit boundary.
01409  */
01410 static int32_t cfstore_realloc_ex(ARM_CFSTORE_SIZE size, uint64_t *allocated_size)
01411 {
01412     uint8_t* ptr = NULL;
01413     int32_t ret = ARM_DRIVER_ERROR;
01414     int32_t len_diff = 0;
01415     cfstore_ctx_t* ctx = cfstore_ctx_get();
01416     cfstore_file_t* file;
01417     cfstore_list_node_t* node;
01418     cfstore_list_node_t* file_list = &ctx->file_list;
01419     ARM_CFSTORE_SIZE total_kv_size = size;
01420 
01421     /* Switch on the size of the sram area to create:
01422      * - if size > 0 (but may be shrinking) then use REALLOC.
01423      * - if size == 0 then the area is being deleted so free the memory
01424      * Note:
01425      * - realloc can return NULL when the last KV is deleted
01426      * - It also appears that realloc can return non-zero ptr when size = 0.
01427      *   Hence for this case free() is used.
01428      */
01429     CFSTORE_FENTRYLOG("%s:entered:\n", __func__);
01430     CFSTORE_TP(CFSTORE_TP_MEM, "%s:cfstore_ctx_g.area_0_head=%p, cfstore_ctx_g.area_0_tail=%p, cfstore_ctx_g.area_0_len=%d, size=%d, \n", __func__, ctx->area_0_head, ctx->area_0_tail, (int) ctx->area_0_len, (int) size);
01431 
01432     if(size > 0)
01433     {
01434         /* In the general case (size % program_unit > 0). The new area_0 size is
01435          * aligned to a flash program_unit boundary to facilitate r/w to flash
01436          * and so the memory realloc size is calculated to align, as follows */
01437         if(size % cfstore_ctx_get_program_unit(ctx) > 0){
01438             size += (cfstore_ctx_get_program_unit(ctx) - (size % cfstore_ctx_get_program_unit(ctx)));
01439         }
01440 
01441         ptr = (uint8_t*) CFSTORE_REALLOC((void*) ctx->area_0_head, size);
01442         if (ptr == NULL) {
01443             if (total_kv_size <= ctx->area_0_len) {
01444                 /* Size is shrinking so a realloc failure is recoverable.
01445                  * Update ptr so it matches the previous head.
01446                  */
01447                 ptr = ctx->area_0_head;
01448             }
01449         }
01450         if(ptr == NULL){
01451             CFSTORE_ERRLOG("%s:Error: unable to allocate memory (size=%d)\n", __func__, (int) size);
01452             /* realloc() has failed to allocate the required memory object. If previously
01453              * allocation has been made, the old memory object remains allocated. On error, the client
01454              * is expected to clean up including making a call to Uninitialize() which will free the
01455              * old memory object.
01456              */
01457             return ARM_CFSTORE_DRIVER_ERROR_OUT_OF_MEMORY;
01458         }
01459         /* check realloc() hasn't move area in memory from cfstore_ctx_g.area_0_head */
01460         if(ptr != ctx->area_0_head){
01461             /* realloc() has moved the area in memory */
01462             CFSTORE_TP(CFSTORE_TP_MEM, "%s: realloc() has moved memory area and area_0_head ptr must change. old cfstore_ctx_g.area_0_head=%p, new head ptr=%p)\n", __func__, ctx->area_0_head, ptr);
01463 
01464             /* now have to walk the file list updating head pointers to point into the realloc-ed
01465              * To begin with, leave the relative position of the file pointers unaltered */
01466             node = file_list->next;
01467             while(node != file_list){
01468                 file = (cfstore_file_t*) node;
01469                 file->head = (uint8_t *) (file->head - ctx->area_0_head);
01470                 file->head = (uint8_t *) ((int32_t) file->head + (int32_t) ptr);
01471                 node = node->next;
01472             }
01473             ctx->area_0_head = ptr;
01474         }
01475 
01476         /* If the area is growing then zero the new space at the end of the area */
01477         len_diff = size - (int32_t) ctx->area_0_len;
01478         if(len_diff > 0) {
01479             memset(ptr + ctx->area_0_len, 0, len_diff);
01480         }
01481         /* Set area_0_tail to be the memory address after the end of the last KV in the memory area.
01482          * This is the only place that area_0_tail should be changed, apart from cfstore_flash_set_tail()
01483          * which is only called when attributes are loaded from flash.
01484          */
01485         ctx->area_0_len = size;
01486         ctx->area_0_tail = ptr + total_kv_size;
01487         if(allocated_size != NULL) {
01488             *allocated_size = size;
01489         }
01490     }
01491     else
01492     {
01493         /* size = 0 so delete the memory */
01494         CFSTORE_FREE((void*) ctx->area_0_head);
01495         ctx->area_0_head = NULL;
01496         ctx->area_0_tail = NULL;
01497         ctx->area_0_len = 0;
01498     }
01499     CFSTORE_TP(CFSTORE_TP_MEM, "%s:cfstore_ctx_g.area_0_head=%p, cfstore_ctx_g.area_0_tail=%p\n", __func__, ctx->area_0_head, ctx->area_0_tail);
01500     ret = ARM_DRIVER_OK;
01501     return ret;
01502 
01503 }
01504 
01505 
01506 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
01507 
01508 /*
01509  * flash helper functions
01510  */
01511 
01512 /* @brief   table for mapping flash journal error codes to equivalent cfstore error codes */
01513 static cfstore_flash_journal_error_code_node cfstore_flash_journal_error_code_map[]=
01514 {
01515     { JOURNAL_STATUS_OK,                                ARM_DRIVER_OK},
01516     { JOURNAL_STATUS_ERROR,                             ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_ERROR},
01517     { JOURNAL_STATUS_BUSY,                              ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_BUSY},
01518     { JOURNAL_STATUS_TIMEOUT,                           ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_TIMEOUT},
01519     { JOURNAL_STATUS_UNSUPPORTED,                       ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_UNSUPPORTED},
01520     { JOURNAL_STATUS_PARAMETER,                         ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_PARAMETER},
01521     { JOURNAL_STATUS_BOUNDED_CAPACITY,                  ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_BOUNDED_CAPACITY},
01522     { JOURNAL_STATUS_STORAGE_API_ERROR,                 ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_STORAGE_API_ERROR},
01523     { JOURNAL_STATUS_STORAGE_IO_ERROR,                  ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_STORAGE_IO_ERROR},
01524     { JOURNAL_STATUS_NOT_INITIALIZED,                   ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_NOT_INITIALIZED},
01525     { JOURNAL_STATUS_EMPTY,                             ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_EMPTY},
01526     { JOURNAL_STATUS_SMALL_LOG_REQUEST,                 ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_SMALL_LOG_REQUEST},
01527     { CFSTORE_SENTINEL, CFSTORE_SENTINEL}
01528 };
01529 
01530 static int32_t cfstore_flash_map_error(int32_t flash_journal_status_code)
01531 {
01532     cfstore_flash_journal_error_code_node* node = cfstore_flash_journal_error_code_map;
01533 
01534     while(node->flash_journal_error_code != (int32_t) CFSTORE_SENTINEL)
01535     {
01536         if(flash_journal_status_code == node->flash_journal_error_code)
01537         {
01538             return node->cfstore_error_code;
01539         }
01540     }
01541     return ARM_CFSTORE_DRIVER_ERROR_INTERNAL;
01542 }
01543 
01544 
01545 /* @brief   Callback registered with flash journal for async operation
01546  *          completion notifications.
01547  *
01548  * @note    The callback is called at interrupt context.
01549  *          The critical section to used police access to context variables
01550  *          modified by both the interrupt and application context processing.
01551  *          The interrupt context prevents application context from running and
01552  *          hence its only necessary to use the critical_section_xxx in the
01553  *          application execution context.
01554  *
01555  *          In flash journal async mode, when:
01556  *              - a FlashJournal_xxx() function has been invoked, and
01557  *              - before the async completion has been received and processed
01558  *          the application context code should alway co-ordinate access to
01559  *          context variables modified by interrupt and application context
01560  *          by use of the critical_section_xxx.
01561  */
01562 static void cfstore_flash_journal_callback(int32_t status, FlashJournal_OpCode_t cmd_code)
01563 {
01564     cfstore_ctx_t* ctx = cfstore_ctx_get();
01565 
01566     CFSTORE_FENTRYLOG("%s:entered: status=%d, cmd_code=%d (%s)\n", __func__, (int) status, (int) cmd_code, cfstore_flash_opcode_str[cmd_code]);
01567     switch(cmd_code)
01568     {
01569     case FLASH_JOURNAL_OPCODE_FORMAT:
01570         ctx->fsm.event = cfstore_fsm_event_format_done;
01571         break;
01572     case FLASH_JOURNAL_OPCODE_INITIALIZE:
01573         ctx->fsm.event = cfstore_fsm_event_init_done;
01574         break;
01575     case FLASH_JOURNAL_OPCODE_READ_BLOB:
01576         ctx->fsm.event = cfstore_fsm_event_read_done;
01577         break;
01578     case FLASH_JOURNAL_OPCODE_LOG_BLOB:
01579         ctx->fsm.event = cfstore_fsm_event_log_done;
01580         break;
01581     case FLASH_JOURNAL_OPCODE_COMMIT:
01582         ctx->fsm.event = cfstore_fsm_event_commit_done;
01583         break;
01584     case FLASH_JOURNAL_OPCODE_RESET:
01585         ctx->fsm.event = cfstore_fsm_event_reset_done;
01586         break;
01587     case FLASH_JOURNAL_OPCODE_GET_INFO:
01588     default:
01589         CFSTORE_ERRLOG("%s:Error: notification of unsupported cmd_code event (status=%d, cmd_code=%d)\n", __func__, (int) status, (int) cmd_code);
01590         return;
01591     }
01592     ctx->status = status;
01593     ctx->cmd_code = cmd_code;
01594     cfstore_fsm_state_handle_event(&ctx->fsm, ctx->fsm.event, (void*) ctx);
01595     return;
01596 }
01597 
01598 
01599 /* @brief */
01600 static int32_t cfstore_fsm_stop_on_entry(void* context)
01601 {
01602     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
01603 
01604     /* reset fsm state */
01605     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
01606     CFSTORE_ASSERT(ctx->fsm.state == cfstore_fsm_state_stopped);
01607 
01608     ctx->fsm.event = cfstore_fsm_event_max;
01609     ctx->cmd_code = (FlashJournal_OpCode_t)((int) FLASH_JOURNAL_OPCODE_RESET+1);
01610     return ARM_DRIVER_OK;
01611 }
01612 
01613 /* static int32_t cfstore_fsm_stop_on_exit(void* context) {(void) context; }*/
01614 
01615 
01616 /* @brief   fsm on entry function for the initing state
01617  * @note
01618  *  flash journal sync mode: (see async mode notes)
01619  *  flash journal async mode:
01620  *      This is typically called in app context (not intr context) for both flash
01621  *      journal sync and asyc modes. There are no outstanding async requests
01622  *      so it cannot be interrupted, and therefore doesnt need CS protection.
01623  */
01624 static int32_t cfstore_fsm_init_on_entry(void* context)
01625 {
01626     int32_t ret = ARM_DRIVER_ERROR;
01627     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
01628 
01629     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
01630 
01631     ret = cfstore_svm_init(&cfstore_journal_mtd);
01632     if(ret < ARM_DRIVER_OK){
01633         CFSTORE_DBGLOG("%s:Error: Unable to initialize storage volume manager\n", __func__);
01634         cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_formatting, ctx);
01635         return ARM_DRIVER_OK;
01636     }
01637 
01638     ret = FlashJournal_initialize(&ctx->jrnl, (ARM_DRIVER_STORAGE *) &cfstore_journal_mtd, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, cfstore_flash_journal_callback);
01639     CFSTORE_TP(CFSTORE_TP_FSM, "%s:FlashJournal_initialize ret=%d\n", __func__, (int) ret);
01640     if(ret < ARM_DRIVER_OK){
01641         if(ret == JOURNAL_STATUS_NOT_FORMATTED) {
01642             CFSTORE_DBGLOG("%s:Error: flash not formatted\n", __func__);
01643             cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_formatting, ctx);
01644             return ARM_DRIVER_OK;
01645         }
01646         if(ret == JOURNAL_STATUS_METADATA_ERROR) {
01647             CFSTORE_ERRLOG("%s:Error: flash meta-data (CRC) error detected when initializing flash. Reformatting flash.\n", __func__);
01648             cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_formatting, ctx);
01649             return ARM_DRIVER_OK;
01650         }
01651         CFSTORE_ERRLOG("%s:Error: failed to initialize flash journaling layer (ret=%d)\n", __func__, (int) ret);
01652         cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_stopped, ctx);
01653     }
01654     else if(ret > 0){
01655         /* operation completed synchronously*/
01656         cfstore_flash_journal_callback(ret, FLASH_JOURNAL_OPCODE_INITIALIZE);
01657     }
01658     return ret;
01659 }
01660 
01661 
01662 /* @brief   fsm initing state handler function
01663  * @note
01664  *  flash journal sync mode:
01665  *      CS protection not required as there are no callbacks.
01666  *  flash journal async mode:
01667  *      This is typically called at intr context (not app context) when flash
01668  *      journal invokes the callback handler for FLASH_JOURNAL_OPCODE_INITIALIZE
01669  *      Hence as running at intr level, no CS protection is required.
01670  */
01671 static int32_t cfstore_fsm_initing(void* context)
01672 {
01673     int32_t ret = ARM_DRIVER_OK;
01674     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
01675 
01676     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
01677     CFSTORE_ASSERT(ctx->fsm.state == cfstore_fsm_state_initing);
01678     CFSTORE_ASSERT(ctx->cmd_code == FLASH_JOURNAL_OPCODE_INITIALIZE);
01679 
01680     /* only change state if status > 0*/
01681     if(ctx->status > 0){
01682         ret = cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_reading, ctx);
01683     } else if(ctx->status < 0) {
01684         CFSTORE_ERRLOG("%s:Error: failed to initialize flash journaling layer (ret=%d)\n", __func__, (int) ctx->status);
01685         cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_stopped, ctx);
01686     }
01687     return ret;
01688 }
01689 
01690 /* static int32_t cfstore_fsm_init_on_exit(void* context) */
01691 
01692 
01693 /* @brief   fsm on entry function for the reading state
01694  * @note
01695  *  flash journal sync mode:
01696  *      CS protection not required as there are no callbacks.
01697  *  flash journal async mode:
01698  *      This is typically called at intr context (not app context) when flash
01699  *      journal invokes the callback handler for FLASH_JOURNAL_OPCODE_INITIALIZE
01700  *      Hence as running at intr level, no CS protection is required.
01701  */
01702 static int32_t cfstore_fsm_read_on_entry(void* context)
01703 {
01704     int32_t ret = 0;
01705     FlashJournal_Status_t status = JOURNAL_STATUS_ERROR;
01706     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
01707 
01708     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
01709     CFSTORE_ASSERT(ctx != NULL);
01710     /* FlashJournal_getInfo() is synchronous */
01711     status = FlashJournal_getInfo(&ctx->jrnl, &ctx->info);
01712     if(status < JOURNAL_STATUS_OK){
01713         CFSTORE_TP(CFSTORE_TP_FSM, "%s:Error: failed get journal info (status=%d)\n", __func__, (int) status);
01714         /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01715         cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01716         ret = ARM_CFSTORE_DRIVER_ERROR_INTERNAL;
01717         goto out;
01718     }
01719     if(ctx->info.sizeofJournaledBlob > 0)
01720     {
01721         /* setup the expected blob size for writing */
01722         ctx->expected_blob_size = ctx->info.sizeofJournaledBlob;
01723         ret = cfstore_realloc_ex(ctx->expected_blob_size, &ctx->expected_blob_size);
01724         if(ret < ARM_DRIVER_OK){
01725             CFSTORE_ERRLOG("%s:Error: cfstore_realloc_ex() failed (ret=%d)\n", __func__, (int) ret);
01726             /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01727             cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01728             goto out;
01729         }
01730         ret = FlashJournal_read(&ctx->jrnl, (void*) ctx->area_0_head, ctx->info.sizeofJournaledBlob);
01731         if(ret < ARM_DRIVER_OK){
01732             CFSTORE_ERRLOG("%s:Error: failed to initialize flash journaling layer (ret=%d)\n", __func__, (int) ret);
01733             /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01734             cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01735             goto out;
01736         } else if(ret > 0){
01737             /* read has completed synchronously*/
01738             CFSTORE_TP(CFSTORE_TP_FSM, "%s:debug:ret > 0: (ret=%d)\n", __func__, (int) ret);
01739             cfstore_flash_journal_callback(ret, FLASH_JOURNAL_OPCODE_READ_BLOB);
01740             ret = ctx->status;
01741             goto out;
01742         }
01743         /* keep lock and wait for async callback */
01744     } else {
01745         /* there is no blob, move to next state. need a +ve status value to indicate async completion
01746          * to the fsm reading state handler. use CFSTORE_FLASH_AREA_SIZE_MIN for this value */
01747         ctx->expected_blob_size = CFSTORE_FLASH_AREA_SIZE_MIN;
01748         status = (FlashJournal_Status_t) CFSTORE_FLASH_AREA_SIZE_MIN;
01749         cfstore_flash_journal_callback(status, FLASH_JOURNAL_OPCODE_READ_BLOB);
01750         ret = ctx->status;
01751         goto out;
01752     }
01753 out:
01754     return ret;
01755 }
01756 
01757 
01758 /* @brief  fsm handler when in reading state */
01759 static int32_t cfstore_fsm_reading(void* context)
01760 {
01761     int32_t ret = ARM_DRIVER_ERROR;
01762     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
01763 
01764     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
01765     CFSTORE_ASSERT(ctx->fsm.state == cfstore_fsm_state_reading);
01766     CFSTORE_ASSERT(ctx->cmd_code == FLASH_JOURNAL_OPCODE_READ_BLOB);
01767     if(ctx->status > 0)
01768     {
01769         if(ctx->status > (int32_t) CFSTORE_FLASH_AREA_SIZE_MIN)
01770         {
01771             CFSTORE_TP(CFSTORE_TP_FSM, "%s:debug:ctx->status > (int32_t) CFSTORE_FLASH_AREA_SIZE_MIN:\n", __func__);
01772             /* check the correct amount of data was read, which is the status code */
01773             if(ctx->status == (int32_t) ctx->expected_blob_size)
01774             {
01775                 /* now have to allow for the fact that there may have been some padding
01776                  * at the end of the last _log() to flash, so the read back area may have
01777                  * padding at the end, and the tail_pointer needs to not point to the
01778                  * end where the padding is located, but to the end of the last KV.
01779                  */
01780                 ret = cfstore_flash_set_tail();
01781                 if(ret < ARM_DRIVER_OK){
01782                     CFSTORE_ERRLOG("%s:Error: cfstore_flash_set_tail() failed (ret=%d)\n", __func__, (int) ret);
01783                     /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01784                     cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01785                     memset(&ctx->info, 0, sizeof(ctx->info));
01786                     goto out;
01787                 }
01788                 ret = cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01789                 if(ret < ARM_DRIVER_OK){
01790                     CFSTORE_ERRLOG("%s:Error: cfstore_fsm_state_set() failed (ret=%d)\n", __func__, (int) ret);
01791                     goto out;
01792                 }
01793                 ret = ctx->status;
01794             }
01795             else
01796             {
01797                 CFSTORE_ERRLOG("%s:Error: read bytes (%d) does not equal requested read size (%d)\n", __func__, (int) ctx->status, (int) ctx->expected_blob_size);
01798                 ret = cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01799                 if(ret < ARM_DRIVER_OK){
01800                     /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01801                     CFSTORE_ERRLOG("%s:Error: cfstore_fsm_state_set() failed (ret=%d)\n", __func__, (int) ret);
01802                     goto out;
01803                 }
01804                 ret = ctx->status;
01805             }
01806         }
01807         else
01808         {
01809             CFSTORE_TP(CFSTORE_TP_FSM, "%s:debug:ctx->status <= (int32_t) CFSTORE_FLASH_AREA_SIZE_MIN:\n", __func__);
01810             ret = cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01811             if(ret < ARM_DRIVER_OK){
01812                 /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01813                 CFSTORE_ERRLOG("%s:Error: cfstore_fsm_state_set() failed (ret=%d)\n", __func__, (int) ret);
01814                 goto out;
01815             }
01816             ret = ctx->status;
01817         }
01818     }
01819     else if(ctx->status < 0)
01820     {
01821         CFSTORE_TP(CFSTORE_TP_FSM, "%s:debug:ctx->status < 0:\n", __func__);
01822         ret = ctx->status;
01823     }
01824 out:
01825     return ret;
01826 }
01827 
01828 
01829 static int32_t cfstore_fsm_read_on_exit(void* context)
01830 {
01831     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
01832 
01833     CFSTORE_FENTRYLOG("%s:entered:\n", __func__);
01834     /* notify client of initialisation status */
01835     cfstore_client_notify_data_init(&ctx->client_notify_data, CFSTORE_OPCODE_INITIALIZE, ctx->status, NULL);
01836     ctx->client_callback_notify_flag = true;
01837     return ARM_DRIVER_OK;
01838 }
01839 
01840 /* int32_t cfstore_fsm_log_on_entry(void* context){ (void) context;} */
01841 
01842 /* @brief   on entry to writing state, update value */
01843 int32_t cfstore_fsm_log_on_entry(void* context)
01844 {
01845     int32_t ret = 0;
01846     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
01847     FlashJournal_Info_t info;
01848     FlashJournal_Status_t status = JOURNAL_STATUS_ERROR;
01849 
01850     CFSTORE_FENTRYLOG("%s:entered:\n", __func__);
01851     memset(&info, 0, sizeof(info));
01852 
01853     status = FlashJournal_getInfo(&ctx->jrnl, &info);
01854     if(status < JOURNAL_STATUS_OK){
01855         CFSTORE_ERRLOG("%s:Error: failed get journal info (status=%d)\n", __func__, (int) status);
01856         /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01857         cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01858         return cfstore_flash_map_error(status);
01859     }
01860     /* compute the expected_blob_size = area_size plus the padding at the end of the area to align with program_unit*/
01861     ctx->expected_blob_size = cfstore_ctx_get_kv_total_len();
01862     if(ctx->expected_blob_size % info.program_unit > 0){
01863         ctx->expected_blob_size += (info.program_unit - (ctx->expected_blob_size % info.program_unit));
01864     }
01865     /* log the changes to flash even when the area has shrunk to 0, as its necessary to erase the flash */
01866     if(ctx->area_dirty_flag == true)
01867     {
01868         if(ctx->expected_blob_size > 0){
01869             CFSTORE_TP(CFSTORE_TP_FLUSH, "%s:logging: ctx->area_0_head=%p, ctx->expected_blob_size-%d\n", __func__, ctx->area_0_head, (int) ctx->expected_blob_size);
01870             ret = FlashJournal_log(&ctx->jrnl, (const void*) ctx->area_0_head, ctx->expected_blob_size);
01871             if(ret < JOURNAL_STATUS_OK){
01872                 CFSTORE_ERRLOG("%s:Error: FlashJournal_commit() failed (ret=%d)\n", __func__, (int) ret);
01873                 ret = cfstore_flash_map_error(status);
01874                 /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01875                 cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01876                 goto out0;
01877             } else if(ret > 0){
01878                 /* read has completed synchronously*/
01879                 cfstore_flash_journal_callback(ret, FLASH_JOURNAL_OPCODE_LOG_BLOB);
01880                 ret = ctx->status;
01881             }
01882             /* wait for async completion handler*/
01883         } else {
01884             /* expected_blob_size == 0
01885              * There are no entries in the cfstore (e.g. last entry has been deleted) and this needs
01886              * reflecting in the flash. A log is not required (as there is not data). Initiate the
01887              * commit which will zero the flash
01888              * */
01889             CFSTORE_TP(CFSTORE_TP_FLUSH, "%s:skip logging: initiate commit to erase flash\n", __func__);
01890             ret = JOURNAL_STATUS_OK;
01891             cfstore_flash_journal_callback(ret, FLASH_JOURNAL_OPCODE_LOG_BLOB);
01892         }
01893     }
01894     else
01895     {
01896         /* nothing to be logged so move back to ready state indicating success*/
01897         CFSTORE_TP(CFSTORE_TP_FLUSH, "%s:not logging: ctx->area_0_head=%p, ctx->expected_blob_size-=%d\n", __func__, ctx->area_0_head, (int) ctx->expected_blob_size);
01898         cfstore_flash_journal_callback(ctx->expected_blob_size, FLASH_JOURNAL_OPCODE_LOG_BLOB);
01899     }
01900 out0:
01901     return ret;
01902 }
01903 
01904 /* @brief  fsm handler when in reading state */
01905 static int32_t cfstore_fsm_logging(void* context)
01906 {
01907     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
01908 
01909     CFSTORE_FENTRYLOG("%s:entered:ctx->status=%ld\n", __func__, ctx->status);
01910     /* check the correct amount of data was written */
01911     if(ctx->status < JOURNAL_STATUS_OK){
01912         CFSTORE_ERRLOG("%s:Error: FlashJournal_log() failed (ret=%d)\n", __func__, (int) ctx->status);
01913         /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01914         cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01915         ctx->status = cfstore_flash_map_error(ctx->status);
01916     }
01917     else
01918     {   /* ctx->status >= 0 (status == 0 when everything is deleted) */
01919         if(ctx->status == (int32_t)ctx->expected_blob_size){
01920             /* move to the committing state to commit to flash*/
01921             ctx->status = cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_committing, ctx);
01922         } else {
01923             CFSTORE_ERRLOG("%s:Error: FlashJournal_log() failed to log the expected number of bytes (ctx->expected_blob_size=%d, committed=%d)\n", __func__, (int) ctx->expected_blob_size, (int) ctx->status);
01924             ctx->status = ARM_DRIVER_ERROR;
01925         }
01926     }
01927     return ctx->status;
01928 }
01929 
01930 
01931 static int32_t cfstore_fsm_log_on_exit(void* context)
01932 {
01933     (void) context;
01934     CFSTORE_FENTRYLOG("%s:entered:\n", __func__);
01935     return ARM_DRIVER_OK;
01936 }
01937 
01938 
01939 /* @brief  fsm handler when entering committing state
01940  * @note
01941  * Its unnecessary to provide CS protection for the flashJouranl_commit() as the all the
01942  * _log() operations affecting the commit have been performed, and no more _log() operations
01943  * can happen until we're back in the ready state
01944  */
01945 static int32_t cfstore_fsm_commit_on_entry(void* context)
01946 {
01947     int32_t ret = JOURNAL_STATUS_OK;
01948     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
01949 
01950     CFSTORE_FENTRYLOG("%s:entered:\n", __func__);
01951     if(ctx->area_dirty_flag == true)
01952     {
01953         ret = FlashJournal_commit(&ctx->jrnl);
01954         CFSTORE_TP(CFSTORE_TP_FSM, "%s:debug: FlashJournal_commit() (ret=%d)\n", __func__, (int) ret);
01955         if(ret < JOURNAL_STATUS_OK){
01956             CFSTORE_ERRLOG("%s:Error: FlashJournal_commit() failed (ret=%d)\n", __func__, (int) ret);
01957             /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01958             cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01959         } else if(ret > 0){
01960             /* read has completed synchronously*/
01961             cfstore_flash_journal_callback(ret, FLASH_JOURNAL_OPCODE_COMMIT);
01962             ret = ctx->status;
01963         }
01964     }
01965     else
01966     {
01967         /* a commit should not be made because there have been no flashJournal_log() calls since the last commit.
01968          * If a _commit() call was made without any _log() calls then it would result in the flash being erased
01969          * because flash journal essentially contains a mirror image of the configuration store sram area, which
01970          * has to be *** FULLY*** repopulated before each _commit(). */
01971         cfstore_flash_journal_callback(ARM_DRIVER_OK_DONE, FLASH_JOURNAL_OPCODE_COMMIT);
01972         ret = ctx->status;
01973     }
01974     /* wait for async callback */
01975     CFSTORE_FENTRYLOG("%s:exiting: FlashJournal_commit() (ret=%d)\n", __func__, (int) ret);
01976     return ret;
01977 }
01978 
01979 
01980 /* @brief  fsm handler when in committing state
01981  * @note
01982  * Its unnecessary to provide CS protection for the flashJouranl_commit() as the all the
01983  * _log() operations affecting the commit have been performed, and no more _log() operations
01984  * can happen until we're back in the ready state
01985  */
01986 static int32_t cfstore_fsm_committing(void* context)
01987 {
01988     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
01989 
01990     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
01991     CFSTORE_ASSERT(ctx->fsm.state == cfstore_fsm_state_committing);
01992     CFSTORE_ASSERT(ctx->cmd_code == FLASH_JOURNAL_OPCODE_COMMIT);
01993 
01994     /* check the correct amount of data was written */
01995     if(ctx->status < JOURNAL_STATUS_OK){
01996         CFSTORE_ERRLOG("%s:Error: FlashJournal_commit() failed (ret=%d)\n", __func__, (int) ctx->status);
01997         /* move to ready state. cfstore client is expected to Uninitialize() before further calls */
01998         cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
01999         ctx->status = cfstore_flash_map_error(ctx->status);
02000     }
02001     else if(ctx->status == JOURNAL_STATUS_OK)
02002     {
02003         ctx->status = cfstore_flash_map_error(ctx->status);
02004     }
02005     else
02006     {   /* ctx->status > 0. for flash-journal-strategy-sequential version >0.4.0, commit() return no longer reports size of commit block */
02007         ctx->status = cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_ready, ctx);
02008     }
02009     return ctx->status;
02010 }
02011 
02012 static int32_t cfstore_fsm_commit_on_exit(void* context)
02013 {
02014     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
02015 
02016     CFSTORE_FENTRYLOG("%s:entered:\n", __func__);
02017     ctx->area_dirty_flag = false;
02018     /* notify client of commit status */
02019     cfstore_client_notify_data_init(&ctx->client_notify_data, CFSTORE_OPCODE_FLUSH, ctx->status, NULL);
02020     ctx->client_callback_notify_flag = true;
02021     return ARM_DRIVER_OK;
02022 }
02023 
02024 /* int32_t cfstore_fsm_reset_on_entry(void* context){ (void) context;} */
02025 /* int32_t cfstore_fsm_resetting(void* context){ (void) context;} */
02026 /* int32_t cfstore_fsm_reset_on_exit(void* context){ (void) context;} */
02027 
02028 
02029 static int32_t cfstore_fsm_ready_on_commit_req(void* context)
02030 {
02031     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
02032     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
02033     return cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_logging, ctx);
02034 }
02035 
02036 /* int32_t cfstore_fsm_ready_on_entry(void* context){ (void) context;} */
02037 /* int32_t cfstore_fsm_ready(void* context){ (void) context;} */
02038 /* int32_t cfstore_fsm_ready_on_exit(void* context){ (void) context;} */
02039 
02040 
02041 /** @brief  fsm handler when entering the formatting state
02042  */
02043 static int32_t cfstore_fsm_format_on_entry(void* context)
02044 {
02045     int32_t ret = ARM_DRIVER_ERROR;
02046     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
02047 
02048     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
02049 
02050     ret = flashJournalStrategySequential_format((ARM_DRIVER_STORAGE *) &cfstore_journal_mtd, CFSTORE_FLASH_NUMSLOTS, cfstore_flash_journal_callback);
02051     CFSTORE_TP(CFSTORE_TP_FSM, "%s:flashJournalStrategySequential_format ret=%d\n", __func__, (int) ret);
02052     if(ret < ARM_DRIVER_OK){
02053         CFSTORE_ERRLOG("%s:Error: failed to format flash (ret=%d)\n", __func__, (int) ret);
02054         cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_stopped, ctx);
02055     }
02056     else if(ret > 0){
02057         /* operation completed synchronously*/
02058         cfstore_flash_journal_callback(ret, FLASH_JOURNAL_OPCODE_FORMAT);
02059     }
02060     return ret;
02061 }
02062 
02063 /** @brief  fsm handler when in formatting state
02064  */
02065 int32_t cfstore_fsm_formatting(void* context)
02066 {
02067     int32_t ret = ARM_DRIVER_OK;
02068     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
02069 
02070     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
02071     CFSTORE_ASSERT(ctx->fsm.state == cfstore_fsm_state_formatting);
02072     CFSTORE_ASSERT(ctx->cmd_code == FLASH_JOURNAL_OPCODE_FORMAT);
02073 
02074     /* only change state if status > 0*/
02075     if(ctx->status > 0){
02076         ret = cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_initing, ctx);
02077     } else if(ctx->status < 0) {
02078         CFSTORE_ERRLOG("%s:Error: failed to format flash (ret=%d)\n", __func__, (int) ctx->status);
02079         cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_stopped, ctx);
02080     }
02081     return ret;
02082 }
02083 
02084 /* int32_t cfstore_fsm_format_on_exit(void* context){ (void) context;} */
02085 
02086 
02087 /* handler functions while in state */
02088 static cfstore_fsm_handler cfstore_flash_fsm[cfstore_fsm_state_max][cfstore_fsm_event_max] =
02089 {
02090 /* state\event:   init_done               read_done             log_done              commit_req                            commit_done               reset_done                format_done, */
02091 /* stopped    */  {cfstore_fsm_null,      cfstore_fsm_null,     cfstore_fsm_null,     cfstore_fsm_null,                     cfstore_fsm_null,         cfstore_fsm_null,     cfstore_fsm_null        },
02092 /* init       */  {cfstore_fsm_initing,   cfstore_fsm_null,     cfstore_fsm_null,     cfstore_fsm_null,                     cfstore_fsm_null,         cfstore_fsm_null,     cfstore_fsm_null        },
02093 /* reading    */  {cfstore_fsm_null,      cfstore_fsm_reading,  cfstore_fsm_null,     cfstore_fsm_null,                     cfstore_fsm_null,         cfstore_fsm_null,     cfstore_fsm_null        },
02094 /* logging    */  {cfstore_fsm_null,      cfstore_fsm_null,     cfstore_fsm_logging,  cfstore_fsm_null,                     cfstore_fsm_null,         cfstore_fsm_null,     cfstore_fsm_null        },
02095 /* committing */  {cfstore_fsm_null,      cfstore_fsm_null,     cfstore_fsm_null,     cfstore_fsm_null,                     cfstore_fsm_committing,   cfstore_fsm_null,     cfstore_fsm_null        },
02096 /* resetting  */  {cfstore_fsm_null,      cfstore_fsm_null,     cfstore_fsm_null,     cfstore_fsm_null,                     cfstore_fsm_null,         cfstore_fsm_null,     cfstore_fsm_null        },
02097 /* ready      */  {cfstore_fsm_null,      cfstore_fsm_null,     cfstore_fsm_null,     cfstore_fsm_ready_on_commit_req,      cfstore_fsm_null,         cfstore_fsm_null,     cfstore_fsm_null        },
02098 /* formatting */  {cfstore_fsm_null,      cfstore_fsm_null,     cfstore_fsm_null,     cfstore_fsm_null,                     cfstore_fsm_null,         cfstore_fsm_null,     cfstore_fsm_formatting  },
02099 };
02100 
02101 /* handler functions for entering the state*/
02102 cfstore_fsm_handler cfstore_fsm_on_entry[cfstore_fsm_state_max] =
02103 {
02104     cfstore_fsm_stop_on_entry,
02105     cfstore_fsm_init_on_entry,
02106     cfstore_fsm_read_on_entry,
02107     cfstore_fsm_log_on_entry,
02108     cfstore_fsm_commit_on_entry,
02109     cfstore_fsm_null,               /* cfstore_fsm_reset_on_entry */
02110     cfstore_fsm_null,               /* cfstore_fsm_ready_on_entry */
02111     cfstore_fsm_format_on_entry     /* cfstore_fsm_format_on_entry */
02112 };
02113 
02114 /* handler functions for exiting state, currently none used */
02115 cfstore_fsm_handler cfstore_fsm_on_exit[cfstore_fsm_state_max] =
02116 {
02117     cfstore_fsm_null,             /* cfstore_fsm_stop_on_exit */
02118     cfstore_fsm_null,             /* cfstore_fsm_init_on_exit */
02119     cfstore_fsm_read_on_exit,
02120     cfstore_fsm_log_on_exit,
02121     cfstore_fsm_commit_on_exit,
02122     cfstore_fsm_null,             /* cfstore_fsm_reset_on_exit */
02123     cfstore_fsm_null,             /* cfstore_fsm_ready_on_exit */
02124     cfstore_fsm_null              /* cfstore_fsm_format_on_exit */
02125 };
02126 
02127 
02128 /* @brief   inject event into fsm */
02129 static int32_t cfstore_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_fsm_event_t event, void* context)
02130 {
02131     int32_t ret = ARM_DRIVER_ERROR;
02132     cfstore_ctx_t* ctx = (cfstore_ctx_t*) context;
02133 
02134     CFSTORE_FENTRYLOG("%s:entered: fsm=%p, fsm->state=%d, event=%d (%s), ctx=%p\n", __func__, fsm, fsm->state, event, cfstore_flash_event_str[event], ctx);
02135     CFSTORE_ASSERT(event < cfstore_fsm_event_max);
02136     fsm->event = event;
02137     if(cfstore_flash_fsm[fsm->state][fsm->event] != NULL){
02138         ret = cfstore_flash_fsm[fsm->state][fsm->event](ctx);
02139         if(ret < ARM_DRIVER_OK){
02140             #ifdef CFSTORE_DEBUG
02141             CFSTORE_ERRLOG("%s:FSM:EVT:Error: cfstore_flash_fsm[%s][%s] failed\n", __func__, (char*) cfstore_flash_state_str[fsm->state], (char*) cfstore_flash_event_str[fsm->event]);
02142             #endif
02143             return ret;
02144         }
02145     }
02146 
02147     /* do not clear context data set by caller as it may be used later
02148      *  fsm->event = cfstore_fsm_event_max;
02149      *  ctx->status = 0;
02150      *  ctx->cmd_code =  (FlashJournal_OpCode_t)((int) FLASH_JOURNAL_OPCODE_RESET+1);
02151      */
02152     return ret;
02153 }
02154 
02155 
02156 /* @brief   get the current state of the fsm */
02157 static cfstore_fsm_state_t cfstore_fsm_state_get(cfstore_fsm_t* fsm)
02158 {
02159     return fsm->state;
02160 }
02161 
02162 /* @brief   function to move to new fsm state, calling state exit function for old state and entry function for new state */
02163 static int32_t cfstore_fsm_state_set(cfstore_fsm_t* fsm, cfstore_fsm_state_t new_state, void* ctx)
02164 {
02165     int32_t ret = ARM_DRIVER_ERROR;
02166     cfstore_ctx_t* context = (cfstore_ctx_t*) ctx;
02167     #ifdef CFSTORE_DEBUG
02168     cfstore_fsm_state_t old_state = fsm->state;
02169     #endif
02170 
02171     CFSTORE_FENTRYLOG("%s:entered: fsm=%p, ctx=%p\n", __func__, fsm, ctx);
02172     #ifdef CFSTORE_DEBUG
02173     CFSTORE_TP(CFSTORE_TP_FSM, "%s:FSM:REQ RX: fsm->state=%d (%s): new_state=%d (%s)\n", __func__, (int) fsm->state, cfstore_flash_state_str[fsm->state], (int) new_state, cfstore_flash_state_str[new_state]);
02174     #endif
02175     CFSTORE_ASSERT(fsm != NULL);
02176     CFSTORE_ASSERT(new_state < cfstore_fsm_state_max);
02177     CFSTORE_ASSERT(ctx != NULL);
02178     CFSTORE_ASSERT(fsm->state < cfstore_fsm_state_max);
02179 
02180     if(cfstore_fsm_on_exit[fsm->state] != NULL){
02181         ret = cfstore_fsm_on_exit[fsm->state](ctx);
02182         if(ret < ARM_DRIVER_OK){
02183             #ifdef CFSTORE_DEBUG
02184             CFSTORE_ERRLOG("%s:FSM:REQ RX:%s:%s:Error: cfstore_fsm_on_exit() failed\n", __func__, cfstore_flash_state_str[fsm->state], cfstore_flash_state_str[new_state]);
02185             #endif
02186             /* handling of the error is done in the on_exit() method, which best knows how the state to move to */
02187             return ret;
02188         }
02189     }
02190     fsm->state = new_state;
02191     if(cfstore_fsm_on_entry[new_state] != NULL){
02192         ret = cfstore_fsm_on_entry[new_state](ctx);
02193         if(ret < ARM_DRIVER_OK){
02194             #ifdef CFSTORE_DEBUG
02195             CFSTORE_TP(CFSTORE_TP_FSM, "%s:FSM:REQ RX: fsm->state=%d (%s): new_state=%d (%s): Error: cfstore_fsm_on_entry() failed (ret=%d)\n", __func__, (int) fsm->state, cfstore_flash_state_str[fsm->state], (int) new_state, cfstore_flash_state_str[new_state], (int) ret);
02196             #endif
02197             /* handling of the error is done in the on_entry() method, which best knows how the state to move to */
02198             return ret;
02199         }
02200     }
02201     if(context->client_callback_notify_flag == true)
02202     {
02203         cfstore_client_notify_data_t notify_data;
02204 
02205         CFSTORE_TP(CFSTORE_TP_FSM, "%s:doing client callback\n", __func__);
02206 
02207         /* only one set of client notify data is required as there can only be 1 outstanding flash journal async notificaion
02208          * at one time. */
02209         context->client_callback_notify_flag = false; /* prevents re-calling callback if this function gets called again */
02210         memcpy(&notify_data, &context->client_notify_data, sizeof(cfstore_client_notify_data_t));
02211         /* clear context state before initiating call */
02212         cfstore_client_notify_data_init(&context->client_notify_data, CFSTORE_OPCODE_MAX, ARM_DRIVER_ERROR, NULL);
02213         cfstore_ctx_client_notify(ctx, &notify_data);
02214     }
02215     CFSTORE_TP(CFSTORE_TP_FSM, "%s:FSM:REQ DONE: fsm->state=%d (%s): new_state=%d (%s)\n", __func__, (int) old_state, cfstore_flash_state_str[old_state], (int) new_state, cfstore_flash_state_str[new_state]);
02216     return ret;
02217 }
02218 
02219 static bool cfstore_flash_journal_is_async_op_pending(cfstore_ctx_t* ctx)
02220 {
02221     CFSTORE_FENTRYLOG("%s:entered: fsm->state=%s\n", __func__, (char*) cfstore_flash_state_str[cfstore_fsm_state_get(&ctx->fsm)]);
02222     if(cfstore_fsm_state_get(&ctx->fsm) != cfstore_fsm_state_ready)
02223     {
02224         /* flash journal async operation is in progress */
02225         return true;
02226     }
02227     return false;
02228 }
02229 
02230 static int32_t cfstore_flash_init(void)
02231 {
02232     int32_t ret = ARM_DRIVER_ERROR;
02233     cfstore_ctx_t* ctx = cfstore_ctx_get();
02234 
02235     CFSTORE_FENTRYLOG("%s:entered: \n", __func__);
02236     ctx->cmd_code = (FlashJournal_OpCode_t)((int) FLASH_JOURNAL_OPCODE_RESET+1);
02237     ctx->expected_blob_size = 0;
02238     ctx->fsm.event = cfstore_fsm_event_max;
02239     ctx->fsm.state = cfstore_fsm_state_stopped;
02240     memset(&ctx->info, 0, sizeof(ctx->info));
02241     ret = cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_initing, ctx);
02242     if(ret < 0){
02243         CFSTORE_DBGLOG("%s:Error: cfstore_fsm_state_set() failed\n", __func__);
02244         return ret;
02245     }
02246     return ret;
02247 }
02248 
02249 
02250 /* @brief   de-initialise the flash journal */
02251 static int32_t cfstore_flash_deinit(void)
02252 {
02253     int32_t ret = ARM_DRIVER_ERROR;
02254     cfstore_ctx_t* ctx = cfstore_ctx_get();
02255 
02256     CFSTORE_FENTRYLOG("%s:entered: fsm->state=%s\n", __func__, (char*) cfstore_flash_state_str[cfstore_fsm_state_get(&ctx->fsm)]);
02257     ret = cfstore_fsm_state_set(&ctx->fsm, cfstore_fsm_state_stopped, ctx);
02258     if(ret < 0){
02259         CFSTORE_TP(CFSTORE_TP_INIT, "%s:Error: cfstore_fsm_state_set() failed\n", __func__);
02260     }
02261     return ret;
02262 }
02263 
02264 /*
02265 static int32_t cfstore_flash_reset(void)
02266 {
02267     int32_t ret = ARM_DRIVER_ERROR;
02268     cfstore_ctx_t* ctx = cfstore_ctx_get();
02269 
02270     ret = FlashJournal_reset(&ctx->jrnl);
02271     if(ret != JOURNAL_STATUS_OK){
02272         CFSTORE_ERRLOG("%s:Error: failed to reset flash journal (ret=%d)\n", __func__, (int) ret);
02273         goto out0;
02274     }
02275 out0:
02276     return ret;
02277 }
02278 */
02279 
02280 static int32_t cfstore_flash_flush(cfstore_ctx_t* ctx)
02281 {
02282     int32_t ret = ARM_DRIVER_OK;
02283 
02284     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
02285     /* put the async completion code state variables into a known state */
02286     ctx->status = ARM_DRIVER_OK;
02287     ctx->cmd_code = (FlashJournal_OpCode_t)((int) FLASH_JOURNAL_OPCODE_RESET+1);
02288 
02289     /* cfstore_fsm_state_handle_event() is called at intr context via
02290      * cfstore_flash_journal_callback(), and hence calls from app context are
02291      * protected with CSs */
02292     cfstore_critical_section_lock(&ctx->rw_area0_lock, __func__);
02293     ret = cfstore_fsm_state_handle_event(&ctx->fsm, cfstore_fsm_event_commit_req, (void*) ctx);
02294     cfstore_critical_section_unlock(&ctx->rw_area0_lock, __func__);
02295     return ret;
02296 }
02297 
02298 #else /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
02299 
02300 static bool cfstore_flash_journal_is_async_op_pending(cfstore_ctx_t* ctx) { CFSTORE_FENTRYLOG("%s:SRAM:entered:\n", __func__); (void) ctx; return false; }
02301 
02302 /* @brief   generate the CFSTORE_OPCODE_INITIALIZE callback notification */
02303 static int32_t cfstore_flash_init(void)
02304 {
02305     cfstore_client_notify_data_t notify_data;
02306     cfstore_ctx_t* ctx = cfstore_ctx_get();
02307 
02308     CFSTORE_FENTRYLOG("%s:SRAM:entered:\n", __func__);
02309     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_INITIALIZE, ARM_DRIVER_OK, NULL);
02310     cfstore_ctx_client_notify(ctx, &notify_data);
02311     return ARM_DRIVER_OK;
02312 }
02313 
02314 static int32_t cfstore_flash_deinit(void){ CFSTORE_FENTRYLOG("%s:SRAM:entered:\n", __func__); return ARM_DRIVER_OK; }
02315 /* static int32_t cfstore_flash_reset(void) { CFSTORE_FENTRYLOG("%s:SRAM:entered:\n", __func__); return ARM_DRIVER_OK; }*/
02316 static int32_t cfstore_flash_flush(cfstore_ctx_t* ctx)
02317 {
02318     cfstore_client_notify_data_t notify_data;
02319 
02320     CFSTORE_FENTRYLOG("%s:SRAM:entered:\n", __func__);
02321     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_FLUSH, ARM_DRIVER_OK, NULL);
02322     cfstore_ctx_client_notify(ctx, &notify_data);
02323     return ARM_DRIVER_OK;
02324 }
02325 
02326 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
02327 
02328 
02329 /** @brief  After a cfstore KV area memmove() operation, update the file pointers
02330  *          to reflect the new location in memory of KVs.
02331  *
02332  * @param   head
02333  * the position at which size_diff bytes have been inserted/deleted
02334  *
02335  * @param   size_diff
02336  * Change in size (size difference) of the KV memory area.
02337  *  - size_diff > 0 => increase in area, |size_diff| bytes have been inserted at head,
02338  *    and the previously following KVs shifted up to higher memory addresses
02339  *  - size_diff < 0 => decrease in area, |size_diff| bytes have been removed at head,
02340  *    and the previously following KVs shifted down to lower memory addresses
02341  * */
02342 static int32_t cfstore_file_update(uint8_t* head, int32_t size_diff)
02343 {
02344     cfstore_ctx_t* ctx = cfstore_ctx_get();
02345     cfstore_file_t* file;
02346     cfstore_list_node_t* node;
02347     cfstore_list_node_t* file_list = &ctx->file_list;
02348 
02349     CFSTORE_FENTRYLOG("%s:entered:(ctx->area_0_head=%p, ctx->area_0_tail=%p)\n", __func__, ctx->area_0_head, ctx->area_0_tail);
02350 
02351     /* walk the file list updating head pointers for the KVs that remain*/
02352     node = file_list->next;
02353     while(node != file_list){
02354         /* Any KV positioned later in the area than the deleted KV will require file head pointers updating.
02355          * If file's head pointer is beyond the deleted KV tail then the file->head needs to be updated
02356          * to reflect the memove
02357          */
02358         file = (cfstore_file_t*) node;
02359         if(file->head >= head){
02360             /* sign of sign_diff used to move file->head up/down in memory*/
02361             file->head += size_diff;
02362         }
02363         node = node->next;
02364     }
02365     return ARM_DRIVER_OK;
02366 }
02367 
02368 
02369 static int32_t cfstore_delete_ex(cfstore_area_hkvt_t* hkvt)
02370 {
02371     int32_t ret = ARM_DRIVER_ERROR;
02372     ARM_CFSTORE_SIZE kv_size = 0;
02373     ARM_CFSTORE_SIZE kv_total_size = 0;
02374     ARM_CFSTORE_SIZE realloc_size = 0;      /* size aligned to flash program_unit size */
02375     cfstore_ctx_t* ctx = cfstore_ctx_get();
02376 
02377     CFSTORE_FENTRYLOG("%s:entered:(ctx->area_0_head=%p, ctx->area_0_tail=%p)\n", __func__, ctx->area_0_head, ctx->area_0_tail);
02378     kv_size  = cfstore_hkvt_get_size(hkvt);
02379     kv_total_size = cfstore_ctx_get_kv_total_len();
02380 
02381     /* Note the following:
02382      *  1. memmove() above shifts the position of the KVs falling after the deleted KV to be at
02383      *     lower memory addresses. The code (A) updates the cfstore_file_t::head pointers for these KVs
02384      *     so they point to the new locations.
02385      *  2. The operation at 1. above has to happen before the realloc because realloc() can move the
02386      *     start of heap block to a new location, in which case all cfstore_file_t::head pointers
02387      *     need to be updated. cfstore_realloc() can only do this starting from a set of correct
02388      *     cfstore_file_t::head pointers i.e. after 1. has been completed.
02389      */
02390     memmove(hkvt->head, hkvt->tail, ctx->area_0_tail - hkvt->tail);
02391     /* zero the deleted KV memory */
02392     memset(ctx->area_0_tail-kv_size, 0, kv_size);
02393 
02394     /* The KV area has shrunk so a negative size_diff should be indicated to cfstore_file_update(). */
02395     ret = cfstore_file_update(hkvt->head, -1 *(int32_t)kv_size);
02396     if(ret < ARM_DRIVER_OK){
02397         CFSTORE_ERRLOG("%s:Error:file update failed\n", __func__);
02398         goto out0;
02399     }
02400 
02401     /* setup the reallocation memory size. */
02402     realloc_size = kv_total_size - kv_size;
02403     ret = cfstore_realloc_ex(realloc_size, NULL);
02404     if(ret < ARM_DRIVER_OK){
02405         CFSTORE_ERRLOG("%s:Error:realloc failed\n", __func__);
02406         goto out0;
02407     }
02408 out0:
02409     return ret;
02410 }
02411 
02412 
02413 /*
02414  * File operations
02415  */
02416 
02417 static cfstore_file_t* cfstore_file_get(ARM_CFSTORE_HANDLE  hkey)
02418 {
02419     return (cfstore_file_t*) hkey;
02420 }
02421 
02422 static cfstore_file_t* cfstore_file_create(cfstore_area_hkvt_t* hkvt, ARM_CFSTORE_FMODE flags, ARM_CFSTORE_HANDLE  hkey, cfstore_list_node_t *list_head)
02423 {
02424     int32_t ret = ARM_DRIVER_ERROR;
02425     cfstore_file_t* file = (cfstore_file_t*) hkey;
02426 
02427     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
02428     if(file != NULL){
02429         memset(file, 0, sizeof(cfstore_file_t));
02430         CFSTORE_INIT_LIST_HEAD(&file->node);
02431         ret = cfstore_hkvt_refcount_inc(hkvt, NULL);
02432         if(ret < ARM_DRIVER_OK){
02433             CFSTORE_ERRLOG("%s:Error: cfstore_hkvt_refcount_inc() failed (ret=%d)\n", __func__, (int) ret);
02434             return NULL;
02435         }
02436         file->head = hkvt->head;
02437         file->flags.read = flags.read;
02438         file->flags.write = flags.write;
02439         if(list_head != NULL){
02440             cfstore_listAdd(list_head, &file->node, list_head);
02441         }
02442     }
02443     return file;
02444 }
02445 
02446 /* @brief   required to be in critical section when called. */
02447 static int32_t cfstore_file_destroy(cfstore_file_t* file)
02448 {
02449     int32_t ret = ARM_DRIVER_ERROR;
02450     cfstore_area_hkvt_t hkvt;
02451     uint8_t refcount = 0;
02452 
02453     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
02454     if(file) {
02455         hkvt = cfstore_get_hkvt_from_head_ptr(file->head);
02456         CFSTORE_ASSERT(cfstore_hkvt_is_valid(&hkvt, cfstore_ctx_get()->area_0_tail) == true);
02457         ret = ARM_DRIVER_OK;
02458         cfstore_hkvt_refcount_dec(&hkvt, &refcount);
02459         CFSTORE_TP(CFSTORE_TP_FILE, "%s:refcount =%d file->head=%p\n", __func__, (int)refcount, file->head);
02460         if(refcount == 0){
02461             /* check for delete */
02462             CFSTORE_TP(CFSTORE_TP_FILE, "%s:checking delete flag\n", __func__);
02463             if(cfstore_hkvt_get_flags_delete(&hkvt)){
02464                 ret = cfstore_delete_ex(&hkvt);
02465             }
02466         }
02467         /* reset client buffer to empty ready for reuse */
02468         /* delete the file even if not deleting the KV*/
02469         cfstore_listDel(&file->node);
02470         memset(file, 0, sizeof(cfstore_file_t));
02471     }
02472     return ret;
02473 }
02474 
02475 
02476 /**
02477  * @brief   check whether this is an valid buffer
02478  *
02479  * @param   hkey
02480  *          IN: The key handle to be validated
02481  *
02482  *          ctx
02483  *          IN: cfstore context block
02484  */
02485 static bool cfstore_file_is_valid(ARM_CFSTORE_HANDLE  hkey, cfstore_ctx_t* ctx)
02486 {
02487     cfstore_file_t* file = cfstore_file_get(hkey);
02488 
02489     if(ctx->area_0_head != NULL && ctx->area_0_tail != NULL){
02490         if(file->head < ctx->area_0_head || file->head > ctx->area_0_tail){
02491             return 0;
02492         }
02493         return true;
02494     }
02495     return false;
02496 }
02497 
02498 /**
02499  * @brief   check whether this is an empty buffer, or whether it
02500  *          has valid data
02501  *
02502  * @param   hkey
02503  *          IN: The key handle to be validated
02504  *
02505  *          ctx
02506  *          IN: cfstore context block
02507  */
02508 static bool cfstore_file_is_empty(ARM_CFSTORE_HANDLE  hkey)
02509 {
02510     ARM_CFSTORE_HANDLE_INIT(zero);
02511     if(hkey != NULL){
02512         return !memcmp(hkey, zero, CFSTORE_HANDLE_BUFSIZE);
02513     }
02514     return 0;
02515 }
02516 
02517 
02518 /* @brief  See definition in configuration_store.h for description. */
02519 ARM_CFSTORE_CAPABILITIES cfstore_get_capabilities(void)
02520 {
02521     /* getting capabilities doesn't change the sram area so this can happen independently of
02522      * an outstanding async operation. its unnecessary to check the fsm state */
02523     return cfstore_caps_g;
02524 }
02525 
02526 
02527 /* @brief   check the flags argument are supported */
02528 static int32_t cfstore_validate_fmode_flags(ARM_CFSTORE_FMODE flags)
02529 {
02530     if(flags.continuous){
02531         CFSTORE_ERRLOG("%s:Error:Continuous flag not supported.\n", __func__);
02532         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02533     }
02534     if(flags.lazy_flush){
02535         CFSTORE_ERRLOG("%s:Error:Lazy flush flag not supported.\n", __func__);
02536         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02537     }
02538     if(flags.flush_on_close){
02539         CFSTORE_ERRLOG("%s:Error:Flush on close flag not supported.\n", __func__);
02540         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02541     }
02542     if(flags.storage_detect){
02543         CFSTORE_ERRLOG("%s:Error:Storage detect flag not supported.\n", __func__);
02544         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02545     }
02546     return ARM_DRIVER_OK;
02547 }
02548 
02549 
02550 /* @brief   validate the client supplied opaque handle */
02551 static CFSTORE_INLINE int32_t cfstore_validate_handle(ARM_CFSTORE_HANDLE  hkey)
02552 {
02553     if(hkey == NULL){
02554         return ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE;
02555     }
02556     return ARM_DRIVER_OK;
02557 }
02558 
02559 /* @brief   check the flash security features are valid (internal use only) */
02560 static int32_t cfstore_validate_flash_security_features(const ARM_STORAGE_SECURITY_FEATURES *security)
02561 {
02562     CFSTORE_ASSERT(security != NULL);
02563 
02564     if(security->acls){
02565         CFSTORE_ERRLOG("%s:Error: flash security features acls flag not supported.\n", __func__);
02566         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02567     }
02568     if(security->internal_flash){
02569         CFSTORE_ERRLOG("%s:Error: flash security features internal_flash flag not supported.\n", __func__);
02570         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02571     }
02572     if(security->rollback_protection){
02573         CFSTORE_ERRLOG("%s:Error: flash security features rollback_protection flag not supported.\n", __func__);
02574         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02575     }
02576     if(security->tamper_proof){
02577         CFSTORE_ERRLOG("%s:Error: flash security features tamper_proof flag not supported.\n", __func__);
02578         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02579     }
02580     if(security->board_level_attacks){
02581         CFSTORE_ERRLOG("%s:Error: flash security features board level attacks flag not supported.\n", __func__);
02582         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02583     }
02584     if(security->software_attacks){
02585         CFSTORE_ERRLOG("%s:Error: flash security features device_software flag not supported.\n", __func__);
02586         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02587     }
02588     if(security->chip_level_attacks){
02589         CFSTORE_ERRLOG("%s:Error: flash security features chip level attacks flag not supported.\n", __func__);
02590         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02591     }
02592     if(security->side_channel_attacks){
02593         CFSTORE_ERRLOG("%s:Error: flash security features side channel attacks flag not supported.\n", __func__);
02594         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02595     }
02596     return ARM_DRIVER_OK;
02597 }
02598 
02599 /* @brief   check the key descriptor are valid (internal use only) */
02600 static int32_t cfstore_validate_flash_data_retention_level(const uint8_t drl)
02601 {
02602     int32_t ret = ARM_DRIVER_ERROR;
02603 
02604     switch(drl)
02605     {
02606     case ARM_RETENTION_WHILE_DEVICE_ACTIVE :
02607     case ARM_RETENTION_ACROSS_SLEEP :
02608     case ARM_RETENTION_ACROSS_DEEP_SLEEP :
02609     case ARM_RETENTION_BATTERY_BACKED :
02610     case ARM_RETENTION_NVM :
02611         ret = ARM_DRIVER_OK;
02612         break;
02613     default:
02614         CFSTORE_ERRLOG("%s:Error: data retention level (%d) not supported.\n", __func__, drl);
02615         ret = ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02616         break;
02617 
02618     }
02619     return ret;
02620 }
02621 
02622 /* @brief   check the access control list is valid (internal use only)  */
02623 static int32_t cfstore_validate_access_control_list(const ARM_CFSTORE_ACCESS_CONTROL_LIST acl)
02624 {
02625     if(acl.perm_owner_execute)
02626     {
02627         CFSTORE_ERRLOG("%s:Error: Access control list with permission owner execute set is not supported.\n", __func__);
02628         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02629     }
02630     if(acl.perm_other_execute)
02631     {
02632         CFSTORE_ERRLOG("%s:Error: Access control list with permission other execute set is not supported.\n", __func__);
02633         return ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED;
02634     }
02635     return ARM_DRIVER_OK;
02636 }
02637 
02638 /* @brief   check the key descriptor is valid */
02639 static int32_t cfstore_validate_key_desc(const ARM_CFSTORE_KEYDESC *kdesc)
02640 {
02641     int32_t ret = ARM_DRIVER_ERROR;
02642 
02643     if(kdesc == NULL){
02644         return ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_DESCRIPTOR;
02645     }
02646     ret = cfstore_validate_access_control_list(kdesc->acl);
02647     if(ret < ARM_DRIVER_OK){
02648         return ret;
02649     }
02650     ret = cfstore_validate_flash_data_retention_level(kdesc->drl);
02651     if(ret < ARM_DRIVER_OK){
02652         return ret;
02653     }
02654     ret = cfstore_validate_flash_security_features(&kdesc->security);
02655     if(ret < ARM_DRIVER_OK){
02656         return ret;
02657     }
02658     ret = cfstore_validate_fmode_flags(kdesc->flags);
02659     if(ret < ARM_DRIVER_OK){
02660         return ret;
02661     }
02662     return ARM_DRIVER_OK;
02663 }
02664 
02665 /**
02666  * @brief   check the key_len pointer is valid
02667  *
02668  * @param   hkey
02669  *          IN: The key handle to be validated
02670  */
02671 static CFSTORE_INLINE int32_t cfstore_validate_len_ptr(ARM_CFSTORE_SIZE *len)
02672 {
02673     if(len == NULL){
02674         return ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_LEN;
02675     }
02676     return ARM_DRIVER_OK;
02677 }
02678 
02679 /* @brief   return a pointer to the next { or }, or NULL if not present */
02680 static inline char* cfstore_validate_pos_next_brace(const char* pos)
02681 {
02682     char* pos_open = strchr(pos, '{');
02683     char* pos_close = strchr(pos, '}');
02684     if(pos_open != NULL) {
02685         if(pos_close != NULL){
02686             return pos_open < pos_close ? pos_open : pos_close;
02687         }
02688         return pos_open;
02689     }
02690     return pos_close;
02691 }
02692 
02693 
02694 static int32_t cfstore_validate_key_name_ex(const char* key_name, const char* permissible)
02695 {
02696     char* pos = NULL;
02697     int brace_count = 0;
02698     ARM_CFSTORE_SIZE len = 0;
02699     ARM_CFSTORE_SIZE valid_len = 0;
02700 
02701     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
02702     if(key_name != NULL){
02703         /* check the key_name is terminated by a 0 */
02704         pos = (char*) memchr(key_name, '\0', CFSTORE_KEY_NAME_MAX_LENGTH+1);
02705         if(pos == NULL){
02706             CFSTORE_ERRLOG("%s:key_name does not have terminating null.\n", __func__);
02707             return ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_NAME;
02708         }
02709         /* check for zero length key_name*/
02710         if(strlen(key_name) == 0){
02711             CFSTORE_ERRLOG("%s:Error: invalid key_name.\n", __func__);
02712             return ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_NAME;
02713         }
02714         /* check the key_name len is less than the max length (220) */
02715         len = strlen(key_name);
02716         if(len > CFSTORE_KEY_NAME_MAX_LENGTH){
02717             CFSTORE_ERRLOG("%s:key_name string is longer (%d) than the supported maximum (%d).\n", __func__, (int) len, (int) CFSTORE_KEY_NAME_MAX_LENGTH);
02718             return ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_NAME;
02719         }
02720         /* check the key_name only contains permissible characters */
02721         valid_len = strspn(key_name, permissible);
02722         if(valid_len != len){
02723             CFSTORE_ERRLOG("%s:Invalid character (%c) found in key_name (key_name=%s).\n", __func__, key_name[valid_len], key_name);
02724             return ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_NAME;
02725         }
02726 
02727         /*check there isnt a leading '.' on the kv name */
02728         if(key_name[0] == '.'){
02729             CFSTORE_ERRLOG("%s:Leading (.) character found in key_name (key_name=%s) is not allowed.\n", __func__, key_name);
02730             return ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_NAME;
02731         }
02732 
02733         /* - check for matching '{' for each '}' present
02734          * - only check a string if either { or } are present
02735          *   i.e. dont process string without
02736          *   checking for existence of single brace, and checking for either { or } so
02737          *   that the case where } is the first brace is convered.
02738          * - start loop at first { or } char,  both {} covers case where } is the first brace
02739          * - (brace_count >=0 && brace_count <= 1) must always be true
02740          * - brace_count must == 0 at end of string
02741          */
02742         pos = cfstore_validate_pos_next_brace(key_name);
02743         while(pos != NULL && brace_count >= 0 && brace_count <= 1)
02744         {
02745             switch(*pos)
02746             {
02747             case '{':
02748                 brace_count++;
02749                 break;
02750             case '}':
02751                 brace_count--;
02752                 break;
02753             default:
02754                 break;
02755             }
02756             pos++;
02757             pos = cfstore_validate_pos_next_brace(pos);
02758         }
02759         if(brace_count != 0){
02760             CFSTORE_ERRLOG("%s: Unmatched brace found in key_name (count=%d.\n", __func__, brace_count);
02761             return ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_NAME;
02762         }
02763     }
02764     return ARM_DRIVER_OK;
02765 }
02766 
02767 
02768 /* @brief   check the key name is valid */
02769 static int32_t cfstore_validate_key_name(const char* key_name)
02770 {
02771     int32_t ret = ARM_DRIVER_ERROR;
02772 
02773     ret = cfstore_uvisor_security_context_prefix_check(key_name);
02774     if(ret < ARM_DRIVER_OK){
02775         CFSTORE_ERRLOG("%s:Error: failed uvisor security context check.\n", __func__);
02776         return ret;
02777     }
02778     return cfstore_validate_key_name_ex(key_name, CFSTORE_KEY_NAME_CHARS_ACCEPTABLE);
02779 }
02780 
02781 /* @brief   check the key name query is valid */
02782 static int32_t cfstore_validate_key_name_query(const char* key_name_query)
02783 {
02784     return cfstore_validate_key_name_ex(key_name_query, CFSTORE_KEY_NAME_QUERY_CHARS_ACCEPTABLE);
02785 }
02786 
02787 
02788 /**
02789  * @brief   check the value length field is valid
02790  *
02791  * @param   key_name
02792  *          IN: The key name string to be validated
02793  * @note    This will be replaced with the actual uvisor call, when available.
02794  */
02795 static CFSTORE_INLINE int32_t cfstore_validate_value_len(ARM_CFSTORE_SIZE value_len)
02796 {
02797     if(value_len <= CFSTORE_VALUE_SIZE_MAX) {
02798         return ARM_DRIVER_OK;
02799     }
02800     return ARM_CFSTORE_DRIVER_ERROR_VALUE_SIZE_TOO_LARGE;
02801 }
02802 
02803 
02804 /* @brief  See definition in configuration_store.h for description. */
02805 static int32_t cfstore_get_key_name_ex(cfstore_area_hkvt_t *hkvt, char* key_name, uint8_t *key_name_len)
02806 {
02807     int32_t ret = ARM_DRIVER_OK;
02808     int32_t max_len = 0;
02809 
02810     max_len = cfstore_hkvt_get_key_len(hkvt) + 1;
02811     max_len = max_len <= *key_name_len ? max_len : *key_name_len;
02812     memcpy(key_name, (const char*) hkvt->key, max_len-1);
02813     key_name[max_len-1] = '\0';
02814     *key_name_len = max_len;
02815     return ret;
02816 }
02817 
02818 
02819 /* @brief  See definition in configuration_store.h for description. */
02820 static int32_t cfstore_get_key_name(ARM_CFSTORE_HANDLE  hkey, char* key_name, uint8_t *key_name_len)
02821 {
02822     int32_t ret = ARM_DRIVER_ERROR;
02823     cfstore_area_hkvt_t hkvt;
02824     cfstore_client_notify_data_t notify_data;
02825     cfstore_ctx_t* ctx = cfstore_ctx_get();
02826 
02827     CFSTORE_ASSERT(key_name != NULL);
02828     CFSTORE_ASSERT(key_name_len != NULL);
02829 
02830     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
02831     if(!cfstore_ctx_is_initialised(ctx)) {
02832         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
02833         ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
02834         goto out0;
02835     }
02836     /* getting a keyname doesnt change the sram area so this can happen independently of
02837      * an oustanding async operation. its unnecessary to check the fsm state */
02838     ret = cfstore_validate_handle(hkey);
02839     if(ret < ARM_DRIVER_OK){
02840         CFSTORE_ERRLOG("%s:Error: invalid handle.\n", __func__);
02841         goto out0;
02842     }
02843     if(key_name == NULL){
02844         CFSTORE_ERRLOG("%s:Error: invalid handle.\n", __func__);
02845         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_NAME;
02846         goto out0;
02847     }
02848     ret = cfstore_validate_len_ptr((ARM_CFSTORE_SIZE*)key_name_len);
02849     if(ret < ARM_DRIVER_OK){
02850         CFSTORE_ERRLOG("%s:Error: invalid key_name_len argument.\n", __func__);
02851         goto out0;
02852     }
02853     memset(&hkvt, 0, sizeof(hkvt));
02854     hkvt = cfstore_get_hkvt(hkey);
02855     if(!cfstore_hkvt_is_valid(&hkvt, ctx->area_0_tail)){
02856         CFSTORE_ERRLOG("%s:ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE\n", __func__);
02857         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE;
02858         goto out0;
02859     }
02860     ret = cfstore_get_key_name_ex(&hkvt, key_name, key_name_len);
02861     if(ret < ARM_DRIVER_OK){
02862         CFSTORE_ERRLOG("%s:Error: cfstore_get_key_name_ex() returned error.\n", __func__);
02863         goto out0;
02864     }
02865     ret = *key_name_len;
02866 out0:
02867     /* GetKeyName() always completes synchronously irrespective of flash mode, so indicate to caller */
02868     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_GET_KEY_NAME, ret, hkey);
02869     cfstore_ctx_client_notify(ctx, &notify_data);
02870     return ret;
02871 }
02872 
02873 /* @brief  See definition in configuration_store.h for description. */
02874 static ARM_CFSTORE_STATUS cfstore_get_status(void)
02875 {
02876     ARM_CFSTORE_STATUS status;
02877     cfstore_ctx_t* ctx = cfstore_ctx_get();
02878 
02879     memset(&status, 0, sizeof(status));
02880     if(!cfstore_ctx_is_initialised(ctx)) {
02881         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
02882         status.error = true;
02883     }
02884     /* getting status doesnt change the sram area so this can happen independently of
02885      * an oustanding async operation. */
02886     if(cfstore_flash_journal_is_async_op_pending(ctx))
02887     {
02888         status.in_progress = true;
02889     }
02890     else
02891     {
02892         status.in_progress = false;
02893     }
02894     return status;
02895 }
02896 
02897 /* @brief  See definition in configuration_store.h for description. */
02898 static int32_t cfstore_get_value_len(ARM_CFSTORE_HANDLE  hkey, ARM_CFSTORE_SIZE *value_len)
02899 {
02900     int32_t ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
02901     cfstore_area_hkvt_t hkvt;
02902     cfstore_client_notify_data_t notify_data;
02903     cfstore_ctx_t* ctx = cfstore_ctx_get();
02904 
02905     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
02906     CFSTORE_ASSERT(hkey != NULL);
02907     CFSTORE_ASSERT(value_len != NULL);
02908 
02909     if(!cfstore_ctx_is_initialised(ctx)) {
02910         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
02911         goto out0;
02912     }
02913     /* getting a value len doesnt change the sram area so this can happen independently of
02914      * an outstanding async operation. its unnecessary to check the fsm state */
02915     ret = cfstore_validate_handle(hkey);
02916     if(ret < ARM_DRIVER_OK){
02917         CFSTORE_ERRLOG("%s:Error: invalid handle.\n", __func__);
02918         goto out0;
02919     }
02920     ret = cfstore_validate_len_ptr(value_len);
02921     if(ret < ARM_DRIVER_OK){
02922         CFSTORE_ERRLOG("%s:Error: invalid value len argument.\n", __func__);
02923         goto out0;
02924     }
02925     hkvt = cfstore_get_hkvt(hkey);
02926     if(!cfstore_hkvt_is_valid(&hkvt, ctx->area_0_tail)){
02927         CFSTORE_ERRLOG("%s:ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE\n", __func__);
02928         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE;
02929         goto out0;
02930     }
02931     *value_len = cfstore_hkvt_get_value_len(&hkvt);
02932     ret = (int32_t) *value_len;
02933 out0:
02934     /* GetValueLen() always completes synchronously irrespective of flash mode, so indicate to caller */
02935     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_GET_VALUE_LEN, ret, hkey);
02936     cfstore_ctx_client_notify(ctx, &notify_data);
02937     return ret;
02938 }
02939 
02940 #ifdef CFSTORE_DEBUG
02941 
02942 /* @brief   debug trace a struct cfstore_area_hkvt_t, providing values for key field. */
02943 static CFSTORE_INLINE void cfstore_hkvt_dump(cfstore_area_hkvt_t* hkvt, const char* tag)
02944 {
02945 /* #define CFSTORE_HKVT_DUMP_ON */
02946 #ifdef CFSTORE_HKVT_DUMP_ON
02947     char kname[CFSTORE_KEY_NAME_MAX_LENGTH+1];
02948     char value[CFSTORE_KEY_NAME_MAX_LENGTH+1];
02949     uint32_t klen = 0;
02950     uint32_t vlen = 0;
02951     cfstore_ctx_t* ctx = cfstore_ctx_get();
02952 
02953     memset(kname, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
02954     memset(value, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
02955     klen = cfstore_hkvt_get_key_len(hkvt);
02956     vlen = cfstore_hkvt_get_value_len(hkvt);
02957     memcpy((void*)kname, (void*) hkvt->key, klen);
02958     memcpy((void*)value, (void*) hkvt->value, vlen);
02959     kname[klen] = '\0';
02960     value[vlen] = '\0';
02961 
02962     /* table column description
02963      * col 1: tag, descriptive string supplied by client to identify context of table dump
02964      * col 2: hkvt struct member that is to be reported i.e. head, key, value, tail
02965      * col 3: the value of the pointer described in col 2.
02966      * col 4: the value of the pointer described in col 3 as an offset from the start of the sram area
02967      * col 5: field specified data e.g. for header, the extracted key length, value_length.
02968      */
02969     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:hkvt->head:%8p:%8p:klen=%08d:vlen=%08d:\n", tag, hkvt->head, (void*)(hkvt->head - ctx->area_0_head), (int) klen, (int) vlen);
02970     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:hkvt->key :%8p:%8p:%s\n", tag, hkvt->key, (void*)(hkvt->key - ctx->area_0_head), kname);
02971     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:hkvt->val :%8p:%8p:%s\n", tag, hkvt->value, (void*)(hkvt->value - ctx->area_0_head), value);
02972     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:hkvt->tail:%8p:%8p:\n", tag, hkvt->tail, (void*)(hkvt->tail - ctx->area_0_head));
02973     return;
02974 #else
02975     (void) hkvt;
02976     (void) tag;
02977 
02978 #endif /*  CFSTORE_HKVT_DUMP_ON */
02979 }
02980 
02981 static CFSTORE_INLINE void cfstore_flags_dump(ARM_CFSTORE_FMODE flag, const char* tag)
02982 {
02983     int pos = 0;
02984     char flags[9];
02985 
02986     pos += snprintf(&flags[pos], 9, "%c", flag.continuous ? 'C' : 'c');
02987     pos += snprintf(&flags[pos], 9, "%c", flag.lazy_flush ? 'L' : 'l');
02988     pos += snprintf(&flags[pos], 9, "%c", flag.flush_on_close ? 'F' : 'f');
02989     pos += snprintf(&flags[pos], 9, "%c", flag.read ? 'R' : 'r');
02990     pos += snprintf(&flags[pos], 9, "%c", flag.write ? 'W' : 'w');
02991     pos += snprintf(&flags[pos], 9, "%c", flag.storage_detect ? 'S' : 's');
02992     pos += snprintf(&flags[pos], 9, "--");
02993 
02994     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:flags     :%s:(C=>continuous set, L=>lazy flush, F=>flush on close, R=>read, W=>write, S=>storage detect)\n", tag, flags);
02995     return;
02996 }
02997 
02998 static CFSTORE_INLINE void cfstore_file_dump(cfstore_file_t* file, const char* tag)
02999 {
03000 /*#define CFSTORE_FILE_DUMP_ON */
03001 #ifdef CFSTORE_FILE_DUMP_ON
03002     cfstore_area_hkvt_t hkvt;
03003 
03004     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:*** Dumping File Contents : Start ***\n", tag);
03005     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:file==hkey:%p\n", tag, file);
03006     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:rloc/wloc :%08u/%08u:\n", tag, (unsigned int)  file->rlocation, (unsigned int)  file->wlocation);
03007     cfstore_flags_dump(file->flags, tag);
03008     hkvt = cfstore_get_hkvt((ARM_CFSTORE_HANDLE )file);
03009     cfstore_hkvt_dump(&hkvt, tag);
03010     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:*** Dumping File Contents : End ***\n", tag);
03011     return;
03012 #else
03013     (void) file;
03014     (void) tag;
03015 
03016 #endif /*  CFSTORE_FILE_DUMP_ON */
03017 }
03018 
03019 /* dump sram contents of cfstore in a useful manner for debugging */
03020 static CFSTORE_INLINE void cfstore_dump_contents(const char* tag)
03021 {
03022     int32_t ret = ARM_DRIVER_ERROR;
03023     cfstore_area_hkvt_t hkvt;
03024     cfstore_ctx_t* ctx = cfstore_ctx_get();
03025 
03026     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:*** Dumping CFSTORE Contents : Start ***\n", tag);
03027     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:cfstore_ctx_g.area_0_head=%8p\n", tag, ctx->area_0_head);
03028     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:cfstore_ctx_g.area_0_tail=%8p\n", tag, ctx->area_0_tail);
03029     ret = cfstore_get_head_hkvt(&hkvt);
03030     if(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND){
03031         CFSTORE_TP(CFSTORE_TP_VERBOSE1, "%s:CFSTORE has no KVs\n", tag);
03032         goto out0;
03033     } else if(ret < ARM_DRIVER_OK){
03034         CFSTORE_ERRLOG("%s:Error: could not get head of list.\n", tag);
03035         goto out0;
03036     }
03037     while(cfstore_get_next_hkvt(&hkvt, &hkvt) != ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND)
03038     {
03039         cfstore_hkvt_dump(&hkvt, tag);
03040     }
03041 out0:
03042     CFSTORE_TP(CFSTORE_TP_VERBOSE3, "%s:*** Dumping CFSTORE Contents : End ***\n", tag);
03043     return;
03044 }
03045 
03046 
03047 
03048 #else
03049 static CFSTORE_INLINE void cfstore_hkvt_dump(cfstore_area_hkvt_t* hkvt, const char* tag){ (void) hkvt; (void) tag; return; }
03050 static CFSTORE_INLINE void cfstore_file_dump(cfstore_file_t* file, const char* tag){ (void) file; (void) tag;  return; }
03051 static CFSTORE_INLINE void cfstore_dump_contents(const char* tag){ (void) tag;  return; }
03052 static CFSTORE_INLINE void cfstore_flags_dump(ARM_CFSTORE_FMODE flag, const char* tag){ (void) flag; (void) tag;  return; }
03053 #endif /*CFSTORE_DEBUG*/
03054 
03055 /*
03056  * CS operations
03057  */
03058 
03059 /* @brief  See definition in configuration_store.h for description. */
03060 ARM_DRIVER_VERSION cfstore_get_version(void)
03061 {
03062     /* getting version info doesnt change the sram area so this can happen independently of
03063      * an oustanding async operation. its unnecessary to check the fsm state */
03064     return cfstore_driver_version_g;
03065 }
03066 
03067 
03068 /*
03069  * CS API Key-Value operations
03070  */
03071 
03072 /* @brief  See definition in configuration_store.h for description. */
03073 static int32_t cfstore_delete(ARM_CFSTORE_HANDLE  hkey)
03074 {
03075     int32_t ret = ARM_DRIVER_ERROR;
03076     cfstore_area_hkvt_t hkvt;
03077     cfstore_ctx_t* ctx = cfstore_ctx_get();
03078     cfstore_client_notify_data_t notify_data;
03079 
03080     CFSTORE_TP((CFSTORE_TP_DELETE|CFSTORE_TP_FENTRY), "%s:entered\n", __func__);
03081     if(!cfstore_ctx_is_initialised(ctx)) {
03082         CFSTORE_TP(CFSTORE_TP_DELETE, "%s:Error: CFSTORE is not initialised.\n", __func__);
03083         ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
03084         goto out0;
03085     }
03086     /* deleting a key will change the sram area while a logging/flushing operation is pending, which
03087      * should not happen while an async operation is outstanding */
03088     if(cfstore_flash_journal_is_async_op_pending(ctx)) {
03089         CFSTORE_TP(CFSTORE_TP_DELETE, "%s:Debug: flash journal operation pending (awaiting asynchronous notification).\n", __func__);
03090         ret = ARM_CFSTORE_DRIVER_ERROR_OPERATION_PENDING;
03091         goto out0;
03092     }
03093     ret = cfstore_validate_handle(hkey);
03094     if(ret < ARM_DRIVER_OK){
03095         CFSTORE_ERRLOG("%s:Error: invalid handle.\n", __func__);
03096         goto out0;
03097     }
03098     if(!cfstore_is_kv_client_deletable((cfstore_file_t*) hkey)){
03099         CFSTORE_ERRLOG("%s:Error: client is not permitted to delete KV.\n", __func__);
03100         ret = ARM_CFSTORE_DRIVER_ERROR_NO_PERMISSIONS;
03101         goto out0;
03102     }
03103     hkvt = cfstore_get_hkvt(hkey);
03104     /* check its a valid hkvt */
03105     if(!cfstore_hkvt_is_valid(&hkvt, ctx->area_0_tail)){
03106         CFSTORE_ERRLOG("%s:ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE\n", __func__);
03107         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE;
03108         goto out0;
03109     }
03110     /* set the delete flag so the delete occurs when the file is closed
03111      * no further handles will be returned to this key */
03112     cfstore_hkvt_set_flags_delete(&hkvt, true);
03113 
03114     /* set the dirty flag so the changes are persisted to backing store when flushed */
03115     ctx->area_dirty_flag = true;
03116 
03117 out0:
03118     /* Delete() always completes synchronously irrespective of flash mode, so indicate to caller */
03119     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_DELETE, ret, NULL);
03120     cfstore_ctx_client_notify(ctx, &notify_data);
03121     return ret;
03122 }
03123 
03124 
03125 /** @brief  Internal find function using hkvt's.
03126  *
03127  * @note
03128  * Not the following:
03129  *  - Any required locks should be taken before this function is called.
03130  *    This function does not affect refcount for underlying KVs.
03131  *  - The function assumes the arguments have been validated before calling this function
03132  *  - No acl policy is enforced by the function.
03133  *
03134  * @return  return_value
03135  *          On success (finding a KV matching the query) ARM_DRIVER_OK is
03136  *          returned. If a KV is not found matching the description then
03137  *          ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND is returned.
03138  */
03139 static int32_t cfstore_find_ex(const char* key_name_query, cfstore_area_hkvt_t *prev, cfstore_area_hkvt_t *next)
03140 {
03141     int32_t ret = ARM_DRIVER_ERROR;
03142     uint8_t next_key_len;
03143     char key_name[CFSTORE_KEY_NAME_MAX_LENGTH+1];
03144     cfstore_ctx_t* ctx = cfstore_ctx_get();
03145 
03146     CFSTORE_TP((CFSTORE_TP_FIND|CFSTORE_TP_FENTRY), "%s:entered: key_name_query=\"%s\", prev=%p, next=%p\n", __func__, key_name_query, prev, next);
03147     if(prev == NULL){
03148         ret = cfstore_get_head_hkvt(next);
03149         /* CFSTORE_TP(CFSTORE_TP_FIND, "%s:next->head=%p, next->key=%p, next->value=%p, next->tail=%p, \n", __func__, next->head, next->key, next->value, next->tail); */
03150         if(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND){
03151             CFSTORE_TP(CFSTORE_TP_FIND, "%s:CFSTORE has no KVs\n", __func__);
03152             return ret;
03153         } else if(ret < ARM_DRIVER_OK) {
03154             CFSTORE_TP(CFSTORE_TP_FIND, "%s:failed to find the first KV in area\n", __func__);
03155             return ret;
03156         }
03157 
03158         /* check for no KVs in the store => hkvt is not valid */
03159         if(!cfstore_hkvt_is_valid(next, ctx->area_0_tail)){
03160             /* no KVs in store */
03161             CFSTORE_TP(CFSTORE_TP_FIND, "%s:hkvt is not valid\n", __func__);
03162             return ARM_DRIVER_OK;
03163         }
03164 
03165     } else {
03166         /* CFSTORE_TP(CFSTORE_TP_FIND, "%s:getting hkvt from prev\n", __func__);*/
03167         ret = cfstore_get_next_hkvt(prev, next);
03168         if(ret < ARM_DRIVER_OK){
03169             /* no more matching entries or error.
03170              * either way, return*/
03171             return ret;
03172         }
03173     }
03174     if(next->head == NULL){
03175         /* no entry*/
03176         CFSTORE_TP(CFSTORE_TP_FIND, "%s:No more entries found\n", __func__);
03177         return ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND;
03178     }
03179     /* CFSTORE_TP(CFSTORE_TP_FIND, "%s:cfstore_ctx_g.area_0_head=%p, cfstore_ctx_g.area_0_tail=%p\n", __func__, cfstore_ctx_g.area_0_head, cfstore_ctx_g.area_0_tail);*/
03180     cfstore_hkvt_dump(next, __func__);
03181     while(cfstore_hkvt_is_valid(next, ctx->area_0_tail))
03182     {
03183         /* CFSTORE_TP(CFSTORE_TP_FIND, "%s:next->head=%p, next->key=%p, next->value=%p, next->tail=%p, \n", __func__, next->head, next->key, next->value, next->tail); */
03184         cfstore_hkvt_dump(next, __func__);
03185 
03186         /* if this KV is deleting then proceed to the next item */
03187         if(cfstore_hkvt_get_flags_delete(next)){
03188             ret = cfstore_get_next_hkvt(next, next);
03189             if(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND) {
03190                 CFSTORE_TP(CFSTORE_TP_FIND, "%s:No more KVs found\n", __func__);
03191                 return ret;
03192             }
03193             continue;
03194         }
03195         /* if this KV is not readable by the client then proceed to the next item */
03196         if(!cfstore_is_kv_client_readable(next)){
03197             ret = cfstore_get_next_hkvt(next, next);
03198             if(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND) {
03199                 CFSTORE_TP(CFSTORE_TP_FIND, "%s:No more KVs found\n", __func__);
03200                 return ret;
03201             }
03202             continue;
03203         }
03204         /* check if this key_name matches the query */
03205         next_key_len = cfstore_hkvt_get_key_len(next);
03206         next_key_len++;
03207         cfstore_get_key_name_ex(next, key_name, &next_key_len);
03208         ret = cfstore_fnmatch(key_name_query, key_name, 0);
03209         if(ret == 0){
03210             /* found the entry in the store. return handle */
03211             CFSTORE_TP(CFSTORE_TP_FIND, "%s:Found matching key (key_name_query = \"%s\", next->key = \"%s\"),next_key_len=%d\n", __func__, key_name_query, key_name, (int) next_key_len);
03212             cfstore_hkvt_dump(next, __func__);
03213             return ARM_DRIVER_OK;
03214         } else if(ret != CFSTORE_FNM_NOMATCH){
03215             CFSTORE_ERRLOG("%s:Error: cfstore_fnmatch() error (ret=%d).\n", __func__, (int) ret);
03216             return ARM_DRIVER_ERROR;
03217         }
03218         /* CFSTORE_FNM_NOMATCH => get the next hkvt if any */
03219         ret = cfstore_get_next_hkvt(next, next);
03220         if(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND) {
03221             CFSTORE_TP(CFSTORE_TP_FIND, "%s:No more KVs found\n", __func__);
03222             return ret;
03223         }
03224     }
03225     return ARM_DRIVER_OK;
03226 }
03227 
03228 
03229 /* @brief  See definition in configuration_store.h for description. */
03230 static int32_t cfstore_find(const char* key_name_query, const ARM_CFSTORE_HANDLE  previous, ARM_CFSTORE_HANDLE  next)
03231 {
03232     char key_name[CFSTORE_KEY_NAME_MAX_LENGTH+1];
03233     uint8_t key_len = 0;
03234     cfstore_area_hkvt_t hkvt_next;
03235     cfstore_area_hkvt_t hkvt_previous;
03236     cfstore_area_hkvt_t *phkvt_previous = NULL;
03237     int32_t ret = ARM_DRIVER_ERROR;
03238     ARM_CFSTORE_FMODE fmode;
03239     cfstore_ctx_t* ctx = cfstore_ctx_get();
03240     cfstore_client_notify_data_t notify_data;
03241 
03242     CFSTORE_ASSERT(next != NULL);
03243     CFSTORE_FENTRYLOG("%s:entered: key_name_query=\"%s\", previous=%p, next=%p\n", __func__, key_name_query, previous, next);
03244     if(!cfstore_ctx_is_initialised(ctx)) {
03245         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
03246         ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
03247         goto out1;
03248     }
03249     /* finding a key doesnt change the sram area so this can happen independently of
03250      * an oustanding async operation. its unnecessary to check the fsm state */
03251     ret = cfstore_validate_key_name_query(key_name_query);
03252     if(ret < ARM_DRIVER_OK){
03253         CFSTORE_ERRLOG("%s:Error: invalid key_name.\n", __func__);
03254         goto out1;
03255     }
03256     ret = cfstore_validate_handle(next);
03257     if(ret < ARM_DRIVER_OK){
03258         CFSTORE_ERRLOG("%s:Error: invalid next argument.\n", __func__);
03259         goto out1;
03260     }
03261     /* note previous can be NULL if this is the first call the find */
03262     memset(&hkvt_next, 0, sizeof(hkvt_next));
03263     memset(&fmode, 0, sizeof(fmode));
03264     if(previous != NULL && cfstore_file_is_valid(previous, ctx)){
03265         ret = cfstore_validate_handle(previous);
03266         if(ret < ARM_DRIVER_OK){
03267             CFSTORE_ERRLOG("%s:Error: invalid handle.\n", __func__);
03268             goto out1;
03269         }
03270         phkvt_previous = &hkvt_previous;
03271         memset(phkvt_previous, 0, sizeof(hkvt_previous));
03272         hkvt_previous = cfstore_get_hkvt(previous);
03273         cfstore_hkvt_dump(&hkvt_previous, __func__);
03274         if(!cfstore_hkvt_is_valid(phkvt_previous, ctx->area_0_tail)){
03275             ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE;
03276             goto out1;
03277         }
03278     } else if(previous != NULL && !cfstore_file_is_empty(previous)){
03279         CFSTORE_TP(CFSTORE_TP_FIND, "%s:Invalid previous hkey buffer.\n", __func__);
03280         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE_BUF;
03281         goto out1;
03282     }
03283     ret = cfstore_find_ex(key_name_query, phkvt_previous, &hkvt_next);
03284     if(ret < ARM_DRIVER_OK){
03285         /* either no more entries or error but either way, return */
03286         CFSTORE_TP(CFSTORE_TP_FIND, "%s:No more KVs found.\n", __func__);
03287         goto out2;
03288     }
03289 
03290     if(!cfstore_hkvt_is_valid(&hkvt_next, ctx->area_0_tail)){
03291         CFSTORE_TP(CFSTORE_TP_FIND, "%s:Did not find any matching KVs.\n", __func__);
03292         ret = ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND;
03293         goto out2;
03294     }
03295 
03296     /* Have a valid kv. cfstore_find_ex() checked the client has
03297      * permission to read the KV, so dont have to perform this check again here. */
03298 
03299     /* return handle to client */
03300     cfstore_file_create(&hkvt_next, fmode, next, &ctx->file_list);
03301     ret = ARM_DRIVER_OK;
03302 out2:
03303     /* previous handle is being returned to CFSTORE with this call so destroy file struct */
03304     if(previous != NULL && cfstore_file_is_valid(previous, ctx))
03305     {
03306         /* do not use ret in this stanza as will loose return state from above */
03307         /* CFSTORE_TP(CFSTORE_TP_FIND, "%s:about to destroy KV, previous=%p.\n", __func__, previous); */
03308         cfstore_file_dump((cfstore_file_t*) previous, __func__);
03309 
03310         key_len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
03311         memset(key_name, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
03312 
03313         cfstore_file_destroy(cfstore_file_get(previous));
03314 
03315         /* check hkvt is valid before trying to retrieve name*/
03316         if(!cfstore_hkvt_is_valid(&hkvt_next, ctx->area_0_tail)){
03317             goto out1;
03318         }
03319         if(cfstore_get_key_name_ex(&hkvt_next, key_name, &key_len) < ARM_DRIVER_OK){
03320             /* either no more entries or error but either way, return */
03321             CFSTORE_TP(CFSTORE_TP_FIND, "%s:debug: cfstore_get_key_name_ex failed or no more kvs.\n", __func__);
03322             goto out1;
03323         }
03324         /* now get hkvt_next again based on the name to overcome the fact that the hkvt
03325          * may be invalid due to the possible deletion of the previous KV.x */
03326         if(cfstore_find_ex(key_name, NULL, &hkvt_next) < ARM_DRIVER_OK){
03327             /* either no more entries or error but either way, return */
03328             CFSTORE_TP(CFSTORE_TP_FIND, "%s:find failed key_name=%s ret=%d.\n", __func__, key_name, (int) ret);
03329             goto out1;
03330         }
03331         cfstore_hkvt_dump(&hkvt_next, __func__);
03332     }
03333 out1:
03334     /* Find() always completes synchronously irrespective of flash mode, so indicate to caller */
03335     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_FIND, ret, next);
03336     cfstore_ctx_client_notify(ctx, &notify_data);
03337     return ret;
03338 }
03339 
03340 
03341 /* @brief  grow/shrink pre-existing KV.
03342  *
03343  * @note rw_lock must be held by the caller of this function rw_area0_lock */
03344 static int32_t cfstore_recreate(const char* key_name, ARM_CFSTORE_SIZE value_len, ARM_CFSTORE_HANDLE  hkey, cfstore_area_hkvt_t* hkvt)
03345 {
03346     uint8_t* old_area_0_head = NULL;
03347     int32_t kv_size_diff = 0;
03348     int32_t ret = ARM_DRIVER_ERROR;
03349     size_t memmove_len = 0;
03350     ARM_CFSTORE_SIZE area_size = 0;
03351     ARM_CFSTORE_FMODE flags;
03352     cfstore_ctx_t* ctx = cfstore_ctx_get();
03353 
03354     CFSTORE_FENTRYLOG("%s:entered: key_name=\"%s\", value_len=%d\n", __func__, key_name, (int) value_len);
03355     cfstore_dump_contents(__func__);
03356     memset(&flags, 0, sizeof(flags));
03357     flags.read = true;
03358     flags.write = true;
03359     kv_size_diff = value_len - cfstore_hkvt_get_value_len(hkvt);
03360     if(kv_size_diff == 0){
03361         /* nothing more to do*/
03362         CFSTORE_TP(CFSTORE_TP_CREATE, "%s:new value length the same as the old\n", __func__);
03363         return ARM_DRIVER_OK;
03364     }
03365 
03366     /* grow the area by the size of the new KV */
03367     area_size = cfstore_ctx_get_kv_total_len();
03368     /* store the area_0_head, and move length for later updating hkvt if realloc moves KV area */
03369     old_area_0_head = ctx->area_0_head;
03370     memmove_len = ctx->area_0_tail - hkvt->tail;
03371 
03372     CFSTORE_TP(CFSTORE_TP_CREATE, "%s:cfstore_ctx_g.area_0_head=%p, cfstore_ctx_g.area_0_tail=%p\n", __func__, ctx->area_0_head, ctx->area_0_tail);
03373     CFSTORE_TP(CFSTORE_TP_CREATE, "%s:sizeof(header)=%d, sizeof(key)=%d, sizeof(value)=%d, kv_size_diff=%d, area_size=%d\n", __func__, (int) sizeof(cfstore_area_header_t ),  (int)(strlen(key_name)), (int)value_len, (int) kv_size_diff, (int) area_size);
03374     if (kv_size_diff < 0){
03375         /* value blob size shrinking => do memmove() before realloc() which will free memory */
03376         memmove(hkvt->tail + kv_size_diff, hkvt->tail, memmove_len);
03377         ret = cfstore_file_update(hkvt->head, kv_size_diff);
03378         if(ret < ARM_DRIVER_OK){
03379             CFSTORE_ERRLOG("%s:Error:file update failed\n", __func__);
03380             goto out0;
03381         }
03382     }
03383 
03384     ret = cfstore_realloc_ex(area_size + kv_size_diff, NULL);
03385     if(ret < ARM_DRIVER_OK){
03386         CFSTORE_ERRLOG("%s:Error:file realloc failed\n", __func__);
03387         goto out0;
03388     }
03389     if(old_area_0_head != ctx->area_0_head){
03390         /* As realloc() has caused the memory to move, hkvt needs re-initialising */
03391         hkvt->head += ctx->area_0_head - old_area_0_head;
03392         hkvt->key += ctx->area_0_head - old_area_0_head;
03393         hkvt->value +=  ctx->area_0_head - old_area_0_head;
03394         hkvt->tail += ctx->area_0_head - old_area_0_head;
03395     }
03396 
03397     if(kv_size_diff > 0) {
03398         /* value blob size growing requires memmove() after realloc() */
03399         memmove(hkvt->tail+kv_size_diff, hkvt->tail, memmove_len);
03400         ret = cfstore_file_update(hkvt->head, kv_size_diff);
03401         if(ret < ARM_DRIVER_OK){
03402             CFSTORE_ERRLOG("%s:Error:file update failed\n", __func__);
03403             goto out0;
03404         }
03405     }
03406     /* hkvt->head, hkvt->key and hkvt->value remain unchanged but hkvt->tail has moved. Update it.*/
03407     hkvt->tail = hkvt->tail + kv_size_diff;
03408 
03409     /* set the new value length in the header */
03410     cfstore_hkvt_set_value_len(hkvt, value_len);
03411     cfstore_file_create(hkvt, flags, hkey, &ctx->file_list);
03412     ctx->area_dirty_flag = true;
03413 
03414 #ifdef CFSTORE_DEBUG
03415     cfstore_hkvt_dump(hkvt, __func__);
03416     cfstore_dump_contents(__func__);
03417 #endif
03418     ret = ARM_DRIVER_OK;
03419 out0:
03420     return ret;
03421 }
03422 
03423 
03424 /* @brief  See definition in configuration_store.h for description. */
03425 static int32_t cfstore_create(const char* key_name, ARM_CFSTORE_SIZE value_len, const ARM_CFSTORE_KEYDESC* kdesc, ARM_CFSTORE_HANDLE  hkey)
03426 {
03427     bool b_acl_default = false;
03428     int32_t ret = ARM_DRIVER_ERROR;
03429     int32_t cfstore_uvisor_box_id = 0;
03430     ARM_CFSTORE_SIZE area_size = 0;
03431     ARM_CFSTORE_SIZE kv_size = 0;
03432     ARM_CFSTORE_SIZE realloc_size = 0;
03433     cfstore_area_header_t * hdr;
03434     cfstore_area_hkvt_t hkvt;
03435     cfstore_ctx_t* ctx = cfstore_ctx_get();
03436     ARM_CFSTORE_FMODE flags;
03437     cfstore_client_notify_data_t notify_data;
03438 
03439     CFSTORE_FENTRYLOG("%s:entered: key_name=\"%s\", value_len=%d, kdesc=%p\n", __func__, key_name, (int)value_len, kdesc);
03440     CFSTORE_ASSERT(kdesc != NULL);
03441     CFSTORE_ASSERT(hkey != NULL);
03442 
03443     memset(&flags, 0, sizeof(flags));
03444     if(!cfstore_ctx_is_initialised(ctx)) {
03445         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
03446         return ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
03447     }
03448     /* creating a key cannot happen while a flashJournal_log() is pending as it would change the sram area being logged*/
03449     if(cfstore_flash_journal_is_async_op_pending(ctx)) {
03450         CFSTORE_TP(CFSTORE_TP_CREATE, "%s:Debug: flash journal operation pending (awaiting asynchronous notification).\n", __func__);
03451         return ARM_CFSTORE_DRIVER_ERROR_OPERATION_PENDING;
03452     }
03453     ret = cfstore_validate_key_name(key_name);
03454     if(ret < ARM_DRIVER_OK){
03455         CFSTORE_ERRLOG("%s:Error: invalid key_name (%s).\n", __func__, key_name);
03456         goto out0;
03457     }
03458     ret = cfstore_validate_handle(hkey);
03459     if(ret < ARM_DRIVER_OK){
03460         CFSTORE_ERRLOG("%s:Error: invalid handle.\n", __func__);
03461         goto out0;
03462     }
03463     ret = cfstore_validate_value_len(value_len);
03464     if(ret < ARM_DRIVER_OK){
03465         CFSTORE_ERRLOG("%s:Error: invalid key_name.\n", __func__);
03466         goto out0;
03467     }
03468     /* check uvisor security */
03469     if(cfstore_is_client_kv_owner(key_name, &cfstore_uvisor_box_id) != ARM_DRIVER_OK){
03470         CFSTORE_ERRLOG("%s:Error: Client has insufficient permissions to create KV.\n", __func__);
03471         ret = ARM_CFSTORE_DRIVER_ERROR_NO_PERMISSIONS;
03472         goto out0;
03473     }
03474     /* the cfstore (uvisor) client is the owner of the KV and therefore is permitted to created it */
03475     /* A null kdesc is permitted if client is growing/shrinking pre-existing key.
03476      * Hence, find if key_name pre-exists before validating kdesc */
03477     ret = cfstore_find_ex(key_name, NULL, &hkvt);
03478     if(ret < ARM_DRIVER_OK && ret != ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND){
03479         CFSTORE_ERRLOG("%s:CFSTORE find() returned error (%d)\n", __func__, (int) ret);
03480         goto out1;
03481     }
03482 
03483     if(ret != ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND && cfstore_hkvt_is_valid(&hkvt, ctx->area_0_tail)){
03484         /* found pre-existing entry; */
03485         if(cfstore_hkvt_get_flags_delete(&hkvt)){
03486             CFSTORE_ERRLOG("%s:CFSTORE pre-existing KV with key_name=\"%s\" deleting\n", __func__, key_name);
03487             ret = ARM_CFSTORE_DRIVER_ERROR_PREEXISTING_KEY_DELETING;
03488             goto out1;
03489         }
03490         if(kdesc != NULL) {
03491             CFSTORE_ERRLOG("%s:CFSTORE contains pre-existing KV with key_name=\"%s\". Cannot create a new KV with the same name\n", __func__, key_name);
03492             ret = ARM_CFSTORE_DRIVER_ERROR_PREEXISTING_KEY;
03493             goto out1;
03494         }
03495 
03496         /* client is requesting to grow/shrink pre-existing key */
03497         ret = cfstore_recreate(key_name, value_len, hkey, &hkvt);
03498         goto out1;
03499     }
03500     /* not a valid hkvt implying the key_name wasnt found */
03501 
03502     /* create new key */
03503     ret = cfstore_validate_key_desc(kdesc);
03504     if(ret < ARM_DRIVER_OK){
03505         CFSTORE_ERRLOG("%s:Error: invalid key descriptor.\n", __func__);
03506         goto out1;
03507     }
03508     /* insert the KV into the area */
03509     kv_size = strlen(key_name);
03510     kv_size += value_len;
03511     kv_size += sizeof(cfstore_area_header_t );
03512 
03513     /* grow the area by the size of the new KV
03514      * In the general case the new ((area_size + kv_size) % program_unit > 0). The new area_size is
03515      * aligned to a program_unit boundary to facilitate r/w to flash and so the memory realloc size
03516      * is calculated to align, as follows */
03517     area_size = cfstore_ctx_get_kv_total_len();
03518     /* setup the reallocation memory size. */
03519     realloc_size = area_size + kv_size;
03520     ret = cfstore_realloc_ex(realloc_size, NULL);
03521     if(ret < ARM_DRIVER_OK){
03522         CFSTORE_ERRLOG("%s:Error:file realloc failed\n", __func__);
03523         goto out1;
03524     }
03525 
03526     /* determine if should adopt a default behavior for acl permission setting */
03527     if(cfstore_acl_is_default(kdesc->acl)){
03528         /* set as read-write by default default */
03529         CFSTORE_TP(CFSTORE_TP_CREATE, "%s:Note: No ACL bits set. Adopting default permissions of owner read and write.\n", __func__);
03530         b_acl_default = true;
03531     }
03532     /* set the header up, then copy key_name into header */
03533     hdr = (cfstore_area_header_t *) (ctx->area_0_head + area_size);
03534     CFSTORE_FENTRYLOG("%s:hdr=%p\n", __func__, hdr);
03535     hdr->klength = (uint8_t) strlen(key_name);
03536     hdr->vlength = value_len;
03537     hdr->perm_owner_read = b_acl_default ? true : kdesc->acl.perm_owner_read;
03538     hdr->perm_owner_write = b_acl_default ? true : kdesc->acl.perm_owner_write;
03539     hdr->perm_owner_execute = kdesc->acl.perm_owner_execute;
03540     hdr->perm_other_read = kdesc->acl.perm_other_read;
03541     hdr->perm_other_write = kdesc->acl.perm_other_write;
03542     hdr->perm_other_execute = kdesc->acl.perm_other_execute;
03543     strncpy((char*)hdr + sizeof(cfstore_area_header_t ), key_name, strlen(key_name));
03544     hkvt = cfstore_get_hkvt_from_head_ptr((uint8_t*) hdr);
03545     if(cfstore_flags_is_default(kdesc->flags)){
03546         /* set as read-only by default default */
03547         flags.read = true;
03548         flags.write = true;
03549     } else {
03550         flags.read = kdesc->flags.read;
03551         flags.write = kdesc->flags.write;
03552     }
03553     cfstore_file_create(&hkvt, flags, hkey, &ctx->file_list);
03554     ctx->area_dirty_flag = true;
03555     ret = ARM_DRIVER_OK;
03556 out1:
03557     cfstore_hkvt_dump(&hkvt,  __func__);
03558 out0:
03559     cfstore_dump_contents(__func__);
03560     /* Create() always completes synchronously irrespective of flash mode, so indicate to caller */
03561     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_CREATE, ret, hkey);
03562     cfstore_ctx_client_notify(ctx, &notify_data);
03563     return ret;
03564 }
03565 
03566 
03567 /* @brief  See definition in configuration_store.h for description. */
03568 static int32_t cfstore_open(const char* key_name, ARM_CFSTORE_FMODE flags, ARM_CFSTORE_HANDLE  hkey)
03569 {
03570     int32_t ret = ARM_DRIVER_ERROR;
03571     cfstore_area_hkvt_t hkvt;
03572     cfstore_file_t *file = NULL;
03573     cfstore_ctx_t* ctx = cfstore_ctx_get();
03574     cfstore_client_notify_data_t notify_data;
03575 
03576     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
03577     cfstore_flags_dump(flags, __func__);
03578     CFSTORE_ASSERT(key_name != NULL);
03579     CFSTORE_ASSERT(hkey != NULL);
03580     if(!cfstore_ctx_is_initialised(ctx)) {
03581         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
03582         ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
03583         goto out1;
03584     }
03585     ret = cfstore_validate_key_name(key_name);
03586     if(ret < ARM_DRIVER_OK){
03587         CFSTORE_ERRLOG("%s:Error: invalid key_name.\n", __func__);
03588         goto out1;
03589     }
03590     ret = cfstore_validate_fmode_flags(flags);
03591     if(ret < ARM_DRIVER_OK){
03592         CFSTORE_ERRLOG("%s:Error: invalid flags.\n", __func__);
03593         goto out1;
03594     }
03595     if(flags.write){
03596         /* opening a pre-existing key for writing can result in the sram area being changed, which
03597          * cannot happen while a flashJournal_xxx() async completion notification is outstanding */
03598         if(cfstore_flash_journal_is_async_op_pending(ctx)) {
03599             CFSTORE_TP(CFSTORE_TP_OPEN, "%s:Debug: flash journal operation pending (awaiting asynchronous notification).\n", __func__);
03600             ret = ARM_CFSTORE_DRIVER_ERROR_OPERATION_PENDING;
03601             goto out1;
03602         }
03603     }
03604     ret = cfstore_validate_handle(hkey);
03605     if(ret < ARM_DRIVER_OK){
03606         CFSTORE_ERRLOG("%s:Error: invalid handle.\n", __func__);
03607         goto out1;
03608     }
03609     /* find the KV and return a handle */
03610     cfstore_hkvt_init(&hkvt);
03611     ret = cfstore_find_ex(key_name, NULL, &hkvt);
03612     if(ret < ARM_DRIVER_OK){
03613         /* either no more entries or error but either way, return */
03614         CFSTORE_TP(CFSTORE_TP_OPEN, "%s:debug: find failed or no more kvs.\n", __func__);
03615         goto out1;
03616     }
03617     if(!cfstore_hkvt_is_valid(&hkvt, ctx->area_0_tail))
03618     {
03619         CFSTORE_ERRLOG("%s:Error: Could not find pre-existing key to open with key_name=(%s).\n", __func__, key_name);
03620         ret = ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND;
03621         goto out1;
03622     }
03623     /* if this KV is deleting then do not allow item to be opened */
03624     if(cfstore_hkvt_get_flags_delete(&hkvt)){
03625         CFSTORE_ERRLOG("%s:Error: Pre-existing key key_name=(%s) is deleting.\n", __func__, key_name);
03626         ret = ARM_CFSTORE_DRIVER_ERROR_PREEXISTING_KEY_DELETING;
03627         goto out1;
03628     }
03629     /* key found, check permissions */
03630     if(cfstore_flags_is_default(flags)){
03631         /* set as read-only by default default */
03632         flags.read = true;
03633     }
03634     if(flags.read == true && !cfstore_is_kv_client_readable(&hkvt)){
03635         CFSTORE_ERRLOG("%s:Error: Client has no read access to KV (key_name=%s).\n", __func__, key_name);
03636         ret = ARM_CFSTORE_DRIVER_ERROR_PERM_NO_READ_ACCESS;
03637         goto out1;
03638     }
03639     if(flags.write == true && !cfstore_is_kv_client_writable(&hkvt)){
03640         CFSTORE_ERRLOG("%s:Error: Client has no write access to KV (key_name=%s).\n", __func__, key_name);
03641         ret = ARM_CFSTORE_DRIVER_ERROR_PERM_NO_WRITE_ACCESS;
03642         goto out1;
03643     }
03644     if(flags.execute == true && !cfstore_is_kv_client_executable(&hkvt)){
03645         CFSTORE_ERRLOG("%s:Error: Client has no execute access to KV (key_name=%s).\n", __func__, key_name);
03646         ret = ARM_CFSTORE_DRIVER_ERROR_PERM_NO_EXECUTE_ACCESS;
03647         goto out1;
03648     }
03649     /* return handle to client */
03650     file = cfstore_file_create(&hkvt, flags, hkey, &ctx->file_list);
03651     if(file) {
03652         cfstore_file_dump(file, __func__);
03653     } else {
03654         CFSTORE_ERRLOG("%s:Error: failed to create file (key_name=%s).\n", __func__, key_name);
03655     }
03656 out1:
03657     /* Open() always completes synchronously irrespective of flash mode, so indicate to caller */
03658     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_OPEN, ret, hkey);
03659     cfstore_ctx_client_notify(ctx, &notify_data);
03660     return ret;
03661 }
03662 
03663 
03664 /* @brief  See definition in configuration_store.h for description. */
03665 static int32_t cfstore_close(ARM_CFSTORE_HANDLE  hkey)
03666 {
03667     int32_t ret = ARM_DRIVER_ERROR;
03668     cfstore_ctx_t* ctx = cfstore_ctx_get();
03669     cfstore_client_notify_data_t notify_data;
03670     cfstore_area_hkvt_t hkvt;
03671 
03672     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
03673     if(!cfstore_ctx_is_initialised(ctx)) {
03674         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
03675         ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
03676         goto out0;
03677     }
03678     /* closing a key can lead to its deletion, which cannot happening while there are pending
03679      * async operations outstanding */
03680     if(cfstore_flash_journal_is_async_op_pending(ctx)) {
03681         CFSTORE_TP(CFSTORE_TP_CLOSE, "%s:Debug: flash journal operation pending (awaiting asynchronous notification).\n", __func__);
03682         ret = ARM_CFSTORE_DRIVER_ERROR_OPERATION_PENDING;
03683         goto out0;
03684     }
03685     ret = cfstore_validate_handle(hkey);
03686     if(ret < ARM_DRIVER_OK){
03687         CFSTORE_ERRLOG("%s:Error: invalid hkey argument.\n", __func__);
03688         goto out0;
03689     }
03690     /* check the hkey is valid */
03691     hkvt = cfstore_get_hkvt(hkey);
03692     if(!cfstore_hkvt_is_valid(&hkvt, ctx->area_0_tail)){
03693         CFSTORE_ERRLOG("%s:ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE\n", __func__);
03694         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE;
03695         goto out0;
03696     }
03697     if(!cfstore_is_kv_client_closable((cfstore_file_t*) hkey)){
03698         CFSTORE_ERRLOG("%s:Error: client is not permitted to close KV.\n", __func__);
03699         ret = ARM_CFSTORE_DRIVER_ERROR_NO_PERMISSIONS;
03700         goto out0;
03701     }
03702     /* delete the file associated with this open handle */
03703     CFSTORE_TP(CFSTORE_TP_CLOSE, "%s:about to call cfstore_file_destroy().\n", __func__);
03704     cfstore_file_dump((cfstore_file_t*) hkey, __func__);
03705     ret = cfstore_file_destroy(cfstore_file_get(hkey));
03706 out0:
03707     /* Close() always completes synchronously irrespective of flash mode, so indicate to caller */
03708     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_CLOSE, ret, NULL);
03709     cfstore_ctx_client_notify(ctx, &notify_data);
03710     return ret;
03711 }
03712 
03713 
03714 /* @brief  See definition in configuration_store.h for description. */
03715 static int32_t cfstore_read(ARM_CFSTORE_HANDLE  hkey, void* data, ARM_CFSTORE_SIZE* len)
03716 {
03717     int32_t ret = ARM_DRIVER_ERROR;
03718     ARM_CFSTORE_SIZE read_len = 0;
03719     cfstore_area_hkvt_t hkvt;
03720     cfstore_ctx_t* ctx = cfstore_ctx_get();
03721     cfstore_file_t* file = cfstore_file_get(hkey);
03722     cfstore_client_notify_data_t notify_data;
03723 
03724     CFSTORE_ASSERT(data);
03725     CFSTORE_ASSERT(len);
03726     CFSTORE_FENTRYLOG("%s:entered, hkey=%p\n", __func__, hkey);
03727     if(!cfstore_ctx_is_initialised(ctx)) {
03728         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
03729         ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
03730         goto out0;
03731     }
03732     /* reading KVs doesnt change the sram area so this can happen independently of
03733      * an oustanding async operation. its unnecessary to check the fsm state */
03734     ret = cfstore_validate_handle(hkey);
03735     if(ret < ARM_DRIVER_OK){
03736         CFSTORE_ERRLOG("%s:Error: invalid handle.\n", __func__);
03737         goto out0;
03738     }
03739     if(data == NULL){
03740         CFSTORE_ERRLOG("%s:Error: invalid read data buffer.\n", __func__);
03741         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_READ_BUFFER;
03742         goto out0;
03743     }
03744     ret = cfstore_validate_len_ptr(len);
03745     if(ret < ARM_DRIVER_OK){
03746         CFSTORE_ERRLOG("%s:Error: invalid len argument.\n", __func__);
03747         goto out0;
03748     }
03749     cfstore_hkvt_init(&hkvt);
03750     hkvt = cfstore_get_hkvt(hkey);
03751     /* check the hkey is valid */
03752     if(!cfstore_hkvt_is_valid(&hkvt, ctx->area_0_tail)){
03753         CFSTORE_ERRLOG("%s:ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE\n", __func__);
03754         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE;
03755         goto out0;
03756     }
03757 
03758     if(!cfstore_is_kv_client_readable(&hkvt)){
03759         CFSTORE_ERRLOG("%s:Error: client does not have permission to read KV.\n", __func__);
03760         ret = ARM_CFSTORE_DRIVER_ERROR_PERM_NO_READ_ACCESS;
03761         goto out0;
03762     }
03763     read_len = *len <= (cfstore_hkvt_get_value_len(&hkvt) - file->rlocation) ? *len : cfstore_hkvt_get_value_len(&hkvt) - file->rlocation;
03764     memcpy(data, hkvt.value + file->rlocation, read_len);
03765     file->rlocation += read_len;
03766     *len = read_len;
03767     ret = read_len;
03768 out0:
03769     /* Read() always completes synchronously irrespective of flash mode, so indicate to caller */
03770     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_READ, ret, hkey);
03771     cfstore_ctx_client_notify(ctx, &notify_data);
03772     return ret;
03773 }
03774 
03775 
03776 /* @brief  See definition in configuration_store.h for description. */
03777 static int32_t cfstore_write(ARM_CFSTORE_HANDLE  hkey, const char* data, ARM_CFSTORE_SIZE* len)
03778 {
03779     int32_t ret = ARM_DRIVER_ERROR;
03780     ARM_CFSTORE_SIZE value_len = 0;
03781     cfstore_area_hkvt_t hkvt;
03782     cfstore_file_t* file = cfstore_file_get(hkey);
03783     cfstore_ctx_t* ctx = cfstore_ctx_get();
03784     cfstore_client_notify_data_t notify_data;
03785 
03786     CFSTORE_FENTRYLOG("%s:entered, hkey=%p\n", __func__, hkey);
03787     CFSTORE_ASSERT(hkey != NULL);
03788     CFSTORE_ASSERT(len != NULL);
03789     if(!cfstore_ctx_is_initialised(ctx)) {
03790         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
03791         ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
03792         goto out0;
03793     }
03794     /* writing a key cannot happen while a flashJournal_xxx() async operation is pending */
03795     if(cfstore_flash_journal_is_async_op_pending(ctx)) {
03796         CFSTORE_TP(CFSTORE_TP_WRITE, "%s:Debug: flash journal operation pending (awaiting asynchronous notification).\n", __func__);
03797         ret = ARM_CFSTORE_DRIVER_ERROR_OPERATION_PENDING;
03798         goto out0;
03799     }
03800     ret = cfstore_validate_handle(hkey);
03801     if(ret < ARM_DRIVER_OK){
03802         CFSTORE_ERRLOG("%s:Error: invalid handle.\n", __func__);
03803         goto out0;
03804     }
03805     if(data == NULL){
03806         CFSTORE_ERRLOG("%s:Error: invalid write data buffer.\n", __func__);
03807         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_WRITE_BUFFER;
03808         goto out0;
03809     }
03810     ret = cfstore_validate_len_ptr(len);
03811     if(ret < ARM_DRIVER_OK){
03812         CFSTORE_ERRLOG("%s:Error: invalid len argument.\n", __func__);
03813         goto out0;
03814     }
03815     ret = cfstore_validate_value_len(*len);
03816     if (ret < ARM_DRIVER_OK) {
03817         CFSTORE_ERRLOG("%s:Error: invalid key_name.\n", __func__);
03818         goto out0;
03819     }
03820     /*check file has write permission set */
03821     if(!file->flags.write){
03822         CFSTORE_ERRLOG("%s:Error: KV is read-only.\n", __func__);
03823         ret = ARM_CFSTORE_DRIVER_ERROR_KEY_READ_ONLY;
03824         goto out0;
03825     }
03826     memset(&hkvt, 0, sizeof(hkvt));
03827     hkvt = cfstore_get_hkvt(hkey);
03828     if(!cfstore_hkvt_is_valid(&hkvt, ctx->area_0_tail)){
03829         CFSTORE_ERRLOG("%s:Error: ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE.\n", __func__);
03830         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE;
03831         goto out0;
03832     }
03833     if(!cfstore_is_kv_client_writable(&hkvt)){
03834         CFSTORE_ERRLOG("%s:Error: client does not have permission to write KV.\n", __func__);
03835         ret = ARM_CFSTORE_DRIVER_ERROR_PERM_NO_WRITE_ACCESS;
03836         goto out0;
03837     }
03838     value_len = (ARM_CFSTORE_SIZE) cfstore_hkvt_get_value_len(&hkvt);
03839     *len = *len < value_len ? *len: value_len;
03840     memcpy(hkvt.value + file->wlocation, data, *len);
03841     file->wlocation += *len;
03842     cfstore_hkvt_dump(&hkvt, __func__);
03843     ctx->area_dirty_flag = true;
03844     ret = *len;
03845 out0:
03846     /* Write() always completes synchronously irrespective of flash mode, so indicate to caller */
03847     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_WRITE, ret, hkey);
03848     cfstore_ctx_client_notify(ctx, &notify_data);
03849     return ret;
03850 }
03851 
03852 
03853 /* @brief  See definition in configuration_store.h for description. */
03854 static int32_t cfstore_rseek(ARM_CFSTORE_HANDLE  hkey, ARM_CFSTORE_OFFSET offset)
03855 {
03856     int32_t ret = ARM_DRIVER_ERROR;
03857     cfstore_area_hkvt_t hkvt;
03858     cfstore_file_t* file = cfstore_file_get(hkey);
03859     cfstore_ctx_t* ctx = cfstore_ctx_get();
03860     cfstore_client_notify_data_t notify_data;
03861 
03862     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
03863     if(!cfstore_ctx_is_initialised(ctx)) {
03864         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
03865         return ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
03866     }
03867     /* read-seeking KVs doesnt change the sram area so this can happen independently of
03868      * an oustanding async operation. its unnecessary to check the fsm state */
03869     ret = cfstore_validate_handle(hkey);
03870     if(ret < ARM_DRIVER_OK){
03871         CFSTORE_ERRLOG("%s:Error: invalid handle.\n", __func__);
03872         return ret;
03873     }
03874     ret = cfstore_validate_value_len(offset);
03875     if(ret < ARM_DRIVER_OK){
03876         CFSTORE_ERRLOG("%s:Error: offset (%u) greater than maximum value blob size (%u).\n", __func__, (unsigned int) offset, CFSTORE_VALUE_SIZE_MAX);
03877         return ret;
03878     }
03879     if(!file->flags.read){
03880         CFSTORE_ERRLOG("%s:Error: KV is not readable.\n", __func__);
03881         ret = ARM_CFSTORE_DRIVER_ERROR_KEY_UNREADABLE;
03882         goto out0;
03883 
03884     }
03885     cfstore_hkvt_init(&hkvt);
03886     hkvt = cfstore_get_hkvt(hkey);
03887     if(!cfstore_hkvt_is_valid(&hkvt, ctx->area_0_tail)){
03888         CFSTORE_ERRLOG("%s:Error: ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE.\n", __func__);
03889         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE;
03890         goto out0;
03891     }
03892     if(!cfstore_is_kv_client_readable(&hkvt)){
03893         CFSTORE_ERRLOG("%s:Error: client does not have permission to read KV.\n", __func__);
03894         ret = ARM_CFSTORE_DRIVER_ERROR_PERM_NO_READ_ACCESS;
03895         goto out0;
03896     }
03897     /* check offset is in range */
03898     if(offset > cfstore_hkvt_get_value_len(&hkvt)){
03899         CFSTORE_ERRLOG("%s:Error: seeking beyond end of value.\n", __func__);
03900         ret = ARM_CFSTORE_DRIVER_ERROR_INVALID_SEEK;
03901         goto out0;
03902 
03903     }
03904     file->rlocation = offset;
03905     ret = (int32_t) offset;
03906 out0:
03907     /* Rseek() always completes synchronously irrespective of flash mode, so indicate to caller */
03908     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_RSEEK, ret, hkey);
03909     cfstore_ctx_client_notify(ctx, &notify_data);
03910     return ret;
03911 }
03912 
03913 
03914 /* @brief  See definition in configuration_store.h for description. */
03915 static int32_t cfstore_flush(void)
03916 {
03917     int32_t ret = ARM_DRIVER_ERROR;
03918     cfstore_ctx_t* ctx = cfstore_ctx_get();
03919 
03920     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
03921     if(!cfstore_ctx_is_initialised(ctx)) {
03922         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
03923         ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
03924         goto out0;
03925     }
03926     /* only 1 flush operation can be outstanding so check whether one is already in progress */
03927     if(cfstore_flash_journal_is_async_op_pending(ctx)) {
03928         CFSTORE_TP(CFSTORE_TP_FLUSH, "%s:Debug: flash journal operation pending (awaiting asynchronous notification).\n", __func__);
03929         return ARM_CFSTORE_DRIVER_ERROR_OPERATION_PENDING;
03930     }
03931     ret = cfstore_flash_flush(ctx);
03932     if(ret < ARM_DRIVER_OK) {
03933         CFSTORE_ERRLOG("%s:Error: cfstore_flash_flush() returned error (ret=%d).\n", __func__, (int) ret);
03934         goto out0;
03935     }
03936 out0:
03937     return ret;
03938 }
03939 
03940 /* @brief  See definition in configuration_store.h for description. */
03941 static int32_t cfstore_initialise(ARM_CFSTORE_CALLBACK callback, void* client_context)
03942 {
03943     int ret = ARM_DRIVER_ERROR;
03944     cfstore_ctx_t* ctx = cfstore_ctx_get();
03945 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
03946     ARM_STORAGE_CAPABILITIES storage_caps;
03947 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
03948 
03949     CFSTORE_FENTRYLOG("%s:entered: callback=%p, client_context=%p, ref_count=%d\n", __func__, callback, client_context, (int) ctx->init_ref_count);
03950     /* init cfstore context the first time this method is called
03951      * note ctx->rw_area0_lock has already been initialised */
03952 
03953     /* CS protection required to get into the fsm into the initing state, without another client g*/
03954     cfstore_critical_section_lock(&ctx->rw_area0_lock, __func__);
03955     if(ctx->init_ref_count == 0)
03956     {
03957         CFSTORE_TP(CFSTORE_TP_INIT, "%s:debug: first time init\n", __func__);
03958         /* perform first time initialisation */
03959         ctx->init_ref_count++;
03960         /* initially there is no memory allocated for the area */
03961         CFSTORE_INIT_LIST_HEAD(&ctx->file_list);
03962         /* ctx->rw_area0_lock initialisation is not required here as the lock is statically initialised to 0 */
03963         ctx->area_0_head = NULL;
03964         ctx->area_0_tail = NULL;
03965 
03966         CFSTORE_ASSERT(sizeof(cfstore_file_t) == CFSTORE_HANDLE_BUFSIZE);
03967         if(sizeof(cfstore_file_t) != CFSTORE_HANDLE_BUFSIZE){
03968             CFSTORE_ERRLOG("%s:Error: sizeof(cfstore_file_t)=(%d) != CFSTORE_HANDLE_BUFSIZE (%d)\n", __func__,(int) sizeof(cfstore_file_t), (int) CFSTORE_HANDLE_BUFSIZE);
03969             ret = ARM_CFSTORE_DRIVER_ERROR_INTERNAL;
03970             goto out0;
03971         }
03972         ctx->client_callback = callback;
03973         ctx->client_context = client_context;
03974         ctx->area_dirty_flag = false;
03975         ctx->client_callback_notify_flag = false;
03976 
03977         cfstore_client_notify_data_init(&ctx->client_notify_data, CFSTORE_OPCODE_MAX, ARM_DRIVER_ERROR, NULL);
03978         ctx->power_state = ARM_POWER_FULL;
03979         ctx->status = ARM_DRIVER_OK;
03980 
03981 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
03982         /* set the cfstore async flag according to the storage driver mode */
03983         storage_caps = cfstore_storage_drv->GetCapabilities();
03984         cfstore_caps_g.asynchronous_ops = storage_caps.asynchronous_ops;
03985 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
03986 
03987         ret = cfstore_flash_init();
03988         if(ret < ARM_DRIVER_OK) {
03989             CFSTORE_ERRLOG("%s:Error: failed to initialise flash layer\n", __func__);
03990             goto out0;
03991         }
03992     }
03993     else
03994     {
03995         CFSTORE_TP(CFSTORE_TP_INIT, "%s:debug: n-th time init\n", __func__);
03996         /* initialisation already done so only increment the ref count */
03997         ctx->init_ref_count++;
03998         ret = ARM_DRIVER_OK;
03999     }
04000 out0:
04001     /* if not initialised already, fsm now in the initing state so safe to come out of CS */
04002     cfstore_critical_section_unlock(&ctx->rw_area0_lock, __func__);
04003     CFSTORE_FENTRYLOG("%s:exiting: callback=%p, client_context=%p, ref_count=%d\n", __func__, callback, client_context, (int) ctx->init_ref_count);
04004     return ret;
04005 }
04006 
04007 
04008 /* @brief  See prototype definition in configuration_store.h for function description.
04009  *
04010  * @note    unitialising cfstore results in all entries that have not been flushed being lost
04011  */
04012 static int32_t cfstore_uninitialise(void)
04013 {
04014     int32_t ret = ARM_DRIVER_ERROR;
04015     ARM_STORAGE_CAPABILITIES caps;
04016     cfstore_ctx_t* ctx = cfstore_ctx_get();
04017     cfstore_file_t* file;
04018     cfstore_list_node_t* node;
04019     cfstore_list_node_t* file_list = &ctx->file_list;
04020 
04021     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04022     memset(&caps, 0, sizeof(caps));
04023 
04024     if(!cfstore_ctx_is_initialised(ctx)) {
04025         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
04026         ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
04027         goto out;
04028     }
04029     /* only uninitialise when there are no flash journal async operations pending*/
04030     if(cfstore_flash_journal_is_async_op_pending(ctx)) {
04031         CFSTORE_TP(CFSTORE_TP_INIT, "%s:Debug: flash journal operation pending (awaiting asynchronous notification).\n", __func__);
04032         ret = ARM_CFSTORE_DRIVER_ERROR_OPERATION_PENDING;
04033         goto out;
04034     }
04035     if(ctx->init_ref_count > 0) {
04036         ctx->init_ref_count--;
04037         CFSTORE_TP(CFSTORE_TP_INIT, "%s:Debug: decremented init_ref_count (%d).\n", __func__, (int) ctx->init_ref_count);
04038     }
04039     if(ctx->init_ref_count == 0)
04040     {
04041         CFSTORE_TP(CFSTORE_TP_INIT, "%s:Debug: init_ref_count == 0 (%d) so uninitialising.\n", __func__, (int) ctx->init_ref_count);
04042         /* check file list is empty and if not, free the items */
04043         if(ctx->file_list.next != ctx->file_list.prev)
04044         {
04045             /* list is not empty. walk the list and close the files, cleaning up state */
04046             node = file_list->next;
04047             while(node != file_list){
04048                 file = (cfstore_file_t*) node;
04049                 cfstore_close((ARM_CFSTORE_HANDLE ) file);
04050                 node = node->next;
04051             }
04052         }
04053         ret = cfstore_flash_deinit();
04054         if(ret < ARM_DRIVER_OK){
04055             CFSTORE_ERRLOG("%s:Error: failed to uninitialise flash journal layer.\n", __func__);
04056             goto out;
04057         }
04058         if(ctx->area_0_head){
04059             CFSTORE_FREE(ctx->area_0_head);
04060             ctx->area_0_head = NULL;
04061             ctx->area_0_tail = NULL;
04062             ctx->area_0_len = 0;
04063         }
04064     }
04065 out:
04066     /* notify client */
04067     cfstore_client_notify_data_init(&ctx->client_notify_data, CFSTORE_OPCODE_UNINITIALIZE, ret, NULL);
04068     cfstore_ctx_client_notify(ctx, &ctx->client_notify_data);
04069     return ret;
04070 }
04071 
04072 
04073 /* @brief  See definition in configuration_store.h for description. */
04074 static int32_t cfstore_power_control(ARM_POWER_STATE state)
04075 {
04076     int32_t ret = ARM_DRIVER_ERROR;
04077     cfstore_ctx_t* ctx = cfstore_ctx_get();
04078     cfstore_client_notify_data_t notify_data;
04079 
04080     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04081     if(!cfstore_ctx_is_initialised(ctx)) {
04082         CFSTORE_ERRLOG("%s:Error: CFSTORE is not initialised.\n", __func__);
04083         ret = ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED;
04084         goto out0;
04085     }
04086     /* setting power state doesnt change the sram area so this can happen independently of
04087      * an oustanding async operation. its unnecessary to check the fsm state */
04088     if(state <= ARM_POWER_FULL){
04089         ctx->power_state = state;
04090         /* set return to a positive value*/
04091         ret = (int32_t) state;
04092     }
04093 out0:
04094     /* PowerControl() always completes synchronously irrespective of flash mode, so indicate to caller */
04095     cfstore_client_notify_data_init(&notify_data, CFSTORE_OPCODE_POWER_CONTROL, ret, NULL);
04096     cfstore_ctx_client_notify(ctx, &notify_data);
04097     return ret;
04098 }
04099 
04100 
04101 #ifdef YOTTA_CFG_CFSTORE_UVISOR
04102 
04103 /*
04104  * uvisor secure gateways for ARM_CFSTORE_DRIVER access methods.
04105  */
04106 
04107 UVISOR_EXTERN int32_t __cfstore_uvisor_close(ARM_CFSTORE_HANDLE  hkey)
04108 {
04109     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04110     return cfstore_close(hkey);
04111 }
04112 
04113 static int32_t cfstore_uvisor_close(ARM_CFSTORE_HANDLE  hkey)
04114 {
04115     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04116     return secure_gateway(configuration_store, __cfstore_uvisor_close, hkey);
04117 }
04118 
04119 UVISOR_EXTERN int32_t __cfstore_uvisor_create(const char* key_name, ARM_CFSTORE_SIZE value_len, const ARM_CFSTORE_KEYDESC* kdesc, ARM_CFSTORE_HANDLE  hkey)
04120 {
04121     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04122     return cfstore_create(key_name, value_len, kdesc, hkey);
04123 }
04124 
04125 static int32_t cfstore_uvisor_create(const char* key_name, ARM_CFSTORE_SIZE value_len, const ARM_CFSTORE_KEYDESC* kdesc, ARM_CFSTORE_HANDLE  hkey)
04126 {
04127     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04128     return secure_gateway(configuration_store, __cfstore_uvisor_create, key_name, value_len, kdesc, hkey);
04129 }
04130 
04131 UVISOR_EXTERN int32_t __cfstore_uvisor_delete(ARM_CFSTORE_HANDLE  hkey)
04132 {
04133     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04134     return cfstore_delete(hkey);
04135 }
04136 
04137 static int32_t cfstore_uvisor_delete(ARM_CFSTORE_HANDLE  hkey)
04138 {
04139     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04140     return secure_gateway(configuration_store, __cfstore_uvisor_delete, hkey);
04141 }
04142 
04143 UVISOR_EXTERN int32_t __cfstore_uvisor_find(const char* key_name_query, const ARM_CFSTORE_HANDLE  previous, ARM_CFSTORE_HANDLE  next)
04144 {
04145     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04146     return cfstore_find(key_name_query, previous, next);
04147 }
04148 
04149 static int32_t cfstore_uvisor_find(const char* key_name_query, const ARM_CFSTORE_HANDLE  previous, ARM_CFSTORE_HANDLE  next)
04150 {
04151     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04152     return secure_gateway(configuration_store, __cfstore_uvisor_find, key_name_query, previous, next);
04153 }
04154 
04155 UVISOR_EXTERN int32_t __cfstore_uvisor_flush(int dummy)
04156 {
04157     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04158     (void) dummy;
04159     return cfstore_flush();
04160 }
04161 
04162 static int32_t cfstore_uvisor_flush(void)
04163 {
04164     int dummy = 0;
04165 
04166     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04167     return secure_gateway(configuration_store, __cfstore_uvisor_flush, dummy);
04168 }
04169 
04170 UVISOR_EXTERN int32_t __cfstore_uvisor_get_key_name(ARM_CFSTORE_HANDLE  hkey, char* key_name, uint8_t *key_name_len)
04171 {
04172     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04173     return cfstore_get_key_name(hkey, key_name, key_name_len);
04174 }
04175 
04176 static int32_t cfstore_uvisor_get_key_name(ARM_CFSTORE_HANDLE  hkey, char* key_name, uint8_t *key_name_len)
04177 {
04178     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04179     return secure_gateway(configuration_store, __cfstore_uvisor_get_key_name, hkey, key_name, key_name_len);
04180 }
04181 
04182 UVISOR_EXTERN int32_t __cfstore_uvisor_get_value_len(ARM_CFSTORE_HANDLE  hkey, ARM_CFSTORE_SIZE *value_len)
04183 {
04184     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04185     return cfstore_get_value_len(hkey, value_len);
04186 }
04187 
04188 static int32_t cfstore_uvisor_get_value_len(ARM_CFSTORE_HANDLE  hkey, ARM_CFSTORE_SIZE *value_len)
04189 {
04190     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04191     return secure_gateway(configuration_store, __cfstore_uvisor_get_value_len, hkey, value_len);
04192 }
04193 
04194 UVISOR_EXTERN int32_t __cfstore_uvisor_initialize(ARM_CFSTORE_CALLBACK callback, void* client_context)
04195 {
04196     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04197     return cfstore_initialise(callback, client_context);
04198 }
04199 
04200 static int32_t cfstore_uvisor_initialise(ARM_CFSTORE_CALLBACK callback, void* client_context)
04201 {
04202     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04203     return secure_gateway(configuration_store, __cfstore_uvisor_initialize, callback, client_context);
04204 }
04205 
04206 /* type to convert between ARM_CFSTORE_FMODE and uint32 for passing flags through secure gw */
04207 typedef union cfstore_fmode_flags_t
04208 {
04209     ARM_CFSTORE_FMODE flags;
04210     uint32_t val;
04211 } cfstore_fmode_flags_t;
04212 
04213 UVISOR_EXTERN int32_t __cfstore_uvisor_open(const char* key_name, uint32_t flags, ARM_CFSTORE_HANDLE  hkey)
04214 {
04215     cfstore_fmode_flags_t uflags;
04216 
04217     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04218     uflags.val = flags;
04219     return cfstore_open(key_name, uflags.flags, hkey);
04220 }
04221 
04222 static int32_t cfstore_uvisor_open(const char* key_name, ARM_CFSTORE_FMODE flags, ARM_CFSTORE_HANDLE  hkey)
04223 {
04224     cfstore_fmode_flags_t uflags;
04225 
04226     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04227     uflags.flags = flags;
04228     return secure_gateway(configuration_store, __cfstore_uvisor_open, key_name, uflags.val, hkey);
04229 }
04230 
04231 UVISOR_EXTERN int32_t __cfstore_uvisor_read(ARM_CFSTORE_HANDLE  hkey, void* data, ARM_CFSTORE_SIZE* len)
04232 {
04233     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04234     return cfstore_read(hkey, data, len);
04235 }
04236 
04237 static int32_t cfstore_uvisor_read(ARM_CFSTORE_HANDLE  hkey, void* data, ARM_CFSTORE_SIZE* len)
04238 {
04239     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04240     return secure_gateway(configuration_store, __cfstore_uvisor_read, hkey, data, len);
04241 }
04242 
04243 UVISOR_EXTERN int32_t __cfstore_uvisor_rseek(ARM_CFSTORE_HANDLE  hkey, ARM_CFSTORE_OFFSET offset)
04244 {
04245     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04246     return cfstore_rseek(hkey, offset);
04247 }
04248 
04249 static int32_t cfstore_uvisor_rseek(ARM_CFSTORE_HANDLE  hkey, ARM_CFSTORE_OFFSET offset)
04250 {
04251     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04252     return secure_gateway(configuration_store, __cfstore_uvisor_rseek, hkey, offset);
04253 }
04254 
04255 UVISOR_EXTERN int32_t __cfstore_uvisor_uninitialise(int dummy)
04256 {
04257     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04258     (void) dummy;
04259     return cfstore_uninitialise();
04260 }
04261 
04262 static int32_t cfstore_uvisor_uninitialize(void)
04263 {
04264     int dummy = 0;
04265 
04266     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04267     return secure_gateway(configuration_store, __cfstore_uvisor_uninitialise, dummy);
04268 }
04269 
04270 UVISOR_EXTERN int32_t __cfstore_uvisor_write(ARM_CFSTORE_HANDLE  hkey, const char* data, ARM_CFSTORE_SIZE* len)
04271 {
04272     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04273     return cfstore_write(hkey, data, len);
04274 }
04275 
04276 static int32_t cfstore_uvisor_write(ARM_CFSTORE_HANDLE  hkey, const char* data, ARM_CFSTORE_SIZE* len)
04277 {
04278     CFSTORE_FENTRYLOG("%s:entered\n", __func__);
04279     return secure_gateway(configuration_store, __cfstore_uvisor_write, hkey, data, len);
04280 }
04281 
04282 
04283 ARM_CFSTORE_DRIVER cfstore_driver =
04284 {
04285         .Close = cfstore_uvisor_close,
04286         .Create = cfstore_uvisor_create,
04287         .Delete= cfstore_uvisor_delete,
04288         .Find = cfstore_uvisor_find,
04289         .Flush = cfstore_uvisor_flush,
04290         .GetCapabilities = cfstore_get_capabilities,
04291         .GetKeyName = cfstore_uvisor_get_key_name,
04292         .GetStatus = cfstore_get_status,
04293         .GetValueLen = cfstore_uvisor_get_value_len,
04294         .GetVersion = cfstore_get_version,
04295         .Initialize = cfstore_uvisor_initialise,
04296         .Open = cfstore_uvisor_open,
04297         .PowerControl = cfstore_power_control,
04298         .Read = cfstore_uvisor_read,
04299         .Rseek = cfstore_uvisor_rseek,
04300         .Uninitialize = cfstore_uvisor_uninitialize,
04301         .Write = cfstore_uvisor_write,
04302 };
04303 
04304 #else
04305 
04306 /* non-uvisor interface */
04307 ARM_CFSTORE_DRIVER cfstore_driver =
04308 {
04309         .Close = cfstore_close,
04310         .Create = cfstore_create,
04311         .Delete= cfstore_delete,
04312         .Find = cfstore_find,
04313         .Flush = cfstore_flush,
04314         .GetCapabilities = cfstore_get_capabilities,
04315         .GetKeyName = cfstore_get_key_name,
04316         .GetStatus = cfstore_get_status,
04317         .GetValueLen = cfstore_get_value_len,
04318         .GetVersion = cfstore_get_version,
04319         .Initialize = cfstore_initialise,
04320         .Open = cfstore_open,
04321         .PowerControl = cfstore_power_control,
04322         .Read = cfstore_read,
04323         .Rseek = cfstore_rseek,
04324         .Uninitialize = cfstore_uninitialise,
04325         .Write = cfstore_write,
04326 };
04327 
04328 #endif /* YOTTA_CFG_CFSTORE_UVISOR */
04329