blob: 1edf5bb16ab3f3da266075520fd322b589f236bc [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2 *
3 * (C)Copyright 2005 - 2011 Marvell. All Rights Reserved.
4 *
5 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
6 * The copyright notice above does not evidence any actual or intended
7 * publication of such source code.
8 * This Module contains Proprietary Information of Marvell and should be
9 * treated as Confidential.
10 * The information in this file is provided for the exclusive use of the
11 * licensees of Marvell.
12 * Such users have the right to use, modify, and incorporate this code into
13 * products for purposes authorized by the license agreement provided they
14 * include this notice and the associated copyright notice with any such
15 * product.
16 * The information in this file is provided "AS IS" without warranty.
17 *
18 ******************************************************************************
19**
20** FILENAME: OBM.c
21**
22** PURPOSE: OBM main routine
23**
24** History: Initial Creation 4/23/06
25******************************************************************************/
26
27//////////////////////////////////////////////////////////////////////
28// Include the main BootLoader header file
29// IMPORTANT:
30// DO NOT include anything from here. Include any header that is
31// needed in the BootLoader.h file.
32//////////////////////////////////////////////////////////////////////
33#include "BootLoader.h"
34#include "obm2osl.h"
35#include "fota.h"
36#include "serial.h"
37
38extern UINT_T isDownload;
39extern UINT_T time_count_enable;
40extern UINT8_T time_count_in_sec;
41extern OBM2OSL *pOBM2OSL_h;
42extern pTEEC_INFO pAsrTeec;
43extern UINT_T Reset;
44UINT8_T FlashInitDone = 0;
45BOOTING_MODE product_mode_select = FUNCTION_MODE;
46
47#if NZA3 || NZAS
48/*
49* If the obm size is not 4bytes aligned, it will cause data abort in bootrom
50* raw nand/spi-flash read API. To workaround this bug, we put a one-dummy-word
51* data section at the end of obm so that its size is always 4bytes aligned.
52*/
53volatile UINT_T dummy4align __attribute__((section("align_data"))) = 0xdeadbeef;
54#endif
55
56//////////////////////////////////////////////////////////////////////
57// This is the entry point for the Boot Loader.
58//
59// Inputs: A pointer to the Transfer Struct that is passed in from BootROM.
60// Outputs: NONE. Transfers control to OS Loader.
61//
62// It mainly functions as following:
63//
64// 1) Initial Setup
65// 2) Validate TIM.
66// 3) Perform TIM based setup.
67// 4) Determine operating mode.
68// a) If Download Path (SW Upgrade or Download)
69// i. Download Descriptor File
70// ii. Validate TIM
71// iii. Download TIM Images
72// b) If BOOT Path (Single TIM or Dual TIM boot)
73// i. Single TIM Boot
74// Configure Flashes and FM
75// Load Images
76// Validate images
77// ii. Dual TIM Boot
78// Configure Flashes and FM
79// Load 2nd TIM
80// Set TIM Pointers
81// Validate 2nd TIM
82// Load Images
83// Validate images
84// 5) BL Finalization setup
85// 6) Transfer Control
86//////////////////////////////////////////////////////////////////////
87void BootLoaderMain( P_TRANSFER_STRUCT pTS_h )
88{
89 FUSE_SET fuses; // Fuse information passed in from BootROM
90 IMAGE_INFO_3_4_0 *pBootImageInfo = NULL;
91 UINT_T Retval = GeneralError;
92 UINT_T ErrorCode = NoError; // Error Code variable
93 OPERATING_MODE_T bootMode = UPGRADESW; // initalized so that coverity doesn't complain
94 UINT_T LoadAddr, ImageSize, ImageID;
95
96 // Transfer struct related parameters
97 UINT_T startOfDayTimerVal = 0; // pTS_h->SOD_ACCR0;
98 UINT_T TIM_Address = 0; // pTS_h->data_pairs[0].location;
99 pTIM pTIM_h = GetTimPointer();
100
101 // Initial setup
102 SetupEnvironment(&TIM_Address, pTS_h, &startOfDayTimerVal, pTIM_h, &fuses);
103
104 // Perform TIM based setup
105 PerformTIMBasedSetup(pTIM_h, &fuses);
106
107#if NZA3 || NZAS
108 dummy4align = 0;
109#endif
110
111 // Determine operating mode
112 bootMode = DetermineOperatingMode(&fuses, pTIM_h);
113
114 switch (bootMode) {
115 // DOWNLOAD PATH
116 case UPGRADESW:
117 case DOWNLOAD:
118 // Download Descriptor File
119 PlatformReleaseEMMDStatus();
120 pBootImageInfo = DownloadModeMain( &fuses, pTIM_h, bootMode);
121 break;
122 // BOOT PATH
123 case SINGLE_TIM_BOOT:
124 case PRODUCT_USB_BOOT:
125 case PRODUCT_UART_BOOT:
126 case RECOVERY_MODE_BOOT:
127 case MENU_MODE_BOOT:
128 pBootImageInfo = BootModeMain(pTIM_h, bootMode, &fuses);
129 break;
130 default:
131 break;
132 }
133
134 // If there is an error or no image is found for booting, we FAIL.
135 if ((pBootImageInfo == NULL) && (!isDownload)) // if it is download, no print this error code
136 {
137 FatalError(NULLPointer, "BLM", NULL);
138 }
139 // Finalization Setup
140 FinalizeSetup(&fuses, pTIM_h);
141
142 #if USE_SERIAL_DEBUG
143 obm_printf("end...\n\r");
144 #endif
145 // Transfer control to the next image.
146 if ((bootMode == UPGRADESW) || (bootMode == DOWNLOAD))
147 {
148 if ( isDownload )
149 { /* Pure Download */
150 if (Reset == 1)
151 {
152 memset(pOBM2OSL_h, 0, sizeof(OBM2OSL));
153 pOBM2OSL_h->booting_mode = OBMNODL;
154 OBMNODL_RST_FLAG = OBMNODL;
155
156 do_wdt_reset(); // reset after download as default
157 }
158
159 ErrorCode = 1;
160 // Infinite loop!
161 while(ErrorCode&1)
162 ErrorCode+=2;// need debugger to step beyond this loop after inspecting input args...
163 }
164 /* bootMode could be UPGRADESW or DOWNLOAD for upload or just a USB enum
165 After upload is finished or time out occurs after usb enum, keep booting to
166 next image, such as uboot or TOS.
167 Reboot or dead loop only for successful download.
168 */
169 }
170
171 if (pBootImageInfo) {
172 LoadAddr = pBootImageInfo->LoadAddr;
173 ImageSize = pBootImageInfo->ImageSize;
174 ImageID = pBootImageInfo->ImageID;
175 }
176
177 /* Transfer control to next image, uboot or TOS */
178 obm_printf("Jump to %s at 0x%x (size 0x%x)\n\r",
179 (ImageID == TZSWIDENTIFIER)?"Trusted OS":"OS-loader",
180 LoadAddr, ImageSize);
181 pOBM2OSL_h->quiet = serial_get_quiet();
182
183#if defined(CONFIG_TEE_OS)
184 /* When TEE_OS is involved, use sw_scratch_reg to pass obm2oslo parameters instead of r11 */
185 BU_REG_WRITE(OBM2OSLO_PARA_REG, (UINT_T)pOBM2OSL_h);
186 if (ImageID == TZSWIDENTIFIER)
187 TransferControl2TOS(LoadAddr, (UINT_T)GetNsEntryLoadAddress(),
188 (UINT_T)pOBM2OSL_h, (UINT_T)pAsrTeec);
189#else
190 TransferControl(LoadAddr, ImageSize, LoadAddr, (UINT_T)pOBM2OSL_h);
191#endif
192}
193
194
195//////////////////////////////////////////////////////////////////////
196// This is the Environment Setup function for the Boot Loader.
197//
198// Inputs: Pointer to the address of TIM, Pointer the Transfer Struct
199// coming from the BootROM, Pointer to the Timer value, Pointer to the
200// Fuses.
201// Outputs: None
202//
203// It mainly functions as following:
204// 1) If IPC read is required, gets the transfer struct from IPC.
205// 2) Parses the transfer struct.
206// 3) Sets the TIM pointers.
207// 4) Initializes the SOD Timer interface.
208// 5) Enables default clocks.
209// 6) Initializes the fuses using platform settings passed in from BootROM.
210// 7) Initializes the Keypad required for SW upgrade.
211// 8) Initializes the Platform Message Queue.
212// 9) Init Security API.
213//////////////////////////////////////////////////////////////////////
214void SetupEnvironment(UINT_T *TIM_Address, P_TRANSFER_STRUCT pTS_h, UINT_T *startOfDayTimerVal, TIM *pTIM_h, pFUSE_SET pFuses)
215{
216 UINT_T retval = NoError;
217
218 // Enable the clocks for the peripherals that will be used
219 CheckDefaultClocks();
220
221 // Initialize the SOD timer interface
222 InitSODTimer();
223
224 ParseTransferStruct(TIM_Address, pTS_h, pFuses, startOfDayTimerVal);
225
226 // serial debug
227#if USE_SERIAL_DEBUG
228 PlatformUARTConfig();
229 serial_init();
230 obm_printf("start at 0x%x\n\r", OBM_USE_DDR_ADDR);
231 obm_printf("%s OBM with SWD >= %s\n\r", PLAT_NAME, HexToSwdObmVersion(SWD_VERSION));
232 OBM_HeapInit();
233 obm_printf(OBM_COMPILE_INFO);
234#endif
235
236 SetTIMPointers((UINT8_T*)*TIM_Address, pTIM_h);
237 if( pTIM_h->pConsTIM->VersionBind.Identifier != TIMIDENTIFIER )
238 {
239 // Set error to indicate no TIM is found and make it a fatal error.
240 FatalError(TIMNotFound, "SE", 1);
241 }
242
243 // Initialize any fuse information passed in by the BootROM
244 obm_printf("pFuses->value[0]: 0x%x\n\r", pFuses->value[0]);
245 obm_printf("pFuses->value[1]: 0x%x\n\r", pFuses->value[1]);
246 //pFuses->bits.SBE = 1;
247 obm_printf("pFuses->bits.SBE: %d\n\r", pFuses->bits.SBE);
248
249 #if TRUSTED && PRODUCT_BUILD
250 obm_printf("Trusted OBM with ProductBuild\n\r");
251 #elif TRUSTED && !PRODUCT_BUILD
252 obm_printf("Trusted OBM without ProductBuild\n\r");
253 #else
254 obm_printf("Non-Trusted OBM\n\r");
255 #endif
256
257 #if ENABLE_MMU
258 obm_printf("MMU Enabled\n\r");
259 #else
260 obm_printf("MMU Disabled\n\r");
261 #endif
262
263 #if I2C
264 I2CInit();
265 #endif
266
267 // Keypad initialization: Required for detecting software upgrade request from the keypad.
268 //These two lines of code conflict with SDMMC on MMP3,hence commenting them out
269#if UPDATE_USE_GPIO
270 PlatformGPIOKeyConfig();
271#endif
272
273 PlatformLateInit();
274
275#if TRUSTED
276 // Init Security API.
277 //if (pFuses->bits.SBE)
278 {
279 obm_printf("SecurityInitialization\n\r");
280 retval = SecurityInitialization(0);
281 if(retval != NoError)
282 {
283 FatalError(retval, "SE", 2);
284 }
285
286 // Init Provisioning API.
287 ProvisioningInitialization();
288 }
289#endif
290
291}
292
293
294//////////////////////////////////////////////////////////////////////
295// This is the Parse Transfer Struct function for the Boot Loader.
296//
297// Inputs: Pointer to the address of TIM, Pointer the Transfer Struct
298// coming from the BootROM, Pointer to the Timer value, Pointer to the
299// Fuses.
300// Outputs: NONE.
301//
302// It mainly functions as following:
303// 1) If the passed in Transfer Struct is not NULL, parse it and initialize
304// the platform settings, the timer value, and the TIM address.
305// 2) Else if it is NULL, look at a fixed location.
306//////////////////////////////////////////////////////////////////////
307void ParseTransferStruct(UINT_T *TIM_Address, P_TRANSFER_STRUCT pTS_h, pFUSE_SET pFuses, UINT_T *startOfDayTimerVal)
308{
309 UINT_T i, TS_Version;
310 P_TRANSFER_STRUCT_v2 pTS_v2;
311
312 // If the passed in Transfer Struct is not NULL, parse it and initialize
313 // the platform settings, the timer value, and the TIM address.
314 if( pTS_h )
315 {
316 TS_Version = pTS_h->TransferID;
317 if (TS_Version == TBR_XFER) // v1 of transfer struct is used by BootRom
318 {
319 pFuses->value[0] = (UINT_T) pTS_h->FuseVal;
320 pFuses->value[1] = 0x0;
321 *startOfDayTimerVal = pTS_h->SOD_ACCR0;
322 #if LAPW
323 ParseBR_ExtraState(pTS_h->ResumeParam[0]);
324 #endif
325
326 // For the case where the TIM is not in TS coming from the IPC,
327 // TS includes random values. In this case, this loop can take a
328 // long time. With MAX_NUMBER_OF_DATA_PAIRS, we put a limit on this.
329 for( i=0; i<pTS_h->num_data_pairs && i<MAX_NUMBER_OF_DATA_PAIRS; i++)
330 {
331 if(pTS_h->data_pairs[i].data_id == TIM_DATA )
332 {
333 *TIM_Address = pTS_h->data_pairs[i].location;
334 return;
335 }
336 }
337 }
338 else // v2 of transfer struct is used by OBM
339 {
340 pTS_v2 = (P_TRANSFER_STRUCT_v2) pTS_h; // cast to v2 of the xfer struct
341 pFuses->value[0] = pTS_v2->FuseVal[0];
342 pFuses->value[1] = pTS_v2->FuseVal[1];
343 *startOfDayTimerVal = pTS_v2->SOD_ACCR0;
344
345 // For the case where the TIM is not in TS coming from the IPC,
346 // TS includes random values. In this case, this loop can take a
347 // long time. With MAX_NUMBER_OF_DATA_PAIRS, we put a limit on this.
348 for( i=0; i<pTS_v2->num_data_pairs && i<MAX_NUMBER_OF_DATA_PAIRS; i++)
349 {
350 if( pTS_v2->data_pairs[i].data_id == TIM_DATA )
351 {
352 *TIM_Address = pTS_v2->data_pairs[i].location;
353 return;
354 }
355 }
356 }
357 } //end if( pTS_h )
358
359 *TIM_Address = 0; // should never be here!
360}
361
362
363//////////////////////////////////////////////////////////////////////
364// This is the Fatal Error function for the Boot Loader.
365//
366// Inputs: Error code,cause, sub code.
367// Outputs: NONE.
368//
369// It mainly stays here in an infinite loop.
370//////////////////////////////////////////////////////////////////////
371void FatalError(UINT_T ErrorCode, const CHAR* ErrStr, UINT_T ErrSubCode)
372{
373 UINT_T odd = 1;
374
375 // Print out why we failed if it is not a port error.
376 if (ErrorCode != DownloadPortError)
377 {
378 AddMessageError(REPORT_ERROR, ErrorCode);
379 }
380
381#if USE_SERIAL_DEBUG
382 err_msg("Fatal Error Code: 0x%x\n\r", ErrorCode);
383
384 if (ErrStr != NULL)
385 {
386 err_msg("Error cause: %s\n\r", ErrStr);
387 }
388
389 if (ErrSubCode != NULL)
390 err_msg("Error sub code: 0x%x\n\r", ErrSubCode);
391
392#endif
393
394 //if( !isDownload ) // no reset for downloading
395 // do_wdt_reset();
396
397#if SPINOR_CODE
398 SPINOR_Disable4BytesMode();
399#endif
400
401 // Infinite loop!
402 while(odd&1)
403 {
404 // need debugger to step beyond this loop after inspecting input args...
405 odd+=2;
406 }
407
408 return;
409}
410
411//////////////////////////////////////////////////////////////////////
412// This is the function that performs TIM based setup in the Boot Loader.
413//
414// Inputs: A pointer to the TIM and a pointer to the Fuses.
415// Outputs: NONE.
416//
417// It mainly functions as following:
418// 1) Configures the operating mode.
419// 2) Configures the DDR.
420// 3) Enables the interrupts.
421// 4) Enables the global interrupts.
422// 5) Checks the TIM for port over-writes. If this fails, initializes
423// the default ports.
424//////////////////////////////////////////////////////////////////////
425void PerformTIMBasedSetup(pTIM pTIM_h, pFUSE_SET pFuses)
426{
427 UINT_T Retval = NoError;
428
429 #if REPORT_DDR_INFO
430 MCK5_Check_LPDDR2_Info(pTIM_h);
431 #endif
432
433 // Configure DDR if BootROM doesn't configure it.
434 if (pFuses->bits.DDRInitialized == FALSE)
435 {
436 Retval = CheckAndConfigureDDR(pTIM_h, pFuses);
437 if (Retval != NoError)
438 {
439 FatalError(Retval, "PTBS", NULL);
440 }
441 }
442
443 // Interrupts may be required, so enable them.
444 // For example, downloading over USB requires interrupts.
445
446 // point the interrupt exception handler to our routine.
447 // this allows us to run in-place out of isram
448 // without having to enable the enable the mmu.
449 SetInterruptVector(VECTOR_SRAM_BASE_ADDR);
450 IRQ_Glb_Dis(); // turns off all interrupts...
451 EnableIrqInterrupts(); // Enable Interrupts at the core
452 IRQ_Glb_Ena(); // Enable Global Ints using the AP Global Interrupt Mask Register
453
454 //if (NoFrequencyChange == 0) // change pp as default
455 // pp_set();
456#if CP_BOOT
457 /* ASR1803S boot to MSA L2SRAM */
458 #if FLCN || FACT
459 BU_REG_WRITE(0xD4050020, 0x23);
460 SetupL2SRAMMPU();
461 #endif
462#endif
463}
464
465static INT FindDkbiPatternInTIM(pTIM pTIM_h)
466{
467 pIMAGE_INFO_3_4_0 pImgInfo = NULL;
468 UINT_T TimSize;
469 UINT_T DkbiPatternAddr;
470
471 pImgInfo = FindImageInTIM(pTIM_h, TIMIDENTIFIER);
472 if(pImgInfo == NULL){
473 return 0;
474 }
475
476 TimSize = (pImgInfo->ImageSize + 3) & (~3); //4byte align
477 DkbiPatternAddr = 0xD1000000 + TimSize;
478
479 if(BU_REG_READ(DkbiPatternAddr) == DKBIDENTIFIER &&
480 BU_REG_READ(DkbiPatternAddr+4) == DKBIDENTIFIER)
481 {
482 BU_REG_WRITE(DkbiPatternAddr, 0);
483 BU_REG_WRITE(DkbiPatternAddr+4, 0);
484 return 1;
485 }
486
487 return 0;
488}
489
490UINT_T PlatformInitFlash(pTIM pTIM_h)
491{
492 UINT_T Retval = NoError;
493 UINT_T FlashNumber;
494
495 if(IsTim4DKBI(pTIM_h)) {
496 /* No valid flash ID in TIMH for DKBI */
497 return NoError;
498 }
499
500 FlashNumber = (pTIM_h->pConsTIM->FlashInfo.BootFlashSign) & 0xFF;
501 if(!FlashInitDone)
502 {
503 // Determine the Flash that will be used to store the downloaded images.
504 Retval = Configure_Flashes (FlashNumber, BOOT_FLASH);
505 if( Retval == NoError)
506 {
507 InitializeDualTimEarly(pTIM_h);
508
509 //turn on the flash management
510 InitializeFM(LEGACY_METHOD, BOOT_FLASH);
511
512#if !UPDATER
513 InitializeDualTimLate(pTIM_h);
514#endif
515
516#ifdef BBM_LEGACY_EXT && !UPDATER
517 DetectScrubBitflipBlocks();
518#endif
519 FlashInitDone = 1;
520
521 obm_printf("Flash Init Done\n\r");
522 }
523 }
524
525 return Retval;
526}
527
528//////////////////////////////////////////////////////////////////////
529// This is the Mode Determining function for the Boot Loader.
530//
531// Inputs: A pointer to the Fuses and a pointer to the TIM.
532// Outputs: Returns one of the following operationg modes:
533// UPGRADESW, DOWNLOAD, SINGLE_TIM_BOOT, or DUAL_TIM_BOOT
534//
535// It mainly functions as following:
536// 1) Sets running as identifier.
537// 2) Check if the HW upgrade request button is pressed. If so, mode = UPGRADESW.
538// 3) Else if there is a DKB ID in the TIM, then mode = DOWNLOAD.
539// 4) Else if there is a DUAL TIM ID in the TIM, then mode = DUAL_TIM_BOOT.
540// 5) Else by default, we have mode = SINGLE_TIM_BOOT.
541//////////////////////////////////////////////////////////////////////
542OPERATING_MODE_T DetermineOperatingMode(FUSE_SET *pFuses, pTIM pTIM_h)
543{
544 OPERATING_MODE_T mode = SINGLE_TIM_BOOT;
545 UINT_T loops;
546 UINT gotkey = 0, Retval;
547 P_FOTA_Firmware pFOTA_T = NULL;
548 UINT_T ATDL_Cfg = 0;
549
550 PlatformInitFlash(pTIM_h);
551
552 // No user request for software update.
553 // Deterimine from TIM headers what to do.
554 // If DKB Identifier is found then we have download mode.
555 if (IsTim4DKBI(pTIM_h) || FindDkbiPatternInTIM(pTIM_h))
556 {
557 mode = DOWNLOAD;
558 time_count_enable = FALSE;
559 obm_printf("Empty Board or Force Download\n\r");
560 return mode;
561 }
562
563 ATDL_Cfg = GetAutoDownloadConfig(pTIM_h);
564 if (ATDL_Cfg) {
565 mode = UPGRADESW;
566 time_count_enable = TRUE;
567 time_count_in_sec = ATDL_Cfg;
568 obm_printf("ATDL download\n\r");
569 return mode;
570 }
571
572 if(PlatformCheckForceUSBEnumFlag())
573 {
574 mode = UPGRADESW;
575 time_count_enable = TRUE;
576 PlatformClearForceUSBEnumFlag();
577 obm_printf("Download due to force usb enum flag\n\r");
578 return mode;
579 }
580
581 if(serial_read_byte() == 0x0D) /* CR pressed */
582 {
583 mode = UPGRADESW;
584 time_count_enable = TRUE;
585 obm_printf("Uart force to download\n\r");
586 return mode;
587 }
588
589 pFOTA_T = OTAGetConfig(pTIM_h);
590 if(pFOTA_T && (pFOTA_T->dlflag[0] == DLFLG) && (pFOTA_T->dlflag[1] != DLDONE))
591 {
592 mode = UPGRADESW;
593 time_count_enable = FALSE;
594 obm_printf("Wait for unfinished download...\n\r");
595 return mode;
596 }
597
598#if TRUSTED
599 if (pFOTA_T && (pFOTA_T->TrustBootStatus != 0) && (pFOTA_T->TrustBootStatus != -1))
600 {
601 Retval = pFOTA_T->TrustBootStatus;
602 pFOTA_T->TrustBootStatus = TB_NO_ERROR;
603 OTA_Save_Config(pTIM_h);
604 #if TB_ERROR_DOWNLOAD
605 obm_printf("Force Download Due to Trust Boot Error: %d\n\r", Retval);
606 mode = UPGRADESW;
607 time_count_enable = FALSE;
608 return mode;
609 #else
610 obm_printf("Dead Loop Due to Trust Boot Error: %d\n\r", Retval);
611 while(1);
612 #endif
613 }
614#endif
615
616 if ( PlatformUSBPluggedIn() )
617 {
618 obm_printf("USB cable plugged in\n\r");
619 if(ASRFlag_InProductionMode(pTIM_h))
620 {
621 if(pOBM2OSL_h->booting_mode != OBMNODL && OBMNODL_RST_FLAG != OBMNODL)
622 {
623 mode = UPGRADESW;
624 time_count_enable = TRUE; // this is active enumeration by OBM if USB is connect, need to set timeout
625 obm_printf("[PROD]Enum USB port\n\r");
626 }else{
627 obm_printf("[PROD]Don't enum USB port\n\r");
628 }
629 OBMNODL_RST_FLAG= 0;
630 } else {
631 UINT_T DlFlag = BU_REG_READ(OBMDL_DDR_ADDRES);
632 if(DlFlag == OBMDL)
633 {
634 BU_REG_WRITE(OBMDL_DDR_ADDRES, 0x0);
635 mode = UPGRADESW;
636 time_count_enable = FALSE;
637 obm_printf("[Non-Prod]Wait for download(AT)...\n\r");
638 }else {
639 obm_printf("[Non-Prod]Don't enum USB port\n\r");
640 }
641 }
642 return mode;
643 }
644
645#if UPDATE_USE_GPIO
646 for(loops = 0; loops < 10; loops++)
647 {
648 gotkey = PlatformCheckGPIOKey();
649 if (gotkey)
650 break;
651 }
652 switch (gotkey)
653 {
654 case KEYID_UPGRADESW_REQUEST:
655 mode = UPGRADESW;
656 time_count_enable = TRUE;
657 break;
658 case KEYID_PRODUCT_USB_MODE_REQUEST:
659 product_mode_select = PRODUCT_USB_MODE;
660 obm_printf("Production mode detected\n\r");
661 break;
662 default:
663 break;
664 }
665#endif
666 return mode;
667}
668
669
670//////////////////////////////////////////////////////////////////////
671// This is the Finalization Setup function for the Boot Loader.
672//
673// Inputs: A pointer to the fuses and a pointer to the TIM.
674// Outputs: NONE.
675//
676// It mainly functions as following:
677// 1) Shut down all the ports.
678// 2) Shuts down the security API.
679// 3) Finalize Flashes.
680// 4) Disable interrupts.
681// 5) Restore platform default configuration.
682//////////////////////////////////////////////////////////////////////
683void FinalizeSetup(pFUSE_SET pFuses, pTIM pTIM_h )
684{
685 UINT_T retval = NoError;
686
687#if TRUSTED
688 // Shut down the security API.
689 //if (pFuses->bits.SBE)
690 {
691 retval = SecurityShutdown();
692 if( retval != NoError)
693 {
694 FatalError(retval, "FS", NULL);
695 }
696 }
697#endif
698
699 // Finalize the Flashes.
700 Finalize_Flashes(BOOT_FLASH); // this will flush the BBT information if necessary.
701
702 // Disable interrupts.
703 DisableIrqInterrupts();
704}
705