blob: 3cc79bbb153587e73eeb427a11a1ba9bad2b5fa0 [file] [log] [blame]
#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;
}