[Feature][Modem]Update MTK MODEM V1.6 baseline version: MOLY.NR15.R3.MD700.IVT.MP1MR3.MP.V1.6
MTK modem version: MT2735_IVT_MOLY.NR15.R3.MD700.IVT.MP1MR3.MP.V1.6.tar.gz
RF modem version: NA
Change-Id: I45a4c2752fa9d1a618beacd5d40737fb39ab64fb
diff --git a/mcu/driver/drv/src/fota_partial.c b/mcu/driver/drv/src/fota_partial.c
new file mode 100644
index 0000000..c7dd8a8
--- /dev/null
+++ b/mcu/driver/drv/src/fota_partial.c
@@ -0,0 +1,3405 @@
+/*****************************************************************************
+* 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__ */