| #include "fota.h" | |
| #include "obm2osl.h" | |
| #include "Flash.h" | |
| #include "malloc.h" | |
| extern SkipBlocksInfoStruct *pSkipAddress; | |
| extern UINT_T All_FF_flag; | |
| extern FOTA_Info FOTAInfo; | |
| static UINT_T DFota_ParseBsdiffPatch(CHAR *BsdiffPatch, UINT_T PatchLen, pBsdiffInfo pBsdiff_h) | |
| { | |
| UINT_T SegNum, i; | |
| CHAR *PatchPtr; | |
| PatchPtr = BsdiffPatch; | |
| if (memcmp(PatchPtr, "BSDIFF40", 8) == 0) { | |
| pBsdiff_h->Version = 40; | |
| } else { | |
| pBsdiff_h->Version = 0; | |
| } | |
| pBsdiff_h->Patch = BsdiffPatch; | |
| pBsdiff_h->PatchLen = PatchLen; | |
| return NoError; | |
| } | |
| UINT_T ImageDFotaProcess(pTIM pTIM_h, PImageStruct_11 pImage_11, | |
| pBsdiffInfo pBsdiff_h, P_FOTA_Firmware pFOTA_T) | |
| { | |
| CHAR *Patch = NULL, *OldBuff = NULL, *NewBuff = NULL; | |
| UINT_T NewLen = 0, EraseLen = 0, OldLen = 0, PatchLen; | |
| UINT_T Retval = NoError; | |
| P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH); | |
| UINT_T BlockSize = pFlashP->BlockSize; | |
| UINT_T NumBlocks = pFlashP->NumBlocks; | |
| UINT_T FlashSize = BlockSize * NumBlocks; | |
| UINT_T FlashAddr = 0; | |
| UINT_T BackupFlashAddr = 0; | |
| FlashAddr = pImage_11->Flash_Start_Address; | |
| obm_printf("Upgrade Image, ID: %s, Address: 0x%x, Length: 0x%x\r\n", | |
| ImageID2String(pImage_11->Image_ID), FlashAddr, pImage_11->length); | |
| BackupFlashAddr = pFOTA_T->FBF_Flash_Address + pFOTA_T->FBF_Size; | |
| BackupFlashAddr = ALIGN_UP(BackupFlashAddr, BlockSize); | |
| Patch = pBsdiff_h->Patch; | |
| PatchLen = pBsdiff_h->PatchLen; | |
| if ( TIM_TYPE == (pImage_11->Image_ID & 0xFFFFFF00) ) { | |
| NewLen = PatchLen; /* TIMs don't use dfota, patch is new tim */ | |
| goto write_new_img; | |
| } | |
| if(pFOTA_T->Dfota_NeedCopyOnly) { | |
| NewLen = ALIGN_UP(pFOTA_T->Dfota_CopyLen, BlockSize); | |
| NewBuff = malloc(NewLen); | |
| if(NewBuff == NULL) | |
| return HeapExhaustedError; | |
| memset(NewBuff, 0xFF, NewLen); | |
| Retval = ReadFlash(BackupFlashAddr, (UINT_T)NewBuff, pFOTA_T->Dfota_CopyLen, BOOT_FLASH); | |
| if(Retval != NoError) goto dfota_process_exit; | |
| goto write_new_img; | |
| } | |
| OldLen = get_oldsize(Patch); | |
| NewLen = get_newsize(Patch); | |
| if(OldLen == 0 || NewLen == 0) | |
| return DfotaDecodeError; | |
| OldLen = ALIGN_UP(OldLen, BlockSize); | |
| NewLen = ALIGN_UP(NewLen, BlockSize); | |
| OldBuff = malloc(OldLen); | |
| if(OldBuff == NULL) | |
| return HeapExhaustedError; | |
| NewBuff = malloc(NewLen); | |
| if(NewBuff == NULL) { | |
| free(OldBuff); | |
| return HeapExhaustedError; | |
| } | |
| memset(NewBuff, 0xFF, NewLen); | |
| memset(OldBuff, 0xFF, OldLen); | |
| Retval = ReadFlash(FlashAddr, (UINT_T)OldBuff, OldLen, BOOT_FLASH); | |
| if (Retval != NoError) goto dfota_process_exit; | |
| Retval = bzpacth(OldBuff, OldLen, NewBuff, &NewLen, Patch, PatchLen); | |
| if(Retval != 0 || NewLen == 0) goto dfota_process_exit; | |
| #if TRUSTED | |
| if (pTIM_h->pConsTIM->VersionBind.Trusted) { | |
| Retval = Fota_ValidateImage(NewBuff, pImage_11, pTIM_h); | |
| if(Retval != NoError) | |
| goto dfota_process_exit; | |
| } | |
| #endif | |
| if((BackupFlashAddr + NewLen) > FlashSize) | |
| { | |
| Retval = DFOTA_PartitionTooSmall; | |
| goto dfota_process_exit; | |
| } | |
| EraseLen = ALIGN_UP(NewLen, BlockSize); | |
| Retval = EraseFlash(BackupFlashAddr, EraseLen, BOOT_FLASH ); | |
| if(Retval != NoError) goto dfota_process_exit; | |
| Retval = WriteFlash( BackupFlashAddr, (UINT_T)NewBuff, NewLen, BOOT_FLASH ); | |
| if(Retval != NoError) goto dfota_process_exit; | |
| //power off protection | |
| pFOTA_T->Dfota_NeedCopyOnly =1; | |
| pFOTA_T->Dfota_CopyLen = NewLen; | |
| OTA_Save_Config(pTIM_h); | |
| write_new_img: | |
| EraseLen = (pImage_11->Flash_erase_size > NewLen) ? pImage_11->Flash_erase_size : NewLen; | |
| #if DUAL_TIM | |
| if ( pImage_11->Image_ID == OBMIDENTIFIER && DualTimEnabled() ) { | |
| if(!DualTimIsEqual()) | |
| EraseLen += MainTimSize; | |
| } | |
| #endif | |
| EraseLen = ALIGN_UP(EraseLen, BlockSize); | |
| Retval = EraseFlash(FlashAddr, EraseLen, BOOT_FLASH); | |
| if(Retval != NoError) goto dfota_process_exit; | |
| #if DUAL_TIM | |
| if ( pImage_11->Image_ID == OBMIDENTIFIER && DualTimEnabled()) { | |
| if (!DualTimIsEqual()) { | |
| UINT8_T *ObmTimBuff = NULL; | |
| ObmTimBuff = malloc(EraseLen); | |
| if(ObmTimBuff == NULL) { | |
| Retval = HeapExhaustedError; | |
| goto dfota_process_exit; | |
| } | |
| if(pImage_11->Image_In_TIM == TIMH_RECOVERY_INC) { | |
| memcpy(ObmTimBuff, NewBuff, NewLen); | |
| if(pTIM_h_Main) | |
| memcpy(ObmTimBuff+NewLen, pTIM_h_Main->pConsTIM, MainTimSize); | |
| Retval = WriteFlash(FlashAddr, ObmTimBuff, NewLen + MainTimSize, BOOT_FLASH); | |
| } else { | |
| memcpy(ObmTimBuff, NewBuff, NewLen); | |
| if(pTIM_h_Backup) | |
| memcpy(ObmTimBuff+NewLen, pTIM_h_Backup->pConsTIM, MainTimSize); | |
| Retval = WriteFlash(FlashAddr, ObmTimBuff, NewLen + BackupTimSize, BOOT_FLASH); | |
| } | |
| free(ObmTimBuff); | |
| } else { | |
| Retval = WriteFlash(FlashAddr, NewBuff, NewLen, BOOT_FLASH); | |
| } | |
| goto dfota_process_exit; | |
| } | |
| #endif | |
| if(pImage_11->Image_ID == TIMIDENTIFIER) { | |
| #if DUAL_TIM | |
| if(pImage_11->Image_In_TIM == TIMH_RECOVERY_INC && DualTimEnabled() ){ | |
| if(!DualTimIsEqual()) { | |
| if(pTIM_h_Backup == NULL) { | |
| Retval = TIMNotFound; | |
| goto dfota_process_exit; | |
| } | |
| Retval = WriteFlash( FlashAddr, pTIM_h_Backup->pConsTIM, BackupTimSize, BOOT_FLASH ); | |
| }else { | |
| if(pTIM_h_Main == NULL) { | |
| Retval = TIMNotFound; | |
| goto dfota_process_exit; | |
| } | |
| Retval = WriteFlash( FlashAddr, pTIM_h_Main->pConsTIM, MainTimSize, BOOT_FLASH ); | |
| } | |
| } | |
| else | |
| #endif | |
| { | |
| if(pTIM_h_Main == NULL) { | |
| Retval = TIMNotFound; | |
| goto dfota_process_exit; | |
| } | |
| Retval = WriteFlash( FlashAddr, pTIM_h_Main->pConsTIM, MainTimSize, BOOT_FLASH ); | |
| } | |
| goto dfota_process_exit; | |
| } | |
| if ( TIM_TYPE != (pImage_11->Image_ID & 0xFFFFFF00) ) /* other TIMs */ | |
| Retval = WriteFlash( FlashAddr, (UINT_T)NewBuff, NewLen, BOOT_FLASH ); | |
| else //All other TIMs | |
| Retval = WriteFlash( FlashAddr, (UINT_T)Patch, PatchLen, BOOT_FLASH ); | |
| dfota_process_exit: | |
| if(NewBuff) { free(NewBuff); NewBuff = NULL; } | |
| if(OldBuff) { free(OldBuff); OldBuff = NULL; } | |
| return Retval; | |
| } | |
| UINT_T DFOTA_Upgrade(P_FOTA_Firmware pFOTA_T, pTIM pTIM_h) | |
| { | |
| UINT_T Retval = GeneralError; | |
| UINT_T LoadAddr = 0; | |
| MasterBlockHeader *pMasterHeader = NULL; | |
| PDeviceHeader_11 pDevHeader_11=NULL; | |
| PImageStruct_11 pImage_11 = NULL; | |
| UINT_T temp_p = NULL; | |
| UINT_T i, ImageAddr; | |
| INT_T imagenum; | |
| P_FOTA_Info pFOTAInfo = &FOTAInfo; | |
| BsdiffInfo BsdiffInfo; | |
| pBsdiffInfo pBsdiff_h = &BsdiffInfo; | |
| LoadAddr = (UINT_T)malloc(pFOTA_T->FBF_Size); | |
| if(LoadAddr == 0){ | |
| obm_printf("malloc error %s %d\n\r", __FUNCTION__, __LINE__); | |
| return HeapExhaustedError; | |
| } | |
| Retval = ReadFlash(pFOTA_T->FBF_Flash_Address, LoadAddr, pFOTA_T->FBF_Size, BOOT_FLASH); | |
| if (Retval != NoError){ | |
| goto error; | |
| } | |
| pMasterHeader = (MasterBlockHeader *)LoadAddr; | |
| temp_p = pMasterHeader->deviceHeaderOffset[0] + LoadAddr; | |
| pDevHeader_11 = (PDeviceHeader_11)temp_p; | |
| Retval = Fota_CommonPreprocess(pTIM_h, pMasterHeader, pFOTA_T, 4); | |
| if(Retval != NoError) { | |
| goto error; | |
| } | |
| if (pFOTA_T->DFota_nOfImages == 0xFFFFFFFF) { | |
| pFOTA_T->DFota_nOfImages= pDevHeader_11->nOfImages; | |
| } | |
| for ( imagenum = pFOTA_T->DFota_nOfImages; imagenum > 0; imagenum -- ) | |
| { | |
| temp_p = (UINT_T)&pDevHeader_11->imageStruct_11[imagenum - 1]; | |
| pImage_11 = (PImageStruct_11)temp_p; | |
| ImageAddr = LoadAddr+(pImage_11->First_Sector<<13); | |
| Retval = Fota_ImagePreprocess(ImageAddr, pImage_11, 4); | |
| if(Retval == FOTA_DummyImage) { | |
| Retval = NoError; /* Dummy Image, do nothing and continue */ | |
| continue; | |
| } else if(Retval != NoError){ | |
| goto error; | |
| } | |
| DFota_ParseBsdiffPatch((CHAR *)ImageAddr, pImage_11->length, pBsdiff_h); | |
| Retval = ImageDFotaProcess(pTIM_h, pImage_11, pBsdiff_h, pFOTA_T); | |
| if(Retval != NoError) goto error; | |
| //power off protection | |
| pFOTA_T->DFota_nOfImages = imagenum - 1; | |
| pFOTA_T->Dfota_NeedCopyOnly = 0; | |
| pFOTA_T->Dfota_CopyLen = 0; | |
| OTA_Save_Config(pTIM_h); | |
| } //for loop | |
| Fota_CommonPostprocess(pTIM_h, pMasterHeader, pFOTA_T, 4); | |
| error: | |
| //free buffers | |
| if(LoadAddr) free((VOID *)LoadAddr); | |
| return Retval; | |
| } | |