Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
configuration_store.c
00001 /** @file configuration_store.c 00002 * 00003 * mbed Microcontroller Library 00004 * Copyright (c) 2006-2016 ARM Limited 00005 * 00006 * Licensed under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 00019 #include "cfstore_config.h" 00020 #include "cfstore_debug.h" 00021 #include "cfstore_list.h" 00022 #include "cfstore_fnmatch.h" 00023 #include "configuration_store.h" 00024 00025 #if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3 00026 #include <core-util/critical.h> 00027 #endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */ 00028 00029 #ifdef YOTTA_CFG_CFSTORE_UVISOR 00030 #include "uvisor-lib/uvisor-lib.h" 00031 #endif /* YOTTA_CFG_CFSTORE_UVISOR */ 00032 00033 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00034 #include "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 13:15:40 by
