| /***************************************************************************** |
| * Copyright Statement: |
| * -------------------- |
| * This software is protected by Copyright and the information contained |
| * herein is confidential. The software may not be copied and the information |
| * contained herein may not be used or disclosed except with the written |
| * permission of MediaTek Inc. (C) 2006 |
| * |
| * BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES |
| * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") |
| * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON |
| * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. |
| * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE |
| * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR |
| * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH |
| * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO |
| * NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S |
| * SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. |
| * |
| * BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE |
| * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, |
| * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, |
| * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO |
| * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. |
| * |
| * THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE |
| * WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF |
| * LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND |
| * RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER |
| * THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). |
| * |
| *****************************************************************************/ |
| |
| /***************************************************************************** |
| * |
| * Filename: |
| * --------- |
| * fota_partial.c |
| * |
| * Project: |
| * -------- |
| * Maui_Software |
| * |
| * Description: |
| * ------------ |
| * This file implement the function of FOTA firmware update downlaod |
| * |
| * Author: |
| * ------- |
| * ------- |
| * |
| *============================================================================ |
| * HISTORY |
| * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! |
| *------------------------------------------------------------------------------ |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| * removed! |
| * removed! |
| * removed! |
| * |
| *------------------------------------------------------------------------------ |
| * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! |
| *============================================================================ |
| ****************************************************************************/ |
| /******************************************* |
| * Include File |
| ********************************************/ |
| #if defined(__FOTA_DM__) |
| |
| #include "kal_general_types.h" |
| #include "kal_debug.h" |
| #include <stdio.h> |
| #include <stdarg.h> |
| #include "fue_err.h" |
| #include "fota.h" |
| #include "flash_opt.h" |
| #include "fat_fs.h" |
| #include "custom_fota.h" |
| #include "custom_img_config.h" |
| #include "fue.h" |
| #include "ssf_fue_support.h" |
| #include "fue_update_support.h" |
| #if defined(__MAUI_BASIC__) |
| #include "uart_sw.h" |
| #endif /* __MAUI_BASIC__ */ |
| #if defined(__HP_FOTA__) |
| #include "Bitfone_update.h" |
| #endif |
| |
| #include "dcl.h" |
| |
| #ifdef __EMMC_BOOTING__ |
| #include "fue_emmc_adapt.h" |
| #endif |
| |
| #define _FUE_PKG_DEBUG_ |
| |
| /******************************************************************************* |
| * Global Function and Structure Definition |
| *******************************************************************************/ |
| |
| FOTA_DATA FOTAData={STATUS_FOTA_NOT_INITIAL}; |
| |
| FOTA_NFB_Update_Control FOTA_Update_Ctrl; |
| FOTA_Package_Control_st FOTA_Package_Ctrl; |
| |
| #pragma arm section zidata = "NONCACHEDZI" |
| |
| kal_uint32 fota_temp_page_buffer[FOTA_FLASH_MAX_PAGE_SIZE]; |
| kal_uint32 fota_replace_page_buffer[FOTA_FLASH_MAX_PAGE_SIZE]; |
| |
| #pragma arm section zidata |
| |
| /******************************************************************************* |
| * Static Function and Structure Definition |
| *******************************************************************************/ |
| static kal_int32 FOTA_MTD_Read_Buffer(void *Buffer, kal_uint32 read_len); |
| |
| /* start address of update package reserved area */ |
| extern const kal_uint32 FOTA_PACKAGE_BASE_ADDRESS; |
| |
| /* Following functions and data varoables are located in FOTA library */ |
| extern FUE_ERROR_CODE FUE_InitializeUpdateRecord(kal_uint32 base_blk, kal_uint32 end_blk, \ |
| Flash_GAL_st *fgal, dbg_trace_func dbg_trace); |
| extern FUE_ERROR_CODE FUE_NFB_Flush_Update_Record(FOTA_Custom_Update_Info* info_buffer, \ |
| dbg_trace_func dbg_trace); |
| extern FUE_ERROR_CODE FUE_NFB_Get_Update_Record(FOTA_Custom_Update_Info* info_buffer,\ |
| dbg_trace_func dbg_trace); |
| |
| extern FUE_ERROR_CODE FUE_NFB_Allocate_Block(kal_uint32 begin_block, kal_uint32 end_block, \ |
| kal_uint32 curr_block, kal_uint32 *alloc_block, \ |
| Flash_GAL_st *fgal, IsBlockAvailable_func check_available, \ |
| dbg_trace_func dbg_trace); |
| |
| extern FUE_ERROR_CODE FUE_BlkInfo_Resume_Package_Blocks(FOTA_Package_Control_st *pkg_ctrl, \ |
| kal_uint32 *found_blocks, \ |
| /*FOTA_Package_Location_st *found_list, \*/ |
| FOTA_Package_List_st *found_list,\ |
| kal_uint32 *buff_ptr, \ |
| kal_uint32 *buff_len, \ |
| /*alloc_pkg_blk alloc_blk, \*/ |
| dbg_trace_func dbg_trace); |
| |
| extern kal_bool FUE_NFB_Is_Available_Block(kal_uint32 block_idx, kal_uint32* buff_ptr, Flash_GAL_st *fgal, \ |
| dbg_trace_func dbg_trace); |
| |
| extern FUE_ERROR_CODE FUE_NFB_Replace_Current_Package_Block(FOTA_Package_Control_st *pkg_ctrl,\ |
| kal_uint32 *buff_ptr, \ |
| dbg_trace_func dbg_trace); |
| |
| extern FUE_ERROR_CODE FUE_NFB_Mark_Package_Block_Complete(FOTA_Package_Control_st *pkg_ctrl, \ |
| FOTA_Package_Info_st *pkg_info, dbg_trace_func dbg_trace); |
| |
| extern FUE_ERROR_CODE FUE_NFB_Allocate_PackageBlock(FOTA_Package_Control_st *pkg_ctrl, kal_uint32 start_block, \ |
| kal_uint32 *alloc_block, dbg_trace_func dbg_trace); |
| |
| extern FUE_ERROR_CODE FUE_NFB_Create_Package_Block(FOTA_Package_Control_st *pkg_ctrl, kal_uint32 block_index,\ |
| kal_uint32 last_block, kal_uint32 replace_block, \ |
| kal_bool add_session, dbg_trace_func dbg_trace); |
| |
| extern FUE_ERROR_CODE FUE_CreateInitialUpdateRecord(FOTA_NFB_Update_Control *update_ctrl, kal_uint32 start_block, \ |
| Flash_GAL_st *fgal, dbg_trace_func dbg_trace); |
| |
| extern FUE_ERROR_CODE FUE_BlkInfo_Is_Package_Block(FOTA_Package_Control_st *pkg_ctrl, kal_uint32 blk_num, dbg_trace_func dbg_trace); |
| |
| extern FUE_ERROR_CODE FUE_BlkInfo_Is_Update_Block(FOTA_NFB_Update_Control *update_ctrl, kal_uint32 blk_num, dbg_trace_func dbg_trace); |
| |
| extern kal_uint32 SSF_GetMAUIImageNumber(void); |
| |
| extern void FUE_Start_Download_State(void); |
| |
| extern void FUE_Start_Package_Verification_State(void); |
| |
| extern FOTA_Area_Info_Wrapper_st FOTA_NFB_Area_Info; |
| |
| /* For update package block management */ |
| extern FOTA_Package_List_st g_fota_package_blocks[FOTA_PACKAGE_BLOCK_NUMBER]; |
| extern kal_uint32 FOTA_PKG_BLOCKS; |
| |
| /* Following functions are located in init.c */ |
| extern kal_uint32 INT_GetCurrentTime(void); |
| |
| |
| /* the NFI access synchronization is implemented in NAND flash MTD layer */ |
| #define FOTA_LOCK() |
| #define FOTA_UNLOCK() |
| |
| /* Forward declaration */ |
| Flash_GAL_st *FOTA_Setup_FGAL(void); |
| static kal_int32 FOTA_MTD_Program_Buffer(void *Buffer, kal_uint32 write_len); |
| |
| kal_int32 FOTA_InitializeUpdateRecord(void); |
| |
| kal_int32 FOTA_InitializePackageReservoir(void); |
| kal_int32 FOTA_FinishPackageBlock(void); |
| kal_int32 FOTA_CheckAvailablePackageBlocks(kal_uint32 *available_num); |
| kal_int32 FOTA_ClearPackageReservoir(void); |
| kal_int32 FOTA_Get_TotalPackageBlock(kal_uint32 *pkg_blks, kal_uint32* pkg_pages); |
| kal_int32 FOTA_Get_CurrentPackagePosition(kal_uint32 *curr_blks, kal_uint32* curr_pages); |
| kal_int32 FOTA_ProgramPackagePage(void* buff, kal_uint32 *page_size); |
| |
| kal_int32 FOTA_GetPackageFlashInfo(kal_uint32 *blk_size, kal_uint32 *page_size); |
| |
| #if defined(__MAUI_BASIC__) |
| |
| |
| #endif /* __MAUI_BASIC__ */ |
| /***************************************************************** |
| Description : dump trace via kal_print function. |
| Input : |
| Output : None |
| ******************************************************************/ |
| kal_char g_char_buff[512]; |
| void fue_dbg_print(kal_char* fmt, ...) |
| { |
| va_list trace_p; |
| va_start(trace_p, fmt); |
| vsprintf(g_char_buff, fmt, trace_p); |
| va_end(trace_p); |
| kal_print(g_char_buff); |
| #if defined(__MAUI_BASIC__) |
| if(KAL_FALSE == kal_query_systemInit()) |
| { |
| while(!UART_CheckTxBufferEmpty(uart_port1)); /* wait for UART dump complete */ |
| } |
| #endif |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Package_Blk_Address |
| DESCRIPTION |
| convert to block aligned address |
| PARAMETER |
| NULL |
| RETURN |
| INVALOD_DWORD : out of range |
| --------------------------------------------------------------------------------- */ |
| kal_uint32 FOTA_Package_Blk_Address(FOTA_Package_Control_st *pkg_ctrl, kal_uint32 dst_addr) |
| { |
| Logical_Flash_info_st info; |
| kal_uint32 blk_idx = 0; |
| kal_uint32 blk_addr = 0; |
| kal_uint32 phy_blk = 0; |
| kal_uint32 curr_blk_num = pkg_ctrl->m_fota_pkg_blocks; |
| Flash_GAL_st *fgal = pkg_ctrl->m_pkg_fgal; |
| |
| ASSERT(fgal); |
| |
| fgal->query_info(&info); |
| for(blk_idx = 0 ; blk_idx < curr_blk_num ; blk_idx++) |
| { |
| phy_blk = pkg_ctrl->m_fota_pkg_list[blk_idx].m_pkg_block_position; |
| blk_addr += (fgal->block_size(phy_blk)- 2*info.Flash_page_size); |
| if(blk_addr >= dst_addr) |
| break; |
| } |
| if( blk_idx == curr_blk_num ) |
| { |
| fue_dbg_print("FOTA_Package_Blk_Idx: address:0x%x is beyond available %dblks!\n\r", |
| dst_addr, curr_blk_num); |
| ASSERT(0); |
| return INVALID_DWORD; |
| } |
| else |
| { |
| if(blk_addr == dst_addr) |
| fue_dbg_print("FOTA_Package_Blk_Idx: address:0x%x is on the bounadry of blk:%d(%d)!\n\r", |
| dst_addr, blk_idx, phy_blk); |
| |
| return blk_addr; |
| } |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Initialize |
| DESCRIPTION |
| FOTA Initialization API |
| 1. Initialize data structure and progress initial step |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_Initialize(void) |
| { |
| kal_int32 Ret; |
| |
| if( STATUS_FOTA_INITIALIZED == FOTAData.Status ) |
| { |
| return ERROR_FOTA_SUCCESS; |
| } |
| |
| Ret = FOTA_InitializeUpdateRecord(); |
| if( (ERROR_FOTA_NO_AVAILABLE_BLOCK == Ret) || (ERROR_FUE_OPERATION_STOP == Ret) || |
| (ERROR_FUE_OVER_DESIGN == Ret) ) |
| return Ret; |
| |
| Ret = FOTA_InitializePackageReservoir(); |
| |
| if(ERROR_FOTA_INVALID_PARAMETER == Ret) |
| { |
| return Ret; |
| } |
| fue_dbg_print("FOTA_Initialize: %d updatable images!\n\r", SSF_GetMAUIImageNumber()); |
| |
| FOTAData.SpareCurrWriteAddr = 0; |
| FOTAData.SpareNextWriteBlockAddr = 0; |
| FOTAData.SpareCurrReadAddr = 0; |
| FOTAData.SpareNextReadBlockAddr = 0; |
| FOTAData.BufferIndex = 0; |
| |
| if((Ret = FOTA_CustomInitialize()) < 0) |
| return Ret; |
| else |
| FOTAData.Status = STATUS_FOTA_INITIALIZED; |
| return ERROR_FOTA_SUCCESS; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_WriteData |
| DESCRIPTION |
| FOTA write data API |
| 1. This function is used to write data to spare image pool |
| 2. This API only allow sequentially writing mechanism |
| 3. Authentication mechanism is executed during writing |
| PARAMETER |
| Length: the length of writing (Unit: Bytes) |
| Buffer: the start address of buffer |
| RETURN |
| 0: means pass write success (ERROR_FOTA_SUCCESS) |
| < 0: writing action is fail |
| ERROR_FOTA_AUTH_ROMINFO: authentication fail, can't find rom info |
| ERROR_FOTA_AUTH_FATBEGIN: authentication fail, fat begin address is different |
| ERROR_FOTA_AUTH_FATLEN: authentication fail, fat length is different |
| ERROR_FOTA_AUTH_HCHECKSUM: authentication fail, header checksum fail |
| ERROR_FOTA_AUTH_ID: authentication fail, platform id is different |
| ERROR_FOTA_AUTH_VERSION: authentication fail, downgrade is not allowed |
| ERROR_FOTA_AUTH_IMAGELEN: authentication fail, image length too large |
| ERROR_FOTA_AUTH_FAIL: authentication fail before |
| ERROR_FOTA_OVERRANGE: write over the spare image pool range |
| ERROR_FOTA_NOT_INITIALIZED: not call FOTA_Initialize before |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_WriteData(kal_uint32 Length, void* Buffer) |
| { |
| kal_int32 result; |
| kal_uint32 buff_addr = (kal_uint32)Buffer; |
| kal_uint8 *byte_ptr = NULL; |
| |
| if (FOTAData.Status == STATUS_FOTA_NOT_INITIAL) |
| return ERROR_FOTA_NOT_INITIALIZED; |
| |
| while(Length > 0) |
| { |
| if ((FOTAData.BufferIndex+Length)>=FOTA_BUFFER_SIZE) |
| { |
| /* no data in write buffer and user buffer is 4-byte aligned */ |
| if( (FOTAData.BufferIndex == 0) && (0 == (buff_addr & 0x03)) ) |
| { |
| result = FOTA_MTD_Program_Buffer((void*)buff_addr, FOTA_BUFFER_SIZE); |
| if (result < 0) |
| return result; |
| buff_addr += FOTA_BUFFER_SIZE; |
| Length -= FOTA_BUFFER_SIZE; |
| } |
| else |
| { |
| if(FOTAData.BufferIndex != FOTA_BUFFER_SIZE) |
| { |
| byte_ptr = (kal_uint8 *)(((kal_uint32)FOTAData.FOTAWriteBuffer) + FOTAData.BufferIndex); |
| //kal_mem_cpy((void*)&FOTAData.FOTABuffer[FOTAData.BufferIndex>>2], Buffer, FOTA_BUFFER_SIZE - FOTAData.BufferIndex); |
| kal_mem_cpy(byte_ptr, (void *)buff_addr, FOTA_BUFFER_SIZE - FOTAData.BufferIndex); |
| buff_addr += (FOTA_BUFFER_SIZE - FOTAData.BufferIndex); |
| Length -= (FOTA_BUFFER_SIZE - FOTAData.BufferIndex); |
| FOTAData.BufferIndex = FOTA_BUFFER_SIZE; |
| } |
| result = FOTA_MTD_Program_Buffer((void*)FOTAData.FOTAWriteBuffer, FOTA_BUFFER_SIZE); |
| if (result < 0) |
| return result; |
| FOTAData.BufferIndex = 0; |
| } |
| } |
| else |
| { |
| byte_ptr = (kal_uint8 *)(((kal_uint32)FOTAData.FOTAWriteBuffer) + FOTAData.BufferIndex); |
| //kal_mem_cpy((void*)&FOTAData.FOTABuffer[FOTAData.BufferIndex/4], Buffer, Length); |
| kal_mem_cpy(byte_ptr, (void *)buff_addr, Length); |
| FOTAData.BufferIndex += Length; |
| buff_addr += Length; |
| Length = 0; |
| } |
| } |
| return ERROR_FOTA_SUCCESS; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_ReadData |
| DESCRIPTION |
| FOTA read data API |
| 1. This function is used to read data from spare image pool |
| 2. This API only support sequentially read operation, i.e. from low address to high address |
| PARAMETER |
| Length: the length of reading (Unit: Bytes) |
| Buffer: the start address of buffer |
| RETURN |
| 0: means pass write success (ERROR_FOTA_SUCCESS) |
| < 0: writing action is fail |
| ERROR_FOTA_AUTH_ROMINFO: authentication fail, can't find rom info |
| ERROR_FOTA_AUTH_FATBEGIN: authentication fail, fat begin address is different |
| ERROR_FOTA_AUTH_FATLEN: authentication fail, fat length is different |
| ERROR_FOTA_AUTH_HCHECKSUM: authentication fail, header checksum fail |
| ERROR_FOTA_AUTH_ID: authentication fail, platform id is different |
| ERROR_FOTA_AUTH_VERSION: authentication fail, downgrade is not allowed |
| ERROR_FOTA_AUTH_IMAGELEN: authentication fail, image length too large |
| ERROR_FOTA_AUTH_FAIL: authentication fail before |
| ERROR_FOTA_OVERRANGE: write over the spare image pool range |
| ERROR_FOTA_NOT_INITIALIZED: not call FOTA_Initialize before |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_ReadData(kal_uint32 Length, void* Buffer) |
| { |
| kal_int32 result = ERROR_FOTA_SUCCESS; |
| kal_uint32 buffer_addr = (kal_uint32)Buffer; |
| kal_uint32 read_len = 0; |
| kal_uint32 copy_size = 0; |
| |
| if (FOTAData.Status == STATUS_FOTA_NOT_INITIAL) |
| return ERROR_FOTA_NOT_INITIALIZED; |
| |
| while(Length > read_len) |
| { |
| if( ( (Length-read_len) >= FOTA_BUFFER_SIZE) && (0 == ((buffer_addr)&0x03)) ) |
| { |
| /* directly read into user's buffer */ |
| result = FOTA_MTD_Read_Buffer((void*)buffer_addr, FOTA_BUFFER_SIZE); |
| if(result < 0) |
| break; |
| buffer_addr += FOTA_BUFFER_SIZE; |
| read_len += FOTA_BUFFER_SIZE; |
| } |
| else |
| { |
| if( (Length-read_len) >= FOTA_BUFFER_SIZE) |
| copy_size = FOTA_BUFFER_SIZE; |
| else |
| copy_size = (Length-read_len); |
| |
| /* read into temporary buffer */ |
| result = FOTA_MTD_Read_Buffer(FOTAData.FOTAReadBuffer, copy_size); |
| if (result < 0) |
| break; |
| |
| kal_mem_cpy((void *)buffer_addr, FOTAData.FOTAReadBuffer, copy_size); |
| buffer_addr += copy_size; |
| read_len += copy_size; |
| } |
| } |
| |
| return result; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Finalize |
| DESCRIPTION |
| FOTA finalization API |
| 1. compare calculated checksum with image checksum in the header after |
| whole image is written |
| 2. mark the status to UPDATE_NEEDED |
| PARAMETER |
| void |
| RETURN |
| 0: means pass error check step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_AUTH_FAIL: authentication fail, final step is not allowed |
| ERROR_FOTA_IMAGE_CHECKSUM: image checksum error |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_Finalize(void) |
| { |
| kal_int32 result = 0; |
| |
| if (FOTAData.Status == STATUS_FOTA_NOT_INITIAL) |
| return ERROR_FOTA_NOT_INITIALIZED; |
| |
| if(FOTAData.BufferIndex != 0) |
| { |
| result = FOTA_MTD_Program_Buffer((void*)FOTAData.FOTAWriteBuffer, FOTAData.BufferIndex); |
| FOTA_FinishPackageBlock(); |
| if (result < 0) |
| return result; |
| FOTAData.BufferIndex = 0; |
| } |
| |
| FOTAData.Status = STATUS_FOTA_FINAL; |
| |
| return ERROR_FOTA_SUCCESS; |
| } |
| |
| /* --------------------------------------------------------------------------------- * |
| * Flash device wrapper functions |
| * --------------------------------------------------------------------------------- */ |
| |
| /************************************************************************************ |
| * NAND flash part |
| *************************************************************************************/ |
| static kal_int32 FOTA_MTD_Program_Buffer(void *Buffer, kal_uint32 write_len) |
| { |
| kal_uint32 buff_offset = 0; |
| kal_int32 left_length = write_len; |
| kal_uint32 page_size = 0; |
| kal_int32 ret_code = ERROR_FOTA_SUCCESS; |
| |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ASSERT(0); |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| |
| while(left_length > 0) |
| { |
| ret_code = FOTA_ProgramPackagePage((void*)(((kal_uint32)Buffer)+buff_offset), &page_size); |
| if(ERROR_FOTA_SUCCESS == ret_code) |
| { |
| buff_offset += page_size; |
| left_length -= page_size; |
| FOTAData.SpareCurrWriteAddr += page_size; |
| } |
| else if( (ERROR_FOTA_NO_AVAILABLE_BLOCK == ret_code) || (ERROR_FOTA_FLASH_DEVICE==ret_code) || |
| (ERROR_FOTA_UNSUPPORTED_CASES == ret_code) ) |
| { |
| break; |
| } |
| } |
| return ret_code; |
| |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_FinishePackageBlock |
| DESCRIPTION |
| download is finished, complete current package block |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_FinishPackageBlock(void) |
| { |
| kal_uint32 page_per_blk = 0; |
| FOTA_Package_Info_st *pkg_info = NULL; |
| kal_int32 ret_code = ERROR_FOTA_SUCCESS; |
| FUE_ERROR_CODE result = ERROR_FUE_NONE; |
| Logical_Flash_info_st info; |
| Flash_GAL_st *fgal = FOTA_Package_Ctrl.m_pkg_fgal; |
| |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ASSERT(0); |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| ASSERT(fgal); |
| pkg_info = &FOTA_Package_Ctrl.m_fota_pkg_info;; |
| //page_per_blk = 1 << FOTA_Package_Ctrl.m_fota_flash_info.Flash_offset_shift; |
| fgal->query_info(&info); |
| page_per_blk = fgal->block_size(pkg_info->m_pkg_current_block)/info.Flash_page_size; |
| |
| if(pkg_info->m_pkg_current_page == page_per_blk) |
| { |
| /* current package has been marked as complete in last package program operation */ |
| if( pkg_info->m_pkg_valid_pages == (page_per_blk-3)) |
| { |
| fue_dbg_print("FOTA_FinishPackageBlock: mark blk:%d as complete is already done!\n\r",\ |
| pkg_info->m_pkg_current_block); |
| } |
| #ifdef _FUE_PKG_DEBUG_ |
| else |
| { |
| fue_dbg_print("FOTA_FinishPackageBlock: incomplete blk:%d has been marked complete already!\n\r",\ |
| pkg_info->m_pkg_current_block); |
| #if defined(__FOTA_DEBUG_ASSERT__) |
| ASSERT(0); |
| #endif /* __FOTA_DEBUG_ASSERT__ */ |
| } |
| #endif /* _FUE_PKG_DEBUG_ */ |
| |
| /* indicate current package download is done */ |
| FOTA_Package_Ctrl.m_fota_pkg_index = INVALID_DWORD; |
| } |
| else |
| { |
| while(1) |
| { |
| /* mark this package block as complete */ |
| result = FUE_NFB_Mark_Package_Block_Complete(&FOTA_Package_Ctrl, pkg_info, fue_dbg_print); |
| if(ERROR_FUE_NONE == result) |
| { |
| fue_dbg_print("FOTA_FinishPackageBlock: mark blk:%d as complete done!\n\r",\ |
| pkg_info->m_pkg_current_block); |
| /* indicate current package download is done */ |
| FOTA_Package_Ctrl.m_fota_pkg_index = INVALID_DWORD; |
| break; |
| } |
| else if(ERROR_FUE_PROGRAM_FAILED == result) |
| { |
| /* block replacement procedure - caused by marking complete function */ |
| result = FUE_NFB_Replace_Current_Package_Block(&FOTA_Package_Ctrl, fota_replace_page_buffer, \ |
| fue_dbg_print); |
| if( ERROR_FUE_OVER_DESIGN == result ) |
| { |
| ret_code = ERROR_FOTA_UNSUPPORTED_CASES; |
| break; |
| } |
| else if( ERROR_FUE_NO_AVAILABLE_BLOCK == result ) |
| { |
| ret_code = ERROR_FOTA_NO_AVAILABLE_BLOCK; |
| break; |
| } |
| else if(ERROR_FUE_NOT_INITIALIZED == result) |
| { |
| ret_code = ERROR_FOTA_NOT_INITIALIZED; |
| break; |
| } |
| } |
| else |
| { |
| /* unexpected status, abort current update package */ |
| fue_dbg_print("FOTA_FinishPackageBlock: unexpected error on blk:%d, Abort!!\n\r",\ |
| pkg_info->m_pkg_current_block); |
| break; |
| } |
| } |
| } |
| return ret_code; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_ProgramPackagePage |
| DESCRIPTION |
| clear downloaded update package |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_ProgramPackagePage(void* buff, kal_uint32 *page_size) |
| { |
| kal_int32 ret_code = ERROR_FOTA_SUCCESS; |
| kal_uint32 page_per_blk = 0; |
| kal_uint32 curr_blk = INVALID_DWORD; |
| kal_uint32 curr_order = INVALID_DWORD; |
| kal_uint32 alloc_block = INVALID_DWORD; |
| FOTA_Package_Info_st *pkg_info = NULL; |
| Logical_Flash_info_st info; |
| Flash_GAL_st *fgal = FOTA_Package_Ctrl.m_pkg_fgal; |
| _FGAL_ERROR_CODE status = ERROR_FGAL_NONE; |
| FUE_ERROR_CODE result = ERROR_FUE_NONE; |
| kal_bool op_done = KAL_FALSE; |
| |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ASSERT(0); |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| ASSERT(fgal); |
| |
| pkg_info = &FOTA_Package_Ctrl.m_fota_pkg_info; |
| fgal = FOTA_Package_Ctrl.m_pkg_fgal; |
| //page_per_blk = 1 << FOTA_Package_Ctrl.m_fota_flash_info.Flash_offset_shift; |
| fgal->query_info(&info); |
| *page_size = 0; |
| |
| if( INVALID_DWORD != pkg_info->m_pkg_current_block ) |
| { |
| page_per_blk = fgal->block_size(pkg_info->m_pkg_current_block)/info.Flash_page_size; |
| if( pkg_info->m_pkg_current_page < (page_per_blk-1) ) |
| { |
| do |
| { |
| if(pkg_info->m_pkg_current_page == (page_per_blk-2)) |
| { |
| /* mark current package block as complete */ |
| result = FUE_NFB_Mark_Package_Block_Complete(&FOTA_Package_Ctrl, pkg_info, fue_dbg_print); |
| if(ERROR_FUE_NONE == result) |
| { |
| break; |
| } |
| } |
| else if(0 == *page_size) |
| { |
| status = fgal->write_page(buff, pkg_info->m_pkg_current_block, pkg_info->m_pkg_current_page); |
| if(ERROR_FGAL_NONE == status) |
| { |
| pkg_info->m_pkg_current_page++; |
| pkg_info->m_pkg_valid_pages++; |
| FOTA_Package_Ctrl.m_fota_pkg_pages++; |
| *page_size = info.Flash_page_size; |
| op_done = KAL_TRUE; |
| } |
| else if(ERROR_FGAL_OPERATION_RETRY == status) |
| { |
| ret_code = ERROR_FOTA_FLASH_DEVICE; |
| break; |
| } |
| } |
| else |
| { |
| /* package page program done */ |
| break; |
| } |
| |
| if( (ERROR_FGAL_WRITE_FAILURE == status) || (ERROR_FUE_PROGRAM_FAILED == result) ) |
| { |
| /* copy valid pages in bad block to new package block */ |
| result = FUE_NFB_Replace_Current_Package_Block(&FOTA_Package_Ctrl, fota_replace_page_buffer, \ |
| fue_dbg_print); |
| if( ERROR_FUE_OVER_DESIGN == result ) |
| { |
| ret_code = ERROR_FOTA_UNSUPPORTED_CASES; |
| break; |
| } |
| else if( ERROR_FUE_NO_AVAILABLE_BLOCK == result ) |
| { |
| ret_code = ERROR_FOTA_NO_AVAILABLE_BLOCK; |
| break; |
| } |
| else if( ERROR_FUE_NOT_INITIALIZED == result ) |
| { |
| ret_code = ERROR_FOTA_NOT_INITIALIZED; |
| break; |
| } |
| } |
| }while(1); |
| } |
| } |
| /* |
| * else start to allocate new package block |
| */ |
| |
| if(!op_done) |
| { |
| if(INVALID_DWORD == pkg_info->m_pkg_current_block) |
| { |
| ASSERT(INVALID_DWORD == FOTA_Package_Ctrl.m_fota_pkg_index); |
| ASSERT(INVALID_DWORD == pkg_info->m_pkg_block_session); |
| curr_blk = FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_base; |
| curr_order = INVALID_DWORD; |
| } |
| else |
| { |
| ASSERT(INVALID_DWORD != FOTA_Package_Ctrl.m_fota_pkg_index); |
| curr_blk = pkg_info->m_pkg_current_block; |
| curr_order = FOTA_Package_Ctrl.m_fota_pkg_list[FOTA_Package_Ctrl.m_fota_pkg_index].m_pkg_block_order; |
| FOTA_Package_Ctrl.m_fota_pkg_list[FOTA_Package_Ctrl.m_fota_pkg_index].m_pkg_valid_pages = |
| pkg_info->m_pkg_valid_pages; |
| FOTA_Package_Ctrl.m_fota_pkg_list[FOTA_Package_Ctrl.m_fota_pkg_index].m_pkg_block_complete = |
| KAL_TRUE; |
| } |
| while(1) |
| { |
| /* allocate new package block */ |
| result = FUE_NFB_Allocate_PackageBlock(&FOTA_Package_Ctrl, curr_blk, &alloc_block, fue_dbg_print); |
| if(ERROR_FUE_NONE == result) |
| { |
| status = fgal->erase_block(alloc_block); |
| if(ERROR_FGAL_ERASE_FAILURE == status) |
| { |
| fgal->mark_bad(alloc_block); |
| curr_blk = alloc_block; |
| continue; |
| } |
| else if(ERROR_FGAL_NONE != status) |
| { |
| fue_dbg_print("FOTA_ProgramPackagePage: erase operation on block:%d error!\n\r", \ |
| alloc_block); |
| ret_code = ERROR_FOTA_FLASH_DEVICE; |
| break; |
| } |
| /* create package block */ |
| result = FUE_NFB_Create_Package_Block(&FOTA_Package_Ctrl, alloc_block, \ |
| pkg_info->m_pkg_current_block,\ |
| INVALID_DWORD, KAL_TRUE, fue_dbg_print); |
| if( (ERROR_FUE_INSUFFICIENT_BUFFER == result) || (ERROR_FUE_INVALID_PARAMETER == result) ) |
| { |
| ret_code = ERROR_FOTA_INVALID_PARAMETER; |
| break; |
| } |
| else if(ERROR_FUE_NONE == result) |
| { |
| status = fgal->write_page(buff, alloc_block, 1); |
| if(ERROR_FGAL_NONE == status) |
| { |
| /* program done, update RAM copy information */ |
| FOTA_Package_Ctrl.m_fota_pkg_index++; |
| FOTA_Package_Ctrl.m_fota_pkg_pages++; |
| FOTA_Package_Ctrl.m_fota_pkg_list[FOTA_Package_Ctrl.m_fota_pkg_index].m_pkg_block_position = |
| alloc_block; |
| FOTA_Package_Ctrl.m_fota_pkg_list[FOTA_Package_Ctrl.m_fota_pkg_index].m_pkg_block_order = |
| curr_order+1; |
| |
| pkg_info->m_pkg_previous_block = pkg_info->m_pkg_current_block; |
| pkg_info->m_pkg_current_block = alloc_block; |
| pkg_info->m_pkg_current_page = 2; |
| pkg_info->m_pkg_valid_pages = 1; |
| pkg_info->m_pkg_block_session++; |
| *page_size = info.Flash_page_size; |
| |
| fue_dbg_print("FOTA_ProgramPackagePage: program on new package block:%d done!\n\r", \ |
| pkg_info->m_pkg_current_block); |
| break; |
| } |
| } |
| //else if(ERROR_FUE_PROGRAM_FAILED == result) |
| if( (ERROR_FUE_PROGRAM_FAILED == result) || (ERROR_FGAL_WRITE_FAILURE == status) ) |
| { |
| /* create package block or program new page failed - try again */ |
| fgal->erase_block(alloc_block); |
| fgal->mark_bad(alloc_block); |
| curr_blk = alloc_block; |
| continue; |
| } |
| else if(ERROR_FUE_OPERATION_STOP == result) |
| { |
| ret_code = ERROR_FOTA_FLASH_DEVICE; |
| break; |
| } |
| else if(ERROR_FUE_OVER_DESIGN == result) |
| { |
| ret_code = ERROR_FOTA_UNSUPPORTED_CASES; |
| break; |
| } |
| } |
| else if(ERROR_FUE_NO_AVAILABLE_BLOCK == result) |
| { |
| ret_code = ERROR_FOTA_NO_AVAILABLE_BLOCK; |
| break; |
| } |
| } |
| } |
| return ret_code; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_ReadPackagePage |
| DESCRIPTION |
| clear downloaded update package |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_ReadPackagePage(void* buff, kal_uint32 page_addr, kal_uint32 *page_size) |
| { |
| kal_int32 ret_code = ERROR_FOTA_SUCCESS; |
| kal_uint32 page_count = 0; |
| kal_int32 left_pages = 0; |
| kal_uint32 blk_idx = 0; |
| kal_uint32 page_idx = 0; |
| kal_uint32 phy_blk = 0; |
| FOTA_Package_Info_st *pkg_info = NULL; |
| Logical_Flash_info_st info; |
| FOTA_Package_Access_st *pkg_read = &FOTA_Package_Ctrl.m_fota_curr_read; |
| Flash_GAL_st *fgal = FOTA_Package_Ctrl.m_pkg_fgal; |
| _FGAL_ERROR_CODE status = ERROR_FGAL_NONE; |
| |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ASSERT(0); |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| ASSERT(fgal); |
| *page_size = 0; |
| |
| fgal = FOTA_Package_Ctrl.m_pkg_fgal; |
| pkg_info = &FOTA_Package_Ctrl.m_fota_pkg_info; |
| fgal->query_info(&info); |
| if( ((pkg_read->m_pkg_curr_addr+info.Flash_page_size) != page_addr) || (INVALID_DWORD == pkg_read->m_pkg_curr_addr)) |
| { |
| page_idx = page_addr/info.Flash_page_size; |
| for(blk_idx = 0 ; blk_idx <= FOTA_Package_Ctrl.m_fota_pkg_index ; blk_idx++) |
| { |
| phy_blk = FOTA_Package_Ctrl.m_fota_pkg_list[blk_idx].m_pkg_block_position; |
| page_count = (fgal->block_size(phy_blk)/info.Flash_page_size) - 3; |
| if(page_idx < page_count) |
| break; |
| else |
| page_idx -= page_count; |
| } |
| } |
| else |
| { |
| blk_idx = pkg_read->m_pkg_curr_blk; |
| phy_blk = FOTA_Package_Ctrl.m_fota_pkg_list[blk_idx].m_pkg_block_position; |
| page_count = (fgal->block_size(phy_blk)/info.Flash_page_size) - 3; |
| if( (pkg_read->m_pkg_curr_page+1) == page_count) |
| { |
| /* advance to next block */ |
| blk_idx = pkg_read->m_pkg_curr_blk+1; |
| page_idx = 0; |
| } |
| else |
| { |
| blk_idx = pkg_read->m_pkg_curr_blk; |
| page_idx = pkg_read->m_pkg_curr_page+1; |
| } |
| } |
| |
| /* sanity check |
| * !CAUTION! all package blocks are assumed to have same size. |
| */ |
| left_pages = FOTA_Package_Ctrl.m_fota_pkg_pages - blk_idx*page_count; |
| if( (blk_idx > FOTA_Package_Ctrl.m_fota_pkg_index) || |
| ((blk_idx == FOTA_Package_Ctrl.m_fota_pkg_index) && ((page_idx+1) > left_pages)) ) |
| { |
| fue_dbg_print("FOTA_ReadPackagePage: read over range:(%d,%d) > (%d,%d)!\n\r", \ |
| blk_idx, page_idx, FOTA_Package_Ctrl.m_fota_pkg_index, pkg_info->m_pkg_valid_pages); |
| ret_code = ERROR_FOTA_OVERRANGE; |
| return ret_code; |
| } |
| else |
| { |
| pkg_read->m_pkg_curr_addr = page_addr; |
| pkg_read->m_pkg_curr_blk = blk_idx; |
| pkg_read->m_pkg_curr_page = page_idx; |
| phy_blk = FOTA_Package_Ctrl.m_fota_pkg_list[blk_idx].m_pkg_block_position; |
| status = fgal->read_page((kal_uint32 *)buff, phy_blk, page_idx+1);/* plus one to bypass header page */ |
| if(ERROR_FGAL_NONE == status) |
| { |
| //*page_size = FOTA_Package_Ctrl.m_fota_flash_info.Flash_page_size; |
| *page_size = info.Flash_page_size; |
| } |
| else if(ERROR_FGAL_READ_FAILURE == status) |
| { |
| ret_code = ERROR_FOTA_READ; |
| } |
| else if(ERROR_FGAL_OPERATION_RETRY == status) |
| { |
| ret_code = ERROR_FOTA_UNSUPPORTED_CASES; |
| } |
| else if(ERROR_FGAL_INVALID_PARAMETER == status) |
| { |
| ret_code = ERROR_FOTA_INVALID_PARAMETER; |
| } |
| } |
| |
| return ret_code; |
| } |
| |
| /* --------------------------------------------------------------------------------- */ |
| static kal_int32 FOTA_MTD_Read_Buffer(void *Buffer, kal_uint32 read_len) |
| { |
| kal_uint32 buff_offset = 0; |
| kal_int32 left_length = read_len; |
| kal_int32 result = 0; |
| kal_uint32 page_size = 0; |
| kal_uint32 buff_addr = (kal_uint32)Buffer; |
| |
| while(left_length > 0) |
| { |
| result = FOTA_ReadPackagePage((void*)(buff_addr+buff_offset), FOTAData.SpareCurrReadAddr, \ |
| &page_size); |
| |
| if(ERROR_FOTA_SUCCESS == result) |
| { |
| buff_offset += page_size; |
| left_length -= page_size; |
| FOTAData.SpareCurrReadAddr += page_size; |
| } |
| else |
| break; |
| } |
| return result; |
| } |
| |
| /* --------------------------------------------------------------------------------- * |
| * Update package download module |
| * --------------------------------------------------------------------------------- */ |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_InitializePackageReservoir |
| DESCRIPTION |
| find out whether any update record block exists |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_InitializePackageReservoir(void) |
| { |
| kal_uint32 idx = 0; |
| kal_int32 ret_code = ERROR_FOTA_SUCCESS; |
| |
| /* set package module control to default value */ |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_block_session = INVALID_DWORD; |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_previous_block = INVALID_DWORD; |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_current_block = INVALID_DWORD; |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_valid_pages = INVALID_DWORD; |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_current_page = INVALID_DWORD; |
| |
| FOTA_Package_Ctrl.m_fota_pkg_index = INVALID_DWORD; |
| FOTA_Package_Ctrl.m_fota_pkg_pages = 0; |
| |
| FOTA_Package_Ctrl.m_fota_curr_read.m_pkg_curr_addr = INVALID_DWORD; |
| FOTA_Package_Ctrl.m_fota_curr_read.m_pkg_curr_blk = INVALID_DWORD; |
| FOTA_Package_Ctrl.m_fota_curr_read.m_pkg_curr_page = INVALID_DWORD; |
| |
| for(idx = 0 ; idx < FOTA_PKG_BLOCKS ; idx++) |
| { |
| FOTA_Package_Ctrl.m_fota_pkg_list[idx].m_pkg_block_order = INVALID_DWORD; |
| FOTA_Package_Ctrl.m_fota_pkg_list[idx].m_pkg_block_position = INVALID_DWORD; |
| FOTA_Package_Ctrl.m_fota_pkg_list[idx].m_pkg_valid_pages = INVALID_DWORD; |
| FOTA_Package_Ctrl.m_fota_pkg_list[idx].m_pkg_block_complete = KAL_FALSE; |
| } |
| |
| /* initialize FGAL driver */ |
| FOTA_Package_Ctrl.m_pkg_fgal = FOTA_Setup_FGAL(); |
| |
| /* get initial reserved area information */ |
| FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_base = FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_start; |
| FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_end = FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_end; |
| |
| /* get flash information */ |
| //FOTA_Package_Ctrl.m_pkg_fgal->query_info(&FOTA_Package_Ctrl.m_fota_flash_info); |
| |
| FOTA_Package_Ctrl.m_fota_pkg_state = FOTA_UPDATE_PACKAGE_STATE; |
| |
| return ret_code; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_ResumeUpdatePackage |
| DESCRIPTION |
| find out whether any valid update package blocks exist |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_ResumeUpdatePackage(void) |
| { |
| kal_uint32 pkg_blocks = INVALID_DWORD; |
| kal_uint32 buff_len = FOTA_FLASH_MAX_PAGE_SIZE; |
| kal_uint32 idx = 0; |
| kal_uint32 start_idx = INVALID_DWORD; |
| kal_uint32 blk_order = 0; |
| FUE_ERROR_CODE result = ERROR_FUE_NONE; |
| kal_int32 ret_code = ERROR_FOTA_SUCCESS; |
| kal_uint32 pkg_pages = 0; |
| FOTA_Package_List_st *pkg_list = NULL; |
| Logical_Flash_info_st info; |
| Flash_GAL_st *fgal = FOTA_Package_Ctrl.m_pkg_fgal; |
| |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ret_code = ERROR_FOTA_NOT_INITIALIZED; |
| return ret_code; |
| } |
| |
| /* try to resume interrupted download process */ |
| /* update current package state to RAM copy */ |
| result = FUE_BlkInfo_Resume_Package_Blocks(&FOTA_Package_Ctrl, &pkg_blocks, g_fota_package_blocks, |
| fota_temp_page_buffer, &buff_len, |
| fue_dbg_print); |
| if(ERROR_FUE_NONE == result) |
| { |
| if( pkg_blocks ) |
| { |
| /* get first element index */ |
| for(idx = 0 ; idx < FOTA_PKG_BLOCKS ; idx++) |
| { |
| if( INVALID_DWORD == g_fota_package_blocks[idx].m_pkg_prev_idx ) |
| { |
| if( INVALID_DWORD != g_fota_package_blocks[idx].m_pkg_block_order ) |
| { |
| start_idx = idx; |
| break; |
| } |
| } |
| } |
| #ifdef _FUE_PKG_DEBUG_ |
| if( INVALID_DWORD == start_idx ) |
| { |
| fue_dbg_print("FOTA_ResumeUpdatePackage: first valid block not found in %d blocks!\n\r", pkg_blocks); |
| #if defined(__FOTA_DEBUG_ASSERT__) |
| ASSERT(0); |
| #endif /* __FOTA_DEBUG_ASSERT__ */ |
| } |
| #endif |
| |
| pkg_list = FOTA_Package_Ctrl.m_fota_pkg_list; |
| while(blk_order < pkg_blocks) |
| { |
| idx = start_idx; |
| while(1) |
| { |
| if(blk_order == g_fota_package_blocks[idx].m_pkg_block_order) |
| { |
| pkg_list[blk_order].m_pkg_block_order = g_fota_package_blocks[idx].m_pkg_block_order; |
| pkg_list[blk_order].m_pkg_block_position = g_fota_package_blocks[idx].m_pkg_block_position; |
| pkg_list[blk_order].m_pkg_valid_pages = g_fota_package_blocks[idx].m_pkg_valid_pages; |
| pkg_list[blk_order].m_pkg_block_complete = g_fota_package_blocks[idx].m_pkg_block_complete; |
| pkg_pages += pkg_list[blk_order].m_pkg_valid_pages; |
| if( (INVALID_DWORD == pkg_list[blk_order].m_pkg_valid_pages) || |
| (0 == pkg_list[blk_order].m_pkg_valid_pages) ) |
| { |
| #ifdef _FUE_PKG_DEBUG_ |
| fue_dbg_print("FOTA_ResumeUpdatePackage: resume operation failed on %dth blk:%d\n\r", \ |
| blk_order, pkg_list[blk_order].m_pkg_block_position); |
| #endif /* _FUE_PKG_DEBUG_ */ |
| #if defined(__FOTA_DEBUG_ASSERT__) |
| ASSERT(0); |
| #endif /* __FOTA_DEBUG_ASSERT__ */ |
| } |
| blk_order++; |
| break; |
| /*TODO: remove this element from g_fota_package_blocks to save searching time */ |
| } |
| idx = g_fota_package_blocks[idx].m_pkg_next_idx; |
| if(INVALID_DWORD == idx) |
| { |
| #ifdef _FUE_PKG_DEBUG_ |
| fue_dbg_print("FOTA_ResumeUpdatePackage: downloading sequence is lost!(%d,%d)\n\r", \ |
| blk_order, pkg_blocks); |
| #if defined(__FOTA_DEBUG_ASSERT__) |
| ASSERT(0); |
| #endif /* __FOTA_DEBUG_ASSERT__ */ |
| #endif /* _FUE_PKG_DEBUG_ */ |
| /* package block order is lost, re-download package from the beggining */ |
| ret_code = ERROR_FOTA_NO_UPDATE_PACKAGE; |
| break; |
| } |
| } |
| } |
| |
| #ifdef _FUE_PKG_DEBUG_ |
| #if 0 /* removed since we do not update m_fota_pkg_info during FUE_BlkInfo_Resume_Package_Blocks() */ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| #endif /* removed */ |
| #endif |
| if(INVALID_DWORD != FOTA_Package_Ctrl.m_fota_pkg_list[blk_order-1].m_pkg_block_position) |
| { |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_current_block = |
| FOTA_Package_Ctrl.m_fota_pkg_list[blk_order-1].m_pkg_block_position; |
| if(pkg_list[blk_order-1].m_pkg_block_complete) |
| { |
| fgal->query_info(&info); |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_current_page = |
| fgal->block_size(FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_current_block)/info.Flash_page_size; |
| } |
| else |
| { |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_current_page = pkg_list[blk_order-1].m_pkg_valid_pages+1; |
| } |
| |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_valid_pages = pkg_list[blk_order-1].m_pkg_valid_pages; |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_block_session = blk_order-1; |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_previous_block = (blk_order > 1) ? |
| FOTA_Package_Ctrl.m_fota_pkg_list[blk_order-2].m_pkg_block_position : INVALID_DWORD; |
| } |
| FOTA_Package_Ctrl.m_fota_pkg_index = blk_order-1; |
| FOTA_Package_Ctrl.m_fota_pkg_blocks = pkg_blocks; |
| FOTA_Package_Ctrl.m_fota_pkg_pages = pkg_pages; |
| |
| //FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_valid_pages = ; |
| if(pkg_blocks != blk_order) |
| { |
| #ifdef _FUE_PKG_DEBUG_ |
| fue_dbg_print("FOTA_ResumeUpdatePackage: blk number:%d <-> blk order:%d!\n\r", \ |
| pkg_blocks, blk_order); |
| #endif /* _FUE_PKG_DEBUG_ */ |
| #if defined(__FOTA_DEBUG_ASSERT__) |
| ASSERT(0); |
| #endif /* __FOTA_DEBUG_ASSERT__ */ |
| ret_code = ERROR_FOTA_NO_UPDATE_PACKAGE; |
| } |
| #ifdef _FUE_PKG_DEBUG_ |
| fue_dbg_print("FOTA_ResumeUpdatePackage: %dth package blk:%d!\n\r", |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_block_session, \ |
| FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_current_block); |
| #endif |
| } |
| else |
| { |
| ret_code = ERROR_FOTA_NO_UPDATE_PACKAGE; |
| } |
| } |
| else if((ERROR_FUE_INSUFFICIENT_BUFFER == result) || (ERROR_FUE_INVALID_PARAMETER == result)) |
| { |
| ret_code = ERROR_FOTA_INVALID_PARAMETER; |
| FOTA_Package_Ctrl.m_fota_pkg_state = INVALID_DWORD; |
| } |
| else if( (ERROR_FUE_NOT_FOUND == result) || (ERROR_FUE_TOO_MANY_PACKAGE_BLOCKS == result) ) |
| { |
| ret_code = ERROR_FOTA_NO_UPDATE_PACKAGE; |
| } |
| else if( (ERROR_FUE_OPERATION_STOP == result) || (ERROR_FUE_READ_FAILURE == result) ) |
| { |
| ret_code = ERROR_FOTA_UNSUPPORTED_CASES; |
| } |
| |
| return ret_code; |
| } |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_CheckAvailablePackageBlocks |
| DESCRIPTION |
| scan all block in package reservoir area to estimate the available storage size |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_CheckAvailablePackageBlocks(kal_uint32 *available_num) |
| { |
| kal_int32 ret_code = ERROR_FOTA_SUCCESS; |
| kal_uint32 base_blk = INVALID_DWORD; |
| kal_uint32 end_blk = INVALID_DWORD; |
| kal_uint32 blk_idx = 0; |
| kal_uint32 blk_num = 0; |
| _FGAL_ERROR_CODE status = ERROR_FGAL_NONE; |
| Flash_GAL_st *fgal = NULL; |
| //Logical_Flash_info_st info; |
| |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ASSERT(0); |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| |
| base_blk = FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_base; |
| end_blk = FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_end; |
| |
| fgal = FOTA_Package_Ctrl.m_pkg_fgal; |
| |
| //fgal->query_info(&info); |
| *available_num = 0; |
| |
| for(blk_idx = base_blk ; blk_idx < (end_blk+1) ; blk_idx++) |
| { |
| status = fgal->check_block(blk_idx); |
| if(ERROR_FGAL_NONE == status) |
| { |
| /* check whether it is occupied */ |
| if(FUE_NFB_Is_Available_Block(blk_idx, fota_temp_page_buffer, fgal, fue_dbg_print)) |
| { |
| blk_num++; |
| } |
| } |
| else if(ERROR_FGAL_READ_FAILURE == status) |
| { |
| ret_code = ERROR_FOTA_READ; |
| break; |
| } |
| else if(ERROR_FGAL_OPERATION_RETRY == status) |
| { |
| ret_code = ERROR_FOTA_FLASH_DEVICE; |
| break; |
| } |
| } |
| if(blk_idx == (end_blk+1)) |
| *available_num = blk_num; |
| |
| return ret_code; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_ClearPackageReservoir |
| DESCRIPTION |
| clear downloaded update package |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_ClearPackageReservoir(void) |
| { |
| kal_int32 ret_code = ERROR_FOTA_SUCCESS; |
| kal_uint32 base_blk = INVALID_DWORD; |
| kal_uint32 end_blk = INVALID_DWORD; |
| kal_uint32 index = 0; |
| kal_uint32 blk_idx = 0; |
| kal_uint32 erase_round = 0; |
| kal_uint32 pkg_num = FOTA_PKG_BLOCKS; |
| kal_uint32 erased_blk = 0; |
| FUE_ERROR_CODE result = ERROR_FUE_NOT_FOUND; |
| _FGAL_ERROR_CODE status = ERROR_FGAL_NONE; |
| Flash_GAL_st *fgal = NULL; |
| |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| |
| base_blk = FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_base; |
| end_blk = FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_end; |
| |
| fgal = FOTA_Package_Ctrl.m_pkg_fgal; |
| |
| /* try to erase all blocks occupied by update package */ |
| for( blk_idx = base_blk ; blk_idx <= end_blk ; blk_idx++ ) |
| { |
| status = fgal->check_block(blk_idx); |
| if(ERROR_FGAL_NONE == status) |
| { |
| result = FUE_BlkInfo_Is_Update_Block(&FOTA_Update_Ctrl, blk_idx, fue_dbg_print); |
| if(ERROR_FUE_NOT_FOUND == result) /* in this flash space, only package or update blocks exist */ |
| { |
| /* erase block */ |
| status = fgal->erase_block(blk_idx); |
| if(ERROR_FGAL_ERASE_FAILURE == status) |
| { |
| fgal->mark_bad(blk_idx); |
| #ifdef _FUE_PKG_DEBUG_ |
| fue_dbg_print("FOTA_ClearPackageReservoir: erase failed on block:%d!\n\r", blk_idx); |
| #endif |
| } |
| else if(ERROR_FGAL_OPERATION_RETRY == status) |
| { |
| #ifdef _FUE_PKG_DEBUG_ |
| fue_dbg_print("FOTA_ClearPackageReservoir: erase operation stopped on block:%d!\n\r", blk_idx); |
| #endif |
| ret_code = ERROR_FOTA_FLASH_DEVICE; |
| break; |
| } |
| erased_blk++; |
| } |
| else if( (ERROR_FUE_OPERATION_STOP == result) || (ERROR_FUE_OVER_DESIGN == result) ) |
| { |
| #ifdef _FUE_PKG_DEBUG_ |
| fue_dbg_print("FOTA_ClearPackageReservoir: read operation stopped on block:%d!\n\r", blk_idx); |
| #endif |
| ret_code = ERROR_FOTA_FLASH_DEVICE; |
| break; |
| } |
| else if(ERROR_FUE_NONE == result) |
| { |
| continue; |
| } |
| else |
| { |
| #ifdef _FUE_PKG_DEBUG_ |
| fue_dbg_print("FOTA_ClearPackageReservoir: unexpected error on block:%d!\n\r", blk_idx); |
| #endif |
| ret_code = ERROR_FOTA_UNSUPPORTED_CASES; |
| break; |
| } |
| } |
| else if(ERROR_FGAL_READ_FAILURE == status) |
| { |
| ret_code = ERROR_FOTA_READ; |
| break; |
| } |
| else if(ERROR_FGAL_OPERATION_RETRY == status) |
| { |
| ret_code = ERROR_FOTA_FLASH_DEVICE; |
| break; |
| } |
| } |
| #ifdef _FUE_PKG_DEBUG_ |
| fue_dbg_print("FOTA_ClearPackageReservoir: clear %d in %d blocks!\n\r", erased_blk, blk_idx-base_blk); |
| #endif |
| return ret_code; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Get_TotalPackageBlock |
| DESCRIPTION |
| return current package block number |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_Get_TotalPackageBlock(kal_uint32 *pkg_blks, kal_uint32* pkg_pages) |
| { |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ASSERT(0); |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| |
| if(INVALID_DWORD != FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_valid_pages) |
| { |
| *pkg_blks = FOTA_Package_Ctrl.m_fota_pkg_blocks-1; |
| *pkg_pages = FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_valid_pages; |
| } |
| else |
| { |
| *pkg_blks = FOTA_Package_Ctrl.m_fota_pkg_blocks; |
| *pkg_pages = 0; |
| } |
| |
| return ERROR_FOTA_SUCCESS; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Get_CurrentPackagePosition |
| DESCRIPTION |
| return current package block position |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_Get_CurrentPackagePosition(kal_uint32 *curr_blk, kal_uint32* curr_page) |
| { |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ASSERT(0); |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| |
| *curr_blk = FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_current_block; |
| *curr_page = FOTA_Package_Ctrl.m_fota_pkg_info.m_pkg_current_page; |
| |
| return ERROR_FOTA_SUCCESS; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Get_AvailablePackageSpace |
| DESCRIPTION |
| return currently downloaded package size |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_Get_AvailablePackageSpace(kal_uint32 *avail_size) |
| { |
| Logical_Flash_info_st info; |
| kal_int32 ret_code = ERROR_FOTA_SUCCESS; |
| kal_uint32 page_size; |
| kal_uint32 blk_idx = 0; |
| kal_uint32 start_blk = 0; |
| kal_uint32 end_blk = 0; |
| kal_uint32 free_size = 0; |
| _FGAL_ERROR_CODE status = ERROR_FGAL_NONE; |
| Flash_GAL_st *fgal = NULL; |
| |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ASSERT(0); |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| |
| fgal = FOTA_Package_Ctrl.m_pkg_fgal; |
| |
| fgal->query_info(&info); |
| page_size = info.Flash_page_size; |
| start_blk = FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_base; |
| end_blk = FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_end; |
| |
| /* try to erase all blocks occupied by update package */ |
| for( blk_idx = start_blk ; blk_idx <= end_blk ; blk_idx++ ) |
| { |
| status = fgal->check_block(blk_idx); |
| if(ERROR_FGAL_NONE == status) |
| { |
| /* check whether it is occupied */ |
| if( FUE_NFB_Is_Available_Block(blk_idx, fota_temp_page_buffer, fgal, fue_dbg_print) || |
| FUE_BlkInfo_Is_Package_Block(&FOTA_Package_Ctrl, blk_idx, fue_dbg_print) ) |
| { |
| free_size += fgal->block_size(blk_idx)-3*page_size;/* header and end mark pages are reserved */ |
| } |
| } |
| else if(ERROR_FGAL_READ_FAILURE == status) |
| { |
| ret_code = ERROR_FOTA_READ; |
| break; |
| } |
| else if(ERROR_FGAL_OPERATION_RETRY == status) |
| { |
| ret_code = ERROR_FOTA_FLASH_DEVICE; |
| break; |
| } |
| } |
| |
| FOTA_Get_CurrentPackagePosition(&start_blk, &end_blk); |
| if(INVALID_DWORD != start_blk) |
| { |
| /* header, end mark and current valid pages are excluded */ |
| free_size += fgal->block_size(start_blk)-(end_blk+3)*page_size; |
| } |
| |
| *avail_size = free_size; |
| |
| return ret_code; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Get_TotalPackageSpace |
| DESCRIPTION |
| return currently downloaded package size |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_Get_TotalPackageSpace(kal_uint32 *avail_size) |
| { |
| Logical_Flash_info_st info; |
| kal_int32 ret_code = ERROR_FOTA_SUCCESS; |
| kal_uint32 page_size; |
| kal_uint32 blk_idx = 0; |
| kal_uint32 start_blk = 0; |
| kal_uint32 end_blk = 0; |
| kal_uint32 free_size = 0; |
| _FGAL_ERROR_CODE status = ERROR_FGAL_NONE; |
| Flash_GAL_st *fgal = NULL; |
| |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ASSERT(0); |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| |
| fgal = FOTA_Package_Ctrl.m_pkg_fgal; |
| |
| fgal->query_info(&info); |
| page_size = info.Flash_page_size; |
| start_blk = FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_base; |
| end_blk = FOTA_Package_Ctrl.m_fota_pkg_area.FOTA_pkg_area_end; |
| |
| /* try to erase all blocks occupied by update package */ |
| for( blk_idx = start_blk ; blk_idx <= end_blk ; blk_idx++ ) |
| { |
| status = fgal->check_block(blk_idx); |
| if(ERROR_FGAL_NONE == status) |
| { |
| /* check whether it is occupied */ |
| if( (ERROR_FUE_NONE == FUE_NFB_Is_Available_Block(blk_idx, fota_temp_page_buffer, fgal, fue_dbg_print)) || |
| (ERROR_FUE_NONE == FUE_BlkInfo_Is_Package_Block(&FOTA_Package_Ctrl, blk_idx, fue_dbg_print)) ) |
| { |
| free_size += fgal->block_size(blk_idx)-3*page_size;/* header and end mark pages are reserved */ |
| } |
| } |
| else if(ERROR_FGAL_READ_FAILURE == status) |
| { |
| ret_code = ERROR_FOTA_READ; |
| break; |
| } |
| else if(ERROR_FGAL_OPERATION_RETRY == status) |
| { |
| ret_code = ERROR_FOTA_FLASH_DEVICE; |
| break; |
| } |
| } |
| |
| /* one block is reserved for update state record replacement */ |
| *avail_size = free_size-(fgal->block_size(start_blk)-3*page_size);/* header and end mark pages are reserved */ |
| |
| return ret_code; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Get_DownloadedPackageSize |
| DESCRIPTION |
| return currently downloaded package size |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_Get_DownloadedPackageSize(kal_uint32 *curr_size) |
| { |
| Logical_Flash_info_st info; |
| if(FOTA_UPDATE_PACKAGE_STATE != FOTA_Package_Ctrl.m_fota_pkg_state) |
| { |
| ASSERT(0); |
| return ERROR_FOTA_NOT_INITIALIZED; |
| } |
| |
| FOTA_Package_Ctrl.m_pkg_fgal->query_info(&info); |
| if(INVALID_DWORD != FOTA_Package_Ctrl.m_fota_pkg_pages) |
| *curr_size = FOTA_Package_Ctrl.m_fota_pkg_pages*info.Flash_page_size; |
| else |
| *curr_size = 0; |
| |
| return ERROR_FOTA_SUCCESS; |
| } |
| |
| #if 0 |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| #endif |
| /* --------------------------------------------------------------------------------- * |
| * Update staus record control module |
| * --------------------------------------------------------------------------------- */ |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_InitializeUpdateRecord |
| DESCRIPTION |
| create an update record block or find out the existing update record block |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_InitializeUpdateRecord(void) |
| { |
| kal_uint32 start_block = INVALID_DWORD; |
| kal_uint32 end_block = INVALID_DWORD; |
| FUE_ERROR_CODE result = ERROR_FUE_NONE; |
| _FGAL_ERROR_CODE status = ERROR_FGAL_NONE; |
| |
| /* initialize FGAL driver */ |
| FOTA_Update_Ctrl.m_update_fgal = FOTA_Setup_FGAL(); |
| |
| /* get initial reserved area information */ |
| start_block = FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_start; |
| end_block = FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_end; |
| //FOTA_Update_Ctrl.m_update_fgal->query_info(&FOTA_Update_Ctrl.m_nand_flash_info); |
| |
| /* set up update record module */ |
| result = FUE_InitializeUpdateRecord(start_block, end_block, \ |
| FOTA_Update_Ctrl.m_update_fgal/*&FOTA_Nand_Fgal*/,\ |
| fue_dbg_print); |
| if(ERROR_FUE_NO_AVAILABLE_BLOCK == result) |
| { |
| status = ERROR_FOTA_NO_AVAILABLE_BLOCK; |
| } |
| else if(ERROR_FUE_OPERATION_STOP == result) |
| { |
| status = ERROR_FOTA_FLASH_DEVICE; |
| } |
| else if(ERROR_FUE_OVER_DESIGN == result) |
| { |
| status = ERROR_FOTA_UNSUPPORTED_CASES; |
| } |
| else |
| { |
| FOTA_Update_Ctrl.FOTA_UPDATE_ID = UPDATE_STATE_RECORD_ID; |
| } |
| |
| return status; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_WriteUpdateRecord |
| DESCRIPTION |
| FOTA update state information write API |
| download client and update agent use this information to communicate with each other |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_WriteUpdateRecord(FOTA_Custom_Update_Info* record) |
| { |
| kal_int32 ret = ERROR_FOTA_SUCCESS; |
| FUE_ERROR_CODE result = ERROR_FUE_NONE; |
| |
| /* check whether FOTA is initialized */ |
| if(UPDATE_STATE_RECORD_ID != FOTA_Update_Ctrl.FOTA_UPDATE_ID) |
| { |
| ret = ERROR_FOTA_NOT_INITIALIZED; |
| } |
| else |
| { |
| result = FUE_NFB_Flush_Update_Record(record, fue_dbg_print); |
| |
| if(ERROR_FUE_NONE == result ) |
| { |
| ret = ERROR_FOTA_SUCCESS; |
| } |
| else if(ERROR_FUE_OPERATION_STOP == result) |
| { |
| #ifdef FOTA_DEBUG |
| ASSERT(0); |
| #endif |
| ret = ERROR_FOTA_FLASH_DEVICE; |
| } |
| } |
| return ret; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_ReadUpdateRecord |
| DESCRIPTION |
| FOTA update state information read API |
| download client and update agent use this information to communicate with each other |
| PARAMETER |
| NULL |
| RETURN |
| 0: means pass initialization step (ERROR_FOTA_SUCCESS) |
| < 0: means fail |
| ERROR_FOTA_CUSTOMIZATION: wrong customization |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_ReadUpdateRecord(FOTA_Custom_Update_Info* record) |
| { |
| kal_int32 ret = ERROR_FOTA_SUCCESS; |
| FUE_ERROR_CODE result = ERROR_FUE_NONE; |
| |
| /* check whether FOTA is initialized */ |
| if(UPDATE_STATE_RECORD_ID != FOTA_Update_Ctrl.FOTA_UPDATE_ID) |
| { |
| ret = ERROR_FOTA_NOT_INITIALIZED; |
| } |
| else |
| { |
| result = FUE_NFB_Get_Update_Record(record, fue_dbg_print); |
| |
| if(ERROR_FUE_UNRECOVERABLE_ECC == result) |
| { |
| ret = ERROR_FOTA_READ; |
| } |
| else if(ERROR_FUE_OPERATION_STOP == result) |
| { |
| ret = ERROR_FOTA_FLASH_DEVICE; |
| } |
| } |
| return ret; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Inform_Update_State |
| DESCRIPTION |
| Download client use this function to query the result of update process |
| PARAMETER |
| NULL |
| RETURN |
| --------------------------------------------------------------------------------- */ |
| FOTA_update_result FOTA_Inform_Update_State(void) |
| { |
| FOTA_update_result ret = FOTA_UPDATE_NONE; |
| FUE_ERROR_CODE result = ERROR_FUE_NONE; |
| FOTA_Custom_Update_Info upt_info; |
| |
| /* check whether FOTA is initialized */ |
| if(UPDATE_STATE_RECORD_ID != FOTA_Update_Ctrl.FOTA_UPDATE_ID) |
| { |
| ret = FOTA_UPDATE_NONE; |
| } |
| else |
| { |
| result = FOTA_ReadUpdateRecord(&upt_info); |
| |
| if(ERROR_FUE_NONE == result) |
| { |
| /* check customer's state */ |
| if( FUE_UA_COMPLETE_PHASE == upt_info.FOTA_test_info1 ) |
| { |
| ret = FOTA_UPDATE_SUCCEEDED; |
| } |
| else |
| { |
| #if 0 |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| #endif |
| { |
| ret = FOTA_UPDATE_FAILED; |
| } |
| } |
| } |
| else |
| { |
| ret = FOTA_UPDATE_NONE; |
| } |
| } |
| |
| return ret; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Start_Download_State |
| DESCRIPTION |
| Download client use this function to query the result of update process |
| PARAMETER |
| NULL |
| RETURN |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_Start_Download_State(void) |
| { |
| kal_int32 ret = ERROR_FOTA_SUCCESS; |
| FOTA_Custom_Update_Info upt_info; |
| |
| if(UPDATE_STATE_RECORD_ID != FOTA_Update_Ctrl.FOTA_UPDATE_ID) |
| { |
| ret = ERROR_FOTA_NOT_INITIALIZED; |
| } |
| else |
| { |
| kal_mem_set(&upt_info,0xff,sizeof(FOTA_Custom_Update_Info)); |
| FUE_Start_Download_State(); |
| ret = FOTA_WriteUpdateRecord(&upt_info); |
| } |
| |
| return ret; |
| } |
| |
| /* --------------------------------------------------------------------------------- |
| FUNCTION |
| FOTA_Start_Update_State |
| DESCRIPTION |
| Download client use this function to query the result of update process |
| PARAMETER |
| NULL |
| RETURN |
| --------------------------------------------------------------------------------- */ |
| kal_int32 FOTA_Start_Update_State(void) |
| { |
| kal_int32 ret = ERROR_FOTA_SUCCESS; |
| FOTA_Custom_Update_Info upt_info; |
| |
| if(UPDATE_STATE_RECORD_ID != FOTA_Update_Ctrl.FOTA_UPDATE_ID) |
| { |
| ret = ERROR_FOTA_NOT_INITIALIZED; |
| } |
| else |
| { |
| kal_mem_set(&upt_info,0xff,sizeof(FOTA_Custom_Update_Info)); |
| FUE_Start_Package_Verification_State(); |
| ret = FOTA_WriteUpdateRecord(&upt_info); |
| } |
| |
| return ret; |
| } |
| |
| |
| /* --------------------------------------------------------------------------------- * |
| * Flash Generic Access Layer |
| * --------------------------------------------------------------------------------- */ |
| #define FOTA_FGAL_READY (0x59445246) |
| kal_uint32 g_FOTA_fgal_state; |
| |
| #if defined(_NAND_FLASH_BOOTING_) || (defined(__UP_PKG_ON_NAND__) && defined(NAND_SUPPORT)) |
| |
| #if !defined(__NAND_FDM_50__) |
| #include "NAND_FDM.h" |
| #include "nand_mtd.h" |
| #include "nand_mtd_internal.h" |
| #else |
| #include "NAND_MTD_FDM50.h" |
| #include "NAND_DAL.h" |
| #include "NAND_MTD_FDM50_internal.h" |
| #include "NAND_DAL_internal.h" |
| |
| extern kal_uint8 IsGoodBlock(void* D, void * Spare); |
| #endif /* !__NAND_FDM_50__ */ |
| |
| /* Following functions and variables are located in NAND_MTD.c */ |
| extern int NFB_ReadPhysicalPage(kal_uint32 PhyBlock, kal_uint32 PhyPage, void * Data); |
| extern int NFB_ReadPhysicalSpare(kal_uint32 PhyBlock, kal_uint32 PhyPage, void * Data, kal_bool chksum); |
| extern int NFB_ProgramPhysicalPage(kal_uint32 PhyBlock, kal_uint32 PhyPage, void * Data, kal_bool DALRemap); |
| extern int NFB_ProgramPhysicalSpare(kal_uint32 PhyBlock, kal_uint32 PhyPage, void * Data, kal_bool chksum, kal_bool DALRemap); |
| extern int NFB_ErasePhysicalBlock(kal_uint32 PhyBlock, kal_bool DALRemap); |
| extern void get_NFI_bus(void); |
| extern void free_NFI_bus(void); |
| |
| extern int NFBPageSize; |
| extern int NFBBlockSize; |
| |
| #if defined(__NAND_FDM_50__) |
| |
| extern flash_info_2 Flash_Info; |
| |
| #else /* NAND FDM 4.x */ |
| |
| extern NAND_FLASH_DRV_DATA NANDFlashDriveData; |
| |
| #endif |
| |
| /* Forward declaration */ |
| _FGAL_ERROR_CODE FOTA_NAND_Init_func(void); |
| _FGAL_ERROR_CODE FOTA_NAND_Page_Read_func(kal_uint32* ptr, kal_uint32 blk, kal_uint32 page); |
| _FGAL_ERROR_CODE FOTA_NAND_Query_Info_func(Logical_Flash_info_st* info); |
| _FGAL_ERROR_CODE FOTA_NAND_Page_Program_func(kal_uint32* ptr, kal_uint32 blk, kal_uint32 page); |
| _FGAL_ERROR_CODE FOTA_NAND_Is_Good_Block_func(kal_uint32 blk); |
| _FGAL_ERROR_CODE FOTA_NAND_Mark_Bad_Block_func(kal_uint32 blk); |
| _FGAL_ERROR_CODE FOTA_NAND_Erase_Block_func(kal_uint32 blk); |
| _FGAL_ERROR_CODE FOTA_NAND_Is_Page_Empty_func(kal_uint32 *buff, kal_uint32 blk, kal_uint32 page); |
| _FGAL_ERROR_CODE FOTA_NAND_Lock_Block_func(kal_uint32 blk, kal_bool locked); |
| kal_uint32 FOTA_NAND_Block_Size_func(kal_uint32 blk); |
| kal_uint32 FOTA_NAND_Block_Index_func(kal_uint32 blk_addr); |
| |
| /* |
| * Macro definition |
| */ |
| #define FOTA_NAND_STATE_VALID (0x5644544D) |
| |
| #define FOTA_MAX_SPARE_SIZE (64) |
| |
| /* |
| * Global variable definition |
| */ |
| kal_uint32 g_FOTA_NAND_MTD_STATE; |
| |
| kal_uint32 g_fota_spare_buffer[FOTA_MAX_SPARE_SIZE>>2]; |
| |
| /* For flash generic access layer */ |
| Flash_GAL_st FOTA_Nand_Fgal; |
| |
| /***************************************************************** |
| Description : wait for a specific period counted by 32Khz tick. |
| Input : |
| Output : None |
| ******************************************************************/ |
| static void delay32KHzTick(kal_uint32 count) |
| { |
| kal_uint32 begin_time = 0; |
| kal_uint32 current_time = 0; |
| |
| begin_time = INT_GetCurrentTime(); |
| do |
| { |
| current_time = INT_GetCurrentTime(); |
| if(current_time > begin_time) |
| { |
| if( (current_time-begin_time) > count ) |
| break; |
| } |
| else |
| { |
| if( (0xFFFFFFFF - begin_time + current_time + 1) > count) |
| break; |
| } |
| }while(1); |
| } |
| |
| /***************************************************************** |
| Description : set up FGAL structure. |
| Input : |
| Output : None |
| ******************************************************************/ |
| |
| |
| Flash_GAL_st *FOTA_Setup_FGAL(void) |
| { |
| if(FOTA_FGAL_READY == g_FOTA_fgal_state) |
| return &FOTA_Nand_Fgal; |
| |
| /* set up FGAL */ |
| FOTA_Nand_Fgal.init_drv = FOTA_NAND_Init_func; |
| FOTA_Nand_Fgal.query_info = FOTA_NAND_Query_Info_func; |
| FOTA_Nand_Fgal.read_page = FOTA_NAND_Page_Read_func; |
| FOTA_Nand_Fgal.write_page = FOTA_NAND_Page_Program_func; |
| FOTA_Nand_Fgal.check_block = FOTA_NAND_Is_Good_Block_func; |
| FOTA_Nand_Fgal.mark_bad = FOTA_NAND_Mark_Bad_Block_func; |
| FOTA_Nand_Fgal.erase_block = FOTA_NAND_Erase_Block_func; |
| FOTA_Nand_Fgal.check_empty_page = FOTA_NAND_Is_Page_Empty_func; |
| FOTA_Nand_Fgal.block_size = FOTA_NAND_Block_Size_func; |
| FOTA_Nand_Fgal.block_index = FOTA_NAND_Block_Index_func; |
| FOTA_Nand_Fgal.lock_block = FOTA_NAND_Lock_Block_func; |
| |
| /* initialize FGAL driver */ |
| FOTA_Nand_Fgal.init_drv(); |
| |
| g_FOTA_fgal_state = FOTA_FGAL_READY; |
| return &FOTA_Nand_Fgal; |
| } |
| |
| /***************************************************************** |
| Description : check whether the provided buffer comes from empty page. |
| Input : |
| Output : None |
| ******************************************************************/ |
| kal_bool FOTA_NAND_MTD_Check_Page_Empty(kal_uint8* page_buffer, kal_uint8* spare_buffer) |
| { |
| kal_uint32 spare_len = 0; |
| kal_uint32 idx = 0, j = 0; |
| kal_uint32* long_ptr = NULL; |
| kal_int32 byte_count = 0; |
| kal_int32 long_len = 0; |
| kal_uint32 page_size = NFBPageSize; |
| |
| switch(page_size) |
| { |
| case 4096: |
| spare_len = 128; |
| break; |
| case 2048: |
| spare_len = 64; |
| break; |
| case 512: |
| spare_len = 16; |
| break; |
| default: |
| ASSERT(0); |
| } |
| /* compare with 0xFF */ |
| if(page_buffer) |
| { |
| long_ptr = (kal_uint32 *)(((kal_uint32)page_buffer+3) & ~(0x03)); |
| long_len = ((((kal_uint32)page_buffer+page_size) & ~(0x03)) - (kal_uint32)long_ptr) >> 2; |
| byte_count = (kal_uint32)long_ptr - (kal_uint32)page_buffer; |
| /* chech page content */ |
| if(byte_count > 0) |
| { |
| for(j = 0 ; j < byte_count ; j++) |
| { |
| if(page_buffer[j] != 0xFF) |
| return KAL_FALSE; |
| } |
| } |
| for(idx = 0 ; idx < long_len ; idx++) |
| { |
| if(long_ptr[idx] != 0xFFFFFFFF) |
| return KAL_FALSE; |
| } |
| byte_count = page_size - byte_count - (long_len<<2); |
| if(byte_count > 0) |
| { |
| for(j = byte_count ; j > 0 ; j--) |
| { |
| if(page_buffer[page_size-j] != 0xFF) |
| return KAL_FALSE; |
| } |
| } |
| } |
| |
| if(spare_buffer) |
| { |
| /* check spare content */ |
| long_ptr = (kal_uint32 *)(((kal_uint32)spare_buffer+3) & ~(0x03)); |
| long_len = ((((kal_uint32)spare_buffer+spare_len) & ~(0x03)) - (kal_uint32)long_ptr) >> 2; |
| byte_count = (kal_uint32)long_ptr - (kal_uint32)spare_buffer; |
| if(byte_count > 0) |
| { |
| for(j = 0 ; j < byte_count ; j++) |
| { |
| if(spare_buffer[j] != 0xFF) |
| return KAL_FALSE; |
| } |
| } |
| for(idx = 0 ; idx < long_len ; idx++) |
| { |
| if(long_ptr[idx] != 0xFFFFFFFF) |
| return KAL_FALSE; |
| } |
| byte_count = spare_len - byte_count - (long_len<<2); |
| if(byte_count > 0) |
| { |
| for(j = byte_count ; j > 0 ; j--) |
| { |
| if(spare_buffer[page_size-j] != 0xFF) |
| return KAL_FALSE; |
| } |
| } |
| } |
| return KAL_TRUE;; |
| } |
| |
| /***************************************************************** |
| Description : check whether the provided buffer comes from spare area of bad block. |
| Input : |
| Output : None |
| ******************************************************************/ |
| void FOTA_NAND_MTD_Set_Spare_Bad_Mark(kal_uint8* spare_buffer) |
| { |
| kal_uint8 *byte_ptr = spare_buffer; |
| kal_bool word_flag = KAL_FALSE; |
| #if !defined(__NAND_FDM_50__) |
| flash_info_struct *nand_info = &NANDFlashDriveData.flash_info; |
| |
| if(IO_ACCESS_16BIT == nand_info->io_width) |
| { |
| word_flag = KAL_TRUE; |
| } |
| |
| #else |
| |
| if(Flash_Info.deviceInfo_CE[0].IOWidth == 16) |
| { |
| word_flag = KAL_TRUE; |
| } |
| |
| #endif /* __NAND_FDM_50__ */ |
| |
| if(512 == NFBPageSize) |
| { |
| if(!word_flag) |
| { |
| byte_ptr[5] = 0x0B; |
| } |
| else |
| { |
| byte_ptr[0] = 0x0B; |
| byte_ptr[10] = 0x0B; |
| } |
| } |
| else if((2048 == NFBPageSize)||(4096 == NFBPageSize)) |
| { |
| if(!word_flag) |
| { |
| byte_ptr[0] = 0x0B; |
| } |
| else |
| { |
| byte_ptr[0] = 0x0B; |
| byte_ptr[1] = 0x0B; |
| } |
| } |
| } |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Init_func |
| * |
| * DESCRIPTION |
| * Initialze NAND flash MTD driver |
| ************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NAND_Init_func(void) |
| { |
| kal_int32 status = -1; |
| |
| status = NFB_ReadPhysicalPage(0xFFFFFFFF, 0xFFFFFFFF, NULL); |
| |
| g_FOTA_NAND_MTD_STATE = FOTA_NAND_STATE_VALID; |
| |
| #if defined(__NAND_FDM_50__) |
| NFBPageSize = Flash_Info.pageSize; |
| //NFBBlockSize = Flash_Info.pageSize*Flash_Info.blockPage; |
| #endif /* __NAND_FDM_50__ */ |
| |
| #if defined(__UP_PKG_ON_NAND__) |
| FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_start = FOTA_NAND_Block_Index_func(FOTA_PACKAGE_STORAGE_BASE); |
| FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_end = FOTA_NAND_Block_Index_func(FOTA_PACKAGE_STORAGE_BASE+FOTA_PACKAGE_STORAGE_SIZE)-1; |
| #endif /* __UP_PKG_ON_NAND__ */ |
| |
| return ERROR_FGAL_NONE; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Page_Read_func |
| * |
| * DESCRIPTION |
| * Read one page from NAND flash |
| ************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NAND_Page_Read_func(kal_uint32* ptr, kal_uint32 blk, kal_uint32 page) |
| { |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| kal_int32 status = 0; |
| #if !defined(__NFI_VERSION2__) && !defined(__NFI_VERSION3_1__) |
| static kal_uint32 empty_spare[64>>2]; |
| #endif /* !__NFI_VERSION2__ && !__NFI_VERSION3_1__*/ |
| |
| ASSERT( FOTA_NAND_STATE_VALID == g_FOTA_NAND_MTD_STATE); |
| |
| status = NFB_ReadPhysicalPage(blk, page, ptr); |
| |
| switch(status) |
| { |
| case ERROR_NFB_BAD_BLOCK: |
| result = ERROR_FGAL_BAD_BLOCK; |
| /* should not happen */ |
| EXT_ASSERT(0, 0, 0, 0); |
| break; |
| case ERROR_NFB_READ: |
| #if !defined(__NFI_VERSION2__) && !defined(__NFI_VERSION3_1__) |
| /* empty page read will generate ECC failure on NFI version1 */ |
| kal_mem_set(empty_spare, 0xFF, 64); |
| NFB_ReadPhysicalSpare(blk, page, empty_spare, KAL_FALSE); |
| if(FOTA_NAND_MTD_Check_Page_Empty((kal_uint8 *)ptr, (kal_uint8 *)empty_spare)) |
| { |
| result = ERROR_FGAL_NONE; |
| } |
| else |
| { |
| result = ERROR_FGAL_ECC_FAILURE; |
| } |
| #else /* __NFI_VERSION2__ || __NFI_VERSION3_1__*/ |
| result = ERROR_FGAL_ECC_FAILURE; |
| #endif /* !__NFI_VERSION2__ && !__NFI_VERSION3_1__*/ |
| break; |
| default: |
| if(NFBPageSize == status) |
| result = ERROR_FGAL_NONE; |
| else |
| { |
| ASSERT(0); |
| result = ERROR_FGAL_OPERATION_RETRY; |
| } |
| } |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Query_Info_func |
| * |
| * DESCRIPTION |
| * Query NAND flash device information |
| ************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NAND_Query_Info_func(Logical_Flash_info_st* info) |
| { |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| kal_uint32 page_size = 0; |
| kal_uint32 offset = 0; |
| kal_uint32 pages_per_block = 0; |
| kal_uint32 page_shift = 0; |
| #if !defined(__NAND_FDM_50__) |
| flash_info_struct *nand_info = &NANDFlashDriveData.flash_info; |
| #endif /* __NAND_FDM_50__ */ |
| |
| ASSERT( FOTA_NAND_STATE_VALID == g_FOTA_NAND_MTD_STATE); |
| |
| #if defined(__NAND_FDM_50__) |
| |
| page_size = Flash_Info.pageSize; |
| if(4096 == page_size) |
| { |
| page_shift = 12; |
| } |
| else if(2048 == page_size) |
| { |
| page_shift = 11; |
| } |
| else if(512 == page_size) |
| { |
| page_shift = 9; |
| } |
| else |
| { |
| /* incorrect device configuration */ |
| ASSERT(0); |
| } |
| |
| pages_per_block = Flash_Info.blockPage; |
| |
| info->Flash_page_size = page_size; |
| info->Flash_block_size = page_size*pages_per_block; |
| info->Flash_io_width = Flash_Info.deviceInfo_CE[0].IOWidth; |
| |
| #else /* NAND FDM 4 */ |
| |
| if(PAGE_2K == nand_info->page_type) |
| { |
| page_size = 2048; |
| page_shift = 11; |
| } |
| else if(PAGE_512 == nand_info->page_type) |
| { |
| page_size = 512; |
| page_shift = 9; |
| } |
| else |
| { |
| /* incorrect device configuration */ |
| ASSERT(0); |
| } |
| |
| pages_per_block = nand_info->pages_per_block; |
| |
| info->Flash_page_size = page_size; |
| info->Flash_block_size = page_size*nand_info->pages_per_block; |
| info->Flash_io_width = nand_info->io_width; |
| |
| #endif |
| |
| /* Assumptions: pages per block is power of 2 */ |
| info->Flash_offset_shift = INVALID_DWORD; |
| for( offset = 0 ; offset < 32 ; offset++) |
| { |
| if( (1 << offset) == pages_per_block ) |
| { |
| info->Flash_offset_shift = offset; |
| info->Flash_block_shift = offset+page_shift; |
| break; |
| } |
| } |
| if(INVALID_DWORD == info->Flash_offset_shift) |
| ASSERT(0); /* incorrect device configuration */ |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Page_Program_func |
| * |
| * DESCRIPTION |
| * Write one page to NAND flash |
| ************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NAND_Page_Program_func(kal_uint32* ptr, kal_uint32 blk, kal_uint32 page) |
| { |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| kal_int32 status = 0; |
| |
| ASSERT( FOTA_NAND_STATE_VALID == g_FOTA_NAND_MTD_STATE); |
| |
| status = NFB_ProgramPhysicalPage(blk, page, ptr, KAL_TRUE); |
| |
| switch(status) |
| { |
| case ERROR_NFB_BAD_BLOCK: |
| result = ERROR_FGAL_BAD_BLOCK; |
| /* should not happen */ |
| EXT_ASSERT(0, 0, 0, 0); |
| break; |
| case ERROR_NFB_PROGRAM: |
| result = ERROR_FGAL_WRITE_FAILURE; |
| break; |
| default: |
| if(NFBPageSize == status) |
| result = ERROR_FGAL_NONE; |
| else |
| { |
| ASSERT(0); |
| result = ERROR_FGAL_OPERATION_RETRY; |
| } |
| } |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Is_Good_Block_func |
| * |
| * DESCRIPTION |
| * Check whether block is good or bad. |
| ************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NAND_Is_Good_Block_func(kal_uint32 blk) |
| { |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| kal_int32 status = 0; |
| kal_uint8 *byte_ptr = (kal_uint8 *)g_fota_spare_buffer; |
| #if !defined(__NAND_FDM_50__) |
| void *nand_info = (void *)&NANDFlashDriveData; |
| #else /* !__NAND_FDM_50__ */ |
| void *nand_info = (void *)&Flash_Info; |
| #endif |
| |
| ASSERT( FOTA_NAND_STATE_VALID == g_FOTA_NAND_MTD_STATE); |
| |
| status = NFB_ReadPhysicalSpare(blk, 0, g_fota_spare_buffer, KAL_FALSE); |
| if(ERROR_NFB_SUCCESS == status) |
| { |
| if(IsGoodBlock(nand_info, byte_ptr) > 0) |
| { |
| status = NFB_ReadPhysicalSpare(blk, 1, g_fota_spare_buffer, KAL_FALSE); |
| if(ERROR_NFB_SUCCESS == status) |
| { |
| if(IsGoodBlock(nand_info, byte_ptr) > 0) |
| { |
| result = ERROR_FGAL_NONE; |
| } |
| else |
| { |
| result = ERROR_FGAL_BAD_BLOCK; |
| } |
| } |
| } |
| else |
| { |
| result = ERROR_FGAL_BAD_BLOCK; |
| } |
| } |
| else |
| { |
| if(ERROR_NFB_READ == status) |
| result = ERROR_FGAL_READ_FAILURE; |
| else |
| ASSERT(0); |
| } |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Mark_Bad_Block_func |
| * |
| * DESCRIPTION |
| * Read one page from NAND flash |
| *************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NAND_Mark_Bad_Block_func(kal_uint32 blk) |
| { |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| kal_int32 status = 0; |
| kal_uint8 *byte_ptr = (kal_uint8 *)g_fota_spare_buffer; |
| |
| ASSERT( FOTA_NAND_STATE_VALID == g_FOTA_NAND_MTD_STATE); |
| |
| NFB_ErasePhysicalBlock(blk, KAL_TRUE); |
| |
| kal_mem_set(g_fota_spare_buffer, 0xFF, FOTA_MAX_SPARE_SIZE); |
| FOTA_NAND_MTD_Set_Spare_Bad_Mark(byte_ptr); |
| |
| status = NFB_ProgramPhysicalSpare(blk, 0, byte_ptr, KAL_FALSE, KAL_TRUE); |
| if(ERROR_NFB_SUCCESS == status) |
| { |
| status = NFB_ProgramPhysicalSpare(blk, 1, byte_ptr, KAL_FALSE, KAL_TRUE); |
| } |
| |
| switch(status) |
| { |
| case ERROR_NFB_BAD_BLOCK: |
| result = ERROR_FGAL_BAD_BLOCK; |
| /* should not happen */ |
| EXT_ASSERT(0, 0, 0, 0); |
| break; |
| case ERROR_NFB_PROGRAM: |
| result = ERROR_FGAL_WRITE_FAILURE; |
| break; |
| case ERROR_NFB_SUCCESS: |
| result = ERROR_FGAL_NONE; |
| break; |
| default: |
| ASSERT(0); |
| result = ERROR_FGAL_OPERATION_RETRY; |
| } |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Erase_Block_func |
| * |
| * DESCRIPTION |
| * Erase one block on NAND flash |
| *************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NAND_Erase_Block_func(kal_uint32 blk) |
| { |
| kal_uint32 trial = 0; |
| kal_int32 status = -1; |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| |
| ASSERT( FOTA_NAND_STATE_VALID == g_FOTA_NAND_MTD_STATE); |
| |
| for(trial = 0 ; trial < 3 ; trial++) |
| { |
| status = NFB_ErasePhysicalBlock(blk, KAL_TRUE); |
| if(ERROR_NFB_ERASE != status) |
| break; |
| delay32KHzTick(1000); |
| } |
| |
| switch(status) |
| { |
| case ERROR_NFB_BAD_BLOCK: |
| result = ERROR_FGAL_BAD_BLOCK; |
| /* should not happen */ |
| EXT_ASSERT(0, 0, 0, 0); |
| break; |
| case ERROR_NFB_ERASE: |
| result = ERROR_FGAL_ERASE_FAILURE; |
| break; |
| case ERROR_NFB_SUCCESS: |
| result = ERROR_FGAL_NONE; |
| break; |
| default: |
| ASSERT(0); |
| result = ERROR_FGAL_OPERATION_RETRY; |
| } |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Is_Page_Empty_func |
| * |
| * DESCRIPTION |
| * Read one page from NAND flash |
| *************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NAND_Is_Page_Empty_func(kal_uint32 *buff, kal_uint32 blk, kal_uint32 page) |
| { |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| kal_int32 status = ERROR_NFB_READ; |
| kal_int32 status2 = ERROR_NFB_READ; |
| |
| ASSERT( FOTA_NAND_STATE_VALID == g_FOTA_NAND_MTD_STATE); |
| |
| kal_mem_set(g_fota_spare_buffer, 0x0, FOTA_MAX_SPARE_SIZE); |
| kal_mem_set(buff, 0x0, NFBPageSize); |
| |
| status = NFB_ReadPhysicalPage(blk, page, buff); |
| status2 = NFB_ReadPhysicalSpare(blk, page, g_fota_spare_buffer, KAL_FALSE); |
| |
| if( (NFBPageSize == status) && (ERROR_NFB_SUCCESS == status2) ) |
| { |
| status = ERROR_NFB_SUCCESS; |
| } |
| else |
| { |
| status = ERROR_NFB_READ; |
| } |
| |
| switch(status) |
| { |
| case ERROR_NFB_BAD_BLOCK: |
| result = ERROR_FGAL_BAD_BLOCK; |
| /* should not happen */ |
| EXT_ASSERT(0, 0, 0, 0); |
| break; |
| case ERROR_NFB_READ: /* empty page in 28/29 is covered here */ |
| if(!FOTA_NAND_MTD_Check_Page_Empty((kal_uint8 *)buff, (kal_uint8 *)g_fota_spare_buffer)) |
| result = ERROR_FGAL_NON_EMPTY; |
| break; |
| case ERROR_NFB_SUCCESS: |
| if(!FOTA_NAND_MTD_Check_Page_Empty((kal_uint8 *)buff, (kal_uint8 *)g_fota_spare_buffer)) |
| result = ERROR_FGAL_NON_EMPTY_CHECK; |
| break; |
| default: |
| ASSERT(0); |
| result = ERROR_FGAL_OPERATION_RETRY; |
| } |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Lock_Block_func |
| * |
| * DESCRIPTION |
| * Lock one block on NAND flash |
| *************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NAND_Lock_Block_func(kal_uint32 blk, kal_bool locked) |
| { |
| return ERROR_FGAL_NONE; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Block_Size_func |
| * |
| * DESCRIPTION |
| * Erase one block on NAND flash |
| *************************************************************************/ |
| kal_uint32 FOTA_NAND_Block_Size_func(kal_uint32 blk) |
| { |
| kal_uint32 blk_size = 0; |
| #if !defined(__NAND_FDM_50__) |
| flash_info_struct *nand_info = &NANDFlashDriveData.flash_info; |
| |
| if(PAGE_2K == nand_info->page_type) |
| { |
| blk_size = 2048*nand_info->pages_per_block; |
| } |
| else if(PAGE_512 == nand_info->page_type) |
| { |
| blk_size = 512*nand_info->pages_per_block; |
| } |
| else |
| ASSERT(0); /* incorrect configuration */ |
| |
| #else |
| |
| blk_size = Flash_Info.pageSize*Flash_Info.blockPage; |
| |
| #endif |
| |
| return blk_size; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NAND_Block_Index_func |
| * |
| * DESCRIPTION |
| * Erase one block on NAND flash |
| *************************************************************************/ |
| kal_uint32 FOTA_NAND_Block_Index_func(kal_uint32 blk_addr) |
| { |
| kal_uint32 blk_size = 0; |
| #if !defined(__NAND_FDM_50__) |
| flash_info_struct *nand_info = &NANDFlashDriveData.flash_info; |
| |
| if(PAGE_2K == nand_info->page_type) |
| { |
| blk_size = 2048*nand_info->pages_per_block; |
| } |
| else if(PAGE_512 == nand_info->page_type) |
| { |
| blk_size = 512*nand_info->pages_per_block; |
| } |
| else |
| ASSERT(0); /* incorrect configuration */ |
| |
| #else |
| |
| blk_size = Flash_Info.pageSize*Flash_Info.blockPage; |
| |
| #endif |
| |
| ASSERT(blk_size);/* incorrect device configuration */ |
| |
| return blk_addr/blk_size; |
| } |
| |
| #elif defined(__EMMC_BOOTING__) |
| |
| /* For flash generic access layer */ |
| Flash_GAL_st FOTA_eMMC_Fgal; |
| |
| Flash_GAL_st *FOTA_Setup_FGAL(void) |
| { |
| if(FOTA_FGAL_READY == g_FOTA_fgal_state) |
| return &FOTA_eMMC_Fgal; |
| |
| /* set up FGAL */ |
| FOTA_eMMC_Fgal.init_drv = FGAL2FTL_Init; |
| FOTA_eMMC_Fgal.query_info = FGAL2FTL_Query_Info; |
| FOTA_eMMC_Fgal.read_page = FGAL2FTL_Read_Page; |
| FOTA_eMMC_Fgal.write_page = FGAL2FTL_Write_Page; |
| FOTA_eMMC_Fgal.check_block = FGAL2FTL_Is_Good_Block; |
| FOTA_eMMC_Fgal.mark_bad = FGAL2FTL_Mard_Bad_Block; |
| FOTA_eMMC_Fgal.erase_block = FGAL2FTL_Erase_Block; |
| FOTA_eMMC_Fgal.check_empty_page = FGAL2FTL_Is_Empty_Page; |
| FOTA_eMMC_Fgal.block_size = FGAL2FTL_Block_Size; |
| FOTA_eMMC_Fgal.block_index = FGAL2FTL_Block_Index; |
| FOTA_eMMC_Fgal.lock_block = FGAL2FTL_Lock_Block; |
| |
| /* initialize FGAL driver */ |
| FOTA_eMMC_Fgal.init_drv(); |
| |
| g_FOTA_fgal_state = FOTA_FGAL_READY; |
| return &FOTA_eMMC_Fgal; |
| } |
| |
| |
| #else /* !_NAND_FLASH_BOOTING_ */ |
| |
| #include "custom_MemoryDevice.h" |
| #include "DrvFlash.h" |
| #include "reg_base.h" |
| #include "fue_init.h" |
| |
| /* Forward declaration */ |
| _FGAL_ERROR_CODE FOTA_NOR_Init_func(void); |
| _FGAL_ERROR_CODE FOTA_NOR_Page_Read_func(kal_uint32* ptr, kal_uint32 blk, kal_uint32 page); |
| _FGAL_ERROR_CODE FOTA_NOR_Query_Info_func(Logical_Flash_info_st* info); |
| _FGAL_ERROR_CODE FOTA_NOR_Page_Program_func(kal_uint32* ptr, kal_uint32 blk, kal_uint32 page); |
| _FGAL_ERROR_CODE FOTA_NOR_Is_Good_Block_func(kal_uint32 blk); |
| _FGAL_ERROR_CODE FOTA_NOR_Mark_Bad_Block_func(kal_uint32 blk); |
| _FGAL_ERROR_CODE FOTA_NOR_Erase_Block_func(kal_uint32 blk); |
| _FGAL_ERROR_CODE FOTA_NOR_Is_Page_Empty_func(kal_uint32 *buff, kal_uint32 blk, kal_uint32 page); |
| _FGAL_ERROR_CODE FOTA_NOR_Lock_Block_func(kal_uint32 blk, kal_bool locked); |
| kal_uint32 FOTA_NOR_Block_Size_func(kal_uint32 blk); |
| kal_uint32 FOTA_NOR_Block_Index_func(kal_uint32 blk_addr); |
| |
| /* Following functions and variables are located in custom_blconfig.c */ |
| extern kal_uint32 custom_Block_Size(kal_uint32 nor_addr); |
| extern kal_uint32 custom_get_NORFLASH_ROMSpace(void); |
| extern kal_uint32 custom_get_NORFLASH_Base(void); |
| |
| /* |
| * Macro definition |
| */ |
| #define FOTA_NOR_STATE_VALID (0x5644544D) |
| |
| #define FOTA_MAX_SPARE_SIZE (64) |
| |
| /* |
| * Global variable definition |
| */ |
| kal_uint32 g_FOTA_NOR_MTD_STATE; |
| /* |
| * For flash generic access layer |
| */ |
| Flash_GAL_st FOTA_Nor_Fgal; |
| |
| NOR_FLASH_DRV_Data NORFlashDriveData; |
| NOR_Flash_MTD_Data FOTA_nor_mtdflash; |
| |
| |
| /* |
| * External variable reference |
| */ |
| |
| extern NOR_MTD_Driver NORFlashMtd; |
| |
| |
| /***************************************************************** |
| Description : acquire FDM synchronization lock. |
| Input : |
| Output : None |
| ******************************************************************/ |
| void retrieve_FDM_lock(void) |
| { |
| #if defined(__NOR_FDM5__) |
| |
| extern void nFDM_LOCK(void); |
| nFDM_LOCK(); |
| |
| #else |
| |
| extern void FDM_LOCK(void); |
| FDM_LOCK(); |
| |
| #endif |
| } |
| |
| /***************************************************************** |
| Description : relieve FDM synchronization lock. |
| Input : |
| Output : None |
| ******************************************************************/ |
| void release_FDM_lock(void) |
| { |
| #if defined(__NOR_FDM5__) |
| |
| extern void nFDM_UNLOCK(void); |
| nFDM_UNLOCK(); |
| |
| #else |
| |
| extern void FDM_UNLOCK(void); |
| FDM_UNLOCK(); |
| |
| #endif |
| } |
| |
| /***************************************************************** |
| Description : Wait device ready before operation |
| Input : |
| Output : None |
| ******************************************************************/ |
| void FOTA_WaitEraseDone(void) |
| { |
| #if defined(__NOR_FDM5__) |
| |
| return; |
| |
| #else // !__SINGLE_BANK_NOR_FLASH_SUPPORT__ && __NOR_FDM4__ |
| |
| extern NOR_FLASH_DRV_Data FlashDriveData; |
| extern void WaitEraseDone(NOR_FLASH_DRV_Data * D, kal_uint32 frame_tick); |
| //#define INVALID_BLOCK_INDEX 0xFFFFFFFF |
| if( FlashDriveData.ReclaimBlockID != 0xFFFFFFFF ) |
| { |
| WaitEraseDone(&FlashDriveData,70); |
| } |
| #endif |
| } |
| |
| /***************************************************************** |
| Description : set up FGAL structure. |
| Input : |
| Output : None |
| ******************************************************************/ |
| #define FOTA_FGAL_READY (0x59445246) |
| kal_uint32 g_FOTA_fgal_state; |
| extern kal_uint8 RandomNum; |
| |
| Flash_GAL_st *FOTA_Setup_FGAL(void) |
| { |
| |
| if(FOTA_FGAL_READY == g_FOTA_fgal_state) |
| return &FOTA_Nor_Fgal; |
| |
| /* set up FGAL */ |
| FOTA_Nor_Fgal.init_drv = FOTA_NOR_Init_func; |
| FOTA_Nor_Fgal.query_info = FOTA_NOR_Query_Info_func; |
| FOTA_Nor_Fgal.read_page = FOTA_NOR_Page_Read_func; |
| FOTA_Nor_Fgal.write_page = FOTA_NOR_Page_Program_func; |
| FOTA_Nor_Fgal.check_block = FOTA_NOR_Is_Good_Block_func; |
| FOTA_Nor_Fgal.mark_bad = FOTA_NOR_Mark_Bad_Block_func; |
| FOTA_Nor_Fgal.erase_block = FOTA_NOR_Erase_Block_func; |
| FOTA_Nor_Fgal.check_empty_page = FOTA_NOR_Is_Page_Empty_func; |
| FOTA_Nor_Fgal.block_size = FOTA_NOR_Block_Size_func; |
| FOTA_Nor_Fgal.block_index = FOTA_NOR_Block_Index_func; |
| FOTA_Nor_Fgal.lock_block = FOTA_NOR_Lock_Block_func; |
| |
| /* initialize FGAL driver */ |
| FOTA_Nor_Fgal.init_drv(); |
| |
| g_FOTA_fgal_state = FOTA_FGAL_READY; |
| |
| |
| return &FOTA_Nor_Fgal; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Init_func |
| * |
| * DESCRIPTION |
| * Initialze NOR flash MTD driver |
| ************************************************************************/ |
| |
| #if defined(__SERIAL_FLASH__) |
| |
| extern FlashRegionInfo CMEM_FOTA_NORRegionInfo[]; |
| |
| _FGAL_ERROR_CODE FOTA_NOR_Init_func(void) |
| { |
| |
| if( (FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE) && |
| (~((kal_uint32)CMEM_FOTA_NORRegionInfo) == ((NOR_Flash_MTD_Data*)(NORFlashDriveData.MTDData))->Signature) ) |
| return ERROR_FGAL_NONE; |
| |
| g_FOTA_NOR_MTD_STATE = FOTA_NOR_STATE_VALID; |
| |
| /* Initialize MTD data table */ |
| CMEM_Init_FOTA(); |
| |
| /* prepare update package area information */ |
| // RegionInfo must be assigned before invoke FOTA_NOR_Block_Index_func |
| FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_start = FOTA_NOR_Block_Index_func(FOTA_PACKAGE_STORAGE_BASE); |
| FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_end = FOTA_NOR_Block_Index_func(FOTA_PACKAGE_STORAGE_BASE+FOTA_PACKAGE_STORAGE_SIZE)-1; |
| |
| NORFlashDriveData.FlashInfo.baseUnlockBlock = FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_start; |
| NORFlashDriveData.FlashInfo.endUnlockBlock = FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_end; |
| |
| NORFlashDriveData.MTDDriver->MountDevice(NORFlashDriveData.MTDData, (void*)&NORFlashDriveData.FlashInfo); |
| /* prepare update package area information */ |
| //FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_start = FOTA_NOR_Block_Index_func(FOTA_PACKAGE_STORAGE_BASE); |
| //FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_end = FOTA_NOR_Block_Index_func(FOTA_PACKAGE_STORAGE_BASE+FOTA_PACKAGE_STORAGE_SIZE)-1; |
| /* TODO: unlock all blocks reserved for update package */ |
| return ERROR_FGAL_NONE; |
| } |
| |
| #else // !__COMBO_MEMORY_SUPPORT__ && !__SERIAL_FLASH__ |
| _FGAL_ERROR_CODE FOTA_NOR_Init_func(void) |
| { |
| if( (FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE) && |
| (~((kal_uint32)NORRegionInfo) == FOTA_nor_mtdflash.Signature) ) |
| return ERROR_FGAL_NONE; |
| |
| g_FOTA_NOR_MTD_STATE = FOTA_NOR_STATE_VALID; |
| /* Initialize MTD data table */ |
| FOTA_nor_mtdflash.Signature = ~((kal_uint32)NORRegionInfo); |
| |
| NORFlashDriveData.MTDDriver = &NORFlashMtd; |
| NORFlashDriveData.MTDData = &FOTA_nor_mtdflash; |
| |
| #ifdef __MTK_TARGET__ |
| FOTA_nor_mtdflash.BaseAddr = (BYTE *)INT_RetrieveFlashBaseAddr(); |
| #endif /* __MTK_TARGET__ */ |
| |
| FOTA_nor_mtdflash.RegionInfo = (FlashRegionInfo *)NORRegionInfo; |
| /* prepare update package area information */ |
| FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_start = FOTA_NOR_Block_Index_func(FOTA_PACKAGE_STORAGE_BASE); |
| FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_end = FOTA_NOR_Block_Index_func(FOTA_PACKAGE_STORAGE_BASE+FOTA_PACKAGE_STORAGE_SIZE)-1; |
| |
| NORFlashDriveData.FlashInfo.baseUnlockBlock = FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_start; |
| NORFlashDriveData.FlashInfo.endUnlockBlock = FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_end; |
| |
| NORFlashDriveData.MTDDriver->MountDevice(NORFlashDriveData.MTDData, (void*)&NORFlashDriveData.FlashInfo); |
| /* prepare update package area information */ |
| //FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_start = FOTA_NOR_Block_Index_func(FOTA_PACKAGE_STORAGE_BASE); |
| //FOTA_NFB_Area_Info.m_fota_pkg_area.m_pkg_area_end = FOTA_NOR_Block_Index_func(FOTA_PACKAGE_STORAGE_BASE+FOTA_PACKAGE_STORAGE_SIZE)-1; |
| /* TODO: unlock all blocks reserved for update package */ |
| return ERROR_FGAL_NONE; |
| } |
| #endif //__COMBO_MEMORY_SUPPORT__ || __SERIAL_FLASH__ |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Page_Read_func |
| * |
| * DESCRIPTION |
| * Read one page from NOR flash |
| ************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NOR_Page_Read_func(kal_uint32* ptr, kal_uint32 blk, kal_uint32 page) |
| { |
| NOR_Flash_MTD_Data *mtdflash = (NOR_Flash_MTD_Data *)NORFlashDriveData.MTDData; |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| kal_int32 status = 0; |
| kal_uint32 blk_size = 0; |
| kal_uint32 src_addr = 0; |
| |
| ASSERT( FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE); |
| retrieve_FDM_lock(); |
| |
| FOTA_WaitEraseDone(); |
| |
| blk_size = BlockSize(mtdflash, blk); |
| ASSERT(page < (blk_size/FOTA_FLASH_MAX_PAGE_SIZE)); |
| src_addr = (kal_uint32)BlockAddress(mtdflash, blk) + page*FOTA_FLASH_MAX_PAGE_SIZE; |
| kal_mem_cpy(ptr, (void *)src_addr, FOTA_FLASH_MAX_PAGE_SIZE); |
| |
| release_FDM_lock(); |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Query_Info_func |
| * |
| * DESCRIPTION |
| * Query NOR flash device information |
| * The information is specific for flash area reserved for update package |
| ************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NOR_Query_Info_func(Logical_Flash_info_st* info) |
| { |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| #if 0 |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| /* under construction !*/ |
| #else |
| info->Flash_page_size = FOTA_FLASH_MAX_PAGE_SIZE; |
| info->Flash_io_width = 16; |
| #endif |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Page_Program_func |
| * |
| * DESCRIPTION |
| * Write one page to NOR flash |
| ************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NOR_Page_Program_func(kal_uint32* ptr, kal_uint32 blk, kal_uint32 page) |
| { |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| kal_int32 status = 0; |
| kal_uint32 blk_size = 0; |
| kal_uint32 dst_addr = 0; |
| kal_uint32 src_addr = (kal_uint32)ptr; |
| kal_uint32 left_len = FOTA_FLASH_MAX_PAGE_SIZE; |
| kal_uint32 write_len = 0; |
| kal_uint32 pbp_len = 0; |
| NOR_MTD_Driver *mtd_drv = NORFlashDriveData.MTDDriver; |
| NOR_Flash_MTD_Data *mtdflash = (NOR_Flash_MTD_Data *)NORFlashDriveData.MTDData; |
| |
| ASSERT( FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE); |
| blk_size = BlockSize(mtdflash, blk); |
| ASSERT(page < (blk_size/FOTA_FLASH_MAX_PAGE_SIZE)); |
| |
| MapWindow(mtdflash, blk, 0); |
| //mtdflash->CurrAddr = (BYTE *)BlockAddress(mtdflash, blk); |
| |
| dst_addr = (kal_uint32)mtdflash->CurrAddr + page*FOTA_FLASH_MAX_PAGE_SIZE; |
| |
| retrieve_FDM_lock(); |
| |
| FOTA_WaitEraseDone(); |
| |
| |
| |
| if(BUFFER_PROGRAM_ITERATION_LENGTH) |
| { |
| pbp_len = BUFFER_PROGRAM_ITERATION_LENGTH<<1; |
| } |
| else |
| { |
| pbp_len = 2; |
| } |
| |
| while(left_len) |
| { |
| if(left_len > pbp_len) |
| { |
| write_len = pbp_len; |
| } |
| else |
| { |
| write_len = left_len; |
| } |
| |
| status = mtd_drv->ProgramData(mtdflash, (void *)dst_addr, (void *)src_addr, write_len); |
| if(RESULT_FLASH_FAIL == status) |
| { |
| break; |
| } |
| else |
| { |
| left_len -= write_len; |
| dst_addr += write_len; |
| src_addr += write_len; |
| } |
| } |
| |
| |
| release_FDM_lock(); |
| |
| if(RESULT_FLASH_FAIL == status) |
| { |
| result = ERROR_FGAL_WRITE_FAILURE; |
| } |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Is_Good_Block_func |
| * |
| * DESCRIPTION |
| * Check whether block is good or bad. |
| * Always return good since no bad block is allowed in NOR flash |
| ************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NOR_Is_Good_Block_func(kal_uint32 blk) |
| { |
| ASSERT( FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE); |
| |
| return ERROR_FGAL_NONE; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Mark_Bad_Block_func |
| * |
| * DESCRIPTION |
| * mark a block as bad, should not be called on NOR flash |
| *************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NOR_Mark_Bad_Block_func(kal_uint32 blk) |
| { |
| ASSERT( FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE); |
| |
| /* should not happen */ |
| EXT_ASSERT(0, 0, 0, 0); |
| |
| return ERROR_FGAL_OPERATION_RETRY; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Erase_Block_func |
| * |
| * DESCRIPTION |
| * Erase one block on NOR flash |
| *************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NOR_Erase_Block_func(kal_uint32 blk) |
| { |
| kal_uint32 trial = 0; |
| kal_int32 status = -1; |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| NOR_MTD_Driver *mtd_drv = NORFlashDriveData.MTDDriver; |
| NOR_Flash_MTD_Data *mtdflash = (NOR_Flash_MTD_Data *)NORFlashDriveData.MTDData; |
| |
| MapWindow(mtdflash, blk, 0); |
| |
| ASSERT( FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE); |
| retrieve_FDM_lock(); |
| |
| FOTA_WaitEraseDone(); |
| |
| |
| |
| status = mtd_drv->EraseBlock(mtdflash, blk); |
| |
| |
| release_FDM_lock(); |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Is_Page_Empty_func |
| * |
| * DESCRIPTION |
| * Read one page from NOR flash |
| *************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NOR_Is_Page_Empty_func(kal_uint32 *buff, kal_uint32 blk, kal_uint32 page) |
| { |
| kal_uint32 *page_ptr = NULL; |
| kal_uint32 blk_size = 0; |
| kal_uint32 idx = 0; |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| NOR_Flash_MTD_Data *mtdflash = (NOR_Flash_MTD_Data *)NORFlashDriveData.MTDData; |
| |
| ASSERT( FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE); |
| blk_size = BlockSize(mtdflash, blk); |
| ASSERT(page < (blk_size/FOTA_FLASH_MAX_PAGE_SIZE)); |
| |
| mtdflash->CurrAddr = (BYTE *)BlockAddress(mtdflash, blk); |
| page_ptr = (kal_uint32 *)((kal_uint32)mtdflash->CurrAddr + page*FOTA_FLASH_MAX_PAGE_SIZE); |
| |
| retrieve_FDM_lock(); |
| |
| FOTA_WaitEraseDone(); |
| |
| for(idx = 0 ; idx < (FOTA_NOR_FLASH_PAGE_SIZE>>2) ; idx++) |
| { |
| if(*(page_ptr+idx) != INVALID_DWORD) |
| { |
| result = ERROR_FGAL_NON_EMPTY_CHECK; |
| break; |
| } |
| } |
| |
| release_FDM_lock(); |
| |
| if(ERROR_FGAL_NON_EMPTY_CHECK == result) |
| { |
| kal_mem_cpy(buff, page_ptr, FOTA_FLASH_MAX_PAGE_SIZE); |
| } |
| |
| return result; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Lock_Block_func |
| * |
| * DESCRIPTION |
| * Erase one block on NOR flash |
| *************************************************************************/ |
| _FGAL_ERROR_CODE FOTA_NOR_Lock_Block_func(kal_uint32 blk, kal_bool locked) |
| { |
| _FGAL_ERROR_CODE result = ERROR_FGAL_NONE; |
| kal_uint32 blk_addr = 0; |
| kal_uint32 blk_action = 0; |
| NOR_Flash_MTD_Data *mtdflash = (NOR_Flash_MTD_Data *)NORFlashDriveData.MTDData; |
| NOR_MTD_Driver *mtd_drv = NORFlashDriveData.MTDDriver; |
| |
| ASSERT( FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE); |
| blk_addr = (kal_uint32)BlockAddress(mtdflash, blk); |
| if(locked) |
| { |
| blk_action = ACTION_LOCK; |
| } |
| else |
| { |
| blk_action = ACTION_UNLOCK; |
| } |
| |
| retrieve_FDM_lock(); |
| |
| FOTA_WaitEraseDone(); |
| |
| mtd_drv->LockEraseBlkAddr(mtdflash, (void *)blk_addr, blk_action); |
| |
| release_FDM_lock(); |
| return ERROR_FGAL_NONE; |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Block_Size_func |
| * |
| * DESCRIPTION |
| * Erase one block on NAND flash |
| *************************************************************************/ |
| kal_uint32 FOTA_NOR_Block_Size_func(kal_uint32 blk) |
| { |
| NOR_Flash_MTD_Data *mtdflash = (NOR_Flash_MTD_Data *)NORFlashDriveData.MTDData; |
| ASSERT( FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE); |
| |
| return BlockSize((void *)mtdflash, blk); |
| } |
| |
| /************************************************************************* |
| * FUNCTION |
| * FOTA_NOR_Block_Index_func |
| * |
| * DESCRIPTION |
| * Erase one block on NAND flash |
| *************************************************************************/ |
| kal_uint32 FOTA_NOR_Block_Index_func(kal_uint32 blk_addr) |
| { |
| NOR_Flash_MTD_Data *mtdflash = (NOR_Flash_MTD_Data *)NORFlashDriveData.MTDData; |
| ASSERT( FOTA_NOR_STATE_VALID == g_FOTA_NOR_MTD_STATE); |
| |
| return BlockIndex((void *)mtdflash, blk_addr & (~((kal_uint32)mtdflash->BaseAddr))); |
| //return BlockIndex((void *)mtdflash, blk_addr - FOTA_PACKAGE_STORAGE_BASE); |
| } |
| |
| #endif /* NAND_FLASH_BOOTING */ |
| |
| |
| #endif /* __FOTA_DM__ */ |