b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | |
| 2 | /****************************************************************************** |
| 3 | * |
| 4 | * (C)Copyright 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 | * FILENAME: TIMDownload.c |
| 21 | * |
| 22 | * PURPOSE: Contains BootLoader's TIM based download code. |
| 23 | * |
| 24 | ******************************************************************************/ |
| 25 | |
| 26 | |
| 27 | ////////////////////////////////////////////////////////////////////// |
| 28 | // Library Support for the TIMDownload.c |
| 29 | // Include any shared libraries in the TIMDownload.h file to keep this |
| 30 | // code clean. |
| 31 | ////////////////////////////////////////////////////////////////////// |
| 32 | #include "TIMDownload.h" |
| 33 | #include "obm2osl.h" |
| 34 | #include "fota.h" |
| 35 | #include "tim.h" |
| 36 | #include "ProtocolManager.h" |
| 37 | |
| 38 | UINT_T NandID = 0x0; // make sure the nand ID OBM detected is the equals to the nand ID OBM got from SWD |
| 39 | UINT_T Reset = 1; |
| 40 | UINT_T Flash_size = 0x01000000; // default 16MB |
| 41 | extern UINT8_T FlashInitDone; |
| 42 | extern FOTA_Info FOTAInfo; |
| 43 | |
| 44 | extern UINT_T ddr_id_update_with_crc; |
| 45 | static INT_T DownloadReadBackCRC = IMAGE_READ_BACK_CRC_DISABLED; |
| 46 | static ImageCRCInfo AllImageCRCInfo __attribute__ ((aligned (4))); |
| 47 | |
| 48 | SkipBlocksInfoStruct *pSkipAddress = NULL; |
| 49 | UINT_T All_FF_flag = 0; |
| 50 | INT_T AB_DL = 0; //Indicate if AB system download |
| 51 | |
| 52 | pTIM pTIM_DTIM = NULL; |
| 53 | |
| 54 | Platform_ID Lookup_ChipID(UINT_T chipID) |
| 55 | { |
| 56 | Platform_ID ID = PLAT_UNKNOWN; |
| 57 | |
| 58 | switch (chipID) |
| 59 | { |
| 60 | //SWD treat below SoCs as 1826 for now |
| 61 | case 0x1829: |
| 62 | case 0x1901: |
| 63 | case 0x1803: |
| 64 | case 0x1802: |
| 65 | case 0x1806: |
| 66 | case 0x1906: |
| 67 | case 0x1903: |
| 68 | case 0x1826: |
| 69 | ID = PLAT_NEZHA3; |
| 70 | break; |
| 71 | case 0x1822: |
| 72 | ID = PLAT_NEZHA2; |
| 73 | break; |
| 74 | default: |
| 75 | break; |
| 76 | } |
| 77 | |
| 78 | return ID; |
| 79 | } |
| 80 | |
| 81 | UINT_T PlatformCheckChipID(Platform_ID chip_ID_num) |
| 82 | { |
| 83 | UINT_T ChipID_value; |
| 84 | Platform_ID ID_num, ID_numV2; |
| 85 | |
| 86 | ChipID_value = PlatformGetChipID(); |
| 87 | |
| 88 | if (chip_ID_num == PLAT_UNKNOWN) |
| 89 | return 1; |
| 90 | |
| 91 | ID_num = Lookup_ChipID(ChipID_value & 0xffff); |
| 92 | |
| 93 | if (ID_num == chip_ID_num) |
| 94 | return 0; |
| 95 | else |
| 96 | return 1; // chip ID check fail |
| 97 | } |
| 98 | |
| 99 | UINT32 PlatformGetPlatId(void) |
| 100 | { |
| 101 | UINT_T ChipID_value, PlatId; |
| 102 | ChipID_value = PlatformGetChipID(); |
| 103 | |
| 104 | PlatId = ChipID_value & 0xFFFF; |
| 105 | |
| 106 | if(ChipID_value == 0x1829) |
| 107 | PlatId = 0x1828; |
| 108 | |
| 109 | if(ChipID_value == 0x1802) |
| 110 | { |
| 111 | if(PlatformCoreIsCR5()) |
| 112 | PlatId = 0x531802; //1802S |
| 113 | else |
| 114 | PlatId = 0x4C531802; //1802SL |
| 115 | } |
| 116 | |
| 117 | |
| 118 | return PlatId; |
| 119 | } |
| 120 | |
| 121 | /* return value: 0 : CHIP and OS are both matched, 1: not matched*/ |
| 122 | INT PlatformFBFDevCheckChipOS(PDeviceHeader_11 pDevHeader) |
| 123 | { |
| 124 | UINT32 FFOSTypeInFbf, ChipIDinFbf, FFOSType, ChipIDinDevPara; |
| 125 | |
| 126 | FFOSTypeInFbf = pDevHeader->DeviceParameters[1]; |
| 127 | ChipIDinFbf = pDevHeader->ChipID; |
| 128 | |
| 129 | //FFOS_Type is not supported yet, old way, only check chip ID |
| 130 | if(FFOSTypeInFbf == 0) |
| 131 | { |
| 132 | return PlatformCheckChipID(ChipIDinFbf); |
| 133 | } |
| 134 | |
| 135 | if(PlatformCoreIsCR5()) |
| 136 | FFOSType = RTOS; |
| 137 | else |
| 138 | FFOSType = OWRT; |
| 139 | |
| 140 | if(FFOSType != FFOSTypeInFbf){ |
| 141 | return 1; //OS doesn't match |
| 142 | } |
| 143 | |
| 144 | /* ChipID mismatch, return */ |
| 145 | if(PlatformCheckChipID(ChipIDinFbf)){ |
| 146 | return 1; |
| 147 | } |
| 148 | |
| 149 | /* ChipID in FBF of 1826/1826S/1901/1803/1802SL are all PLAT_NEZHA3, |
| 150 | * need to check detail in DeviceParameters[0] |
| 151 | */ |
| 152 | if(ChipIDinFbf == PLAT_NEZHA3) |
| 153 | { |
| 154 | ChipIDinDevPara = pDevHeader->DeviceParameters[0]; |
| 155 | if(ChipIDinDevPara == PlatformGetPlatId()){ |
| 156 | return 0; |
| 157 | } |
| 158 | else{ |
| 159 | return 1; |
| 160 | } |
| 161 | } |
| 162 | return 0; |
| 163 | } |
| 164 | |
| 165 | /* return value: 0: CMOD matched, 1: not matched*/ |
| 166 | UINT_T PlatformFBFCheckCMOD(pTIM pTIM_FBF, PDeviceHeader_11 pDevHeader_11) |
| 167 | { |
| 168 | UINT_T imagenum; |
| 169 | INT_T temp_p; |
| 170 | TIM FlashTim; |
| 171 | pTIM pTIM_H_DL;; |
| 172 | pTIM pTIM_H_Flash = &FlashTim; |
| 173 | PImageStruct_11 pImage_11 = NULL; |
| 174 | pCMOD_INFO pCmodDlTim, pCmodFlashTim; |
| 175 | UINT_T Retval = NoError; |
| 176 | pWTP_RESERVED_AREA_HEADER pWRAH = NULL; |
| 177 | INT NoDLTimCMOD = 0; |
| 178 | INT NoDLTIM = 0; |
| 179 | INT i; |
| 180 | UCHAR *TempBuffer = 0; |
| 181 | |
| 182 | TempBuffer = malloc(0x4000); |
| 183 | |
| 184 | if(TempBuffer == NULL) |
| 185 | return HeapExhaustedError; |
| 186 | |
| 187 | pTIM_H_DL = pTIM_FBF; |
| 188 | |
| 189 | ReadFlash(0, TempBuffer, 0x4000, BOOT_FLASH); //Read TIM in flash, max tim is 16KB for all platforms |
| 190 | |
| 191 | SetTIMPointers((UINT8_T *)TempBuffer, pTIM_H_Flash); |
| 192 | |
| 193 | if(pTIM_H_DL->pConsTIM->VersionBind.Identifier != TIMIDENTIFIER){ |
| 194 | //obm_printf("Warning: No valid TIM in FBF\n\r"); |
| 195 | NoDLTIM = 1; |
| 196 | } |
| 197 | |
| 198 | if(NoDLTIM == 0) { |
| 199 | pWRAH = FindPackageInReserved(&Retval, pTIM_H_DL, CMODID); |
| 200 | if ((pWRAH == NULL) || (Retval != NoError)) |
| 201 | { |
| 202 | //obm_printf("No CMODID in DL TIM\n\r"); |
| 203 | NoDLTimCMOD = 1; |
| 204 | } |
| 205 | else |
| 206 | { |
| 207 | pCmodDlTim = (pCMOD_INFO) pWRAH; |
| 208 | } |
| 209 | } else { |
| 210 | NoDLTimCMOD == 1; |
| 211 | } |
| 212 | |
| 213 | /* If CMOD is "ASRCMODFORCEERASE", only erase all only is allowed */ |
| 214 | if( (NoDLTimCMOD == 0) && |
| 215 | (pCmodDlTim->Length == 17) && |
| 216 | (memcmp(pCmodDlTim->CMOD, "ASRCMODFORCEERASE", 17) == 0)) |
| 217 | { |
| 218 | free(TempBuffer); |
| 219 | if(pDevHeader_11->FlashOpt.EraseAll == 2){ |
| 220 | obm_printf("Magic CMOD to force erase\n\r"); |
| 221 | return 0; |
| 222 | }else{ |
| 223 | return 1; |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | if(pTIM_H_Flash->pConsTIM->VersionBind.Identifier != TIMIDENTIFIER){ |
| 228 | //obm_printf("No valid Flash TIM\n\r"); |
| 229 | free(TempBuffer); |
| 230 | return 0; //Allow to burn any version to an empty board except CMOD is ASRCMODFORCEERASE |
| 231 | } |
| 232 | |
| 233 | pWRAH = FindPackageInReserved(&Retval, pTIM_H_Flash, CMODID); |
| 234 | if ((pWRAH == NULL) || (Retval != NoError)) |
| 235 | { |
| 236 | //obm_printf("No CMOD in In Flash TIM\n\r"); |
| 237 | free(TempBuffer); |
| 238 | return 0; |
| 239 | } |
| 240 | else |
| 241 | { |
| 242 | if(NoDLTimCMOD == 1 || NoDLTIM == 1){ |
| 243 | //obm_printf("Flash TIM has CMOD, No DL TIM or No CMOD in DL TIM\n\r"); |
| 244 | free(TempBuffer); |
| 245 | return 1; |
| 246 | } |
| 247 | pCmodFlashTim = (pCMOD_INFO) pWRAH; |
| 248 | } |
| 249 | |
| 250 | obm_printf("CMOD in DL TIM: "); |
| 251 | for(i =0; i < pCmodDlTim->Length; i++) |
| 252 | obm_printf("%c", pCmodDlTim->CMOD[i]); |
| 253 | obm_printf("\n\r"); |
| 254 | |
| 255 | obm_printf("CMOD in In Flash TIM:"); |
| 256 | for(i =0; i < pCmodFlashTim->Length; i++) |
| 257 | obm_printf("%c", pCmodFlashTim->CMOD[i]); |
| 258 | obm_printf("\n\r"); |
| 259 | |
| 260 | free(TempBuffer); |
| 261 | |
| 262 | if(pCmodDlTim->Length != pCmodFlashTim->Length) |
| 263 | return 1; |
| 264 | |
| 265 | if(memcmp(pCmodDlTim->CMOD, pCmodFlashTim->CMOD, pCmodFlashTim->Length) == 0) |
| 266 | return 0; |
| 267 | else |
| 268 | return 1; |
| 269 | } |
| 270 | |
| 271 | UINT32 PlatformFBFCheckDownload(pTIM pTIM_FBF, PDeviceHeader_11 pDevHeader_11) |
| 272 | { |
| 273 | UINT32 Retval = NoError; |
| 274 | |
| 275 | if(PlatformFBFCheckCMOD(pTIM_FBF, pDevHeader_11)) |
| 276 | Retval = CMODMISMATCH; |
| 277 | |
| 278 | if(PlatformFBFDevCheckChipOS(pDevHeader_11)) |
| 279 | Retval = CHIPIDMISMATCH; |
| 280 | |
| 281 | if(Retval != NoError) |
| 282 | { |
| 283 | ASRFlag_DLStatus_Update(pTIM_FBF, 0, 0); |
| 284 | |
| 285 | FatalError(Retval, "PFCD", NULL); |
| 286 | } |
| 287 | |
| 288 | return Retval; |
| 289 | } |
| 290 | |
| 291 | UINT32 PlatformFBFCheckSWDVersion(PDeviceHeader_11 pDevHeader_11) |
| 292 | { |
| 293 | UINT_T LegacySWDNotSupported = 0; |
| 294 | UINT32 SWDVerInFBF = pDevHeader_11->DeviceParameters[3]; |
| 295 | |
| 296 | #if defined(CONFIG_AB_SYSTEM) || (ENABLE_ATRB) |
| 297 | /* legacy SWD is the one older than 4.9.1.9 |
| 298 | * which doesn't support SWD version in FBF |
| 299 | */ |
| 300 | LegacySWDNotSupported = 1; |
| 301 | #endif |
| 302 | |
| 303 | if(LegacySWDNotSupported && (SWDVerInFBF == 0)) |
| 304 | { |
| 305 | goto swd_out_of_date; |
| 306 | } |
| 307 | |
| 308 | if (SWDVerInFBF != 0) |
| 309 | { |
| 310 | obm_printf("SWDownloader used: %s\n\r", HexToSwdObmVersion(SWDVerInFBF)); |
| 311 | |
| 312 | if(SWDVerInFBF < SWD_VERSION) { |
| 313 | goto swd_out_of_date; |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | return NoError; |
| 318 | |
| 319 | swd_out_of_date: |
| 320 | obm_printf("SWDownloader is out of date\n\r"); |
| 321 | obm_printf("Please upgrade to %s\n\r", HexToSwdObmVersion(SWD_VERSION)); |
| 322 | return SWD_OUTOFDATE; |
| 323 | } |
| 324 | |
| 325 | #if ENABLE_ATRB |
| 326 | /* For Downloading, only check major version anti-rollback */ |
| 327 | UINT_T TIMDownloadAntiRollbackCheck(pTIM pTIM_h) |
| 328 | { |
| 329 | UINT_T Retval = NoError; |
| 330 | UINT_T MajorVersionInTIM = 0; |
| 331 | UINT_T AntiRollbackTimEnabled; |
| 332 | UINT_T AntiRollbackFuseEnabled; |
| 333 | INT_T AntiRollbackFuseVersion; |
| 334 | |
| 335 | AntiRollbackTimEnabled = CheckAntiRollbackPackage(pTIM_h, &MajorVersionInTIM); |
| 336 | AntiRollbackTimEnabled &= MAJOR_ATRB_ENABLED; |
| 337 | |
| 338 | AntiRollbackFuseEnabled = GEU_MajorAntiRollBackEnabled(); |
| 339 | if(AntiRollbackFuseEnabled) |
| 340 | { |
| 341 | /* The chip is already burned to enable anti-rollback */ |
| 342 | AntiRollbackFuseVersion = GEU_ReadMajorVersion(); |
| 343 | if(AntiRollbackTimEnabled == 0 || MajorVersionInTIM < AntiRollbackFuseVersion) |
| 344 | { |
| 345 | obm_printf("Anti-rollback error: %d %d %d\n\r", AntiRollbackTimEnabled, |
| 346 | MajorVersionInTIM, AntiRollbackFuseVersion); |
| 347 | FatalError(ATRB_MajorRollbackError, "ATRB", 1); |
| 348 | return ATRB_MajorRollbackError; |
| 349 | } |
| 350 | |
| 351 | if(MajorVersionInTIM > AntiRollbackFuseVersion) |
| 352 | { |
| 353 | Retval = GEU_ProgramMajorVersion(pTIM_h); |
| 354 | if(Retval != NoError) |
| 355 | FatalError(Retval, "ATRB", 2); |
| 356 | } |
| 357 | return Retval; |
| 358 | } |
| 359 | |
| 360 | /* The chip is not already burned to enable anti-rollback, burn it here */ |
| 361 | if(AntiRollbackTimEnabled) |
| 362 | { |
| 363 | Retval = GEU_ProgramMajorVersion(pTIM_h); |
| 364 | if(Retval != NoError) |
| 365 | FatalError(Retval, "ATRB", 3); |
| 366 | obm_printf("ATRB: burn major version as %d\n\r", MajorVersionInTIM); |
| 367 | } |
| 368 | |
| 369 | return Retval; |
| 370 | } |
| 371 | #endif |
| 372 | |
| 373 | INT_T IsDLImageDTIM(PImageStruct_11 pImage_11) |
| 374 | { |
| 375 | #if BURN_DTIM_LAST |
| 376 | if (((pImage_11->Image_ID & 0xFFFFFF00) == TIM_TYPE)) |
| 377 | { |
| 378 | switch(pImage_11->Image_In_TIM) { |
| 379 | case 0: /* NTIM */ |
| 380 | case 1: /* TIMH */ |
| 381 | case 5: /* TIMH recovery */ |
| 382 | return 0; |
| 383 | default: /* differnet DTIMs */ |
| 384 | return 1; |
| 385 | } |
| 386 | } |
| 387 | |
| 388 | #if defined(CONFIG_ASR_SDTIM) && OUM4DFOTA |
| 389 | /* If SDTIM is enabled and OUM is used, |
| 390 | * OUM locates in first 10 blocks and has a SDTIM ahead. |
| 391 | * Then OUM also needs to be burned after TIMH/OBMI |
| 392 | */ |
| 393 | if (pImage_11->Image_ID == OUMIDENTIFIER) |
| 394 | return 1; |
| 395 | #endif |
| 396 | |
| 397 | #endif |
| 398 | |
| 399 | return 0; |
| 400 | } |
| 401 | |
| 402 | static pDtimDlInfo_t DtimDLInfo[MAX_DL_DTIM_NUM]; |
| 403 | static INT_T DtimDLNums = 0; |
| 404 | |
| 405 | VOID SaveDTIMs2Memory(PImageStruct_11 pImage_11, UINT_T FbfLoadAddr) |
| 406 | { |
| 407 | pDtimDlInfo_t pDtimDLInfo = NULL; |
| 408 | |
| 409 | pDtimDLInfo = malloc(sizeof(DtimDlInfo_t) + pImage_11->length); |
| 410 | if(pDtimDLInfo == NULL) |
| 411 | FatalError(HeapExhaustedError, NULL, NULL); |
| 412 | |
| 413 | pDtimDLInfo->Image_ID = pImage_11->Image_ID; |
| 414 | pDtimDLInfo->Length = pImage_11->length; |
| 415 | pDtimDLInfo->FlashOffsetA = pImage_11->Flash_Start_Address; |
| 416 | pDtimDLInfo->FlashOffsetB = pImage_11->Flash_Start_Address_B; |
| 417 | |
| 418 | memcpy(pDtimDLInfo->Buffer, FbfLoadAddr+(pImage_11->First_Sector<<12), pImage_11->length); |
| 419 | |
| 420 | DtimDLInfo[DtimDLNums] = pDtimDLInfo; |
| 421 | DtimDLNums ++; |
| 422 | |
| 423 | if (DtimDLNums == MAX_DL_DTIM_NUM) |
| 424 | FatalError(TooMuchDlDTims, NULL, NULL); |
| 425 | } |
| 426 | |
| 427 | VOID BurnDTIMs2Flash(VOID) |
| 428 | { |
| 429 | INT_T i; |
| 430 | UINT_T Retval = NoError; |
| 431 | pDtimDlInfo_t pDtimDLInfo = NULL; |
| 432 | |
| 433 | if (DtimDLNums == 0) |
| 434 | return; |
| 435 | |
| 436 | for (i = 0; i < DtimDLNums; i ++) |
| 437 | { |
| 438 | pDtimDLInfo = DtimDLInfo[i]; |
| 439 | Retval = WriteFlash(pDtimDLInfo->FlashOffsetA, pDtimDLInfo->Buffer, pDtimDLInfo->Length, BOOT_FLASH); |
| 440 | if(Retval == NoError && pDtimDLInfo->FlashOffsetB != 0xFFFFFFFF) { |
| 441 | Retval = WriteFlash(pDtimDLInfo->FlashOffsetB, pDtimDLInfo->Buffer, pDtimDLInfo->Length, BOOT_FLASH); |
| 442 | } |
| 443 | if(Retval) |
| 444 | obm_printf("Write %s fails\n\r", ImageID2String(pDtimDLInfo->Image_ID)); |
| 445 | free(pDtimDLInfo); |
| 446 | } |
| 447 | } |
| 448 | |
| 449 | ////////////////////////////////////////////////////////////////////// |
| 450 | // This is the entry point for the TIM based download functionality. |
| 451 | // |
| 452 | // Inputs: Pointer to the TIM we just downloaded. |
| 453 | // Outputs: Returns the next image (OBM) that we will transfer the control to. |
| 454 | // |
| 455 | // It mainly functions as following: |
| 456 | // 1) Sets the TIM pointers. |
| 457 | // 2) Validates the downloaded TIM. |
| 458 | // 3) Configures the Flashes. |
| 459 | // 4) Wipes the whole Flash device. |
| 460 | // 5) Checks if there is already a FBBT on the Flash. If there is |
| 461 | // NO FBBT on the Flash, creates it. |
| 462 | // 6) Checks if there is a PT being downloaded. If so, it first |
| 463 | // tries to validate it with the existing HW partitions on the |
| 464 | // Flash. If they don't match, re-creates the HW partitions. |
| 465 | // If HW partitions are not supported, these functions will do |
| 466 | // nothing and return. Next, the downloaded PT is loaded into |
| 467 | // Flash Management (FM). |
| 468 | // 7) Runtime-BBT is generated. |
| 469 | // 8) Writes the downloaded TIM, created FBBT, PT to Flash. |
| 470 | // 9) Download TIM Images LOOP implements the following: |
| 471 | // i. Download Image |
| 472 | // ii. Validate Image |
| 473 | // iii. Set Partition |
| 474 | // iv. Erase Image Area from Flash |
| 475 | // v. Write the image to Flash |
| 476 | // vi. Verify the Flash write |
| 477 | // 10) The RBBT is written to the Flash. |
| 478 | ////////////////////////////////////////////////////////////////////// |
| 479 | pIMAGE_INFO_3_4_0 TIMDownloadMain(pFUSE_SET pFuses, pTIM pTIM_h) |
| 480 | { |
| 481 | pIMAGE_INFO_3_4_0 pImageInfo = NULL; |
| 482 | UINT_T Retval = NoError; |
| 483 | UINT8_T FlashNumber = 0; |
| 484 | pWTP_RESERVED_AREA_HEADER pWRAH = NULL; |
| 485 | pImage_CRC_Check crcCheck; |
| 486 | |
| 487 | // setup the TIM pointers in pTIM_h |
| 488 | Retval = LoadTim((UINT8_T*)pTIM_h->pConsTIM, pTIM_h, TRUE); |
| 489 | if (Retval != NoError) |
| 490 | { |
| 491 | FatalError(Retval, "TDM", 1); |
| 492 | } |
| 493 | |
| 494 | #if ENABLE_ATRB |
| 495 | Retval = TIMDownloadAntiRollbackCheck(pTIM_h); |
| 496 | if (Retval != NoError) |
| 497 | { |
| 498 | FatalError(Retval, "TDM", 2); |
| 499 | } |
| 500 | #endif |
| 501 | |
| 502 | Retval = PlatformInitFlash(pTIM_h); |
| 503 | if( Retval != NoError) |
| 504 | FatalError(Retval, "TDM", 3); |
| 505 | |
| 506 | |
| 507 | #if IMG_RBC |
| 508 | pWRAH = FindPackageInReserved(&Retval, pTIM_h, CRCS); |
| 509 | if ((pWRAH == NULL) || (Retval != NoError)) |
| 510 | { |
| 511 | DownloadReadBackCRC = IMAGE_READ_BACK_CRC_DISABLED; |
| 512 | } |
| 513 | else |
| 514 | { |
| 515 | crcCheck = (pImage_CRC_Check) pWRAH; |
| 516 | if(crcCheck->Enabled) |
| 517 | DownloadReadBackCRC = IMAGE_READ_BACK_CRC_ENABLED; |
| 518 | else |
| 519 | DownloadReadBackCRC = IMAGE_READ_BACK_CRC_DISABLED; |
| 520 | } |
| 521 | |
| 522 | if(IMAGE_READ_BACK_CRC_ENABLED == DownloadReadBackCRC) |
| 523 | obm_printf("Image RB/CRC Enabled\n\r"); |
| 524 | else |
| 525 | obm_printf("Image RB/CRC disabled\n\r"); |
| 526 | #endif |
| 527 | |
| 528 | ASRFlag_DLStatus_Update(pTIM_h, DLFLG, 0); |
| 529 | |
| 530 | obm_printf("Download...\n\r"); |
| 531 | |
| 532 | // At this point, we can start downloading images one by one. |
| 533 | // IMPORTANT: For now, we download all the images to their load address that is |
| 534 | // specified in the TIM. We assume that the images will not overwrite the existing |
| 535 | // DKB code that is already running. |
| 536 | // |
| 537 | // KDA TO DO: |
| 538 | // Potentially, we might want to download all the images to a specific |
| 539 | // DOWNLOAD_AREAD in the DDR. |
| 540 | pImageInfo = DownloadTIMImages(pFuses, pTIM_h); |
| 541 | |
| 542 | return pImageInfo; |
| 543 | } |
| 544 | |
| 545 | UINT_T ValidateTIMInFBF(UINT_T address, PImageStruct_11 pTIM_Image, TIMIncluded_Type type, UINT_T verify_aux) |
| 546 | { |
| 547 | pTIM pTIM_h = NULL; |
| 548 | #if TRUSTED && SECURE_DOWNLOAD |
| 549 | pTIM pTIM_h_boot = NULL; |
| 550 | #endif |
| 551 | UINT_T Retval = NoError; |
| 552 | |
| 553 | if (type == TIMH_NOTINC) |
| 554 | return NoError; |
| 555 | else |
| 556 | pTIM_h = (pTIM_DTIM + type); |
| 557 | |
| 558 | Retval = SetTIMPointers((UINT8_T *)(address + (pTIM_Image->First_Sector << 12)), pTIM_h); |
| 559 | if (Retval != NoError) |
| 560 | return 1; |
| 561 | |
| 562 | #if TRUSTED && SECURE_DOWNLOAD |
| 563 | if (verify_aux) { |
| 564 | switch(type) { |
| 565 | case DTIM_PRIMARY_INC: |
| 566 | case DTIM_RECOVERY_INC: |
| 567 | pTIM_h_boot = GetBootTIMH(); |
| 568 | if (pTIM_h_boot == NULL) |
| 569 | return 4; |
| 570 | Retval = ValiateDTIM(pTIM_h, pTIM_h_boot); |
| 571 | if (Retval!= NoError) |
| 572 | return 5; |
| 573 | return NoError; |
| 574 | break; |
| 575 | case TIMH_RECOVERY_INC: |
| 576 | case TIMH_INC: |
| 577 | Retval = VerifyPlatformKey(pTIM_h); |
| 578 | if (Retval != NoError) |
| 579 | return 3; |
| 580 | break; |
| 581 | default: |
| 582 | break; |
| 583 | } |
| 584 | } |
| 585 | #endif |
| 586 | |
| 587 | if (pTIM_h->pConsTIM->VersionBind.Trusted) |
| 588 | { |
| 589 | Retval = ValidateTIMSignature(pTIM_h); // validate TIMH |
| 590 | if (Retval != NoError) |
| 591 | return 2; |
| 592 | } |
| 593 | |
| 594 | return Retval; |
| 595 | } |
| 596 | |
| 597 | UINT_T ValidateImageInTIM(UINT_T address, PImageStruct_11 pImage, pTIM pTIM_h) |
| 598 | { |
| 599 | UINT_T Retval = NoError; |
| 600 | UINT_T ImageAddr; |
| 601 | #ifdef CONFIG_ASR_SDTIM |
| 602 | pIMAGE_INFO_3_4_0 pSDtimImageInfo = NULL; |
| 603 | pTIM pSDTim_h = NULL; |
| 604 | #endif |
| 605 | pIMAGE_INFO_3_4_0 pImageInfo = NULL; |
| 606 | pTIM pTIM_V = NULL; |
| 607 | UINT8_T *ImageBuff = NULL; |
| 608 | UINT_T ImageType; |
| 609 | UINT_T DecompressLen = 0; |
| 610 | |
| 611 | #if XZ_SUPPORT || XZDEC_SUPPORT |
| 612 | VOID *nextInBuf = NULL; |
| 613 | INT_T compressed = 0; |
| 614 | #endif |
| 615 | |
| 616 | |
| 617 | if ((pTIM_h != NULL) && (pImage->Image_In_TIM != TIMH_NOTINC)) |
| 618 | { |
| 619 | if ((pImage->Image_ID & 0xFFFFFF00) != TIM_TYPE) // this is not TIMx in FBF file |
| 620 | { |
| 621 | if (pTIM_h->pConsTIM->VersionBind.Trusted) |
| 622 | { |
| 623 | ImageAddr = address + (pImage->First_Sector << 12); |
| 624 | #ifdef CONFIG_ASR_SDTIM |
| 625 | pImageInfo = FindImageInTIM(pTIM_h, pImage->Image_ID); |
| 626 | if(pImageInfo == NULL) |
| 627 | return Retval; |
| 628 | |
| 629 | if(ImageIsSDTIMIncluded(pImageInfo)) { |
| 630 | pSDTim_h = malloc(sizeof(TIM)); |
| 631 | if(pSDTim_h == NULL) |
| 632 | return HeapExhaustedError; |
| 633 | |
| 634 | Retval = SetTIMPointers(ImageAddr, pSDTim_h); |
| 635 | if(Retval) |
| 636 | return TIMNotFound; |
| 637 | |
| 638 | pSDtimImageInfo = FindImageInTIM(pSDTim_h, SDTIM); |
| 639 | if(pSDtimImageInfo == NULL) { |
| 640 | free(pSDTim_h); |
| 641 | return Retval; |
| 642 | } |
| 643 | |
| 644 | if (0 == GetSDTimSecureConfig(pSDtimImageInfo)) |
| 645 | goto exit; |
| 646 | ImageAddr += GetSDTimSpaceSize(pSDtimImageInfo); |
| 647 | pTIM_V = pSDTim_h; |
| 648 | |
| 649 | } else |
| 650 | #endif |
| 651 | { |
| 652 | pTIM_V = pTIM_h; |
| 653 | } |
| 654 | |
| 655 | #if LZMA_SUPPORT |
| 656 | ImageType = IMAGE_TYPE(pImage->commands); |
| 657 | if (DLCMD_IMG_LZMA_IMAGE_TYPE == ImageType) { |
| 658 | pImageInfo = FindImageInTIM(pTIM_V, pImage->Image_ID); |
| 659 | if (pImageInfo == NULL) |
| 660 | { |
| 661 | Retval = ImageNotFound; |
| 662 | goto exit; |
| 663 | } |
| 664 | DecompressLen = pImageInfo->ImageSizeToHash; |
| 665 | ImageBuff = malloc(DecompressLen); |
| 666 | if(ImageBuff == NULL) { |
| 667 | Retval = HeapExhaustedError; |
| 668 | goto exit; |
| 669 | } |
| 670 | Retval = LZMA_Decompress(ImageBuff, |
| 671 | &DecompressLen, |
| 672 | ImageAddr, |
| 673 | pImage->length, |
| 674 | 0x0); |
| 675 | if(Retval != NoError) { |
| 676 | obm_printf("LZMA Decompress error\n\r"); |
| 677 | goto exit; |
| 678 | } |
| 679 | ImageAddr = ImageBuff; |
| 680 | } |
| 681 | #endif |
| 682 | |
| 683 | #if XZ_SUPPORT || XZDEC_SUPPORT |
| 684 | ImageType = IMAGE_TYPE(pImage->commands); |
| 685 | if (DLCMD_IMG_MXZ_IMAGE_TYPE == ImageType) { |
| 686 | pImageInfo = FindImageInTIM(pTIM_V, pImage->Image_ID); |
| 687 | if (pImageInfo == NULL) |
| 688 | { |
| 689 | Retval = ImageNotFound; |
| 690 | goto exit; |
| 691 | } |
| 692 | ImageBuff = malloc(pImageInfo->ImageSizeToHash); |
| 693 | if(ImageBuff == NULL) { |
| 694 | Retval = HeapExhaustedError; |
| 695 | goto exit; |
| 696 | } |
| 697 | DecompressLen = pImageInfo->ImageSizeToHash; |
| 698 | Retval = xz_decompress(ImageAddr, pImage->length, ImageBuff, &DecompressLen, &nextInBuf, &compressed); |
| 699 | if(Retval) { |
| 700 | Retval = XZDecodeError; |
| 701 | goto exit; |
| 702 | } |
| 703 | ImageAddr = ImageBuff; |
| 704 | } |
| 705 | #endif |
| 706 | |
| 707 | Retval = ValidateImage(ImageAddr, pImage->Image_ID, pTIM_V); |
| 708 | if (Retval != NoError) |
| 709 | FatalError(Retval, "VIIT", NULL); |
| 710 | |
| 711 | return Retval; |
| 712 | } |
| 713 | } |
| 714 | } |
| 715 | |
| 716 | exit: |
| 717 | |
| 718 | #ifdef CONFIG_ASR_SDTIM |
| 719 | if(pSDTim_h) free(pSDTim_h); |
| 720 | #endif |
| 721 | |
| 722 | return Retval; |
| 723 | } |
| 724 | |
| 725 | UINT_T DLEraseFlashToBurnImage(PImageStruct_11 pImage_11) |
| 726 | { |
| 727 | UINT_T Retval = NoError; |
| 728 | P_FOTA_Info pFOTAInfo = &FOTAInfo; |
| 729 | |
| 730 | #if MMC_CODE |
| 731 | if (((pImage_11->commands & 0xF) == 2) || //erase only for eMMC, NAND needs to erase before writing |
| 732 | (pImage_11->Flash_erase_size > pImage_11->length) // erase eMMC if user set erase size in blf |
| 733 | ) |
| 734 | #endif |
| 735 | { |
| 736 | Retval = EraseFlash(pImage_11->Flash_Start_Address, pImage_11->Flash_erase_size, BOOT_FLASH ); |
| 737 | if(AB_DL && (pImage_11->Flash_Start_Address_B != 0xFFFFFFFF)) |
| 738 | Retval |= EraseFlash(pImage_11->Flash_Start_Address_B, pImage_11->Flash_erase_size, BOOT_FLASH ); |
| 739 | } |
| 740 | |
| 741 | if(Retval != NoError ) |
| 742 | FatalError(Retval, "DLEF", NULL); |
| 743 | |
| 744 | if(pFOTAInfo->FOTA_Addr >= pImage_11->Flash_Start_Address && |
| 745 | (pFOTAInfo->FOTA_Addr+sizeof(FOTA_Firmware)) <= (pImage_11->Flash_Start_Address+pImage_11->Flash_erase_size)) |
| 746 | { |
| 747 | //Force ASR flag re-init later. |
| 748 | pFOTAInfo->InitFlag = 0; |
| 749 | } |
| 750 | |
| 751 | if(AB_DL && (pFOTAInfo->FOTA_Addr >= pImage_11->Flash_Start_Address_B) && |
| 752 | (pFOTAInfo->FOTA_Addr+sizeof(FOTA_Firmware)) <= (pImage_11->Flash_Start_Address_B+pImage_11->Flash_erase_size)) |
| 753 | { |
| 754 | //Force ASR flag re-init later. |
| 755 | pFOTAInfo->InitFlag = 0; |
| 756 | } |
| 757 | |
| 758 | return Retval; |
| 759 | } |
| 760 | |
| 761 | UINT_T DLBurnImageToFlash(PImageStruct_11 pImage_11, UINT_T loadAddr) |
| 762 | { |
| 763 | UINT_T Retval = NoError; |
| 764 | UINT_T imageType = DLCMD_RAW_BINARY_IMAGE_TYPE; |
| 765 | #if NZAS |
| 766 | P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH); |
| 767 | UINT_T Temp1 = 0, Temp2 = 0, Len1, Len2; |
| 768 | #endif |
| 769 | |
| 770 | #if DUAL_TIM |
| 771 | UINT8_T *TmpBuf = NULL; |
| 772 | pIMAGE_INFO_3_4_0 pTimInfo = NULL; |
| 773 | pIMAGE_INFO_3_4_0 pObmInfo = NULL; |
| 774 | UINT_T TimOBMLen = 0; |
| 775 | pTIM pTIM_h; |
| 776 | #endif |
| 777 | |
| 778 | imageType = IMAGE_TYPE(pImage_11->commands); |
| 779 | #if NAND_CODE |
| 780 | if ( imageType == DLCMD_YAFFS_IMAGE_TYPE) |
| 781 | { |
| 782 | SetUseSpareArea( TRUE, BOOT_FLASH ); |
| 783 | All_FF_flag = 1; |
| 784 | } |
| 785 | else if(imageType == DLCMD_UBIFS_IMAGE_TYPE) |
| 786 | { |
| 787 | SetUseSpareArea( FALSE, BOOT_FLASH); |
| 788 | All_FF_flag = 1; |
| 789 | } |
| 790 | else |
| 791 | { |
| 792 | SetUseSpareArea( FALSE, BOOT_FLASH ); |
| 793 | All_FF_flag = 0; |
| 794 | } |
| 795 | #endif |
| 796 | |
| 797 | #if MMC_CODE |
| 798 | if (imageType == DLCMD_SPARSE_IMAGE_TYPE) |
| 799 | { |
| 800 | Retval = HandleSparseImage(loadAddr+(pImage_11->First_Sector<<12), |
| 801 | pImage_11->Flash_Start_Address, |
| 802 | pImage_11->length, |
| 803 | BOOT_FLASH); |
| 804 | } |
| 805 | else |
| 806 | #endif |
| 807 | { /* not MMC_CODE */ |
| 808 | #if NZAC |
| 809 | //To workaroud the issue that 1802SL BootROM miss a word when OBM size is bigger than 0x1df88 in SPI-NOR |
| 810 | if(PlatformIsNezhac() && (pImage_11->Image_ID == OBMIDENTIFIER) && (pFlashP->FlashType == SPI_FLASH) |
| 811 | && (pImage_11->length > 0x1df88)) |
| 812 | { |
| 813 | Temp1 = loadAddr+(pImage_11->First_Sector<<12); |
| 814 | Temp2 = malloc(256*1024); |
| 815 | if(Temp2 == NULL) |
| 816 | return HeapExhaustedError; |
| 817 | Len1 = Len2 = pImage_11->length; |
| 818 | while(Len1) |
| 819 | { |
| 820 | memcpy((void *)Temp2, (void *)Temp1, 0x1df88); |
| 821 | Temp1 += 0x1df88; |
| 822 | Temp2 += 0x1df88; |
| 823 | *(UINT_T *)Temp2 = 0xdeadbeef;//This word will not be read by BootROM |
| 824 | Temp2 += 4; |
| 825 | Len2 += 4; |
| 826 | Len1 -= 0x1df88; |
| 827 | if(Len1 <= 0x1df88){ |
| 828 | memcpy((void *)Temp2, (void *)Temp1, Len1); |
| 829 | break; |
| 830 | } |
| 831 | } |
| 832 | Retval = WriteFlash( pImage_11->Flash_Start_Address, |
| 833 | Temp2, |
| 834 | Len2, BOOT_FLASH ); |
| 835 | free(Temp2); |
| 836 | goto read_back_check; |
| 837 | } |
| 838 | #endif /* NZAS */ |
| 839 | |
| 840 | #if DUAL_TIM |
| 841 | if((pImage_11->Image_ID == OBMIDENTIFIER) && DualTimEnabled() && !DualTimIsEqual()) |
| 842 | { |
| 843 | pTIM_h = pTIM_DTIM + TIMH_INC; /* main TIMH */ |
| 844 | if(pTIM_h->pConsTIM->VersionBind.Identifier != TIMIDENTIFIER) |
| 845 | FatalError(TIMNotFound, "DLB", 1); |
| 846 | pTimInfo = FindImageInTIM(pTIM_h, TIMIDENTIFIER); |
| 847 | pObmInfo = FindImageInTIM(pTIM_h, OBMIDENTIFIER); |
| 848 | if(pTimInfo == NULL || pObmInfo == NULL) |
| 849 | FatalError(ImageNotFound, "DLB", 2); |
| 850 | TimOBMLen = pImage_11->length + pTimInfo->ImageSize; |
| 851 | #if MMC_CODE |
| 852 | if(TimOBMLen > MAX_OBM_SIZE) |
| 853 | #else |
| 854 | if(TimOBMLen > GetFlashProperties(BOOT_FLASH)->BlockSize) |
| 855 | #endif |
| 856 | obm_printf("Warning :OBM may be too big for Dual-TIM\n\r"); |
| 857 | |
| 858 | TmpBuf = malloc(TimOBMLen); |
| 859 | if(TmpBuf == NULL) |
| 860 | return HeapExhaustedError; |
| 861 | |
| 862 | memset(TmpBuf, 0, TimOBMLen); |
| 863 | memcpy(TmpBuf, loadAddr+(pImage_11->First_Sector<<12), pImage_11->length); |
| 864 | #if MMC_CODE |
| 865 | if (pImage_11->Flash_partition == MMC_SD_BOOT_PARTITION) { |
| 866 | #else |
| 867 | if (pObmInfo->FlashEntryAddr == pImage_11->Flash_Start_Address) { |
| 868 | #endif |
| 869 | pTIM_h = pTIM_DTIM + TIMH_RECOVERY_INC; |
| 870 | memcpy(TmpBuf+pImage_11->length, pTIM_h->pConsTIM, pTimInfo->ImageSize); |
| 871 | } |
| 872 | else { |
| 873 | memcpy(TmpBuf+pImage_11->length, pTIM_h->pConsTIM, pTimInfo->ImageSize); |
| 874 | } |
| 875 | Retval = WriteFlash( pImage_11->Flash_Start_Address, |
| 876 | TmpBuf, |
| 877 | TimOBMLen, BOOT_FLASH); |
| 878 | free(TmpBuf); |
| 879 | } else if(pImage_11->Image_ID == TIMIDENTIFIER && |
| 880 | pImage_11->Image_In_TIM == TIMH_RECOVERY_INC && |
| 881 | DualTimIsEqual()) |
| 882 | { |
| 883 | pTIM_h = pTIM_DTIM + TIMH_INC; /* main TIMH */ |
| 884 | Retval = WriteFlash( pImage_11->Flash_Start_Address, |
| 885 | pTIM_h->pConsTIM, |
| 886 | pImage_11->length, BOOT_FLASH); |
| 887 | }else |
| 888 | #endif |
| 889 | { |
| 890 | Retval = WriteFlash( pImage_11->Flash_Start_Address, |
| 891 | loadAddr+(pImage_11->First_Sector<<12), |
| 892 | pImage_11->length, BOOT_FLASH); |
| 893 | |
| 894 | |
| 895 | if(AB_DL && (pImage_11->Flash_Start_Address_B != 0xFFFFFFFF)) { |
| 896 | Retval |= WriteFlash( pImage_11->Flash_Start_Address_B, |
| 897 | loadAddr+(pImage_11->First_Sector<<12), |
| 898 | pImage_11->length, BOOT_FLASH); |
| 899 | } |
| 900 | } |
| 901 | |
| 902 | read_back_check: |
| 903 | #if IMG_RBC |
| 904 | if(Retval == NoError && DownloadReadBackCRC == IMAGE_READ_BACK_CRC_ENABLED) |
| 905 | { |
| 906 | Retval = ImageReadBackAndCRC(pImage_11); |
| 907 | } |
| 908 | #else |
| 909 | ; //do nothing, avoid "label at end of compound statement" error |
| 910 | #endif |
| 911 | } /* not MMC_CODE */ |
| 912 | |
| 913 | return Retval; |
| 914 | } |
| 915 | |
| 916 | ////////////////////////////////////////////////////////////////////// |
| 917 | // This is the actual image downloading function for the TIM based |
| 918 | // download mode. |
| 919 | // |
| 920 | // Inputs: TIM which includes a list of all the images that will be |
| 921 | // downloaded. |
| 922 | // Outputs: Returns the OBM image to whom we will trasfer control to. |
| 923 | // |
| 924 | // It mainly iterates through all the images listed in the TIM and |
| 925 | // 1) If NOT TIM, downloads the image. |
| 926 | // 2) Validates the image. |
| 927 | // 3) Calls the Erase and Write function for this image. |
| 928 | // 4) Finally, finds the OBM image in the TIM and returns it. |
| 929 | ////////////////////////////////////////////////////////////////////// |
| 930 | pIMAGE_INFO_3_4_0 DownloadTIMImages (pFUSE_SET pFuses, pTIM pTIM_h) |
| 931 | { |
| 932 | UINT_T Retval = NoError; |
| 933 | UINT_T ImageSize; |
| 934 | pIMAGE_INFO_3_4_0 pImageInfo = NULL, pNextImageInfo = NULL; |
| 935 | UINT_T NumImages; |
| 936 | UINT_T loadAddr = 0; |
| 937 | UINT_T OKtoErase = 1; |
| 938 | MasterBlockHeader* pMasterHeader = NULL; |
| 939 | PDeviceHeader_11 pDevHeader_11=NULL; |
| 940 | PImageStruct_11 pImage_11 = NULL; |
| 941 | UINT_T imagenum, i, skip_blocks; |
| 942 | UINT_T temp_p = NULL; |
| 943 | UINT_T NandID_Right; |
| 944 | UINT_T OBMFlashAddr; |
| 945 | P_FOTA_Info pFOTAInfo = &FOTAInfo; |
| 946 | INT_T TIMHLoaded = 0; |
| 947 | CHAR MVersionStr[128]; |
| 948 | CHAR *PStr = NULL; |
| 949 | INT_T MVersionInFbf = 0; |
| 950 | P_FOTA_Firmware pFOTA_T = NULL; |
| 951 | |
| 952 | // Depending on the version of the TIM, determine the size of each image in bytes. |
| 953 | // We will use this size to iterate through the TIM binary from image to image. |
| 954 | if (pTIM_h->pConsTIM->VersionBind.Version >= TIM_3_4_00) |
| 955 | ImageSize = sizeof(IMAGE_INFO_3_4_0); |
| 956 | else |
| 957 | ImageSize = sizeof(IMAGE_INFO_3_2_0); |
| 958 | |
| 959 | // This is the very initial TIM image! Assumes that the TIM image is located at the top of the |
| 960 | // TIM file. Otherwise, we would skip images. |
| 961 | NumImages = pTIM_h->pConsTIM->NumImages; |
| 962 | pImageInfo = (IMAGE_INFO_3_4_0*)((unsigned char*)pTIM_h->pImg + (NumImages-1)*ImageSize); // index to last image info record. |
| 963 | |
| 964 | // For each image, download, validate and copy |
| 965 | while (NumImages && (Retval == NoError)) |
| 966 | { |
| 967 | if (NumImages > 1) |
| 968 | { |
| 969 | loadAddr = malloc(pImageInfo->ImageSize + 0x20000); |
| 970 | if(loadAddr == 0) |
| 971 | return HeapExhaustedError; |
| 972 | Retval = PM_ReceiveImage(NULL, loadAddr, pImageInfo->ImageSize, pImageInfo->ImageID); |
| 973 | if(Retval == UnknownImageError) |
| 974 | { |
| 975 | Retval = NoError; |
| 976 | goto nextimage; |
| 977 | } |
| 978 | if (Retval != NoError) |
| 979 | FatalError(Retval, "DTI", 1); |
| 980 | } |
| 981 | else loadAddr = (UINT_T)(pTIM_h->pConsTIM); // first image, TIM. use the address provided by caller. |
| 982 | |
| 983 | #if COPYIMAGESTOFLASH |
| 984 | if(pImageInfo->FlashEntryAddr == 0xFFFFFFFF) |
| 985 | goto nextimage; |
| 986 | // Copy the Image |
| 987 | AddMessageError(REPORT_NOTIFICATION, PlatformBusy); |
| 988 | |
| 989 | if ((pImageInfo->ImageID & 0xFFFFFF00) == FBFIDENTIFIER0) |
| 990 | { |
| 991 | Retval = PlatfromFBFBoundaryScan(pImageInfo); |
| 992 | if (Retval != NoError) |
| 993 | FatalError(Retval, "DTI", 2); |
| 994 | |
| 995 | pMasterHeader = (MasterBlockHeader*)loadAddr; |
| 996 | |
| 997 | if ((pMasterHeader->Format_Version != 11)) |
| 998 | FatalError(FBF_VersionNotMatch, "DTI", 3); |
| 999 | |
| 1000 | if (pMasterHeader->nOfDevices != 1) |
| 1001 | FatalError(FBF_DeviceMoreThanOne, "DTI", 4); |
| 1002 | |
| 1003 | temp_p = pMasterHeader->deviceHeaderOffset[0] + loadAddr; |
| 1004 | pDevHeader_11 = (PDeviceHeader_11)temp_p; |
| 1005 | AB_DL = pDevHeader_11->DeviceParameters[2]; |
| 1006 | if(AB_DL) |
| 1007 | obm_printf("AB system Downloading\n\r"); |
| 1008 | |
| 1009 | Retval = PlatformFBFCheckSWDVersion(pDevHeader_11); |
| 1010 | if(Retval != NoError) |
| 1011 | FatalError(Retval, "DTI", 5); |
| 1012 | |
| 1013 | // check nand ID |
| 1014 | #if NAND_CODE |
| 1015 | NandID_Right = pDevHeader_11->FlashOpt.NandID; |
| 1016 | obm_printf("NandID: 0x%x\n\r", NandID); |
| 1017 | if (NandID_Right != 0xFFFF && NandID != NandID_Right) |
| 1018 | { |
| 1019 | #if (!NEZHA701) |
| 1020 | FatalError(NANDIDDISMATCH, "DTI", 6); |
| 1021 | #endif |
| 1022 | } |
| 1023 | |
| 1024 | for ( imagenum = 0; imagenum < pDevHeader_11->nOfImages; imagenum++ ) |
| 1025 | { |
| 1026 | temp_p = (UINT_T)&pDevHeader_11->imageStruct_11[imagenum]; |
| 1027 | pImage_11 = (PImageStruct_11)temp_p; |
| 1028 | |
| 1029 | if(pImage_11->Image_ID == OBMIDENTIFIER) //OBMI |
| 1030 | { |
| 1031 | OBMFlashAddr = pImage_11->Flash_Start_Address; |
| 1032 | //To word around the issue that BootROM disable sprare area |
| 1033 | DisableSpareAreaForOBM(pImage_11->Flash_Start_Address, pImage_11->length); |
| 1034 | } |
| 1035 | } |
| 1036 | #endif |
| 1037 | |
| 1038 | #if SPINOR_CODE |
| 1039 | AddMessageError(REPORT_FLASH_SIZE_NOTIFICATION, Flash_size); |
| 1040 | #endif |
| 1041 | |
| 1042 | // skip blocks |
| 1043 | skip_blocks = pDevHeader_11->FlashOpt.Skip_Blocks_Struct.Total_Number_Of_SkipBlocks; |
| 1044 | if (skip_blocks > 0) |
| 1045 | pSkipAddress = &pDevHeader_11->FlashOpt.Skip_Blocks_Struct; |
| 1046 | else |
| 1047 | pSkipAddress = NULL; |
| 1048 | |
| 1049 | // productMode = pDevHeader_11->ProductMode; |
| 1050 | Reset = pDevHeader_11->OptValue; |
| 1051 | |
| 1052 | /* Check if FBF package is right for this platform */ |
| 1053 | PlatformFBFCheckDownload(pTIM_h, pDevHeader_11); |
| 1054 | |
| 1055 | pTIM_DTIM = (TIM *)malloc(DTIM_CUSTMOZIED_MAX*sizeof(TIM)); |
| 1056 | if ( pTIM_DTIM == NULL ) |
| 1057 | return HeapExhaustedError; |
| 1058 | |
| 1059 | memset(pTIM_DTIM, 0, DTIM_CUSTMOZIED_MAX*sizeof(TIM)); |
| 1060 | // find out all TIMH and DTIM for secured download) |
| 1061 | for (imagenum = 0; imagenum < pDevHeader_11->nOfImages; imagenum++) |
| 1062 | { |
| 1063 | temp_p = (UINT_T)&pDevHeader_11->imageStruct_11[imagenum]; |
| 1064 | pImage_11= (PImageStruct_11)temp_p; |
| 1065 | |
| 1066 | if (!ImageIsTIM(pImage_11->Image_ID)) |
| 1067 | continue; |
| 1068 | |
| 1069 | switch (pImage_11->Image_In_TIM) |
| 1070 | { |
| 1071 | case TIMH_NOTINC: /* NTIM */ |
| 1072 | break; |
| 1073 | case TIMH_INC: /* TIMH */ |
| 1074 | TIMHLoaded = 1; |
| 1075 | case TIMH_RECOVERY_INC: /* backup TIMH */ |
| 1076 | default: /* Other TIMs */ |
| 1077 | Retval = ValidateTIMInFBF(loadAddr, pImage_11, pImage_11->Image_In_TIM, pFuses->bits.SBE); |
| 1078 | if (Retval != NoError) { |
| 1079 | ASRFlag_DLStatus_Update(pTIM_h, 0, 0); |
| 1080 | FatalError(InvalidTIMImageError, "VTIF", Retval); |
| 1081 | } |
| 1082 | break; |
| 1083 | } |
| 1084 | } |
| 1085 | |
| 1086 | if (OKtoErase) |
| 1087 | { |
| 1088 | if (pDevHeader_11->FlashOpt.EraseAll == 2) // erase all flash partition without burning |
| 1089 | { |
| 1090 | #if PRODUCT_BUILD |
| 1091 | if (pFuses->bits.SBE == 1) { |
| 1092 | ASRFlag_DLStatus_Update(pTIM_h, 0, 0); |
| 1093 | FatalError(NotSupportedError, "DTI", 12); |
| 1094 | } |
| 1095 | #endif |
| 1096 | |
| 1097 | AddMessageError(REPORT_NOTIFICATION, PlatformEraseAllFlashWithoutBurn); // notify SWD |
| 1098 | |
| 1099 | Retval = EraseAllFlashWithoutBurn(BOOT_FLASH); |
| 1100 | if (Retval != NoError) |
| 1101 | { |
| 1102 | FatalError(Retval, "DTI", 7); |
| 1103 | } |
| 1104 | |
| 1105 | //Force ASR flag re-init later. |
| 1106 | pFOTAInfo->InitFlag = 0; |
| 1107 | |
| 1108 | AddMessageError(REPORT_NOTIFICATION, PlatformEraseAllFlashWithoutBurnDone); // notify SWD |
| 1109 | AddMessageError(REPORT_NOTIFICATION, PlatformReady); |
| 1110 | |
| 1111 | break; |
| 1112 | } |
| 1113 | |
| 1114 | // check erase all flag |
| 1115 | if (pDevHeader_11->FlashOpt.EraseAll == 1) // erase user partition with burning |
| 1116 | { |
| 1117 | // check reset BBT flag |
| 1118 | if (pDevHeader_11->FlashOpt.ResetBBT) |
| 1119 | { |
| 1120 | AddMessageError(REPORT_NOTIFICATION, PlatformResetBBT); // notify SWD that OBM/flasher will reset BBT |
| 1121 | ResetBBT(); |
| 1122 | //After BBT is reset, OBM start address need to be updated, too. |
| 1123 | #if NAND_CODE //To word around the issue that BootROM disable sprare area |
| 1124 | DisableSpareAreaForOBM(OBMFlashAddr, 0); |
| 1125 | #endif |
| 1126 | } |
| 1127 | |
| 1128 | AddMessageError(REPORT_NOTIFICATION, PlatformEraseAllFlash); // notify SWD that OBM/flasher will erase all flash |
| 1129 | Retval = EraseAllFlash(BOOT_FLASH); |
| 1130 | if (Retval != NoError) |
| 1131 | { |
| 1132 | FatalError(Retval, "DTI", 8); |
| 1133 | } |
| 1134 | |
| 1135 | //Force ASR flag re-init later. |
| 1136 | pFOTAInfo->InitFlag = 0; |
| 1137 | |
| 1138 | OKtoErase = 0; |
| 1139 | AddMessageError(REPORT_NOTIFICATION, PlatformEraseAllFlashDone); // notify SWD that OBM/flasher erases all flash done |
| 1140 | } |
| 1141 | } |
| 1142 | |
| 1143 | for ( imagenum = 0; imagenum < pDevHeader_11->nOfImages; imagenum++ ) |
| 1144 | { |
| 1145 | temp_p = (UINT_T)&pDevHeader_11->imageStruct_11[imagenum]; |
| 1146 | pImage_11 = (PImageStruct_11)temp_p; |
| 1147 | |
| 1148 | #if TRUSTED && SECURE_DOWNLOAD |
| 1149 | if (pFuses->bits.SBE) |
| 1150 | { |
| 1151 | switch (pImage_11->Image_In_TIM) |
| 1152 | { |
| 1153 | case TIMH_NOTINC: |
| 1154 | break; |
| 1155 | default: |
| 1156 | ValidateImageInTIM(loadAddr, pImage_11, (pTIM_DTIM + pImage_11->Image_In_TIM)); |
| 1157 | break; |
| 1158 | } |
| 1159 | } |
| 1160 | #endif |
| 1161 | |
| 1162 | if(pImage_11->Image_ID == FOTA_FBFVERSION_IMAGEID) |
| 1163 | { |
| 1164 | memset(MVersionStr, 0, 128); |
| 1165 | PStr = (CHAR *)( loadAddr + (pImage_11->First_Sector << 12) ); |
| 1166 | if(strcmpl(PStr, "OTA0", 4) == 0) { |
| 1167 | PStr += 4; |
| 1168 | for( i = 0; i < 128 && *PStr != ';'; i++) |
| 1169 | MVersionStr[i] = *PStr++; |
| 1170 | |
| 1171 | if(i < 128) { |
| 1172 | MVersionInFbf = 1; |
| 1173 | obm_printf("Download to: %s\n\r", MVersionStr); |
| 1174 | } |
| 1175 | } |
| 1176 | continue; |
| 1177 | } |
| 1178 | |
| 1179 | #if MMC_CODE |
| 1180 | if((pTIM_h->pConsTIM->VersionBind.Version) >= TIM_3_2_00) |
| 1181 | { |
| 1182 | Retval = SetPartition(pImage_11->Flash_partition, BOOT_FLASH); |
| 1183 | if (Retval != NoError) |
| 1184 | { |
| 1185 | FatalError(Retval, "DTI", 9); |
| 1186 | } |
| 1187 | } |
| 1188 | #endif |
| 1189 | |
| 1190 | if(OKtoErase && (pImage_11->commands & DLCMD_DO_ERASE_BLOCKS) ) |
| 1191 | { |
| 1192 | Retval = DLEraseFlashToBurnImage(pImage_11); |
| 1193 | } |
| 1194 | |
| 1195 | //if ((pImage_11->commands & 0xF) == 2) //erase only |
| 1196 | // continue; |
| 1197 | |
| 1198 | if(pImage_11->commands & DLCMD_DO_VERIFY_WRITE) { |
| 1199 | if (!IsDLImageDTIM(pImage_11)) { |
| 1200 | Retval = DLBurnImageToFlash(pImage_11, loadAddr); |
| 1201 | if(Retval != NoError ) |
| 1202 | FatalError(Retval, "DTI", 10); |
| 1203 | |
| 1204 | AddMessageError(REPORT_BURNT_IMAGE_LENGTH, pImage_11->length); // report burnt image length |
| 1205 | } |
| 1206 | #if BURN_DTIM_LAST |
| 1207 | else{ |
| 1208 | SaveDTIMs2Memory(pImage_11, loadAddr); |
| 1209 | } |
| 1210 | #endif |
| 1211 | } |
| 1212 | } |
| 1213 | |
| 1214 | #if IMG_RBC |
| 1215 | if(DownloadReadBackCRC == IMAGE_READ_BACK_CRC_ENABLED){ |
| 1216 | DownloadReadBackCRC = IMAGE_READ_BACK_CRC_DONE; |
| 1217 | AllImageCRCInfo.MCPID = ((NandID & 0xFF) << 16) | (ddr_id_update_with_crc & 0xFF); |
| 1218 | } |
| 1219 | #endif |
| 1220 | |
| 1221 | if (TIMHLoaded) { /* TIMH is loaded and parsed in pTIM_DTIM */ |
| 1222 | Retval = ProvisionPlatform(pFuses, pTIM_DTIM + TIMH_INC); |
| 1223 | // If ProvisionPlatform() returned an error, this means that an error occurred |
| 1224 | // during fuse burning. So stop booting and go to Fatal Error. |
| 1225 | if (Retval != NoError) |
| 1226 | { |
| 1227 | FatalError(Retval, "DTI", 11); |
| 1228 | } |
| 1229 | TIMHLoaded = 0; |
| 1230 | } |
| 1231 | } /* FBF */ |
| 1232 | |
| 1233 | pNextImageInfo = (IMAGE_INFO_3_4_0*)((unsigned char*)pImageInfo - ImageSize); |
| 1234 | |
| 1235 | /* Last FBF is handled, update DL flag as DLDONE */ |
| 1236 | if (NumImages == 2 /* FBF0(current) and TIMH, */ |
| 1237 | && pNextImageInfo->ImageID == TIMIDENTIFIER) { |
| 1238 | |
| 1239 | #if BURN_DTIM_LAST |
| 1240 | BurnDTIMs2Flash(); |
| 1241 | #endif |
| 1242 | |
| 1243 | if(MVersionInFbf == 1) { |
| 1244 | pFOTA_T = OTAGetConfig(pTIM_h); |
| 1245 | memset(pFOTA_T->MVersion, 0, sizeof(pFOTA_T->MVersion)); |
| 1246 | memcpy(pFOTA_T->MVersion, MVersionStr, strlen(MVersionStr)); |
| 1247 | #ifdef CONFIG_AB_SYSTEM |
| 1248 | memset(pFOTA_T->MVersion_B, 0, sizeof(pFOTA_T->MVersion_B)); |
| 1249 | memcpy(pFOTA_T->MVersion_B, MVersionStr, strlen(MVersionStr)); |
| 1250 | #endif |
| 1251 | } |
| 1252 | ASRFlag_DLStatus_Update(pTIM_h, DLFLG, DLDONE); |
| 1253 | free(pTIM_DTIM); |
| 1254 | |
| 1255 | UpdateBBT(); |
| 1256 | |
| 1257 | } |
| 1258 | |
| 1259 | AddMessageError(REPORT_NOTIFICATION, PlatformReady); |
| 1260 | #endif /* end of COPYIMAGESTOFLASH */ |
| 1261 | |
| 1262 | nextimage: |
| 1263 | NumImages--; |
| 1264 | pImageInfo = (IMAGE_INFO_3_4_0*)((unsigned char*)pImageInfo - ImageSize); // index to previous image info record. |
| 1265 | if(NumImages != 0) |
| 1266 | free(loadAddr); |
| 1267 | loadAddr = 0; |
| 1268 | } // end WHILE |
| 1269 | |
| 1270 | #if NAND_CODE |
| 1271 | SetUseSpareArea( FALSE, BOOT_FLASH ); |
| 1272 | #endif |
| 1273 | UpdateBBT(); |
| 1274 | |
| 1275 | #if SPINOR_CODE |
| 1276 | SPINOR_Disable4BytesMode(); |
| 1277 | #endif |
| 1278 | |
| 1279 | return NULL; |
| 1280 | } |
| 1281 | |
| 1282 | INT_T ImageReadBackAndCRC(PImageStruct_11 pImage_11) |
| 1283 | { |
| 1284 | UINT_T * Buffer = NULL; |
| 1285 | INT_T Retval = NoError; |
| 1286 | UINT_T Len = 0; |
| 1287 | |
| 1288 | #if NZAC |
| 1289 | UINT_T Temp1 = 0, Temp2 = 0; |
| 1290 | P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH); |
| 1291 | #endif |
| 1292 | |
| 1293 | if(DownloadReadBackCRC != IMAGE_READ_BACK_CRC_ENABLED){ |
| 1294 | return NotSupportedError; |
| 1295 | } |
| 1296 | |
| 1297 | if(AllImageCRCInfo.ImageNum >= CRC_MAX_IMAGE_NUM) |
| 1298 | { |
| 1299 | obm_printf("No more CRC buffer for 0x%08x\n\r", pImage_11->Image_ID); |
| 1300 | return NotSupportedError; |
| 1301 | } |
| 1302 | |
| 1303 | if(DTIM_PPSETTING == pImage_11->Image_ID) |
| 1304 | { |
| 1305 | AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].ImageID = pImage_11->Image_ID; |
| 1306 | //CRC of DTim.PPsetting |
| 1307 | AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].CRC32 = 0xc3751676; |
| 1308 | AllImageCRCInfo.ImageNum++; |
| 1309 | return Retval; |
| 1310 | } |
| 1311 | |
| 1312 | Len = pImage_11->length; |
| 1313 | |
| 1314 | #if NZAC |
| 1315 | if(PlatformIsNezhac() && (pImage_11->Image_ID == OBMIDENTIFIER) && (pFlashP->FlashType == SPI_FLASH) |
| 1316 | && (pImage_11->length > 0x1df88)) |
| 1317 | Len += (pImage_11->length/0x1df88)*4; |
| 1318 | #endif |
| 1319 | |
| 1320 | Buffer = malloc(Len); |
| 1321 | if(Buffer == NULL) |
| 1322 | return HeapExhaustedError; |
| 1323 | |
| 1324 | Retval = ReadFlash( pImage_11->Flash_Start_Address, Buffer, Len, BOOT_FLASH); |
| 1325 | |
| 1326 | if(Retval != NoError){ |
| 1327 | DownloadReadBackCRC = IMAGE_READ_BACK_CRC_FAIL; |
| 1328 | free(Buffer); |
| 1329 | return Retval; |
| 1330 | } |
| 1331 | |
| 1332 | #if NZAC |
| 1333 | //To workaroud the issue that 1802SL BootROM miss a word when OBM size is bigger than 0x1df88 in SPI-NOR |
| 1334 | if(PlatformIsNezhac() && (pImage_11->Image_ID == OBMIDENTIFIER) && (pFlashP->FlashType == SPI_FLASH) |
| 1335 | && (pImage_11->length > 0x1df88)) |
| 1336 | { |
| 1337 | Len = pImage_11->length; |
| 1338 | Temp1 = Buffer; |
| 1339 | Temp2 = malloc(256*1024); |
| 1340 | if(Temp2 == NULL) |
| 1341 | return HeapExhaustedError; |
| 1342 | |
| 1343 | while(Len) |
| 1344 | { |
| 1345 | memcpy((void *)Temp2, (void *)Temp1, 0x1df88); |
| 1346 | Temp1 += 0x1df88; |
| 1347 | Temp2 += 0x1df88; |
| 1348 | Temp1 += 4; //Ignore the extra word added to workaourd BootROM SPINOR read issue |
| 1349 | Len -= 0x1df88; |
| 1350 | if(Len <= 0x1df88){ |
| 1351 | memcpy((void *)Temp2, (void *)Temp1, Len); |
| 1352 | break; |
| 1353 | } |
| 1354 | } |
| 1355 | Buffer = Temp2; |
| 1356 | } |
| 1357 | #endif |
| 1358 | |
| 1359 | AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].ImageID = pImage_11->Image_ID; |
| 1360 | AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].CRC32 = CalcCRC32(Buffer, pImage_11->length, 0xFFFFFFFF); |
| 1361 | AllImageCRCInfo.ImageNum++; |
| 1362 | |
| 1363 | if(AB_DL && (pImage_11->Flash_Start_Address_B != 0xFFFFFFFF)) |
| 1364 | { |
| 1365 | Retval = ReadFlash( pImage_11->Flash_Start_Address_B, Buffer, Len, BOOT_FLASH); |
| 1366 | |
| 1367 | if(Retval != NoError){ |
| 1368 | DownloadReadBackCRC = IMAGE_READ_BACK_CRC_FAIL; |
| 1369 | #if NZAC |
| 1370 | if(Temp2) free(Temp2); |
| 1371 | #endif |
| 1372 | free(Buffer); |
| 1373 | return Retval; |
| 1374 | } |
| 1375 | AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].ImageID = pImage_11->Image_ID; |
| 1376 | AllImageCRCInfo.ImageCRC[AllImageCRCInfo.ImageNum].CRC32 = CalcCRC32(Buffer, pImage_11->length, 0xFFFFFFFF); |
| 1377 | AllImageCRCInfo.ImageNum++; |
| 1378 | } |
| 1379 | |
| 1380 | #if NZAC |
| 1381 | if(Temp2) free(Temp2); |
| 1382 | #endif |
| 1383 | |
| 1384 | free(Buffer); |
| 1385 | return Retval; |
| 1386 | } |
| 1387 | |
| 1388 | |
| 1389 | INT_T GetImageReadBackCrcBuffer(UINT_T *BufferAddr, INT_T *BufferLen) |
| 1390 | { |
| 1391 | int i; |
| 1392 | if(DownloadReadBackCRC != IMAGE_READ_BACK_CRC_DONE) |
| 1393 | { |
| 1394 | return CRCFailedError; |
| 1395 | } |
| 1396 | |
| 1397 | *BufferAddr = (UINT_T)(&AllImageCRCInfo); |
| 1398 | *BufferLen = sizeof(ImageCRCInfo); |
| 1399 | return NoError; |
| 1400 | } |
| 1401 | |