b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | |
| 2 | /****************************************************************************** |
| 3 | * |
| 4 | * (C)Copyright 2005 - 2011 Marvell. All Rights Reserved. |
| 5 | * |
| 6 | * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL. |
| 7 | * The copyright notice above does not evidence any actual or intended |
| 8 | * publication of such source code. |
| 9 | * This Module contains Proprietary Information of Marvell and should be |
| 10 | * treated as Confidential. |
| 11 | * The information in this file is provided for the exclusive use of the |
| 12 | * licensees of Marvell. |
| 13 | * Such users have the right to use, modify, and incorporate this code into |
| 14 | * products for purposes authorized by the license agreement provided they |
| 15 | * include this notice and the associated copyright notice with any such |
| 16 | * product. |
| 17 | * The information in this file is provided "AS IS" without warranty. |
| 18 | * |
| 19 | ****************************************************************************** |
| 20 | * |
| 21 | * |
| 22 | * FILENAME: BootMode.c |
| 23 | * |
| 24 | * PURPOSE: Contains BootLoader's BootMode Code. Mainly handles the |
| 25 | * SINGLE and DUAL TIM MODE boot functions. |
| 26 | * |
| 27 | ******************************************************************************/ |
| 28 | |
| 29 | |
| 30 | ////////////////////////////////////////////////////////////////////// |
| 31 | // Library Support for the BootMode.c |
| 32 | // Include any shared libraries in the BootMode.h file to keep this |
| 33 | // code clean. |
| 34 | ////////////////////////////////////////////////////////////////////// |
| 35 | #include "BootMode.h" |
| 36 | #include "loadoffsets.h" |
| 37 | #include "obm2osl.h" |
| 38 | |
| 39 | #if LZMA_SUPPORT |
| 40 | #include "LzmaDecode.h" |
| 41 | #endif |
| 42 | |
| 43 | pIMAGE_INFO_3_4_0 pNextImageToTransferTo = NULL; // the next image we want to transfer control to |
| 44 | pIMAGE_INFO_3_4_0 pImageNsEntry = NULL; |
| 45 | extern OBM2OSL *pOBM2OSL_h; |
| 46 | extern UINT8_T FlashInitDone; |
| 47 | |
| 48 | ////////////////////////////////////////////////////////////////////// |
| 49 | // This is the entry point for the Boot Mode. |
| 50 | // |
| 51 | // Inputs: Current TIM pointer, BootMode(SINGLE or DUAL) |
| 52 | // Outputs: Returns the next image that we will transfer the control to. |
| 53 | // |
| 54 | // It mainly functions as following depending on the BOOT MODE: |
| 55 | // 1) SINGLE TIM BOOT MODE: |
| 56 | // a) Configures the Flashes and Initializes the Flash Management |
| 57 | // b) Loads (and validates) all the images using a loop. |
| 58 | // c) If TRUSTED, provisions the platform before finishing |
| 59 | // d) Returns the next image that we will transfer the control to. |
| 60 | // 2) DUAL TIM BOOT MODE: |
| 61 | // a) Configures the Flashes and Initializes the Flash Management |
| 62 | // b) Loads (and validates) the second TIM. |
| 63 | // c) Configures the Flashes and Initializes the Flash Management |
| 64 | // using the new TIM. |
| 65 | // d) Loads (and validates) all the images using a loop. |
| 66 | // e) If TRUSTED, provisions the platform before finishing |
| 67 | // f) Returns the next image that we will transfer the control to. |
| 68 | ////////////////////////////////////////////////////////////////////// |
| 69 | pIMAGE_INFO_3_4_0 BootModeMain(pTIM pTIM_h, OPERATING_MODE_T BootMode, pFUSE_SET pFuses) |
| 70 | { |
| 71 | UINT_T Retval = NoError; |
| 72 | pIMAGE_INFO_3_4_0 pBootImageInfo = NULL; |
| 73 | |
| 74 | Retval = PlatformInitFlash(pTIM_h); |
| 75 | if( Retval != NoError) |
| 76 | FatalError(Retval, "BMM", 1); |
| 77 | |
| 78 | #if ENABLE_MMU |
| 79 | EnableDataCache(); |
| 80 | #endif |
| 81 | |
| 82 | #if TRUSTED |
| 83 | DisplayFuses(); |
| 84 | #endif |
| 85 | |
| 86 | #if EMMD_SUPPORT |
| 87 | if (PlatformCheckEMMDStatus()) { |
| 88 | pBootImageInfo = LoadAllImages(pFuses, pTIM_h); |
| 89 | #if ENABLE_MMU |
| 90 | DisableDataCache(); |
| 91 | #endif |
| 92 | return pBootImageInfo; |
| 93 | } |
| 94 | #endif |
| 95 | |
| 96 | PlatformReleaseEMMDStatus(); |
| 97 | |
| 98 | Retval = fota_upgrade(pTIM_h, pFuses); |
| 99 | obm_printf("FOTA return: 0x%x\n\r", Retval); |
| 100 | if (Retval == NoError) |
| 101 | { |
| 102 | PlatformReleaseEMMDStatus(); |
| 103 | PlatformSetFOTAFlag(); |
| 104 | do_wdt_reset(); |
| 105 | } |
| 106 | else |
| 107 | { |
| 108 | pBootImageInfo = LoadAllImages(pFuses, pTIM_h); |
| 109 | } |
| 110 | |
| 111 | #if TRUSTED |
| 112 | Retval = ProvisionPlatform(pFuses, pTIM_h); |
| 113 | |
| 114 | // If ProvisionPlatform() returned an error, this means that an error occurred |
| 115 | // during fuse burning. So stop booting and go to Fatal Error. |
| 116 | if (Retval != NoError) |
| 117 | { |
| 118 | FatalError(Retval, "BMM", 2); |
| 119 | } |
| 120 | #endif |
| 121 | |
| 122 | #if ENABLE_MMU |
| 123 | DisableDataCache(); |
| 124 | #endif |
| 125 | |
| 126 | return pBootImageInfo; |
| 127 | } |
| 128 | |
| 129 | ////////////////////////////////////////////////////////////////////// |
| 130 | // This function mainly loads ALL the images available in the TIM |
| 131 | // (except TIM, DUALTIM, and OBM) and validates them. |
| 132 | // It essentially returns the next image that we will transfer the |
| 133 | // control to. |
| 134 | // |
| 135 | // Inputs: Current TIM pointer, BootMode(SINGLE or DUAL) |
| 136 | // Outputs: Returns the next image that we will transfer the control to. |
| 137 | ////////////////////////////////////////////////////////////////////// |
| 138 | pIMAGE_INFO_3_4_0 LoadAllImages(pFUSE_SET pFuses, pTIM pTIM_h) |
| 139 | { |
| 140 | UINT_T Retval = NoError, decompressLength; |
| 141 | UINT_T ImageID = 0; // Initialize it as an invalid image |
| 142 | UINT_T ImageIndex, ImageSize; |
| 143 | pIMAGE_INFO_3_4_0 pImageInfo = NULL; |
| 144 | pWTP_RESERVED_AREA_HEADER pWRAH = NULL; |
| 145 | pTransfer_Info_PACKAGE pInfo = NULL; |
| 146 | UINT_T i; |
| 147 | |
| 148 | OBM2OSL_Init(pFuses, pTIM_h); |
| 149 | |
| 150 | // no need to validate TIM since it's validated by BootROM already |
| 151 | |
| 152 | // Depending on the version of the TIM, determine the size of each image in bytes. |
| 153 | // We will use this size to iterate through the TIM binary from image to image. |
| 154 | if (pTIM_h->pConsTIM->VersionBind.Version >= TIM_3_4_00) |
| 155 | ImageSize = sizeof(IMAGE_INFO_3_4_0); |
| 156 | else |
| 157 | ImageSize = sizeof(IMAGE_INFO_3_2_0); |
| 158 | |
| 159 | // This is the very initial TIM image! Assumes that the TIM image is located at the top of the |
| 160 | // TIM file. Otherwise, we would skip images. |
| 161 | pImageInfo = pTIM_h->pImg; |
| 162 | |
| 163 | // Read in the number of images from the TIM and iterate through each of these images. |
| 164 | // We load them and we validate them. |
| 165 | for( ImageIndex = 0; ImageIndex < pTIM_h->pConsTIM->NumImages; ImageIndex++ ) |
| 166 | { |
| 167 | // We skip the TIM, DUALTIM, and OBM images. We load/validate all the others. |
| 168 | if( (pImageInfo->ImageID != TIMIDENTIFIER) && |
| 169 | (pImageInfo->ImageID != OBMIDENTIFIER) && |
| 170 | (pImageInfo->ImageID != OBM2IDENTIFIER) && |
| 171 | (pImageInfo->ImageID != TZIIDENTIFIER) && |
| 172 | (pImageInfo->ImageID != OUMIDENTIFIER) && |
| 173 | (pImageInfo->LoadAddr != 0xFFFFFFFF) |
| 174 | ) |
| 175 | { |
| 176 | Retval = Loadimage(pImageInfo, pFuses, pTIM_h, 0); |
| 177 | if(Retval != NoError) { |
| 178 | obm_printf("Load %s error: 0x%x\n\r", ImageID2String(pImageInfo->ImageID), Retval); |
| 179 | pImageInfo = (IMAGE_INFO_3_4_0*)((UCHAR *)pImageInfo + ImageSize); |
| 180 | continue; |
| 181 | } |
| 182 | switch(pImageInfo->ImageID) |
| 183 | { |
| 184 | case TZSWIDENTIFIER: |
| 185 | obm_printf("Trusted OS in TIM\n\r"); |
| 186 | pNextImageToTransferTo = pImageInfo; |
| 187 | break; |
| 188 | case OSLOADERID: |
| 189 | obm_printf("Uboot in TIM\n\r"); |
| 190 | if(pNextImageToTransferTo == NULL) |
| 191 | pNextImageToTransferTo = pImageInfo; |
| 192 | if(pImageNsEntry == NULL) |
| 193 | pImageNsEntry = pImageInfo; |
| 194 | break; |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | #if SPINOR_CODE |
| 199 | if (pImageInfo->ImageID == TIMIDENTIFIER) |
| 200 | { |
| 201 | TransCITA_2_OBM2OSLO(pTIM_h, pOBM2OSL_h); |
| 202 | } |
| 203 | #endif |
| 204 | |
| 205 | // Get a pointer to the next image we will load. |
| 206 | // For the last iteration (e.g. after the last image), we won't find an image. |
| 207 | // However, this is OK because pImageInfo is not used again. |
| 208 | pImageInfo = (IMAGE_INFO_3_4_0*)((UCHAR *)pImageInfo + ImageSize); |
| 209 | } |
| 210 | |
| 211 | // system needs to boot up if there is no IMAP |
| 212 | LoadImagesOTA(pFuses, pTIM_h); |
| 213 | |
| 214 | if(pNextImageToTransferTo == NULL) { |
| 215 | obm_printf("No Next Image to transfer to\n\r"); |
| 216 | FatalError(ImageNotFound, "LAI", NULL); |
| 217 | } |
| 218 | |
| 219 | #if SPINOR_CODE |
| 220 | SPINOR_Disable4BytesMode(); |
| 221 | #endif |
| 222 | |
| 223 | return pNextImageToTransferTo; |
| 224 | } |
| 225 | |
| 226 | unsigned int GetNsEntryLoadAddress() |
| 227 | { |
| 228 | unsigned int addr = 0; |
| 229 | if(pImageNsEntry) |
| 230 | addr = pImageNsEntry->LoadAddr; |
| 231 | return addr; |
| 232 | } |
| 233 | |
| 234 | INT_T Loadimage(pIMAGE_INFO_3_4_0 pImageInfo, pFUSE_SET pFuses, pTIM pTIM_h, INT_T TimType) |
| 235 | { |
| 236 | UINT_T Retval = NoError; |
| 237 | UINT_T offset; |
| 238 | UINT_T decompressLength; |
| 239 | UINT_T imgValidate = 1; |
| 240 | UINT_T AB_system = 0; |
| 241 | |
| 242 | #ifdef CONFIG_AB_SYSTEM |
| 243 | pWTP_RESERVED_AREA_HEADER pWRAH = NULL; |
| 244 | pABSP_INFO pABSP_info = NULL; |
| 245 | AB_system = 1; |
| 246 | #endif |
| 247 | |
| 248 | #if MMC_CODE |
| 249 | if((pTIM_h->pConsTIM->VersionBind.Version) >= TIM_3_2_00) |
| 250 | { |
| 251 | SetPartition(pImageInfo->PartitionNumber.bits.PartitionNumber, BOOT_FLASH); |
| 252 | } |
| 253 | #endif |
| 254 | |
| 255 | #ifdef CONFIG_AB_SYSTEM |
| 256 | if(TimType == RecoveryImage) { |
| 257 | pWRAH = FindPackageInReserved (&Retval, pTIM_h, ABSPID); |
| 258 | if (Retval != NoError) { |
| 259 | obm_printf("ABSP Package Not Found\n\r"); |
| 260 | return ImageLoadError; |
| 261 | } |
| 262 | pABSP_info = (pABSP_INFO) pWRAH; |
| 263 | offset = pImageInfo->PartitionNumber.bits.Reserved << pABSP_info->FlashAddrShift; |
| 264 | #if MMC_CODE |
| 265 | offset /= 512; |
| 266 | #endif |
| 267 | } else |
| 268 | #endif |
| 269 | { |
| 270 | offset = pImageInfo->FlashEntryAddr; |
| 271 | } |
| 272 | |
| 273 | #ifdef CONFIG_ASR_SDTIM |
| 274 | TIM *pSDTIM_h = NULL; |
| 275 | CHAR *SDTimBuf = NULL; |
| 276 | pIMAGE_INFO_3_4_0 pSdtimImageInfo = NULL; |
| 277 | if (ImageIsSDTIMIncluded(pImageInfo)) { |
| 278 | SDTimBuf = malloc(SDTIM_MAX_SIZE); |
| 279 | pSDTIM_h = malloc(sizeof(TIM)); |
| 280 | if(SDTimBuf == NULL || pSDTIM_h == NULL) |
| 281 | return HeapExhaustedError; |
| 282 | |
| 283 | Retval = ReadFlash(offset, SDTimBuf, SDTIM_MAX_SIZE, BOOT_FLASH); |
| 284 | if(Retval != NoError) { |
| 285 | free(SDTimBuf); free(pSDTIM_h); |
| 286 | return ImageLoadError; |
| 287 | } |
| 288 | |
| 289 | Retval = SetTIMPointers( SDTimBuf, pSDTIM_h); |
| 290 | if(Retval) |
| 291 | return ImageLoadError; |
| 292 | |
| 293 | pSdtimImageInfo = FindImageInTIM(pSDTIM_h, SDTIM); |
| 294 | if(pSdtimImageInfo == NULL) { |
| 295 | free(SDTimBuf); free(pSDTIM_h); |
| 296 | return ImageLoadError; |
| 297 | } |
| 298 | |
| 299 | imgValidate = GetSDTimSecureConfig(pSdtimImageInfo); |
| 300 | |
| 301 | #if MMC_CODE |
| 302 | offset += GetSDTimSpaceSize(pSdtimImageInfo)/512; |
| 303 | #else |
| 304 | offset += GetSDTimSpaceSize(pSdtimImageInfo); |
| 305 | #endif |
| 306 | pImageInfo = FindImageInTIM(pSDTIM_h, pImageInfo->ImageID); |
| 307 | if(pImageInfo == NULL) { |
| 308 | free(SDTimBuf); free(pSDTIM_h); |
| 309 | return ImageLoadError; |
| 310 | } |
| 311 | } else { |
| 312 | pSDTIM_h = pTIM_h; /* old way, SDTIM and DTIM is equal */ |
| 313 | } |
| 314 | #endif |
| 315 | |
| 316 | #if LZMA_SUPPORT |
| 317 | if (pImageInfo->PartitionNumber.bits.ImageType == DLCMD_IMG_LZMA_IMAGE_TYPE) |
| 318 | { |
| 319 | UINT_T *DecompressBuff = NULL; |
| 320 | DecompressBuff = malloc(pImageInfo->ImageSizeToHash); |
| 321 | if(DecompressBuff == NULL) |
| 322 | return HeapExhaustedError; |
| 323 | if(PlatformCheckEMMDStatus() == 1) { |
| 324 | decompressLength = DECOMPRESS_LENGTH_RDP; /* TODO */ |
| 325 | } else { |
| 326 | decompressLength = DECOMPRESS_LENGTH; |
| 327 | } |
| 328 | Retval = ReadFlash(offset, DecompressBuff, pImageInfo->ImageSize, BOOT_FLASH); |
| 329 | if (Retval != NoError) |
| 330 | { |
| 331 | free(DecompressBuff); |
| 332 | obm_printf("%s Load Error: 0x%x\n\r", ImageID2String(pImageInfo->ImageID), Retval); |
| 333 | return ImageLoadError; |
| 334 | } |
| 335 | decompressLength = DECOMPRESS_LENGTH; |
| 336 | Retval = LZMA_Decompress((UINT_T *)pImageInfo->LoadAddr, |
| 337 | &decompressLength, |
| 338 | (UINT_T *)DecompressBuff, |
| 339 | pImageInfo->ImageSize, |
| 340 | 0x0); |
| 341 | if (Retval != NoError) |
| 342 | { |
| 343 | free(DecompressBuff); |
| 344 | obm_printf("%s LZMA decompress Error: 0x%x\n\r", ImageID2String(pImageInfo->ImageID), Retval); |
| 345 | return ImageLoadError; |
| 346 | } |
| 347 | free(DecompressBuff); |
| 348 | goto img_validate; |
| 349 | } |
| 350 | #endif |
| 351 | |
| 352 | #if XZ_SUPPORT || XZDEC_SUPPORT |
| 353 | if (pImageInfo->PartitionNumber.bits.ImageType == DLCMD_IMG_MXZ_IMAGE_TYPE) { |
| 354 | CHAR *DecompressBuff = NULL; |
| 355 | UINT_T outLen = 0x2000000; /* 32MB */ |
| 356 | CHAR *inBuf, *inEnd, *outBuf, *outEnd; |
| 357 | VOID *nextInBuf = NULL; |
| 358 | INT compressed = 0; |
| 359 | UINT_T i = 0; |
| 360 | UINT_T outSize; |
| 361 | |
| 362 | DecompressBuff = malloc(pImageInfo->ImageSizeToHash); |
| 363 | if(DecompressBuff == NULL) |
| 364 | return HeapExhaustedError; |
| 365 | Retval = ReadFlash(offset, (UINT_T)DecompressBuff, pImageInfo->ImageSize, BOOT_FLASH); |
| 366 | |
| 367 | if (Retval != NoError) |
| 368 | { |
| 369 | free(DecompressBuff); |
| 370 | obm_printf("%s Load Error: 0x%x\n\r", ImageID2String(pImageInfo->ImageID), Retval); |
| 371 | return ImageLoadError; |
| 372 | } |
| 373 | inBuf = DecompressBuff; |
| 374 | inEnd = DecompressBuff + pImageInfo->ImageSize; |
| 375 | outBuf = (CHAR *)pImageInfo->LoadAddr; |
| 376 | outEnd = (CHAR *)(pImageInfo->LoadAddr + outLen); |
| 377 | |
| 378 | //obm_printf("Image info: 0x%x 0x%x 0x%x\n\r", pImageInfo->LoadAddr, pImageInfo->ImageSize, pImageInfo->ImageSizeToHash); |
| 379 | while (inBuf != inEnd) |
| 380 | { |
| 381 | outSize = outEnd - outBuf; |
| 382 | Retval = xz_decompress(inBuf, inEnd - inBuf, |
| 383 | outBuf, &outSize, |
| 384 | &nextInBuf, &compressed); |
| 385 | if (Retval) |
| 386 | { |
| 387 | FatalError(XZDecodeError, "LI", NULL); |
| 388 | } |
| 389 | |
| 390 | if(!compressed) |
| 391 | break; |
| 392 | |
| 393 | //obm_printf("MXZ dec loop: %d 0x%x\n\r", i, outSize); |
| 394 | ++i; |
| 395 | outBuf += outSize; |
| 396 | inBuf = (CHAR *) nextInBuf; |
| 397 | } |
| 398 | free(DecompressBuff); |
| 399 | goto img_validate; |
| 400 | } |
| 401 | #endif |
| 402 | |
| 403 | Retval = ReadFlash(offset, pImageInfo->LoadAddr, pImageInfo->ImageSize, BOOT_FLASH); |
| 404 | if (Retval != NoError) |
| 405 | return ImageLoadError; |
| 406 | |
| 407 | img_validate: |
| 408 | if (imgValidate || AB_system) |
| 409 | { |
| 410 | #ifdef CONFIG_ASR_SDTIM |
| 411 | Retval = ValidateImage(pImageInfo->LoadAddr, pImageInfo->ImageID, pSDTIM_h); |
| 412 | if(SDTimBuf) free(SDTimBuf);if(pSDTIM_h) free(pSDTIM_h); |
| 413 | #else |
| 414 | Retval = ValidateImage(pImageInfo->LoadAddr, pImageInfo->ImageID, pTIM_h); |
| 415 | #endif |
| 416 | if (Retval != NoError){ |
| 417 | obm_printf("%s Validation Error: 0x%x\n\r", ImageID2String(pImageInfo->ImageID), Retval); |
| 418 | return ImageValidationError; |
| 419 | } |
| 420 | } |
| 421 | |
| 422 | return Retval; |
| 423 | } |
| 424 | |
| 425 | #if 0 /* Deprecated */ |
| 426 | ////////////////////////////////////////////////////////////////////// |
| 427 | // This function loads uboot only for EMMD |
| 428 | ////////////////////////////////////////////////////////////////////// |
| 429 | pIMAGE_INFO_3_4_0 LoadUboot(pFUSE_SET pFuses, pTIM pTIM_h) |
| 430 | { |
| 431 | pIMAGE_INFO_3_4_0 pImageInfo = NULL; |
| 432 | |
| 433 | OBM2OSL_Init(pFuses, pTIM_h); |
| 434 | |
| 435 | #if QSPINOR_CODE |
| 436 | TransCITA_2_OBM2OSLO(pTIM_h, pOBM2OSL_h); |
| 437 | ASRFlag_ParseCfgToOBM2OSLO(pTIM_h); |
| 438 | #endif |
| 439 | pImageInfo = FindImageInTIM(pTIM_h, OSLOADERID); |
| 440 | if (pImageInfo != NULL) |
| 441 | { |
| 442 | pNextImageToTransferTo = pImageInfo; |
| 443 | Loadimage(pImageInfo, pFuses, pTIM_h, 0); |
| 444 | } |
| 445 | else |
| 446 | { |
| 447 | LoadUbootOTA(pFuses, pTIM_h); |
| 448 | } |
| 449 | |
| 450 | // Return the OSLO image. |
| 451 | return pNextImageToTransferTo; |
| 452 | } |
| 453 | #endif |
| 454 | |