/*! @brief _fta_var_alloc_i allocate the list record(internal) @param [in] var_header header of the area @param [in] access_info access information @param [in] key_info key @param [in] alloc_len size of the record @retval NULL: over the max record @retval others: pointer of record */ static void *_fta_var_alloc_i(fta_var_store_header *var_header, const fta_var_record_access_info *access_info, const void *key_info, uint32 alloc_len) { uint8 *var_dataarea; void *var_record = NULL; uint32 key_size; uint32 datalen_size; uint32 datalen; if(!FTA_LIB_CHECKBIT(var_header->cmn.statbit, FTA_STORE_STATBIT_RECORDING)) { goto _fta_var_alloc_exit; } key_size = access_info->key_size; datalen_size = access_info->datalen_size; if(alloc_len < key_size + datalen_size || alloc_len > var_header->cmn.size - var_header->cmn.offset) { goto _fta_var_alloc_exit; } datalen = alloc_len - (key_size + datalen_size); if((datalen_size == 0 && datalen > 0) || (datalen_size == 1 && datalen > 0xFF) || (datalen_size == 2 && datalen > 0xFFFF) || (datalen_size == 3 && datalen > 0xFFFFFF)) { goto _fta_var_alloc_exit; } alloc_len = FTA_LIB_ALIGN4_32(alloc_len); if(access_info->check_func != NULL) { if(access_info->check_func(var_header, key_info, alloc_len) == FALSE) { goto _fta_var_alloc_exit; } } if(alloc_len > var_header->cmn.size - var_header->cmn.offset - var_header->bottom) { goto _fta_var_alloc_exit; } var_dataarea = FTA_LIB_OFFSET_ADDR(var_header, var_header->cmn.offset); /* append the record */ var_record = (void *)FTA_LIB_OFFSET_ADDR(var_dataarea, var_header->bottom); memcpy(var_record, key_info, key_size); if(datalen_size > 0) { if(datalen_size <= sizeof(uint32)) { memcpy(FTA_LIB_OFFSET_ADDR(var_record, key_size), &datalen, datalen_size); } else { memcpy(FTA_LIB_OFFSET_ADDR(var_record, key_size), &datalen, sizeof(uint32)); memset(FTA_LIB_OFFSET_ADDR(var_record, key_size + sizeof(uint32)), 0, datalen_size - sizeof(uint32)); } } var_header->count++; var_header->bottom += alloc_len; _fta_var_alloc_exit: ; return var_record; }
/*! @brief fta_initialize FTA initialize function @param none @retval none */ void fta_initialize(void) { boolean dofirst = (fta_manager == NULL ? TRUE : FALSE); if(!dofirst) { memset(&fta_lock_keeper, 0, sizeof(fta_lock_keeper)); memset(&fta_reference, 0, sizeof(fta_reference)); } memset(fta_log_area,0,FTA_CONFIG_STORE_MEMORY_SIZE); fta_manager = (fta_manager_store_header *)fta_log_area; fta_manager_initializer.fta_manager = fta_manager; fta_manager_initializer.memory_addr = FTA_LIB_OFFSET_ADDR(((uint8 *)fta_manager), FTA_CALC_MANAGER_SIZE(FTA_CONFIG_STORE_INITIAL_COUNT)); if(_fta_manage_initialize(&fta_manager_initializer)) { _fta_manage_initialize_store_items(fta_manager); fta_manager->cmn.enabled = FTA_STORE_ENABLED_TRUE; FTA_LIB_CHANGEBIT_SET(fta_manager->cmn.statbit, FTA_STORE_STATBIT_RECORDING); fta_manager->parity = fta_lib_check_parity16((uint16 *)fta_manager, fta_manager->cmn.size / 2, fta_manager->parity); FTA_MEMORY_FLUSH(); fta_lock_keeper.manager_status = FTA_MANAGER_STATUS_ENABLED; /* start logging */ FTA_LOG_MESSAGE(FTA_ADMIN, FTA_LOG_LEVEL_NOTICE, "*** FTA INITIALIZED %x %x", fta_log_area, virt_to_phys(fta_log_area),0); } return; }
/*! @brief _fta_manage_get_store_item get the pointer of item for manage @param [in] fta_manager pointer of the manage aera @param [in] tag tag @retval NULL: not found @retval others: the pointer of item for manage */ fta_manager_store_item *_fta_manage_get_store_item(fta_manager_store_header *fta_manager, uint32 tag) { fta_manager_store_item *store_items; uint32 i; if(fta_manager == NULL) return NULL; store_items = (fta_manager_store_item *) FTA_LIB_OFFSET_ADDR(fta_manager, FTA_MANAGER_STORE_HEADER_LEN); /* - - - - - - - - */ for(i = 0; i < fta_manager->count; i++) { if(store_items[i].tag == tag) { return &store_items[i]; } } /* - - - - - - - - */ return NULL; }
/*! @brief _fta_manage_terminate_store_items terminate for the inidivual area @param [in] fta_manager manage area @retval none */ void _fta_manage_terminate_store_items(fta_manager_store_header *fta_manager) { fta_manager_store_item *store_items; uint32 i; if(fta_manager == NULL) return; store_items = (fta_manager_store_item *) FTA_LIB_OFFSET_ADDR(fta_manager, FTA_MANAGER_STORE_HEADER_LEN); /* - - - - - - - - */ for(i = 0; i < fta_manager->count; i++) { if(store_items[i].def->stop_func != FTA_CONFIG_UNDEFINED) { (store_items[i].def->stop_func)(&store_items[i]); } } /* - - - - - - - - */ return; }
/*! @brief _fta_manage_initialize_store_items initialize for the inidivual area @param [in] fta_manager manage area @retval none */ void _fta_manage_initialize_store_items(fta_manager_store_header *fta_manager) { fta_manager_store_item *store_items; fta_common_store_header *store_addr; uint32 i; if(fta_manager == NULL) return; store_items = (fta_manager_store_item *) FTA_LIB_OFFSET_ADDR(fta_manager, FTA_MANAGER_STORE_HEADER_LEN); /* - - - - - - - - */ for(i = 0; i < fta_manager->count; i++) { _fta_common_init_common(&store_items[i]); store_addr = store_items[i].addr; if(store_items[i].def->init_func != FTA_CONFIG_UNDEFINED) { store_addr->enabled = FTA_STORE_ENABLED_FALSE; FTA_LIB_SETBITVALUE(store_addr->statbit, FTA_STORE_STATBIT_ALLCLEAR); (store_items[i].def->init_func)(&store_items[i]); } else { /* do nothing and do not manage this area when initialize function is undefined */ } } /* - - - - - - - - */ }
/*! @brief _fta_lisext_hash_record?i internal functionn of operating the list hash record @param [in] p_store_item item for manage @param [in] access_info access information @param [in] key_info key @param [in] access_type FTA_LISTEX_HASH_ACCESS_GET: get record FTA_LISTEX_HASH_ACCESS_ADD: add record FTA_LISTEX_HASH_ACCESS_DEL: del record @retval NULL: not found / over the max record @retval others: pointer of record */ static void *_fta_listex_hash_record_i(fta_list_store_header *list_header, const fta_listex_hash_access_info *access_info, const void *key_info, uint32 access_type) { uint8 *list_dataarea; void *list_record = NULL; uint32 fixed_len; uint32 key_size; uint32 record_par; uint32 record_num; fta_listex_hash_id_type *work_buffer; boolean not_found; /* check of a recordable state or an effective state */ if(access_type != FTA_LISTEX_HASH_ACCESS_GET) { if(!FTA_LIB_CHECKBIT(list_header->cmn.statbit, FTA_STORE_STATBIT_RECORDING)) { goto _fta_listex_hash_record_exit; } } else { if(list_header->cmn.enabled != FTA_STORE_ENABLED_TRUE) { goto _fta_listex_hash_record_exit; } } fixed_len = FTA_LIB_ALIGN4_32(access_info->fixed_len); key_size = access_info->key_size; list_dataarea = FTA_LIB_OFFSET_ADDR(list_header, list_header->cmn.offset); work_buffer = access_info->work_buffer; /* registered check */ not_found = TRUE; record_par = 0; memcpy(&record_par, key_info, (key_size > sizeof(uint32) ? sizeof(uint32) : key_size)); record_par %= access_info->hash_size; /* only to 4 bytes of low rank */ record_par += FTA_LISTEX_HASH_BUF_HASHEDINDEX; if(list_header->count > 0) { /* search for the same item */ record_num = work_buffer[record_par]; while(record_num != FTA_LISTEX_HASH_ID_EMPTY) { list_record = (void *)FTA_LIB_OFFSET_ADDR(list_dataarea, record_num * fixed_len); if(memcmp(key_info, list_record, key_size) == 0) { not_found = FALSE; break; } record_par = record_num; record_num = work_buffer[record_par]; } } if(not_found) { /* add record */ if(access_type == FTA_LISTEX_HASH_ACCESS_ADD) { if(list_header->count == 0) { /* simple work area check only once after initialization */ if(work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_BEGIN] != FTA_LISTEX_HASH_ID_EMPTY || work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_END] != FTA_LISTEX_HASH_ID_EMPTY || work_buffer[FTA_LISTEX_HASH_BUF_HASHEDINDEX] != FTA_LISTEX_HASH_ID_EMPTY ) { FTA_LOG_MESSAGE(FTA_LIST, FTA_LOG_LEVEL_CRITICAL, "*** FTA LIST CONFIG ERROR", 0, 0, 0); list_record = NULL; goto _fta_listex_hash_record_exit; } } /* a new record is added */ if((uint32)(list_header->count) >= access_info->entry_max) { /* acquires from an empty list when the number of registration is a maximum */ record_num = work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_BEGIN]; if(record_num == FTA_LISTEX_HASH_ID_EMPTY) { list_record = NULL; goto _fta_listex_hash_record_exit; } /* deletes from an empty list */ work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_BEGIN] = work_buffer[record_num]; if(work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_END] == record_num) { work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_END] = FTA_LISTEX_HASH_ID_EMPTY; } } else { /* adds a new record until the number of registration is a maximum*/ record_num = list_header->count; list_header->count++; list_header->bottom = list_header->count * fixed_len; } /* adds to hash table */ work_buffer[record_num] = work_buffer[record_par]; work_buffer[record_par] = (fta_listex_hash_id_type)record_num; /* return the record position */ list_record = (void *)FTA_LIB_OFFSET_ADDR(list_dataarea, record_num * fixed_len); memcpy(list_record, key_info, key_size); } else { /* do noting */ list_record = NULL; } } else { /* delete record */ if(access_type == FTA_LISTEX_HASH_ACCESS_DEL) { /* set the delete bit */ ((uint8*)list_record)[key_size - 1] |= 0x80; /* deletes from the list and adds to an empty entry */ work_buffer[record_par] = work_buffer[record_num]; work_buffer[record_num] = FTA_LISTEX_HASH_ID_EMPTY; if(work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_BEGIN] == FTA_LISTEX_HASH_ID_EMPTY) { /* with no empty entry */ work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_BEGIN] = (fta_listex_hash_id_type)record_num; work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_END] = (fta_listex_hash_id_type)record_num; } else { /* add to a termination */ work_buffer[work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_END]] = (fta_listex_hash_id_type)record_num; work_buffer[FTA_LISTEX_HASH_BUF_EMPTY_END] = (fta_listex_hash_id_type)record_num; } } } _fta_listex_hash_record_exit: ; return list_record; }
/*! @brief _fta_manage_initialize initialize manage area @param [in] manager_initializer pointer of the manage area @retval TRUE : success @retval FALSE: failed */ boolean _fta_manage_initialize(const fta_manager_initializer_info *manager_initializer) { fta_manager_store_header *fta_manager; const fta_manager_config_store_item * const *p_config_items; fta_manager_store_item *store_items; uint32 manager_size; fta_common_store_header *store_addr; uint32 var_size; uint32 var_num; uint32 i; uint16 config_cnt; boolean config_err = FALSE; if(manager_initializer == NULL) return FALSE; if(manager_initializer->fta_manager == NULL || manager_initializer->p_config_items == NULL || manager_initializer->lock_keeper == NULL || (manager_initializer->memory_size & 3) != 0) { return FALSE; } fta_manager = manager_initializer->fta_manager; p_config_items = manager_initializer->p_config_items; store_items = (fta_manager_store_item *) FTA_LIB_OFFSET_ADDR(fta_manager, FTA_MANAGER_STORE_HEADER_LEN); manager_size = FTA_CALC_MANAGER_SIZE(manager_initializer->config_count); memset(fta_manager, 0, manager_size); fta_manager->cmn.tag = FTA_TAG_MANAGER; fta_manager->cmn.size = manager_size; fta_manager->cmn.enabled = FTA_STORE_ENABLED_FALSE; FTA_LIB_SETBITVALUE(fta_manager->cmn.statbit, FTA_STORE_STATBIT_ALLCLEAR); fta_manager->cmn.offset = FTA_MANAGER_STORE_HEADER_LEN; fta_manager->id = FTA_MANAGER_ID_DEFAULT; fta_manager->reclen = FTA_MANAGER_STORE_ITEM_LEN; fta_manager->count = 0; fta_manager->parity = fta_lib_check_parity16((uint16 *)fta_manager, fta_manager->cmn.size / 2, fta_manager->parity); manager_initializer->lock_keeper->fta_manager = fta_manager; manager_initializer->lock_keeper->manager_status = FTA_MANAGER_STATUS_UNINIT; /* set the manage info from the config table */ store_addr = (fta_common_store_header *)(manager_initializer->memory_addr); var_size = manager_initializer->memory_size; /* calcurate the variable size */ config_cnt = 0; var_num = 0; /* - - - - - - - - */ for(i = 0; i < manager_initializer->config_count; i++) { if(p_config_items[i] != NULL) { if(p_config_items[i]->tag != FTA_CONFIG_UNDEFINED) { if(config_cnt == 0) { var_num = i; } else { if(var_size < p_config_items[i]->size) config_err = TRUE; if((p_config_items[i]->size & 3) != 0) config_err = TRUE; if(p_config_items[i]->offset > p_config_items[i]->size) config_err = TRUE; var_size -= p_config_items[i]->size; } config_cnt++; } } } if(config_cnt > 0) { if(p_config_items[var_num]->offset > var_size) config_err = TRUE; } /* - - - - - - - - */ config_cnt = 0; /* - - - - - - - - */ for(i = 0; i < manager_initializer->config_count; i++) { if(p_config_items[i] != NULL) { if(p_config_items[i]->tag != FTA_CONFIG_UNDEFINED) { store_items[config_cnt].addr = store_addr; store_items[config_cnt].tag = p_config_items[i]->tag; store_items[config_cnt].size = (i == var_num ? var_size : p_config_items[i]->size); store_items[config_cnt].def = p_config_items[i]; store_items[config_cnt].lock_keeper = manager_initializer->lock_keeper; if(p_config_items[i]->set_to != FTA_CONFIG_UNDEFINED) { *(p_config_items[i]->set_to) = &store_items[config_cnt]; } store_addr = (fta_common_store_header *) FTA_LIB_OFFSET_ADDR(store_addr, store_items[config_cnt].size); config_cnt++; } } } /* - - - - - - - - */ fta_manager->count = config_cnt; fta_manager->parity = fta_lib_check_parity16((uint16 *)fta_manager, fta_manager->cmn.size / 2, fta_manager->parity); /* cannot use FTA when configuration is unrecongnized */ if(config_err) { return FALSE; } return TRUE; }
/*! @brief _fta_var_find sarch for the record @param [in] p_store_item item for manage @param [in] key_info key @param [in] alloc_len size of the record @retval NULL: not found @retval others: pointer of record */ void *_fta_var_find(const fta_manager_store_item * const *p_store_item, const fta_var_record_access_info *access_info, const void *key_info) { fta_var_store_header *var_header; void *var_record = NULL; uint8 *var_dataarea = NULL; uint32 dataarea_size = 0; uint32 record_count = 0; uint32 record_num; uint32 record_pos; uint32 key_size; uint32 datalen_size; uint32 datalen; boolean bad_condition = FALSE; if(p_store_item == NULL || access_info == NULL || key_info == NULL) { FTA_LOG_MESSAGE(FTA_VAR, FTA_LOG_LEVEL_CRITICAL, "*** FTA VAR INTERNAL ERROR", 0, 0, 0); return NULL; } FTA_ENTER_LOCK(); /* - - - - - - - - */ do { if(access_info->lock_access) { if(*p_store_item == NULL) { bad_condition = TRUE; break; } if((*p_store_item)->lock_keeper->manager_status != FTA_MANAGER_STATUS_ENABLED) { bad_condition = TRUE; break; } } var_header = (fta_var_store_header *)((*p_store_item)->addr); if(var_header->cmn.enabled != FTA_STORE_ENABLED_TRUE) { bad_condition = TRUE; break; } var_dataarea = FTA_LIB_OFFSET_ADDR(var_header, var_header->cmn.offset); record_count = var_header->count; dataarea_size = var_header->bottom; } while(FALSE); /* - - - - - - - - */ FTA_LEAVE_LOCK(); if(bad_condition) { return var_record; } key_size = access_info->key_size; datalen_size = access_info->datalen_size; record_pos = 0; /* - - - - - - - - */ for(record_num = 0; record_num < record_count; record_num++) { if(dataarea_size < key_size + datalen_size + record_pos) { var_record = NULL; break; } var_record = (void *)FTA_LIB_OFFSET_ADDR(var_dataarea, record_pos); if(memcmp(var_record, key_info, key_size) == 0) { /* matched */ break; } datalen = 0; if(datalen_size <= sizeof(uint32)) { memcpy(&datalen, FTA_LIB_OFFSET_ADDR(var_record, key_size), datalen_size); } else { memcpy(&datalen, FTA_LIB_OFFSET_ADDR(var_record, key_size), sizeof(uint32)); } var_record = NULL; datalen = FTA_LIB_ALIGN4_32(datalen); record_pos += key_size + datalen_size + datalen; } /* - - - - - - - - */ return var_record; }
fta_reference_pointers fta_reference = {0}; /* reference area */ const fta_reference_pointers fta_reference_null = {0}; DEFINE_SPINLOCK(fta_lock); /* -------------------------------- * initial information area * -------------------------------- */ unsigned long fta_log_area[FTA_CONFIG_STORE_MEMORY_SIZE/4] __attribute__((section(".fta.data"))); // char *fta_log_area; fta_manager_initializer_info fta_manager_initializer = FTA_MANAGER_INITIALIZER_INFO_DEF( (fta_manager_store_header *)fta_log_area, fta_initial_config_stores, FTA_CONFIG_STORE_INITIAL_COUNT, FTA_LIB_OFFSET_ADDR(fta_log_area, FTA_CALC_MANAGER_SIZE(FTA_CONFIG_STORE_INITIAL_COUNT)), FTA_CONFIG_STORE_MEMORY_SIZE - FTA_CALC_MANAGER_SIZE(FTA_CONFIG_STORE_INITIAL_COUNT), &fta_lock_keeper, ); /* ========================================================================== * FUNCTIONS * ========================================================================== */ /*! @brief fta_initialize FTA initialize function @param none