ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

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