joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

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