| |
| /****************************************************************************** |
| * |
| * (C)Copyright 2005 - 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: BootMode.c |
| * |
| * PURPOSE: Contains BootLoader's BootMode Code. Mainly handles the |
| * SINGLE and DUAL TIM MODE boot functions. |
| * |
| ******************************************************************************/ |
| |
| |
| ////////////////////////////////////////////////////////////////////// |
| // Library Support for the BootMode.c |
| // Include any shared libraries in the BootMode.h file to keep this |
| // code clean. |
| ////////////////////////////////////////////////////////////////////// |
| #include "BootMode.h" |
| #include "loadoffsets.h" |
| #include "obm2osl.h" |
| |
| #if LZMA_SUPPORT |
| #include "LzmaDecode.h" |
| #endif |
| |
| pIMAGE_INFO_3_4_0 pNextImageToTransferTo = NULL; // the next image we want to transfer control to |
| pIMAGE_INFO_3_4_0 pImageNsEntry = NULL; |
| extern OBM2OSL *pOBM2OSL_h; |
| extern UINT8_T FlashInitDone; |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This is the entry point for the Boot Mode. |
| // |
| // Inputs: Current TIM pointer, BootMode(SINGLE or DUAL) |
| // Outputs: Returns the next image that we will transfer the control to. |
| // |
| // It mainly functions as following depending on the BOOT MODE: |
| // 1) SINGLE TIM BOOT MODE: |
| // a) Configures the Flashes and Initializes the Flash Management |
| // b) Loads (and validates) all the images using a loop. |
| // c) If TRUSTED, provisions the platform before finishing |
| // d) Returns the next image that we will transfer the control to. |
| // 2) DUAL TIM BOOT MODE: |
| // a) Configures the Flashes and Initializes the Flash Management |
| // b) Loads (and validates) the second TIM. |
| // c) Configures the Flashes and Initializes the Flash Management |
| // using the new TIM. |
| // d) Loads (and validates) all the images using a loop. |
| // e) If TRUSTED, provisions the platform before finishing |
| // f) Returns the next image that we will transfer the control to. |
| ////////////////////////////////////////////////////////////////////// |
| pIMAGE_INFO_3_4_0 BootModeMain(pTIM pTIM_h, OPERATING_MODE_T BootMode, pFUSE_SET pFuses) |
| { |
| UINT_T Retval = NoError; |
| pIMAGE_INFO_3_4_0 pBootImageInfo = NULL; |
| |
| Retval = PlatformInitFlash(pTIM_h); |
| if( Retval != NoError) |
| FatalError(Retval, "BMM", 1); |
| |
| #if ENABLE_MMU |
| EnableDataCache(); |
| #endif |
| |
| #if TRUSTED |
| DisplayFuses(); |
| #endif |
| |
| #if EMMD_SUPPORT |
| if (PlatformCheckEMMDStatus()) { |
| pBootImageInfo = LoadAllImages(pFuses, pTIM_h); |
| #if ENABLE_MMU |
| DisableDataCache(); |
| #endif |
| return pBootImageInfo; |
| } |
| #endif |
| |
| PlatformReleaseEMMDStatus(); |
| |
| Retval = fota_upgrade(pTIM_h, pFuses); |
| obm_printf("FOTA return: 0x%x\n\r", Retval); |
| if (Retval == NoError) |
| { |
| PlatformReleaseEMMDStatus(); |
| PlatformSetFOTAFlag(); |
| do_wdt_reset(); |
| } |
| else |
| { |
| pBootImageInfo = LoadAllImages(pFuses, pTIM_h); |
| } |
| |
| #if TRUSTED |
| Retval = ProvisionPlatform(pFuses, pTIM_h); |
| |
| // 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, "BMM", 2); |
| } |
| #endif |
| |
| #if ENABLE_MMU |
| DisableDataCache(); |
| #endif |
| |
| return pBootImageInfo; |
| } |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This function mainly loads ALL the images available in the TIM |
| // (except TIM, DUALTIM, and OBM) and validates them. |
| // It essentially returns the next image that we will transfer the |
| // control to. |
| // |
| // Inputs: Current TIM pointer, BootMode(SINGLE or DUAL) |
| // Outputs: Returns the next image that we will transfer the control to. |
| ////////////////////////////////////////////////////////////////////// |
| pIMAGE_INFO_3_4_0 LoadAllImages(pFUSE_SET pFuses, pTIM pTIM_h) |
| { |
| UINT_T Retval = NoError, decompressLength; |
| UINT_T ImageID = 0; // Initialize it as an invalid image |
| UINT_T ImageIndex, ImageSize; |
| pIMAGE_INFO_3_4_0 pImageInfo = NULL; |
| pWTP_RESERVED_AREA_HEADER pWRAH = NULL; |
| pTransfer_Info_PACKAGE pInfo = NULL; |
| UINT_T i; |
| |
| OBM2OSL_Init(pFuses, pTIM_h); |
| |
| // no need to validate TIM since it's validated by BootROM already |
| |
| // 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. |
| pImageInfo = pTIM_h->pImg; |
| |
| // Read in the number of images from the TIM and iterate through each of these images. |
| // We load them and we validate them. |
| for( ImageIndex = 0; ImageIndex < pTIM_h->pConsTIM->NumImages; ImageIndex++ ) |
| { |
| // We skip the TIM, DUALTIM, and OBM images. We load/validate all the others. |
| if( (pImageInfo->ImageID != TIMIDENTIFIER) && |
| (pImageInfo->ImageID != OBMIDENTIFIER) && |
| (pImageInfo->ImageID != OBM2IDENTIFIER) && |
| (pImageInfo->ImageID != TZIIDENTIFIER) && |
| (pImageInfo->ImageID != OUMIDENTIFIER) && |
| (pImageInfo->LoadAddr != 0xFFFFFFFF) |
| ) |
| { |
| Retval = Loadimage(pImageInfo, pFuses, pTIM_h, 0); |
| if(Retval != NoError) { |
| obm_printf("Load %s error: 0x%x\n\r", ImageID2String(pImageInfo->ImageID), Retval); |
| pImageInfo = (IMAGE_INFO_3_4_0*)((UCHAR *)pImageInfo + ImageSize); |
| continue; |
| } |
| switch(pImageInfo->ImageID) |
| { |
| case TZSWIDENTIFIER: |
| obm_printf("Trusted OS in TIM\n\r"); |
| pNextImageToTransferTo = pImageInfo; |
| break; |
| case OSLOADERID: |
| obm_printf("Uboot in TIM\n\r"); |
| if(pNextImageToTransferTo == NULL) |
| pNextImageToTransferTo = pImageInfo; |
| if(pImageNsEntry == NULL) |
| pImageNsEntry = pImageInfo; |
| break; |
| } |
| } |
| |
| #if SPINOR_CODE |
| if (pImageInfo->ImageID == TIMIDENTIFIER) |
| { |
| TransCITA_2_OBM2OSLO(pTIM_h, pOBM2OSL_h); |
| } |
| #endif |
| |
| // Get a pointer to the next image we will load. |
| // For the last iteration (e.g. after the last image), we won't find an image. |
| // However, this is OK because pImageInfo is not used again. |
| pImageInfo = (IMAGE_INFO_3_4_0*)((UCHAR *)pImageInfo + ImageSize); |
| } |
| |
| // system needs to boot up if there is no IMAP |
| LoadImagesOTA(pFuses, pTIM_h); |
| |
| if(pNextImageToTransferTo == NULL) { |
| obm_printf("No Next Image to transfer to\n\r"); |
| FatalError(ImageNotFound, "LAI", NULL); |
| } |
| |
| #if SPINOR_CODE |
| SPINOR_Disable4BytesMode(); |
| #endif |
| |
| return pNextImageToTransferTo; |
| } |
| |
| unsigned int GetNsEntryLoadAddress() |
| { |
| unsigned int addr = 0; |
| if(pImageNsEntry) |
| addr = pImageNsEntry->LoadAddr; |
| return addr; |
| } |
| |
| INT_T Loadimage(pIMAGE_INFO_3_4_0 pImageInfo, pFUSE_SET pFuses, pTIM pTIM_h, INT_T TimType) |
| { |
| UINT_T Retval = NoError; |
| UINT_T offset; |
| UINT_T decompressLength; |
| UINT_T imgValidate = 1; |
| UINT_T AB_system = 0; |
| |
| #ifdef CONFIG_AB_SYSTEM |
| pWTP_RESERVED_AREA_HEADER pWRAH = NULL; |
| pABSP_INFO pABSP_info = NULL; |
| AB_system = 1; |
| #endif |
| |
| #if MMC_CODE |
| if((pTIM_h->pConsTIM->VersionBind.Version) >= TIM_3_2_00) |
| { |
| SetPartition(pImageInfo->PartitionNumber.bits.PartitionNumber, BOOT_FLASH); |
| } |
| #endif |
| |
| #ifdef CONFIG_AB_SYSTEM |
| if(TimType == RecoveryImage) { |
| pWRAH = FindPackageInReserved (&Retval, pTIM_h, ABSPID); |
| if (Retval != NoError) { |
| obm_printf("ABSP Package Not Found\n\r"); |
| return ImageLoadError; |
| } |
| pABSP_info = (pABSP_INFO) pWRAH; |
| offset = pImageInfo->PartitionNumber.bits.Reserved << pABSP_info->FlashAddrShift; |
| #if MMC_CODE |
| offset /= 512; |
| #endif |
| } else |
| #endif |
| { |
| offset = pImageInfo->FlashEntryAddr; |
| } |
| |
| #ifdef CONFIG_ASR_SDTIM |
| TIM *pSDTIM_h = NULL; |
| CHAR *SDTimBuf = NULL; |
| pIMAGE_INFO_3_4_0 pSdtimImageInfo = NULL; |
| if (ImageIsSDTIMIncluded(pImageInfo)) { |
| SDTimBuf = malloc(SDTIM_MAX_SIZE); |
| pSDTIM_h = malloc(sizeof(TIM)); |
| if(SDTimBuf == NULL || pSDTIM_h == NULL) |
| return HeapExhaustedError; |
| |
| Retval = ReadFlash(offset, SDTimBuf, SDTIM_MAX_SIZE, BOOT_FLASH); |
| if(Retval != NoError) { |
| free(SDTimBuf); free(pSDTIM_h); |
| return ImageLoadError; |
| } |
| |
| Retval = SetTIMPointers( SDTimBuf, pSDTIM_h); |
| if(Retval) |
| return ImageLoadError; |
| |
| pSdtimImageInfo = FindImageInTIM(pSDTIM_h, SDTIM); |
| if(pSdtimImageInfo == NULL) { |
| free(SDTimBuf); free(pSDTIM_h); |
| return ImageLoadError; |
| } |
| |
| imgValidate = GetSDTimSecureConfig(pSdtimImageInfo); |
| |
| #if MMC_CODE |
| offset += GetSDTimSpaceSize(pSdtimImageInfo)/512; |
| #else |
| offset += GetSDTimSpaceSize(pSdtimImageInfo); |
| #endif |
| pImageInfo = FindImageInTIM(pSDTIM_h, pImageInfo->ImageID); |
| if(pImageInfo == NULL) { |
| free(SDTimBuf); free(pSDTIM_h); |
| return ImageLoadError; |
| } |
| } else { |
| pSDTIM_h = pTIM_h; /* old way, SDTIM and DTIM is equal */ |
| } |
| #endif |
| |
| #if LZMA_SUPPORT |
| if (pImageInfo->PartitionNumber.bits.ImageType == DLCMD_IMG_LZMA_IMAGE_TYPE) |
| { |
| UINT_T *DecompressBuff = NULL; |
| DecompressBuff = malloc(pImageInfo->ImageSizeToHash); |
| if(DecompressBuff == NULL) |
| return HeapExhaustedError; |
| if(PlatformCheckEMMDStatus() == 1) { |
| decompressLength = DECOMPRESS_LENGTH_RDP; /* TODO */ |
| } else { |
| decompressLength = DECOMPRESS_LENGTH; |
| } |
| Retval = ReadFlash(offset, DecompressBuff, pImageInfo->ImageSize, BOOT_FLASH); |
| if (Retval != NoError) |
| { |
| free(DecompressBuff); |
| obm_printf("%s Load Error: 0x%x\n\r", ImageID2String(pImageInfo->ImageID), Retval); |
| return ImageLoadError; |
| } |
| decompressLength = DECOMPRESS_LENGTH; |
| Retval = LZMA_Decompress((UINT_T *)pImageInfo->LoadAddr, |
| &decompressLength, |
| (UINT_T *)DecompressBuff, |
| pImageInfo->ImageSize, |
| 0x0); |
| if (Retval != NoError) |
| { |
| free(DecompressBuff); |
| obm_printf("%s LZMA decompress Error: 0x%x\n\r", ImageID2String(pImageInfo->ImageID), Retval); |
| return ImageLoadError; |
| } |
| free(DecompressBuff); |
| goto img_validate; |
| } |
| #endif |
| |
| #if XZ_SUPPORT || XZDEC_SUPPORT |
| if (pImageInfo->PartitionNumber.bits.ImageType == DLCMD_IMG_MXZ_IMAGE_TYPE) { |
| CHAR *DecompressBuff = NULL; |
| UINT_T outLen = 0x2000000; /* 32MB */ |
| CHAR *inBuf, *inEnd, *outBuf, *outEnd; |
| VOID *nextInBuf = NULL; |
| INT compressed = 0; |
| UINT_T i = 0; |
| UINT_T outSize; |
| |
| DecompressBuff = malloc(pImageInfo->ImageSizeToHash); |
| if(DecompressBuff == NULL) |
| return HeapExhaustedError; |
| Retval = ReadFlash(offset, (UINT_T)DecompressBuff, pImageInfo->ImageSize, BOOT_FLASH); |
| |
| if (Retval != NoError) |
| { |
| free(DecompressBuff); |
| obm_printf("%s Load Error: 0x%x\n\r", ImageID2String(pImageInfo->ImageID), Retval); |
| return ImageLoadError; |
| } |
| inBuf = DecompressBuff; |
| inEnd = DecompressBuff + pImageInfo->ImageSize; |
| outBuf = (CHAR *)pImageInfo->LoadAddr; |
| outEnd = (CHAR *)(pImageInfo->LoadAddr + outLen); |
| |
| //obm_printf("Image info: 0x%x 0x%x 0x%x\n\r", pImageInfo->LoadAddr, pImageInfo->ImageSize, pImageInfo->ImageSizeToHash); |
| while (inBuf != inEnd) |
| { |
| outSize = outEnd - outBuf; |
| Retval = xz_decompress(inBuf, inEnd - inBuf, |
| outBuf, &outSize, |
| &nextInBuf, &compressed); |
| if (Retval) |
| { |
| FatalError(XZDecodeError, "LI", NULL); |
| } |
| |
| if(!compressed) |
| break; |
| |
| //obm_printf("MXZ dec loop: %d 0x%x\n\r", i, outSize); |
| ++i; |
| outBuf += outSize; |
| inBuf = (CHAR *) nextInBuf; |
| } |
| free(DecompressBuff); |
| goto img_validate; |
| } |
| #endif |
| |
| Retval = ReadFlash(offset, pImageInfo->LoadAddr, pImageInfo->ImageSize, BOOT_FLASH); |
| if (Retval != NoError) |
| return ImageLoadError; |
| |
| img_validate: |
| if (imgValidate || AB_system) |
| { |
| #ifdef CONFIG_ASR_SDTIM |
| Retval = ValidateImage(pImageInfo->LoadAddr, pImageInfo->ImageID, pSDTIM_h); |
| if(SDTimBuf) free(SDTimBuf);if(pSDTIM_h) free(pSDTIM_h); |
| #else |
| Retval = ValidateImage(pImageInfo->LoadAddr, pImageInfo->ImageID, pTIM_h); |
| #endif |
| if (Retval != NoError){ |
| obm_printf("%s Validation Error: 0x%x\n\r", ImageID2String(pImageInfo->ImageID), Retval); |
| return ImageValidationError; |
| } |
| } |
| |
| return Retval; |
| } |
| |
| #if 0 /* Deprecated */ |
| ////////////////////////////////////////////////////////////////////// |
| // This function loads uboot only for EMMD |
| ////////////////////////////////////////////////////////////////////// |
| pIMAGE_INFO_3_4_0 LoadUboot(pFUSE_SET pFuses, pTIM pTIM_h) |
| { |
| pIMAGE_INFO_3_4_0 pImageInfo = NULL; |
| |
| OBM2OSL_Init(pFuses, pTIM_h); |
| |
| #if QSPINOR_CODE |
| TransCITA_2_OBM2OSLO(pTIM_h, pOBM2OSL_h); |
| ASRFlag_ParseCfgToOBM2OSLO(pTIM_h); |
| #endif |
| pImageInfo = FindImageInTIM(pTIM_h, OSLOADERID); |
| if (pImageInfo != NULL) |
| { |
| pNextImageToTransferTo = pImageInfo; |
| Loadimage(pImageInfo, pFuses, pTIM_h, 0); |
| } |
| else |
| { |
| LoadUbootOTA(pFuses, pTIM_h); |
| } |
| |
| // Return the OSLO image. |
| return pNextImageToTransferTo; |
| } |
| #endif |
| |