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