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