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