Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
configuration_store.c
Go to the documentation of this file.
00001 /** @file configuration_store.c 00002 * 00003 * mbed Microcontroller Library 00004 * Copyright (c) 2006-2016 ARM Limited 00005 * 00006 * Licensed under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 00019 // 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 alway co-ordinate 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 wasnt 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 Sun Jul 17 2022 08:25:21 by 1.7.2