| /****************************************************************************** |
| * |
| * (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: OBM.c |
| ** |
| ** PURPOSE: OBM main routine |
| ** |
| ** History: Initial Creation 4/23/06 |
| ******************************************************************************/ |
| |
| ////////////////////////////////////////////////////////////////////// |
| // Include the main BootLoader header file |
| // IMPORTANT: |
| // DO NOT include anything from here. Include any header that is |
| // needed in the BootLoader.h file. |
| ////////////////////////////////////////////////////////////////////// |
| #include "BootLoader.h" |
| #include "obm2osl.h" |
| #include "fota.h" |
| #include "serial.h" |
| |
| extern UINT_T isDownload; |
| extern UINT_T time_count_enable; |
| extern UINT8_T time_count_in_sec; |
| extern OBM2OSL *pOBM2OSL_h; |
| extern pTEEC_INFO pAsrTeec; |
| extern UINT_T Reset; |
| UINT8_T FlashInitDone = 0; |
| BOOTING_MODE product_mode_select = FUNCTION_MODE; |
| |
| #if NZA3 || NZAS |
| /* |
| * If the obm size is not 4bytes aligned, it will cause data abort in bootrom |
| * raw nand/spi-flash read API. To workaround this bug, we put a one-dummy-word |
| * data section at the end of obm so that its size is always 4bytes aligned. |
| */ |
| volatile UINT_T dummy4align __attribute__((section("align_data"))) = 0xdeadbeef; |
| #endif |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This is the entry point for the Boot Loader. |
| // |
| // Inputs: A pointer to the Transfer Struct that is passed in from BootROM. |
| // Outputs: NONE. Transfers control to OS Loader. |
| // |
| // It mainly functions as following: |
| // |
| // 1) Initial Setup |
| // 2) Validate TIM. |
| // 3) Perform TIM based setup. |
| // 4) Determine operating mode. |
| // a) If Download Path (SW Upgrade or Download) |
| // i. Download Descriptor File |
| // ii. Validate TIM |
| // iii. Download TIM Images |
| // b) If BOOT Path (Single TIM or Dual TIM boot) |
| // i. Single TIM Boot |
| // Configure Flashes and FM |
| // Load Images |
| // Validate images |
| // ii. Dual TIM Boot |
| // Configure Flashes and FM |
| // Load 2nd TIM |
| // Set TIM Pointers |
| // Validate 2nd TIM |
| // Load Images |
| // Validate images |
| // 5) BL Finalization setup |
| // 6) Transfer Control |
| ////////////////////////////////////////////////////////////////////// |
| void BootLoaderMain( P_TRANSFER_STRUCT pTS_h ) |
| { |
| FUSE_SET fuses; // Fuse information passed in from BootROM |
| IMAGE_INFO_3_4_0 *pBootImageInfo = NULL; |
| UINT_T Retval = GeneralError; |
| UINT_T ErrorCode = NoError; // Error Code variable |
| OPERATING_MODE_T bootMode = UPGRADESW; // initalized so that coverity doesn't complain |
| UINT_T LoadAddr, ImageSize, ImageID; |
| |
| // Transfer struct related parameters |
| UINT_T startOfDayTimerVal = 0; // pTS_h->SOD_ACCR0; |
| UINT_T TIM_Address = 0; // pTS_h->data_pairs[0].location; |
| pTIM pTIM_h = GetTimPointer(); |
| |
| // Initial setup |
| SetupEnvironment(&TIM_Address, pTS_h, &startOfDayTimerVal, pTIM_h, &fuses); |
| |
| // Perform TIM based setup |
| PerformTIMBasedSetup(pTIM_h, &fuses); |
| |
| #if NZA3 || NZAS |
| dummy4align = 0; |
| #endif |
| |
| // Determine operating mode |
| bootMode = DetermineOperatingMode(&fuses, pTIM_h); |
| |
| switch (bootMode) { |
| // DOWNLOAD PATH |
| case UPGRADESW: |
| case DOWNLOAD: |
| // Download Descriptor File |
| PlatformReleaseEMMDStatus(); |
| pBootImageInfo = DownloadModeMain( &fuses, pTIM_h, bootMode); |
| break; |
| // BOOT PATH |
| case SINGLE_TIM_BOOT: |
| case PRODUCT_USB_BOOT: |
| case PRODUCT_UART_BOOT: |
| case RECOVERY_MODE_BOOT: |
| case MENU_MODE_BOOT: |
| pBootImageInfo = BootModeMain(pTIM_h, bootMode, &fuses); |
| break; |
| default: |
| break; |
| } |
| |
| // If there is an error or no image is found for booting, we FAIL. |
| if ((pBootImageInfo == NULL) && (!isDownload)) // if it is download, no print this error code |
| { |
| FatalError(NULLPointer, "BLM", NULL); |
| } |
| // Finalization Setup |
| FinalizeSetup(&fuses, pTIM_h); |
| |
| #if USE_SERIAL_DEBUG |
| obm_printf("end...\n\r"); |
| #endif |
| // Transfer control to the next image. |
| if ((bootMode == UPGRADESW) || (bootMode == DOWNLOAD)) |
| { |
| if ( isDownload ) |
| { /* Pure Download */ |
| if (Reset == 1) |
| { |
| memset(pOBM2OSL_h, 0, sizeof(OBM2OSL)); |
| pOBM2OSL_h->booting_mode = OBMNODL; |
| OBMNODL_RST_FLAG = OBMNODL; |
| |
| do_wdt_reset(); // reset after download as default |
| } |
| |
| ErrorCode = 1; |
| // Infinite loop! |
| while(ErrorCode&1) |
| ErrorCode+=2;// need debugger to step beyond this loop after inspecting input args... |
| } |
| /* bootMode could be UPGRADESW or DOWNLOAD for upload or just a USB enum |
| After upload is finished or time out occurs after usb enum, keep booting to |
| next image, such as uboot or TOS. |
| Reboot or dead loop only for successful download. |
| */ |
| } |
| |
| if (pBootImageInfo) { |
| LoadAddr = pBootImageInfo->LoadAddr; |
| ImageSize = pBootImageInfo->ImageSize; |
| ImageID = pBootImageInfo->ImageID; |
| } |
| |
| /* Transfer control to next image, uboot or TOS */ |
| obm_printf("Jump to %s at 0x%x (size 0x%x)\n\r", |
| (ImageID == TZSWIDENTIFIER)?"Trusted OS":"OS-loader", |
| LoadAddr, ImageSize); |
| pOBM2OSL_h->quiet = serial_get_quiet(); |
| |
| #if defined(CONFIG_TEE_OS) |
| /* When TEE_OS is involved, use sw_scratch_reg to pass obm2oslo parameters instead of r11 */ |
| BU_REG_WRITE(OBM2OSLO_PARA_REG, (UINT_T)pOBM2OSL_h); |
| if (ImageID == TZSWIDENTIFIER) |
| TransferControl2TOS(LoadAddr, (UINT_T)GetNsEntryLoadAddress(), |
| (UINT_T)pOBM2OSL_h, (UINT_T)pAsrTeec); |
| #else |
| TransferControl(LoadAddr, ImageSize, LoadAddr, (UINT_T)pOBM2OSL_h); |
| #endif |
| } |
| |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This is the Environment Setup function for the Boot Loader. |
| // |
| // Inputs: Pointer to the address of TIM, Pointer the Transfer Struct |
| // coming from the BootROM, Pointer to the Timer value, Pointer to the |
| // Fuses. |
| // Outputs: None |
| // |
| // It mainly functions as following: |
| // 1) If IPC read is required, gets the transfer struct from IPC. |
| // 2) Parses the transfer struct. |
| // 3) Sets the TIM pointers. |
| // 4) Initializes the SOD Timer interface. |
| // 5) Enables default clocks. |
| // 6) Initializes the fuses using platform settings passed in from BootROM. |
| // 7) Initializes the Keypad required for SW upgrade. |
| // 8) Initializes the Platform Message Queue. |
| // 9) Init Security API. |
| ////////////////////////////////////////////////////////////////////// |
| void SetupEnvironment(UINT_T *TIM_Address, P_TRANSFER_STRUCT pTS_h, UINT_T *startOfDayTimerVal, TIM *pTIM_h, pFUSE_SET pFuses) |
| { |
| UINT_T retval = NoError; |
| |
| // Enable the clocks for the peripherals that will be used |
| CheckDefaultClocks(); |
| |
| // Initialize the SOD timer interface |
| InitSODTimer(); |
| |
| ParseTransferStruct(TIM_Address, pTS_h, pFuses, startOfDayTimerVal); |
| |
| // serial debug |
| #if USE_SERIAL_DEBUG |
| PlatformUARTConfig(); |
| serial_init(); |
| obm_printf("start at 0x%x\n\r", OBM_USE_DDR_ADDR); |
| obm_printf("%s OBM with SWD >= %s\n\r", PLAT_NAME, HexToSwdObmVersion(SWD_VERSION)); |
| OBM_HeapInit(); |
| obm_printf(OBM_COMPILE_INFO); |
| #endif |
| |
| SetTIMPointers((UINT8_T*)*TIM_Address, pTIM_h); |
| if( pTIM_h->pConsTIM->VersionBind.Identifier != TIMIDENTIFIER ) |
| { |
| // Set error to indicate no TIM is found and make it a fatal error. |
| FatalError(TIMNotFound, "SE", 1); |
| } |
| |
| // Initialize any fuse information passed in by the BootROM |
| obm_printf("pFuses->value[0]: 0x%x\n\r", pFuses->value[0]); |
| obm_printf("pFuses->value[1]: 0x%x\n\r", pFuses->value[1]); |
| //pFuses->bits.SBE = 1; |
| obm_printf("pFuses->bits.SBE: %d\n\r", pFuses->bits.SBE); |
| |
| #if TRUSTED && PRODUCT_BUILD |
| obm_printf("Trusted OBM with ProductBuild\n\r"); |
| #elif TRUSTED && !PRODUCT_BUILD |
| obm_printf("Trusted OBM without ProductBuild\n\r"); |
| #else |
| obm_printf("Non-Trusted OBM\n\r"); |
| #endif |
| |
| #if ENABLE_MMU |
| obm_printf("MMU Enabled\n\r"); |
| #else |
| obm_printf("MMU Disabled\n\r"); |
| #endif |
| |
| #if I2C |
| I2CInit(); |
| #endif |
| |
| // Keypad initialization: Required for detecting software upgrade request from the keypad. |
| //These two lines of code conflict with SDMMC on MMP3,hence commenting them out |
| #if UPDATE_USE_GPIO |
| PlatformGPIOKeyConfig(); |
| #endif |
| |
| PlatformLateInit(); |
| |
| #if TRUSTED |
| // Init Security API. |
| //if (pFuses->bits.SBE) |
| { |
| obm_printf("SecurityInitialization\n\r"); |
| retval = SecurityInitialization(0); |
| if(retval != NoError) |
| { |
| FatalError(retval, "SE", 2); |
| } |
| |
| // Init Provisioning API. |
| ProvisioningInitialization(); |
| } |
| #endif |
| |
| } |
| |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This is the Parse Transfer Struct function for the Boot Loader. |
| // |
| // Inputs: Pointer to the address of TIM, Pointer the Transfer Struct |
| // coming from the BootROM, Pointer to the Timer value, Pointer to the |
| // Fuses. |
| // Outputs: NONE. |
| // |
| // It mainly functions as following: |
| // 1) If the passed in Transfer Struct is not NULL, parse it and initialize |
| // the platform settings, the timer value, and the TIM address. |
| // 2) Else if it is NULL, look at a fixed location. |
| ////////////////////////////////////////////////////////////////////// |
| void ParseTransferStruct(UINT_T *TIM_Address, P_TRANSFER_STRUCT pTS_h, pFUSE_SET pFuses, UINT_T *startOfDayTimerVal) |
| { |
| UINT_T i, TS_Version; |
| P_TRANSFER_STRUCT_v2 pTS_v2; |
| |
| // If the passed in Transfer Struct is not NULL, parse it and initialize |
| // the platform settings, the timer value, and the TIM address. |
| if( pTS_h ) |
| { |
| TS_Version = pTS_h->TransferID; |
| if (TS_Version == TBR_XFER) // v1 of transfer struct is used by BootRom |
| { |
| pFuses->value[0] = (UINT_T) pTS_h->FuseVal; |
| pFuses->value[1] = 0x0; |
| *startOfDayTimerVal = pTS_h->SOD_ACCR0; |
| #if LAPW |
| ParseBR_ExtraState(pTS_h->ResumeParam[0]); |
| #endif |
| |
| // For the case where the TIM is not in TS coming from the IPC, |
| // TS includes random values. In this case, this loop can take a |
| // long time. With MAX_NUMBER_OF_DATA_PAIRS, we put a limit on this. |
| for( i=0; i<pTS_h->num_data_pairs && i<MAX_NUMBER_OF_DATA_PAIRS; i++) |
| { |
| if(pTS_h->data_pairs[i].data_id == TIM_DATA ) |
| { |
| *TIM_Address = pTS_h->data_pairs[i].location; |
| return; |
| } |
| } |
| } |
| else // v2 of transfer struct is used by OBM |
| { |
| pTS_v2 = (P_TRANSFER_STRUCT_v2) pTS_h; // cast to v2 of the xfer struct |
| pFuses->value[0] = pTS_v2->FuseVal[0]; |
| pFuses->value[1] = pTS_v2->FuseVal[1]; |
| *startOfDayTimerVal = pTS_v2->SOD_ACCR0; |
| |
| // For the case where the TIM is not in TS coming from the IPC, |
| // TS includes random values. In this case, this loop can take a |
| // long time. With MAX_NUMBER_OF_DATA_PAIRS, we put a limit on this. |
| for( i=0; i<pTS_v2->num_data_pairs && i<MAX_NUMBER_OF_DATA_PAIRS; i++) |
| { |
| if( pTS_v2->data_pairs[i].data_id == TIM_DATA ) |
| { |
| *TIM_Address = pTS_v2->data_pairs[i].location; |
| return; |
| } |
| } |
| } |
| } //end if( pTS_h ) |
| |
| *TIM_Address = 0; // should never be here! |
| } |
| |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This is the Fatal Error function for the Boot Loader. |
| // |
| // Inputs: Error code,cause, sub code. |
| // Outputs: NONE. |
| // |
| // It mainly stays here in an infinite loop. |
| ////////////////////////////////////////////////////////////////////// |
| void FatalError(UINT_T ErrorCode, const CHAR* ErrStr, UINT_T ErrSubCode) |
| { |
| UINT_T odd = 1; |
| |
| // Print out why we failed if it is not a port error. |
| if (ErrorCode != DownloadPortError) |
| { |
| AddMessageError(REPORT_ERROR, ErrorCode); |
| } |
| |
| #if USE_SERIAL_DEBUG |
| err_msg("Fatal Error Code: 0x%x\n\r", ErrorCode); |
| |
| if (ErrStr != NULL) |
| { |
| err_msg("Error cause: %s\n\r", ErrStr); |
| } |
| |
| if (ErrSubCode != NULL) |
| err_msg("Error sub code: 0x%x\n\r", ErrSubCode); |
| |
| #endif |
| |
| //if( !isDownload ) // no reset for downloading |
| // do_wdt_reset(); |
| |
| #if SPINOR_CODE |
| SPINOR_Disable4BytesMode(); |
| #endif |
| |
| // Infinite loop! |
| while(odd&1) |
| { |
| // need debugger to step beyond this loop after inspecting input args... |
| odd+=2; |
| } |
| |
| return; |
| } |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This is the function that performs TIM based setup in the Boot Loader. |
| // |
| // Inputs: A pointer to the TIM and a pointer to the Fuses. |
| // Outputs: NONE. |
| // |
| // It mainly functions as following: |
| // 1) Configures the operating mode. |
| // 2) Configures the DDR. |
| // 3) Enables the interrupts. |
| // 4) Enables the global interrupts. |
| // 5) Checks the TIM for port over-writes. If this fails, initializes |
| // the default ports. |
| ////////////////////////////////////////////////////////////////////// |
| void PerformTIMBasedSetup(pTIM pTIM_h, pFUSE_SET pFuses) |
| { |
| UINT_T Retval = NoError; |
| |
| #if REPORT_DDR_INFO |
| MCK5_Check_LPDDR2_Info(pTIM_h); |
| #endif |
| |
| // Configure DDR if BootROM doesn't configure it. |
| if (pFuses->bits.DDRInitialized == FALSE) |
| { |
| Retval = CheckAndConfigureDDR(pTIM_h, pFuses); |
| if (Retval != NoError) |
| { |
| FatalError(Retval, "PTBS", NULL); |
| } |
| } |
| |
| // Interrupts may be required, so enable them. |
| // For example, downloading over USB requires interrupts. |
| |
| // point the interrupt exception handler to our routine. |
| // this allows us to run in-place out of isram |
| // without having to enable the enable the mmu. |
| SetInterruptVector(VECTOR_SRAM_BASE_ADDR); |
| IRQ_Glb_Dis(); // turns off all interrupts... |
| EnableIrqInterrupts(); // Enable Interrupts at the core |
| IRQ_Glb_Ena(); // Enable Global Ints using the AP Global Interrupt Mask Register |
| |
| //if (NoFrequencyChange == 0) // change pp as default |
| // pp_set(); |
| #if CP_BOOT |
| /* ASR1803S boot to MSA L2SRAM */ |
| #if FLCN || FACT |
| BU_REG_WRITE(0xD4050020, 0x23); |
| SetupL2SRAMMPU(); |
| #endif |
| #endif |
| } |
| |
| static INT FindDkbiPatternInTIM(pTIM pTIM_h) |
| { |
| pIMAGE_INFO_3_4_0 pImgInfo = NULL; |
| UINT_T TimSize; |
| UINT_T DkbiPatternAddr; |
| |
| pImgInfo = FindImageInTIM(pTIM_h, TIMIDENTIFIER); |
| if(pImgInfo == NULL){ |
| return 0; |
| } |
| |
| TimSize = (pImgInfo->ImageSize + 3) & (~3); //4byte align |
| DkbiPatternAddr = 0xD1000000 + TimSize; |
| |
| if(BU_REG_READ(DkbiPatternAddr) == DKBIDENTIFIER && |
| BU_REG_READ(DkbiPatternAddr+4) == DKBIDENTIFIER) |
| { |
| BU_REG_WRITE(DkbiPatternAddr, 0); |
| BU_REG_WRITE(DkbiPatternAddr+4, 0); |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| UINT_T PlatformInitFlash(pTIM pTIM_h) |
| { |
| UINT_T Retval = NoError; |
| UINT_T FlashNumber; |
| |
| if(IsTim4DKBI(pTIM_h)) { |
| /* No valid flash ID in TIMH for DKBI */ |
| return NoError; |
| } |
| |
| FlashNumber = (pTIM_h->pConsTIM->FlashInfo.BootFlashSign) & 0xFF; |
| if(!FlashInitDone) |
| { |
| // Determine the Flash that will be used to store the downloaded images. |
| Retval = Configure_Flashes (FlashNumber, BOOT_FLASH); |
| if( Retval == NoError) |
| { |
| InitializeDualTimEarly(pTIM_h); |
| |
| //turn on the flash management |
| InitializeFM(LEGACY_METHOD, BOOT_FLASH); |
| |
| #if !UPDATER |
| InitializeDualTimLate(pTIM_h); |
| #endif |
| |
| #ifdef BBM_LEGACY_EXT && !UPDATER |
| DetectScrubBitflipBlocks(); |
| #endif |
| FlashInitDone = 1; |
| |
| obm_printf("Flash Init Done\n\r"); |
| } |
| } |
| |
| return Retval; |
| } |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This is the Mode Determining function for the Boot Loader. |
| // |
| // Inputs: A pointer to the Fuses and a pointer to the TIM. |
| // Outputs: Returns one of the following operationg modes: |
| // UPGRADESW, DOWNLOAD, SINGLE_TIM_BOOT, or DUAL_TIM_BOOT |
| // |
| // It mainly functions as following: |
| // 1) Sets running as identifier. |
| // 2) Check if the HW upgrade request button is pressed. If so, mode = UPGRADESW. |
| // 3) Else if there is a DKB ID in the TIM, then mode = DOWNLOAD. |
| // 4) Else if there is a DUAL TIM ID in the TIM, then mode = DUAL_TIM_BOOT. |
| // 5) Else by default, we have mode = SINGLE_TIM_BOOT. |
| ////////////////////////////////////////////////////////////////////// |
| OPERATING_MODE_T DetermineOperatingMode(FUSE_SET *pFuses, pTIM pTIM_h) |
| { |
| OPERATING_MODE_T mode = SINGLE_TIM_BOOT; |
| UINT_T loops; |
| UINT gotkey = 0, Retval; |
| P_FOTA_Firmware pFOTA_T = NULL; |
| UINT_T ATDL_Cfg = 0; |
| |
| PlatformInitFlash(pTIM_h); |
| |
| // No user request for software update. |
| // Deterimine from TIM headers what to do. |
| // If DKB Identifier is found then we have download mode. |
| if (IsTim4DKBI(pTIM_h) || FindDkbiPatternInTIM(pTIM_h)) |
| { |
| mode = DOWNLOAD; |
| time_count_enable = FALSE; |
| obm_printf("Empty Board or Force Download\n\r"); |
| return mode; |
| } |
| |
| ATDL_Cfg = GetAutoDownloadConfig(pTIM_h); |
| if (ATDL_Cfg) { |
| mode = UPGRADESW; |
| time_count_enable = TRUE; |
| time_count_in_sec = ATDL_Cfg; |
| obm_printf("ATDL download\n\r"); |
| return mode; |
| } |
| |
| if(PlatformCheckForceUSBEnumFlag()) |
| { |
| mode = UPGRADESW; |
| time_count_enable = TRUE; |
| PlatformClearForceUSBEnumFlag(); |
| obm_printf("Download due to force usb enum flag\n\r"); |
| return mode; |
| } |
| |
| if(serial_read_byte() == 0x0D) /* CR pressed */ |
| { |
| mode = UPGRADESW; |
| time_count_enable = TRUE; |
| obm_printf("Uart force to download\n\r"); |
| return mode; |
| } |
| |
| pFOTA_T = OTAGetConfig(pTIM_h); |
| if(pFOTA_T && (pFOTA_T->dlflag[0] == DLFLG) && (pFOTA_T->dlflag[1] != DLDONE)) |
| { |
| mode = UPGRADESW; |
| time_count_enable = FALSE; |
| obm_printf("Wait for unfinished download...\n\r"); |
| return mode; |
| } |
| |
| #if TRUSTED |
| if (pFOTA_T && (pFOTA_T->TrustBootStatus != 0) && (pFOTA_T->TrustBootStatus != -1)) |
| { |
| Retval = pFOTA_T->TrustBootStatus; |
| pFOTA_T->TrustBootStatus = TB_NO_ERROR; |
| OTA_Save_Config(pTIM_h); |
| #if TB_ERROR_DOWNLOAD |
| obm_printf("Force Download Due to Trust Boot Error: %d\n\r", Retval); |
| mode = UPGRADESW; |
| time_count_enable = FALSE; |
| return mode; |
| #else |
| obm_printf("Dead Loop Due to Trust Boot Error: %d\n\r", Retval); |
| while(1); |
| #endif |
| } |
| #endif |
| |
| if ( PlatformUSBPluggedIn() ) |
| { |
| obm_printf("USB cable plugged in\n\r"); |
| if(ASRFlag_InProductionMode(pTIM_h)) |
| { |
| if(pOBM2OSL_h->booting_mode != OBMNODL && OBMNODL_RST_FLAG != OBMNODL) |
| { |
| mode = UPGRADESW; |
| time_count_enable = TRUE; // this is active enumeration by OBM if USB is connect, need to set timeout |
| obm_printf("[PROD]Enum USB port\n\r"); |
| }else{ |
| obm_printf("[PROD]Don't enum USB port\n\r"); |
| } |
| OBMNODL_RST_FLAG= 0; |
| } else { |
| UINT_T DlFlag = BU_REG_READ(OBMDL_DDR_ADDRES); |
| if(DlFlag == OBMDL) |
| { |
| BU_REG_WRITE(OBMDL_DDR_ADDRES, 0x0); |
| mode = UPGRADESW; |
| time_count_enable = FALSE; |
| obm_printf("[Non-Prod]Wait for download(AT)...\n\r"); |
| }else { |
| obm_printf("[Non-Prod]Don't enum USB port\n\r"); |
| } |
| } |
| return mode; |
| } |
| |
| #if UPDATE_USE_GPIO |
| for(loops = 0; loops < 10; loops++) |
| { |
| gotkey = PlatformCheckGPIOKey(); |
| if (gotkey) |
| break; |
| } |
| switch (gotkey) |
| { |
| case KEYID_UPGRADESW_REQUEST: |
| mode = UPGRADESW; |
| time_count_enable = TRUE; |
| break; |
| case KEYID_PRODUCT_USB_MODE_REQUEST: |
| product_mode_select = PRODUCT_USB_MODE; |
| obm_printf("Production mode detected\n\r"); |
| break; |
| default: |
| break; |
| } |
| #endif |
| return mode; |
| } |
| |
| |
| ////////////////////////////////////////////////////////////////////// |
| // This is the Finalization Setup function for the Boot Loader. |
| // |
| // Inputs: A pointer to the fuses and a pointer to the TIM. |
| // Outputs: NONE. |
| // |
| // It mainly functions as following: |
| // 1) Shut down all the ports. |
| // 2) Shuts down the security API. |
| // 3) Finalize Flashes. |
| // 4) Disable interrupts. |
| // 5) Restore platform default configuration. |
| ////////////////////////////////////////////////////////////////////// |
| void FinalizeSetup(pFUSE_SET pFuses, pTIM pTIM_h ) |
| { |
| UINT_T retval = NoError; |
| |
| #if TRUSTED |
| // Shut down the security API. |
| //if (pFuses->bits.SBE) |
| { |
| retval = SecurityShutdown(); |
| if( retval != NoError) |
| { |
| FatalError(retval, "FS", NULL); |
| } |
| } |
| #endif |
| |
| // Finalize the Flashes. |
| Finalize_Flashes(BOOT_FLASH); // this will flush the BBT information if necessary. |
| |
| // Disable interrupts. |
| DisableIrqInterrupts(); |
| } |
| |