Lee Kai Xuan / mbed-os

Fork of mbed-os by erkin yucel

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