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