| |
| /****************************************************************************** |
| * |
| * (C)Copyright 2011 Marvell. All Rights Reserved. |
| * |
| * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL. |
| * The copyright notice above does not evidence any actual or intended |
| * publication of such source code. |
| * This Module contains Proprietary Information of Marvell and should be |
| * treated as Confidential. |
| * The information in this file is provided for the exclusive use of the |
| * licensees of Marvell. |
| * Such users have the right to use, modify, and incorporate this code into |
| * products for purposes authorized by the license agreement provided they |
| * include this notice and the associated copyright notice with any such |
| * product. |
| * The information in this file is provided "AS IS" without warranty. |
| * |
| * |
| * FILENAME: TIMDownload.c |
| * |
| * PURPOSE: Contains BootLoader's TIM based download code. |
| * |
| ******************************************************************************/ |
| |
| |
| ////////////////////////////////////////////////////////////////////// |
| // Library Support for the TIMDownload.c |
| // Include any shared libraries in the TIMDownload.h file to keep this |
| // code clean. |
| ////////////////////////////////////////////////////////////////////// |
| #include "TIMDownload.h" |
| #include "obm2osl.h" |
| #include "fota.h" |
| #include "tim.h" |
| #include "ProtocolManager.h" |
| |
| UINT_T NandID = 0x0; // make sure the nand ID OBM detected is the equals to the nand ID OBM got from SWD |
| UINT_T Reset = 1; |
| UINT_T Flash_size = 0x01000000; // default 16MB |
| extern UINT8_T FlashInitDone; |
| extern FOTA_Info FOTAInfo; |
| |
| extern UINT_T ddr_id_update_with_crc; |
| static INT_T DownloadReadBackCRC = IMAGE_READ_BACK_CRC_DISABLED; |
| static ImageCRCInfo AllImageCRCInfo __attribute__ ((aligned (4))); |
| |
| SkipBlocksInfoStruct *pSkipAddress = NULL; |
| UINT_T All_FF_flag = 0; |
| INT_T AB_DL = 0; //Indicate if AB system download |
| |
| pTIM pTIM_DTIM = NULL; |
| |
| Platform_ID Lookup_ChipID(UINT_T chipID) |
| { |
| Platform_ID ID = PLAT_UNKNOWN; |
| |
| switch (chipID) |
| { |
| //SWD treat below SoCs as 1826 for now |
| case 0x1829: |
| case 0x1901: |
| case 0x1803: |
| case 0x1802: |
| case 0x1806: |
| case 0x1906: |
| case 0x1903: |
| case 0x1826: |
| ID = PLAT_NEZHA3; |
| break; |
| case 0x1822: |
| ID = PLAT_NEZHA2; |
| break; |
| default: |
| break; |
| } |
| |
| return ID; |
| } |
| |
| UINT_T PlatformCheckChipID(Platform_ID chip_ID_num) |
| { |
| UINT_T ChipID_value; |
| Platform_ID ID_num, ID_numV2; |
| |
| ChipID_value = PlatformGetChipID(); |
| |
| if (chip_ID_num == PLAT_UNKNOWN) |
| return 1; |
| |
| ID_num = Lookup_ChipID(ChipID_value & 0xffff); |
| |
| if (ID_num == chip_ID_num) |
| return 0; |
| else |
| return 1; // chip ID check fail |
| } |
| |
| UINT32 PlatformGetPlatId(void) |
| { |
| UINT_T ChipID_value, PlatId; |
| ChipID_value = PlatformGetChipID(); |
| |
| PlatId = ChipID_value & 0xFFFF; |
| |
| if(ChipID_value == 0x1829) |
| PlatId = 0x1828; |
| |
| if(ChipID_value == 0x1802) |
| { |
| if(PlatformCoreIsCR5()) |
| PlatId = 0x531802; //1802S |
| else |
| PlatId = 0x4C531802; //1802SL |
| } |
| |
| |
| return PlatId; |
| } |
| |
| /* return value: 0 : CHIP and OS are both matched, 1: not matched*/ |
| INT PlatformFBFDevCheckChipOS(PDeviceHeader_11 pDevHeader) |
| { |
| UINT32 FFOSTypeInFbf, ChipIDinFbf, FFOSType, ChipIDinDevPara; |
| |
| FFOSTypeInFbf = pDevHeader->DeviceParameters[1]; |
| ChipIDinFbf = pDevHeader->ChipID; |
| |
| //FFOS_Type is not supported yet, old way, only check chip ID |
| if(FFOSTypeInFbf == 0) |
| { |
| return PlatformCheckChipID(ChipIDinFbf); |
| } |
| |
| if(PlatformCoreIsCR5()) |
| FFOSType = RTOS; |
| else |
| FFOSType = OWRT; |
| |
| if(FFOSType != FFOSTypeInFbf){ |
| return 1; //OS doesn't match |
| } |
| |
| /* ChipID mismatch, return */ |
| if(PlatformCheckChipID(ChipIDinFbf)){ |
| return 1; |
| } |
| |
| /* ChipID in FBF of 1826/1826S/1901/1803/1802SL are all PLAT_NEZHA3, |
| * need to check detail in DeviceParameters[0] |
| */ |
| if(ChipIDinFbf == PLAT_NEZHA3) |
| { |
| ChipIDinDevPara = pDevHeader->DeviceParameters[0]; |
| if(ChipIDinDevPara == PlatformGetPlatId()){ |
| return 0; |
| } |
| else{ |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| /* return value: 0: CMOD matched, 1: not matched*/ |
| UINT_T PlatformFBFCheckCMOD(pTIM pTIM_FBF, PDeviceHeader_11 pDevHeader_11) |
| { |
| UINT_T imagenum; |
| INT_T temp_p; |
| TIM FlashTim; |
| pTIM pTIM_H_DL;; |
| pTIM pTIM_H_Flash = &FlashTim; |
| PImageStruct_11 pImage_11 = NULL; |
| pCMOD_INFO pCmodDlTim, pCmodFlashTim; |
| UINT_T Retval = NoError; |
| pWTP_RESERVED_AREA_HEADER pWRAH = NULL; |
| INT NoDLTimCMOD = 0; |
| INT NoDLTIM = 0; |
| INT i; |
| UCHAR *TempBuffer = 0; |
| |
| TempBuffer = malloc(0x4000); |
| |
| if(TempBuffer == NULL) |
| return HeapExhaustedError; |
| |
| pTIM_H_DL = pTIM_FBF; |
| |
| ReadFlash(0, TempBuffer, 0x4000, BOOT_FLASH); //Read TIM in flash, max tim is 16KB for all platforms |
| |
| SetTIMPointers((UINT8_T *)TempBuffer, pTIM_H_Flash); |
| |
| if(pTIM_H_DL->pConsTIM->VersionBind.Identifier != TIMIDENTIFIER){ |
| //obm_printf("Warning: No valid TIM in FBF\n\r"); |
| NoDLTIM = 1; |
| } |
| |
| if(NoDLTIM == 0) { |
| pWRAH = FindPackageInReserved(&Retval, pTIM_H_DL, CMODID); |
| if ((pWRAH == NULL) || (Retval != NoError)) |
| { |
| //obm_printf("No CMODID in DL TIM\n\r"); |
| NoDLTimCMOD = 1; |
| } |
| else |
| { |
| pCmodDlTim = (pCMOD_INFO) pWRAH; |
| } |
| } else { |
| NoDLTimCMOD == 1; |
| } |
| |
| /* If CMOD is "ASRCMODFORCEERASE", only erase all only is allowed */ |
| if( (NoDLTimCMOD == 0) && |
| (pCmodDlTim->Length == 17) && |
| (memcmp(pCmodDlTim->CMOD, "ASRCMODFORCEERASE", 17) == 0)) |
| { |
| free(TempBuffer); |
| if(pDevHeader_11->FlashOpt.EraseAll == 2){ |
| obm_printf("Magic CMOD to force erase\n\r"); |
| return 0; |
| }else{ |
| return 1; |
| } |
| } |
| |
| if(pTIM_H_Flash->pConsTIM->VersionBind.Identifier != TIMIDENTIFIER){ |
| //obm_printf("No valid Flash TIM\n\r"); |
| free(TempBuffer); |
| return 0; //Allow to burn any version to an empty board except CMOD is ASRCMODFORCEERASE |
| } |
| |
| pWRAH = FindPackageInReserved(&Retval, pTIM_H_Flash, CMODID); |
| if ((pWRAH == NULL) || (Retval != NoError)) |
| { |
| //obm_printf("No CMOD in In Flash TIM\n\r"); |
| free(TempBuffer); |
| return 0; |
| } |
| else |
| { |
| if(NoDLTimCMOD == 1 || NoDLTIM == 1){ |
| //obm_printf("Flash TIM has CMOD, No DL TIM or No CMOD in DL TIM\n\r"); |
| free(TempBuffer); |
| return 1; |
| } |
| pCmodFlashTim = (pCMOD_INFO) pWRAH; |
| } |
| |
| obm_printf("CMOD in DL TIM: "); |
| for(i =0; i < pCmodDlTim->Length; i++) |
| obm_printf("%c", pCmodDlTim->CMOD[i]); |
| obm_printf("\n\r"); |
| |
| obm_printf("CMOD in In Flash TIM:"); |
| for(i =0; i < pCmodFlashTim->Length; i++) |
| obm_printf("%c", pCmodFlashTim->CMOD[i]); |
| obm_printf("\n\r"); |
| |
| free(TempBuffer); |
| |
| if(pCmodDlTim->Length != pCmodFlashTim->Length) |
| return 1; |
| |
| if(memcmp(pCmodDlTim->CMOD, pCmodFlashTim->CMOD, pCmodFlashTim->Length) == 0) |
| return 0; |
| else |
| return 1; |
| } |
| |
| UINT32 PlatformFBFCheckDownload(pTIM pTIM_FBF, PDeviceHeader_11 pDevHeader_11) |
| { |
| UINT32 Retval = NoError; |
| |
| if(PlatformFBFCheckCMOD(pTIM_FBF, pDevHeader_11)) |
| Retval = CMODMISMATCH; |
| |
| if(PlatformFBFDevCheckChipOS(pDevHeader_11)) |
| Retval = CHIPIDMISMATCH; |
| |
| if(Retval != NoError) |
| { |
| ASRFlag_DLStatus_Update(pTIM_FBF, 0, 0); |
| |
| FatalError(Retval, "PFCD", NULL); |
| } |
| |
| return Retval; |
| } |
| |
| UINT32 PlatformFBFCheckSWDVersion(PDeviceHeader_11 pDevHeader_11) |
| { |
| UINT_T LegacySWDNotSupported = 0; |
| UINT32 SWDVerInFBF = pDevHeader_11->DeviceParameters[3]; |
| |
| #if defined(CONFIG_AB_SYSTEM) || (ENABLE_ATRB) |
| /* legacy SWD is the one older than 4.9.1.9 |
| * which doesn't support SWD version in FBF |
| */ |
| LegacySWDNotSupported = 1; |
| #endif |
| |
| if(LegacySWDNotSupported && (SWDVerInFBF == 0)) |
| { |
| goto swd_out_of_date; |
| } |
| |
| if (SWDVerInFBF != 0) |
| { |
| obm_printf("SWDownloader used: %s\n\r", HexToSwdObmVersion(SWDVerInFBF)); |
| |
| if(SWDVerInFBF < SWD_VERSION) { |
| goto swd_out_of_date; |
| } |
| } |
| |
| return NoError; |
| |
| swd_out_of_date: |
| obm_printf("SWDownloader is out of date\n\r"); |
| obm_printf("Please upgrade to %s\n\r", HexToSwdObmVersion(SWD_VERSION)); |
| return SWD_OUTOFDATE; |
| } |
| |
| #if ENABLE_ATRB |
| /* For Downloading, only check major version anti-rollback */ |
| UINT_T TIMDownloadAntiRollbackCheck(pTIM pTIM_h) |
| { |
| UINT_T Retval = NoError; |
| UINT_T MajorVersionInTIM = 0; |
| UINT_T AntiRollbackTimEnabled; |
| UINT_T AntiRollbackFuseEnabled; |
| INT_T AntiRollbackFuseVersion; |
| |
| AntiRollbackTimEnabled = CheckAntiRollbackPackage(pTIM_h, &MajorVersionInTIM); |
| AntiRollbackTimEnabled &= MAJOR_ATRB_ENABLED; |
| |
| AntiRollbackFuseEnabled = GEU_MajorAntiRollBackEnabled(); |
| if(AntiRollbackFuseEnabled) |
| { |
| /* The chip is already burned to enable anti-rollback */ |
| AntiRollbackFuseVersion = GEU_ReadMajorVersion(); |
| if(AntiRollbackTimEnabled == 0 || MajorVersionInTIM < AntiRollbackFuseVersion) |
| { |
| obm_printf("Anti-rollback error: %d %d %d\n\r", AntiRollbackTimEnabled, |
| MajorVersionInTIM, AntiRollbackFuseVersion); |
| FatalError(ATRB_MajorRollbackError, "ATRB", 1); |
| return ATRB_MajorRollbackError; |
| } |
| |
| if(MajorVersionInTIM > AntiRollbackFuseVersion) |
| { |
| Retval = GEU_ProgramMajorVersion(pTIM_h); |
| if(Retval != NoError) |
| FatalError(Retval, "ATRB", 2); |
| } |
| return Retval; |
| } |
| |
| /* The chip is not already burned to enable anti-rollback, burn it here */ |
| if(AntiRollbackTimEnabled) |
| { |
| Retval = GEU_ProgramMajorVersion(pTIM_h); |
| if(Retval != NoError) |
| FatalError(Retval, "ATRB", 3); |
| obm_printf("ATRB: burn major version as %d\n\r", MajorVersionInTIM); |
| } |
| |
| return Retval; |
| } |
| #endif |
| |
| INT_T IsDLImageDTIM(PImageStruct_11 pImage_11) |
| { |
| #if BURN_DTIM_LAST |
| if (((pImage_11->Image_ID & 0xFFFFFF00) == TIM_TYPE)) |
| { |
| switch(pImage_11->Image_In_TIM) { |
| case 0: /* NTIM */ |
| case 1: /* TIMH */ |
| case 5: /* TIMH recovery */ |
| return 0; |
| default: /* differnet DTIMs */ |
| return 1; |
| } |
| } |
| |
| #if defined(CONFIG_ASR_SDTIM) && OUM4DFOTA |
| /* If SDTIM is enabled and OUM is used, |
| * OUM locates in first 10 blocks and has a SDTIM ahead. |
| * Then OUM also needs to be burned after TIMH/OBMI |
| */ |
| if (pImage_11->Image_ID == OUMIDENTIFIER) |
| return 1; |
| #endif |
| |
| #endif |
| |
| return 0; |
| } |
| |
| static pDtimDlInfo_t DtimDLInfo[MAX_DL_DTIM_NUM]; |
| static INT_T DtimDLNums = 0; |
| |
| VOID SaveDTIMs2Memory(PImageStruct_11 pImage_11, UINT_T FbfLoadAddr) |
| { |
| pDtimDlInfo_t pDtimDLInfo = NULL; |
| |
| pDtimDLInfo = malloc(sizeof(DtimDlInfo_t) + pImage_11->length); |
| if(pDtimDLInfo == NULL) |
| FatalError(HeapExhaustedError, NULL, NULL); |
| |
| pDtimDLInfo->Image_ID = pImage_11->Image_ID; |
| pDtimDLInfo->Length = pImage_11->length; |
| pDtimDLInfo->FlashOffsetA = pImage_11->Flash_Start_Address; |
| pDtimDLInfo->FlashOffsetB = pImage_11->Flash_Start_Address_B; |
| |
| memcpy(pDtimDLInfo->Buffer, FbfLoadAddr+(pImage_11->First_Sector<<12), pImage_11->length); |
| |
| DtimDLInfo[DtimDLNums] = pDtimDLInfo; |
| DtimDLNums ++; |
| |
| if (DtimDLNums == MAX_DL_DTIM_NUM) |
| FatalError(TooMuchDlDTims, NULL, NULL); |
| } |
| |
| VOID BurnDTIMs2Flash(VOID) |
| { |
| INT_T i; |
| UINT_T Retval = NoError; |
| pDtimDlInfo_t pDtimDLInfo = NULL; |
| |
| if (DtimDLNums == 0) |
| return; |
| |
| for (i = 0; i < DtimDLNums; i ++) |
| { |
| pDtimDLInfo = DtimDLInfo[i]; |
| Retval = WriteFlash(pDtimDLInfo->FlashOffsetA, pDtimDLInfo->Buffer, pDtimDLInfo->Length, BOOT_FLASH); |
| if(Retval == NoError && pDtimDLInfo->FlashOffsetB != 0xFFFFFFFF) { |
| Retval = WriteFlash(pDtimDLInfo->FlashOffsetB, pDtimDLInfo->Buffer, pDtimDLInfo->Length, BOOT_FLASH); |
| } |
| if(Retval) |
| obm_printf("Write %s fails\n\r", ImageID2String(pDtimDLInfo->Image_ID)); |
| free(pDtimDLInfo); |
| } |
| } |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This is the entry point for the TIM based download functionality. |
| // |
| // Inputs: Pointer to the TIM we just downloaded. |
| // Outputs: Returns the next image (OBM) that we will transfer the control to. |
| // |
| // It mainly functions as following: |
| // 1) Sets the TIM pointers. |
| // 2) Validates the downloaded TIM. |
| // 3) Configures the Flashes. |
| // 4) Wipes the whole Flash device. |
| // 5) Checks if there is already a FBBT on the Flash. If there is |
| // NO FBBT on the Flash, creates it. |
| // 6) Checks if there is a PT being downloaded. If so, it first |
| // tries to validate it with the existing HW partitions on the |
| // Flash. If they don't match, re-creates the HW partitions. |
| // If HW partitions are not supported, these functions will do |
| // nothing and return. Next, the downloaded PT is loaded into |
| // Flash Management (FM). |
| // 7) Runtime-BBT is generated. |
| // 8) Writes the downloaded TIM, created FBBT, PT to Flash. |
| // 9) Download TIM Images LOOP implements the following: |
| // i. Download Image |
| // ii. Validate Image |
| // iii. Set Partition |
| // iv. Erase Image Area from Flash |
| // v. Write the image to Flash |
| // vi. Verify the Flash write |
| // 10) The RBBT is written to the Flash. |
| ////////////////////////////////////////////////////////////////////// |
| pIMAGE_INFO_3_4_0 TIMDownloadMain(pFUSE_SET pFuses, pTIM pTIM_h) |
| { |
| pIMAGE_INFO_3_4_0 pImageInfo = NULL; |
| UINT_T Retval = NoError; |
| UINT8_T FlashNumber = 0; |
| pWTP_RESERVED_AREA_HEADER pWRAH = NULL; |
| pImage_CRC_Check crcCheck; |
| |
| // setup the TIM pointers in pTIM_h |
| Retval = LoadTim((UINT8_T*)pTIM_h->pConsTIM, pTIM_h, TRUE); |
| if (Retval != NoError) |
| { |
| FatalError(Retval, "TDM", 1); |
| } |
| |
| #if ENABLE_ATRB |
| Retval = TIMDownloadAntiRollbackCheck(pTIM_h); |
| if (Retval != NoError) |
| { |
| FatalError(Retval, "TDM", 2); |
| } |
| #endif |
| |
| Retval = PlatformInitFlash(pTIM_h); |
| if( Retval != NoError) |
| FatalError(Retval, "TDM", 3); |
| |
| |
| #if IMG_RBC |
| pWRAH = FindPackageInReserved(&Retval, pTIM_h, CRCS); |
| if ((pWRAH == NULL) || (Retval != NoError)) |
| { |
| DownloadReadBackCRC = IMAGE_READ_BACK_CRC_DISABLED; |
| } |
| else |
| { |
| crcCheck = (pImage_CRC_Check) pWRAH; |
| if(crcCheck->Enabled) |
| DownloadReadBackCRC = IMAGE_READ_BACK_CRC_ENABLED; |
| else |
| DownloadReadBackCRC = IMAGE_READ_BACK_CRC_DISABLED; |
| } |
| |
| if(IMAGE_READ_BACK_CRC_ENABLED == DownloadReadBackCRC) |
| obm_printf("Image RB/CRC Enabled\n\r"); |
| else |
| obm_printf("Image RB/CRC disabled\n\r"); |
| #endif |
| |
| ASRFlag_DLStatus_Update(pTIM_h, DLFLG, 0); |
| |
| obm_printf("Download...\n\r"); |
| |
| // At this point, we can start downloading images one by one. |
| // IMPORTANT: For now, we download all the images to their load address that is |
| // specified in the TIM. We assume that the images will not overwrite the existing |
| // DKB code that is already running. |
| // |
| // KDA TO DO: |
| // Potentially, we might want to download all the images to a specific |
| // DOWNLOAD_AREAD in the DDR. |
| pImageInfo = DownloadTIMImages(pFuses, pTIM_h); |
| |
| return pImageInfo; |
| } |
| |
| UINT_T ValidateTIMInFBF(UINT_T address, PImageStruct_11 pTIM_Image, TIMIncluded_Type type, UINT_T verify_aux) |
| { |
| pTIM pTIM_h = NULL; |
| #if TRUSTED && SECURE_DOWNLOAD |
| pTIM pTIM_h_boot = NULL; |
| #endif |
| UINT_T Retval = NoError; |
| |
| if (type == TIMH_NOTINC) |
| return NoError; |
| else |
| pTIM_h = (pTIM_DTIM + type); |
| |
| Retval = SetTIMPointers((UINT8_T *)(address + (pTIM_Image->First_Sector << 12)), pTIM_h); |
| if (Retval != NoError) |
| return 1; |
| |
| #if TRUSTED && SECURE_DOWNLOAD |
| if (verify_aux) { |
| switch(type) { |
| case DTIM_PRIMARY_INC: |
| case DTIM_RECOVERY_INC: |
| pTIM_h_boot = GetBootTIMH(); |
| if (pTIM_h_boot == NULL) |
| return 4; |
| Retval = ValiateDTIM(pTIM_h, pTIM_h_boot); |
| if (Retval!= NoError) |
| return 5; |
| return NoError; |
| break; |
| case TIMH_RECOVERY_INC: |
| case TIMH_INC: |
| Retval = VerifyPlatformKey(pTIM_h); |
| if (Retval != NoError) |
| return 3; |
| break; |
| default: |
| break; |
| } |
| } |
| #endif |
| |
| if (pTIM_h->pConsTIM->VersionBind.Trusted) |
| { |
| Retval = ValidateTIMSignature(pTIM_h); // validate TIMH |
| if (Retval != NoError) |
| return 2; |
| } |
| |
| return Retval; |
| } |
| |
| UINT_T ValidateImageInTIM(UINT_T address, PImageStruct_11 pImage, pTIM pTIM_h) |
| { |
| UINT_T Retval = NoError; |
| UINT_T ImageAddr; |
| #ifdef CONFIG_ASR_SDTIM |
| pIMAGE_INFO_3_4_0 pSDtimImageInfo = NULL; |
| pTIM pSDTim_h = NULL; |
| #endif |
| pIMAGE_INFO_3_4_0 pImageInfo = NULL; |
| pTIM pTIM_V = NULL; |
| UINT8_T *ImageBuff = NULL; |
| UINT_T ImageType; |
| UINT_T DecompressLen = 0; |
| |
| #if XZ_SUPPORT || XZDEC_SUPPORT |
| VOID *nextInBuf = NULL; |
| INT_T compressed = 0; |
| #endif |
| |
| |
| if ((pTIM_h != NULL) && (pImage->Image_In_TIM != TIMH_NOTINC)) |
| { |
| if ((pImage->Image_ID & 0xFFFFFF00) != TIM_TYPE) // this is not TIMx in FBF file |
| { |
| if (pTIM_h->pConsTIM->VersionBind.Trusted) |
| { |
| ImageAddr = address + (pImage->First_Sector << 12); |
| #ifdef CONFIG_ASR_SDTIM |
| pImageInfo = FindImageInTIM(pTIM_h, pImage->Image_ID); |
| if(pImageInfo == NULL) |
| return Retval; |
| |
| if(ImageIsSDTIMIncluded(pImageInfo)) { |
| pSDTim_h = malloc(sizeof(TIM)); |
| if(pSDTim_h == NULL) |
| return HeapExhaustedError; |
| |
| Retval = SetTIMPointers(ImageAddr, pSDTim_h); |
| if(Retval) |
| return TIMNotFound; |
| |
| pSDtimImageInfo = FindImageInTIM(pSDTim_h, SDTIM); |
| if(pSDtimImageInfo == NULL) { |
| free(pSDTim_h); |
| return Retval; |
| } |
| |
| if (0 == GetSDTimSecureConfig(pSDtimImageInfo)) |
| goto exit; |
| ImageAddr += GetSDTimSpaceSize(pSDtimImageInfo); |
| pTIM_V = pSDTim_h; |
| |
| } else |
| #endif |
| { |
| pTIM_V = pTIM_h; |
| } |
| |
| #if LZMA_SUPPORT |
| ImageType = IMAGE_TYPE(pImage->commands); |
| if (DLCMD_IMG_LZMA_IMAGE_TYPE == ImageType) { |
| pImageInfo = FindImageInTIM(pTIM_V, pImage->Image_ID); |
| if (pImageInfo == NULL) |
| { |
| Retval = ImageNotFound; |
| goto exit; |
| } |
| DecompressLen = pImageInfo->ImageSizeToHash; |
| ImageBuff = malloc(DecompressLen); |
| if(ImageBuff == NULL) { |
| Retval = HeapExhaustedError; |
| goto exit; |
| } |
| Retval = LZMA_Decompress(ImageBuff, |
| &DecompressLen, |
| ImageAddr, |
| pImage->length, |
| 0x0); |
| if(Retval != NoError) { |
| obm_printf("LZMA Decompress error\n\r"); |
| goto exit; |
| } |
| ImageAddr = ImageBuff; |
| } |
| #endif |
| |
| #if XZ_SUPPORT || XZDEC_SUPPORT |
| ImageType = IMAGE_TYPE(pImage->commands); |
| if (DLCMD_IMG_MXZ_IMAGE_TYPE == ImageType) { |
| pImageInfo = FindImageInTIM(pTIM_V, pImage->Image_ID); |
| if (pImageInfo == NULL) |
| { |
| Retval = ImageNotFound; |
| goto exit; |
| } |
| ImageBuff = malloc(pImageInfo->ImageSizeToHash); |
| if(ImageBuff == NULL) { |
| Retval = HeapExhaustedError; |
| goto exit; |
| } |
| DecompressLen = pImageInfo->ImageSizeToHash; |
| Retval = xz_decompress(ImageAddr, pImage->length, ImageBuff, &DecompressLen, &nextInBuf, &compressed); |
| if(Retval) { |
| Retval = XZDecodeError; |
| goto exit; |
| } |
| ImageAddr = ImageBuff; |
| } |
| #endif |
| |
| Retval = ValidateImage(ImageAddr, pImage->Image_ID, pTIM_V); |
| if (Retval != NoError) |
| FatalError(Retval, "VIIT", NULL); |
| |
| return Retval; |
| } |
| } |
| } |
| |
| exit: |
| |
| #ifdef CONFIG_ASR_SDTIM |
| if(pSDTim_h) free(pSDTim_h); |
| #endif |
| |
| return Retval; |
| } |
| |
| UINT_T DLEraseFlashToBurnImage(PImageStruct_11 pImage_11) |
| { |
| UINT_T Retval = NoError; |
| P_FOTA_Info pFOTAInfo = &FOTAInfo; |
| |
| #if MMC_CODE |
| if (((pImage_11->commands & 0xF) == 2) || //erase only for eMMC, NAND needs to erase before writing |
| (pImage_11->Flash_erase_size > pImage_11->length) // erase eMMC if user set erase size in blf |
| ) |
| #endif |
| { |
| Retval = EraseFlash(pImage_11->Flash_Start_Address, pImage_11->Flash_erase_size, BOOT_FLASH ); |
| if(AB_DL && (pImage_11->Flash_Start_Address_B != 0xFFFFFFFF)) |
| Retval |= EraseFlash(pImage_11->Flash_Start_Address_B, pImage_11->Flash_erase_size, BOOT_FLASH ); |
| } |
| |
| if(Retval != NoError ) |
| FatalError(Retval, "DLEF", NULL); |
| |
| if(pFOTAInfo->FOTA_Addr >= pImage_11->Flash_Start_Address && |
| (pFOTAInfo->FOTA_Addr+sizeof(FOTA_Firmware)) <= (pImage_11->Flash_Start_Address+pImage_11->Flash_erase_size)) |
| { |
| //Force ASR flag re-init later. |
| pFOTAInfo->InitFlag = 0; |
| } |
| |
| if(AB_DL && (pFOTAInfo->FOTA_Addr >= pImage_11->Flash_Start_Address_B) && |
| (pFOTAInfo->FOTA_Addr+sizeof(FOTA_Firmware)) <= (pImage_11->Flash_Start_Address_B+pImage_11->Flash_erase_size)) |
| { |
| //Force ASR flag re-init later. |
| pFOTAInfo->InitFlag = 0; |
| } |
| |
| return Retval; |
| } |
| |
| UINT_T DLBurnImageToFlash(PImageStruct_11 pImage_11, UINT_T loadAddr) |
| { |
| UINT_T Retval = NoError; |
| UINT_T imageType = DLCMD_RAW_BINARY_IMAGE_TYPE; |
| #if NZAS |
| P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH); |
| UINT_T Temp1 = 0, Temp2 = 0, Len1, Len2; |
| #endif |
| |
| #if DUAL_TIM |
| UINT8_T *TmpBuf = NULL; |
| pIMAGE_INFO_3_4_0 pTimInfo = NULL; |
| pIMAGE_INFO_3_4_0 pObmInfo = NULL; |
| UINT_T TimOBMLen = 0; |
| pTIM pTIM_h; |
| #endif |
| |
| imageType = IMAGE_TYPE(pImage_11->commands); |
| #if NAND_CODE |
| if ( imageType == DLCMD_YAFFS_IMAGE_TYPE) |
| { |
| SetUseSpareArea( TRUE, BOOT_FLASH ); |
| All_FF_flag = 1; |
| } |
| else if(imageType == DLCMD_UBIFS_IMAGE_TYPE) |
| { |
| SetUseSpareArea( FALSE, BOOT_FLASH); |
| All_FF_flag = 1; |
| } |
| else |
| { |
| SetUseSpareArea( FALSE, BOOT_FLASH ); |
| All_FF_flag = 0; |
| } |
| #endif |
| |
| #if MMC_CODE |
| if (imageType == DLCMD_SPARSE_IMAGE_TYPE) |
| { |
| Retval = HandleSparseImage(loadAddr+(pImage_11->First_Sector<<12), |
| pImage_11->Flash_Start_Address, |
| pImage_11->length, |
| BOOT_FLASH); |
| } |
| else |
| #endif |
| { /* not MMC_CODE */ |
| #if NZAC |
| //To workaroud the issue that 1802SL BootROM miss a word when OBM size is bigger than 0x1df88 in SPI-NOR |
| if(PlatformIsNezhac() && (pImage_11->Image_ID == OBMIDENTIFIER) && (pFlashP->FlashType == SPI_FLASH) |
| && (pImage_11->length > 0x1df88)) |
| { |
| Temp1 = loadAddr+(pImage_11->First_Sector<<12); |
| Temp2 = malloc(256*1024); |
| if(Temp2 == NULL) |
| return HeapExhaustedError; |
| Len1 = Len2 = pImage_11->length; |
| while(Len1) |
| { |
| memcpy((void *)Temp2, (void *)Temp1, 0x1df88); |
| Temp1 += 0x1df88; |
| Temp2 += 0x1df88; |
| *(UINT_T *)Temp2 = 0xdeadbeef;//This word will not be read by BootROM |
| Temp2 += 4; |
| Len2 += 4; |
| Len1 -= 0x1df88; |
| if(Len1 <= 0x1df88){ |
| memcpy((void *)Temp2, (void *)Temp1, Len1); |
| break; |
| } |
| } |
| Retval = WriteFlash( pImage_11->Flash_Start_Address, |
| Temp2, |
| Len2, BOOT_FLASH ); |
| free(Temp2); |
| goto read_back_check; |
| } |
| #endif /* NZAS */ |
| |
| #if DUAL_TIM |
| if((pImage_11->Image_ID == OBMIDENTIFIER) && DualTimEnabled() && !DualTimIsEqual()) |
| { |
| pTIM_h = pTIM_DTIM + TIMH_INC; /* main TIMH */ |
| if(pTIM_h->pConsTIM->VersionBind.Identifier != TIMIDENTIFIER) |
| FatalError(TIMNotFound, "DLB", 1); |
| pTimInfo = FindImageInTIM(pTIM_h, TIMIDENTIFIER); |
| pObmInfo = FindImageInTIM(pTIM_h, OBMIDENTIFIER); |
| if(pTimInfo == NULL || pObmInfo == NULL) |
| FatalError(ImageNotFound, "DLB", 2); |
| TimOBMLen = pImage_11->length + pTimInfo->ImageSize; |
| #if MMC_CODE |
| if(TimOBMLen > MAX_OBM_SIZE) |
| #else |
| if(TimOBMLen > GetFlashProperties(BOOT_FLASH)->BlockSize) |
| #endif |
| obm_printf("Warning :OBM may be too big for Dual-TIM\n\r"); |
| |
| TmpBuf = malloc(TimOBMLen); |
| if(TmpBuf == NULL) |
| return HeapExhaustedError; |
| |
| memset(TmpBuf, 0, TimOBMLen); |
| memcpy(TmpBuf, loadAddr+(pImage_11->First_Sector<<12), pImage_11->length); |
| #if MMC_CODE |
| if (pImage_11->Flash_partition == MMC_SD_BOOT_PARTITION) { |
| #else |
| if (pObmInfo->FlashEntryAddr == pImage_11->Flash_Start_Address) { |
| #endif |
| pTIM_h = pTIM_DTIM + TIMH_RECOVERY_INC; |
| memcpy(TmpBuf+pImage_11->length, pTIM_h->pConsTIM, pTimInfo->ImageSize); |
| } |
| else { |
| memcpy(TmpBuf+pImage_11->length, pTIM_h->pConsTIM, pTimInfo->ImageSize); |
| } |
| Retval = WriteFlash( pImage_11->Flash_Start_Address, |
| TmpBuf, |
| TimOBMLen, BOOT_FLASH); |
| free(TmpBuf); |
| } else if(pImage_11->Image_ID == TIMIDENTIFIER && |
| pImage_11->Image_In_TIM == TIMH_RECOVERY_INC && |
| DualTimIsEqual()) |
| { |
| pTIM_h = pTIM_DTIM + TIMH_INC; /* main TIMH */ |
| Retval = WriteFlash( pImage_11->Flash_Start_Address, |
| pTIM_h->pConsTIM, |
| pImage_11->length, BOOT_FLASH); |
| }else |
| #endif |
| { |
| Retval = WriteFlash( pImage_11->Flash_Start_Address, |
| loadAddr+(pImage_11->First_Sector<<12), |
| pImage_11->length, BOOT_FLASH); |
| |
| |
| if(AB_DL && (pImage_11->Flash_Start_Address_B != 0xFFFFFFFF)) { |
| Retval |= WriteFlash( pImage_11->Flash_Start_Address_B, |
| loadAddr+(pImage_11->First_Sector<<12), |
| pImage_11->length, BOOT_FLASH); |
| } |
| } |
| |
| read_back_check: |
| #if IMG_RBC |
| if(Retval == NoError && DownloadReadBackCRC == IMAGE_READ_BACK_CRC_ENABLED) |
| { |
| Retval = ImageReadBackAndCRC(pImage_11); |
| } |
| #else |
| ; //do nothing, avoid "label at end of compound statement" error |
| #endif |
| } /* not MMC_CODE */ |
| |
| return Retval; |
| } |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This is the actual image downloading function for the TIM based |
| // download mode. |
| // |
| // Inputs: TIM which includes a list of all the images that will be |
| // downloaded. |
| // Outputs: Returns the OBM image to whom we will trasfer control to. |
| // |
| // It mainly iterates through all the images listed in the TIM and |
| // 1) If NOT TIM, downloads the image. |
| // 2) Validates the image. |
| // 3) Calls the Erase and Write function for this image. |
| // 4) Finally, finds the OBM image in the TIM and returns it. |
| ////////////////////////////////////////////////////////////////////// |
| pIMAGE_INFO_3_4_0 DownloadTIMImages (pFUSE_SET pFuses, pTIM pTIM_h) |
| { |
| UINT_T Retval = NoError; |
| UINT_T ImageSize; |
| pIMAGE_INFO_3_4_0 pImageInfo = NULL, pNextImageInfo = NULL; |
| UINT_T NumImages; |
| UINT_T loadAddr = 0; |
| UINT_T OKtoErase = 1; |
| MasterBlockHeader* pMasterHeader = NULL; |
| PDeviceHeader_11 pDevHeader_11=NULL; |
| PImageStruct_11 pImage_11 = NULL; |
| UINT_T imagenum, i, skip_blocks; |
| UINT_T temp_p = NULL; |
| UINT_T NandID_Right; |
| UINT_T OBMFlashAddr; |
| P_FOTA_Info pFOTAInfo = &FOTAInfo; |
| INT_T TIMHLoaded = 0; |
| CHAR MVersionStr[128]; |
| CHAR *PStr = NULL; |
| INT_T MVersionInFbf = 0; |
| P_FOTA_Firmware pFOTA_T = NULL; |
| |
| // Depending on the version of the TIM, determine the size of each image in bytes. |
| // We will use this size to iterate through the TIM binary from image to image. |
| if (pTIM_h->pConsTIM->VersionBind.Version >= TIM_3_4_00) |
| ImageSize = sizeof(IMAGE_INFO_3_4_0); |
| else |
| ImageSize = sizeof(IMAGE_INFO_3_2_0); |
| |
| // This is the very initial TIM image! Assumes that the TIM image is located at the top of the |
| // TIM file. Otherwise, we would skip images. |
| NumImages = pTIM_h->pConsTIM->NumImages; |
| pImageInfo = (IMAGE_INFO_3_4_0*)((unsigned char*)pTIM_h->pImg + (NumImages-1)*ImageSize); // index to last image info record. |
| |
| // For each image, download, validate and copy |
| while (NumImages && (Retval == NoError)) |
| { |
| if (NumImages > 1) |
| { |
| loadAddr = malloc(pImageInfo->ImageSize + 0x20000); |
| if(loadAddr == 0) |
| return HeapExhaustedError; |
| Retval = PM_ReceiveImage(NULL, loadAddr, pImageInfo->ImageSize, pImageInfo->ImageID); |
| if(Retval == UnknownImageError) |
| { |
| Retval = NoError; |
| goto nextimage; |
| } |
| if (Retval != NoError) |
| FatalError(Retval, "DTI", 1); |
| } |
| else loadAddr = (UINT_T)(pTIM_h->pConsTIM); // first image, TIM. use the address provided by caller. |
| |
| #if COPYIMAGESTOFLASH |
| if(pImageInfo->FlashEntryAddr == 0xFFFFFFFF) |
| goto nextimage; |
| // Copy the Image |
| AddMessageError(REPORT_NOTIFICATION, PlatformBusy); |
| |
| if ((pImageInfo->ImageID & 0xFFFFFF00) == FBFIDENTIFIER0) |
| { |
| Retval = PlatfromFBFBoundaryScan(pImageInfo); |
| if (Retval != NoError) |
| FatalError(Retval, "DTI", 2); |
| |
| pMasterHeader = (MasterBlockHeader*)loadAddr; |
| |
| if ((pMasterHeader->Format_Version != 11)) |
| FatalError(FBF_VersionNotMatch, "DTI", 3); |
| |
| if (pMasterHeader->nOfDevices != 1) |
| FatalError(FBF_DeviceMoreThanOne, "DTI", 4); |
| |
| temp_p = pMasterHeader->deviceHeaderOffset[0] + loadAddr; |
| pDevHeader_11 = (PDeviceHeader_11)temp_p; |
| AB_DL = pDevHeader_11->DeviceParameters[2]; |
| if(AB_DL) |
| obm_printf("AB system Downloading\n\r"); |
| |
| Retval = PlatformFBFCheckSWDVersion(pDevHeader_11); |
| if(Retval != NoError) |
| FatalError(Retval, "DTI", 5); |
| |
| // check nand ID |
| #if NAND_CODE |
| NandID_Right = pDevHeader_11->FlashOpt.NandID; |
| obm_printf("NandID: 0x%x\n\r", NandID); |
| if (NandID_Right != 0xFFFF && NandID != NandID_Right) |
| { |
| #if (!NEZHA701) |
| FatalError(NANDIDDISMATCH, "DTI", 6); |
| #endif |
| } |
| |
| for ( imagenum = 0; imagenum < pDevHeader_11->nOfImages; imagenum++ ) |
| { |
| temp_p = (UINT_T)&pDevHeader_11->imageStruct_11[imagenum]; |
| pImage_11 = (PImageStruct_11)temp_p; |
| |
| if(pImage_11->Image_ID == OBMIDENTIFIER) //OBMI |
| { |
| OBMFlashAddr = pImage_11->Flash_Start_Address; |
| //To word around the issue that BootROM disable sprare area |
| DisableSpareAreaForOBM(pImage_11->Flash_Start_Address, pImage_11->length); |
| } |
| } |
| #endif |
| |
| #if SPINOR_CODE |
| AddMessageError(REPORT_FLASH_SIZE_NOTIFICATION, Flash_size); |
| #endif |
| |
| // skip blocks |
| skip_blocks = pDevHeader_11->FlashOpt.Skip_Blocks_Struct.Total_Number_Of_SkipBlocks; |
| if (skip_blocks > 0) |
| pSkipAddress = &pDevHeader_11->FlashOpt.Skip_Blocks_Struct; |
| else |
| pSkipAddress = NULL; |
| |
| // productMode = pDevHeader_11->ProductMode; |
| Reset = pDevHeader_11->OptValue; |
| |
| /* Check if FBF package is right for this platform */ |
| PlatformFBFCheckDownload(pTIM_h, pDevHeader_11); |
| |
| pTIM_DTIM = (TIM *)malloc(DTIM_CUSTMOZIED_MAX*sizeof(TIM)); |
| if ( pTIM_DTIM == NULL ) |
| return HeapExhaustedError; |
| |
| memset(pTIM_DTIM, 0, DTIM_CUSTMOZIED_MAX*sizeof(TIM)); |
| // find out all TIMH and DTIM for secured download) |
| for (imagenum = 0; imagenum < pDevHeader_11->nOfImages; imagenum++) |
| { |
| temp_p = (UINT_T)&pDevHeader_11->imageStruct_11[imagenum]; |
| pImage_11= (PImageStruct_11)temp_p; |
| |
| if (!ImageIsTIM(pImage_11->Image_ID)) |
| continue; |
| |
| switch (pImage_11->Image_In_TIM) |
| { |
| case TIMH_NOTINC: /* NTIM */ |
| break; |
| case TIMH_INC: /* TIMH */ |
| TIMHLoaded = 1; |
| case TIMH_RECOVERY_INC: /* backup TIMH */ |
| default: /* Other TIMs */ |
| Retval = ValidateTIMInFBF(loadAddr, pImage_11, pImage_11->Image_In_TIM, pFuses->bits.SBE); |
| if (Retval != NoError) { |
| ASRFlag_DLStatus_Update(pTIM_h, 0, 0); |
| FatalError(InvalidTIMImageError, "VTIF", Retval); |
| } |
| break; |
| } |
| } |
| |
| if (OKtoErase) |
| { |
| if (pDevHeader_11->FlashOpt.EraseAll == 2) // erase all flash partition without burning |
| { |
| #if PRODUCT_BUILD |
| if (pFuses->bits.SBE == 1) { |
| ASRFlag_DLStatus_Update(pTIM_h, 0, 0); |
| FatalError(NotSupportedError, "DTI", 12); |
| } |
| #endif |
| |
| AddMessageError(REPORT_NOTIFICATION, PlatformEraseAllFlashWithoutBurn); // notify SWD |
| |
| Retval = EraseAllFlashWithoutBurn(BOOT_FLASH); |
| if (Retval != NoError) |
| { |
| FatalError(Retval, "DTI", 7); |
| } |
| |
| //Force ASR flag re-init later. |
| pFOTAInfo->InitFlag = 0; |
| |
| AddMessageError(REPORT_NOTIFICATION, PlatformEraseAllFlashWithoutBurnDone); // notify SWD |
| AddMessageError(REPORT_NOTIFICATION, PlatformReady); |
| |
| break; |
| } |
| |
| // check erase all flag |
| if (pDevHeader_11->FlashOpt.EraseAll == 1) // erase user partition with burning |
| { |
| // check reset BBT flag |
| if (pDevHeader_11->FlashOpt.ResetBBT) |
| { |
| AddMessageError(REPORT_NOTIFICATION, PlatformResetBBT); // notify SWD that OBM/flasher will reset BBT |
| ResetBBT(); |
| //After BBT is reset, OBM start address need to be updated, too. |
| #if NAND_CODE //To word around the issue that BootROM disable sprare area |
| DisableSpareAreaForOBM(OBMFlashAddr, 0); |
| #endif |
| } |
| |
| AddMessageError(REPORT_NOTIFICATION, PlatformEraseAllFlash); // notify SWD that OBM/flasher will erase all flash |
| Retval = EraseAllFlash(BOOT_FLASH); |
| if (Retval != NoError) |
| { |
| FatalError(Retval, "DTI", 8); |
| } |
| |
| //Force ASR flag re-init later. |
| pFOTAInfo->InitFlag = 0; |
| |
| OKtoErase = 0; |
| AddMessageError(REPORT_NOTIFICATION, PlatformEraseAllFlashDone); // notify SWD that OBM/flasher erases all flash done |
| } |
| } |
| |
| for ( imagenum = 0; imagenum < pDevHeader_11->nOfImages; imagenum++ ) |
| { |
| temp_p = (UINT_T)&pDevHeader_11->imageStruct_11[imagenum]; |
| pImage_11 = (PImageStruct_11)temp_p; |
| |
| #if TRUSTED && SECURE_DOWNLOAD |
| if (pFuses->bits.SBE) |
| { |
| switch (pImage_11->Image_In_TIM) |
| { |
| case TIMH_NOTINC: |
| break; |
| default: |
| ValidateImageInTIM(loadAddr, pImage_11, (pTIM_DTIM + pImage_11->Image_In_TIM)); |
| break; |
| } |
| } |
| #endif |
| |
| if(pImage_11->Image_ID == FOTA_FBFVERSION_IMAGEID) |
| { |
| memset(MVersionStr, 0, 128); |
| PStr = (CHAR *)( loadAddr + (pImage_11->First_Sector << 12) ); |
| if(strcmpl(PStr, "OTA0", 4) == 0) { |
| PStr += 4; |
| for( i = 0; i < 128 && *PStr != ';'; i++) |
| MVersionStr[i] = *PStr++; |
| |
| if(i < 128) { |
| MVersionInFbf = 1; |
| obm_printf("Download to: %s\n\r", MVersionStr); |
| } |
| } |
| continue; |
| } |
| |
| #if MMC_CODE |
| if((pTIM_h->pConsTIM->VersionBind.Version) >= TIM_3_2_00) |
| { |
| Retval = SetPartition(pImage_11->Flash_partition, BOOT_FLASH); |
| if (Retval != NoError) |
| { |
| FatalError(Retval, "DTI", 9); |
| } |
| } |
| #endif |
| |
| if(OKtoErase && (pImage_11->commands & DLCMD_DO_ERASE_BLOCKS) ) |
| { |
| Retval = DLEraseFlashToBurnImage(pImage_11); |
| } |
| |
| //if ((pImage_11->commands & 0xF) == 2) //erase only |
| // continue; |
| |
| if(pImage_11->commands & DLCMD_DO_VERIFY_WRITE) { |
| if (!IsDLImageDTIM(pImage_11)) { |
| Retval = DLBurnImageToFlash(pImage_11, loadAddr); |
| if(Retval != NoError ) |
| FatalError(Retval, "DTI", 10); |
| |
| AddMessageError(REPORT_BURNT_IMAGE_LENGTH, pImage_11->length); // report burnt image length |
| } |
| #if BURN_DTIM_LAST |
| else{ |
| SaveDTIMs2Memory(pImage_11, loadAddr); |
| } |
| #endif |
| } |
| } |
| |
| #if IMG_RBC |
| if(DownloadReadBackCRC == IMAGE_READ_BACK_CRC_ENABLED){ |
| DownloadReadBackCRC = IMAGE_READ_BACK_CRC_DONE; |
| AllImageCRCInfo.MCPID = ((NandID & 0xFF) << 16) | (ddr_id_update_with_crc & 0xFF); |
| } |
| #endif |
| |
| if (TIMHLoaded) { /* TIMH is loaded and parsed in pTIM_DTIM */ |
| Retval = ProvisionPlatform(pFuses, pTIM_DTIM + TIMH_INC); |
| // If ProvisionPlatform() returned an error, this means that an error occurred |
| // during fuse burning. So stop booting and go to Fatal Error. |
| if (Retval != NoError) |
| { |
| FatalError(Retval, "DTI", 11); |
| } |
| TIMHLoaded = 0; |
| } |
| } /* FBF */ |
| |
| pNextImageInfo = (IMAGE_INFO_3_4_0*)((unsigned char*)pImageInfo - ImageSize); |
| |
| /* Last FBF is handled, update DL flag as DLDONE */ |
| if (NumImages == 2 /* FBF0(current) and TIMH, */ |
| && pNextImageInfo->ImageID == TIMIDENTIFIER) { |
| |
| #if BURN_DTIM_LAST |
| BurnDTIMs2Flash(); |
| #endif |
| |
| if(MVersionInFbf == 1) { |
| pFOTA_T = OTAGetConfig(pTIM_h); |
| memset(pFOTA_T->MVersion, 0, sizeof(pFOTA_T->MVersion)); |
| memcpy(pFOTA_T->MVersion, MVersionStr, strlen(MVersionStr)); |
| #ifdef CONFIG_AB_SYSTEM |
| memset(pFOTA_T->MVersion_B, 0, sizeof(pFOTA_T->MVersion_B)); |
| memcpy(pFOTA_T->MVersion_B, MVersionStr, strlen(MVersionStr)); |
| #endif |
| } |
| ASRFlag_DLStatus_Update(pTIM_h, DLFLG, DLDONE); |
| free(pTIM_DTIM); |
| |
| UpdateBBT(); |
| |
| } |
| |
| AddMessageError(REPORT_NOTIFICATION, PlatformReady); |
| #endif /* end of COPYIMAGESTOFLASH */ |
| |
| nextimage: |
| NumImages--; |
| pImageInfo = (IMAGE_INFO_3_4_0*)((unsigned char*)pImageInfo - ImageSize); // index to previous image info record. |
| if(NumImages != 0) |
| free(loadAddr); |
| loadAddr = 0; |
| } // end WHILE |
| |
| #if NAND_CODE |
| SetUseSpareArea( FALSE, BOOT_FLASH ); |
| #endif |
| UpdateBBT(); |
| |
| #if SPINOR_CODE |
| SPINOR_Disable4BytesMode(); |
| #endif |
| |
| return NULL; |
| } |
| |
| INT_T ImageReadBackAndCRC(PImageStruct_11 pImage_11) |
| { |
| UINT_T * Buffer = NULL; |
| INT_T Retval = NoError; |
| UINT_T Len = 0; |
| |
| #if NZAC |
| UINT_T Temp1 = 0, Temp2 = 0; |
| P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH); |
| #endif |
| |
| if(DownloadReadBackCRC != IMAGE_READ_BACK_CRC_ENABLED){ |
| return NotSupportedError; |
| } |
| |
| if(AllImageCRCInfo.ImageNum >= CRC_MAX_IMAGE_NUM) |
| { |
| obm_printf("No more CRC buffer for 0x%08x\n\r", pImage_11->Image_ID); |
| return NotSupportedError; |
| } |
| |
| if(DTIM_PPSETTING == pImage_11->Image_ID) |
| { |
| AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].ImageID = pImage_11->Image_ID; |
| //CRC of DTim.PPsetting |
| AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].CRC32 = 0xc3751676; |
| AllImageCRCInfo.ImageNum++; |
| return Retval; |
| } |
| |
| Len = pImage_11->length; |
| |
| #if NZAC |
| if(PlatformIsNezhac() && (pImage_11->Image_ID == OBMIDENTIFIER) && (pFlashP->FlashType == SPI_FLASH) |
| && (pImage_11->length > 0x1df88)) |
| Len += (pImage_11->length/0x1df88)*4; |
| #endif |
| |
| Buffer = malloc(Len); |
| if(Buffer == NULL) |
| return HeapExhaustedError; |
| |
| Retval = ReadFlash( pImage_11->Flash_Start_Address, Buffer, Len, BOOT_FLASH); |
| |
| if(Retval != NoError){ |
| DownloadReadBackCRC = IMAGE_READ_BACK_CRC_FAIL; |
| free(Buffer); |
| return Retval; |
| } |
| |
| #if NZAC |
| //To workaroud the issue that 1802SL BootROM miss a word when OBM size is bigger than 0x1df88 in SPI-NOR |
| if(PlatformIsNezhac() && (pImage_11->Image_ID == OBMIDENTIFIER) && (pFlashP->FlashType == SPI_FLASH) |
| && (pImage_11->length > 0x1df88)) |
| { |
| Len = pImage_11->length; |
| Temp1 = Buffer; |
| Temp2 = malloc(256*1024); |
| if(Temp2 == NULL) |
| return HeapExhaustedError; |
| |
| while(Len) |
| { |
| memcpy((void *)Temp2, (void *)Temp1, 0x1df88); |
| Temp1 += 0x1df88; |
| Temp2 += 0x1df88; |
| Temp1 += 4; //Ignore the extra word added to workaourd BootROM SPINOR read issue |
| Len -= 0x1df88; |
| if(Len <= 0x1df88){ |
| memcpy((void *)Temp2, (void *)Temp1, Len); |
| break; |
| } |
| } |
| Buffer = Temp2; |
| } |
| #endif |
| |
| AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].ImageID = pImage_11->Image_ID; |
| AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].CRC32 = CalcCRC32(Buffer, pImage_11->length, 0xFFFFFFFF); |
| AllImageCRCInfo.ImageNum++; |
| |
| if(AB_DL && (pImage_11->Flash_Start_Address_B != 0xFFFFFFFF)) |
| { |
| Retval = ReadFlash( pImage_11->Flash_Start_Address_B, Buffer, Len, BOOT_FLASH); |
| |
| if(Retval != NoError){ |
| DownloadReadBackCRC = IMAGE_READ_BACK_CRC_FAIL; |
| #if NZAC |
| if(Temp2) free(Temp2); |
| #endif |
| free(Buffer); |
| return Retval; |
| } |
| AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].ImageID = pImage_11->Image_ID; |
| AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].CRC32 = CalcCRC32(Buffer, pImage_11->length, 0xFFFFFFFF); |
| AllImageCRCInfo.ImageNum++; |
| } |
| |
| #if NZAC |
| if(Temp2) free(Temp2); |
| #endif |
| |
| free(Buffer); |
| return Retval; |
| } |
| |
| |
| INT_T GetImageReadBackCrcBuffer(UINT_T *BufferAddr, INT_T *BufferLen) |
| { |
| int i; |
| if(DownloadReadBackCRC != IMAGE_READ_BACK_CRC_DONE) |
| { |
| return CRCFailedError; |
| } |
| |
| *BufferAddr = (UINT_T)(&AllImageCRCInfo); |
| *BufferLen = sizeof(ImageCRCInfo); |
| return NoError; |
| } |
| |