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