www.pudn.com > iMx31_WCE600.rar > main.c
// // Copyright (c) Microsoft Corporation. All rights reserved. // // // Use of this source code is subject to the terms of the Microsoft end-user // license agreement (EULA) under which you licensed this SOFTWARE PRODUCT. // If you did not accept the terms of the EULA, you are not authorized to use // this source code. For a copy of the EULA, please see the LICENSE.RTF on your // install media. // //------------------------------------------------------------------------------ // // Copyright (C) 2004-2007, Freescale Semiconductor, Inc. All Rights Reserved. // THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS // AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT // //------------------------------------------------------------------------------ // // File: main.c // // Common routines for the bootloader. // //----------------------------------------------------------------------------- #include "bsp.h" #include#pragma warning(push) #pragma warning(disable: 4115) #include #pragma warning(pop) #include "loader.h" //----------------------------------------------------------------------------- // External Functions extern BOOL NANDLoadIPL(VOID); extern BOOL NANDLoadNK(VOID); extern BOOL SDHCLoadNK(VOID); extern BOOL FlashLoadBootCFG(BYTE *pBootCfg, DWORD cbBootCfgSize); extern BOOL FlashStoreBootCFG(BYTE *pBootCfg, DWORD cbBootCfgSize); extern void Launch(unsigned int uAddr); extern BOOL BLMenu(); extern UINT32 OEMGetMagicNumber(); //----------------------------------------------------------------------------- // External Variables extern PCSP_PBC_REGS g_pPBC; //----------------------------------------------------------------------------- // Defines //----------------------------------------------------------------------------- // Types //----------------------------------------------------------------------------- // Global Variables BSP_ARGS *g_pBSPArgs; IMAGE_TYPE g_ImageType; IMAGE_MEMORY g_ImageMemory; BOOT_CFG g_BootCFG; BOOL g_DownloadImage = TRUE; UCHAR *g_DefaultRamAddress; BOOL g_bNandBootloader; BOOL g_bNandExist; BOOL g_bSDHCBootloader; BOOL g_bSDHCExist; // Used to save information about downloaded DIO mage BOOT_BINDIO_CONTEXT g_BinDIO; //----------------------------------------------------------------------------- // Local Variables //------------------------------------------------------------------------------ // Local Functions // BOOL LoadBootCFG(BOOT_CFG *BootCFG); BOOL StoreBootCFG(BOOT_CFG *BootCFG); void ResetDefaultBootCFG(BOOT_CFG *pBootCFG); BOOL OEMVerifyMemory(DWORD dwStartAddr, DWORD dwLength); BOOL OEMReportError (DWORD dwReason, DWORD dwReserved); void OEMMultiBINNotify(const PMultiBINInfo pInfo); //------------------------------------------------------------------------------ // // Function: main // // Bootloader main routine. // // Parameters: // None. // // Returns: // None. // //------------------------------------------------------------------------------ void main(void) { // Common boot loader (blcommon) main routine. // BootloaderMain(); // Should never get here. // SpinForever(); } //------------------------------------------------------------------------------ // // Function: OEMDebugInit // // This function is the first called by the BLCOMMON framework when a boot // loader starts. This function initializes the debug transport, usually just // initializing the debug serial universal asynchronous receiver-transmitter // (UART). // // Parameters: // None. // // Returns: // TRUE indicates success. FALSE indicates failure. // //------------------------------------------------------------------------------ BOOL OEMDebugInit (void) { OEMInitDebugSerial(); return TRUE; } //------------------------------------------------------------------------------ // // Function: OEMPlatformInit // // This function initializes the platform and is called by the BLCOMMON // framework. // // Parameters: // None. // // Returns: // TRUE indicates success. FALSE indicates failure. //------------------------------------------------------------------------------ BOOL OEMPlatformInit (void) { PCSP_CCM_REGS pCCM; UINT32 rcsr; OEMBootInit (); // Get reset status from CCM pCCM = (PCSP_CCM_REGS) OALPAtoUA(CSP_BASE_REG_PA_CCM); rcsr = INREG32(&pCCM->RCSR); // Determine boot mode switch(CSP_BITFEXT(rcsr, CCM_RCSR_BTP)) { // BOOT[4:0] configured for NAND boot case 0x01: case 0x02: case 0x03: case 0x04: case 0x10: case 0x11: case 0x12: case 0x13: g_bNandBootloader = TRUE; KITLOutputDebugString("INFO: Bootloader launched from NAND\r\n"); break; // Otherwise assume NOR bootloader default: KITLOutputDebugString("INFO: Bootloader launched from NOR\r\n"); g_bNandBootloader = FALSE; break; } // Check for image reflash flag from RVD if (CSP_BITFEXT(rcsr, CCM_RCSR_GPF) == 0xF) { KITLOutputDebugString("Reflash request detected!\r\n"); // Write out the image previously downloaded into SDRAM // by RVD OEMWriteFlash((DWORD) OALPAtoCA(IMAGE_BOOT_NORDEV_NOR_PA_START), IMAGE_BOOT_NORDEV_NOR_SIZE); // EBOOT download is unnecessary since RVD downloaded image via JTAG g_DownloadImage = FALSE; // Jump to OS image OEMLaunch(0, 0, (DWORD) OALPAtoCA(IMAGE_BOOT_NKIMAGE_NOR_PA_START), NULL); } // Initialize the BSP args structure. // g_pBSPArgs = (BSP_ARGS *) IMAGE_SHARE_ARGS_UA_START; if ((g_pBSPArgs->header.signature != OAL_ARGS_SIGNATURE) || (g_pBSPArgs->header.oalVersion != OAL_ARGS_VERSION) || (g_pBSPArgs->header.bspVersion != BSP_ARGS_VERSION)) { memset((LPVOID)g_pBSPArgs, 0, sizeof(BSP_ARGS)); g_pBSPArgs->header.signature = OAL_ARGS_SIGNATURE; g_pBSPArgs->header.oalVersion = OAL_ARGS_VERSION; g_pBSPArgs->header.bspVersion = BSP_ARGS_VERSION; g_pBSPArgs->kitl.flags = (OAL_KITL_FLAGS_ENABLED | OAL_KITL_FLAGS_VMINI); g_pBSPArgs->kitl.devLoc.IfcType = Internal; g_pBSPArgs->kitl.devLoc.BusNumber = 0; g_pBSPArgs->kitl.devLoc.LogicalLoc = BSP_BASE_REG_PA_CS8900A_IOBASE; g_pBSPArgs->kitl.devLoc.PhysicalLoc = (PVOID)(BSP_BASE_REG_PA_CS8900A_IOBASE); g_pBSPArgs->updateMode = FALSE; } // Update global BSP args struct with user switches on ADS board OALBspArgsInit(g_pBSPArgs); // Attempt to initialize the NAND flash driver if (!FMD_Init(NULL, NULL, NULL)) { KITLOutputDebugString("WARNING: OEMPlatformInit: Failed to initialize NAND flash device.\r\n"); g_bNandExist = FALSE; } else { KITLOutputDebugString("INFO: OEMPlatformInit: Initialized NAND flash device.\r\n"); g_bNandExist = TRUE; } // Load eboot configuration // if (!LoadBootCFG(&g_BootCFG)) { // Load default bootloader configuration settings. KITLOutputDebugString("ERROR: flash initialization failed - loading bootloader defaults...\r\n"); ResetDefaultBootCFG(&g_BootCFG); } // Set up optional bootloader function pointers. // g_pOEMMultiBINNotify = OEMMultiBINNotify; g_pOEMVerifyMemory = OEMVerifyMemory; g_pOEMReportError = OEMReportError; return TRUE; } //------------------------------------------------------------------------------ // // Function: OEMPreDownload // // This function is called by the BLCOMMON framework prior to download and can // be customized to prompt for user feedback, such as obtaining a static IP // address or skipping the download and jumping to a flash-resident run-time // image. // // Parameters: // None. // // Returns: // Possible return values for OEMPreDownload: // // Value Description // ----- ----------- // BL_DOWNLOAD = 0 Download the OS image from the host machine. // BL_JUMP = 1 Skip the download and jump to a resident OS image. // BL_ERROR = -1 Image download is unsuccessful. //------------------------------------------------------------------------------ DWORD OEMPreDownload(void) { UINT32 rc = (DWORD)BL_ERROR; BOOL fGotJumpImg = FALSE; // User menu code... // if (!BLMenu()) { return rc; } // Create device name based on Ethernet address (this is how Platform Builder identifies this device). // OALKitlCreateName(BSP_DEVICE_PREFIX, g_pBSPArgs->kitl.mac, (CHAR *)g_pBSPArgs->deviceId); KITLOutputDebugString("INFO: Using device name: '%s'\n", g_pBSPArgs->deviceId); fGotJumpImg = GetPreDownloadInfo (&g_BootCFG); if (!g_DownloadImage || // this gets set in the BLMenu() function fGotJumpImg) // this gets set in EbootInitEtherTransport { switch(g_BootCFG.autoDownloadImage) { case BOOT_CFG_AUTODOWNLOAD_NK_NOR: rc = BL_JUMP; break; case BOOT_CFG_AUTODOWNLOAD_NK_NAND: if (NANDLoadNK()) { rc = BL_JUMP; } else { KITLOutputDebugString("ERROR: Failed to load OS image from NAND.\r\n"); } break; case BOOT_CFG_AUTODOWNLOAD_IPL_NAND: if (NANDLoadIPL()) { rc = BL_JUMP; } else { KITLOutputDebugString("ERROR: Failed to load IPL image from NAND.\r\n"); } break; } // Set the clean boot flag so that OAL will let the kernel know that // it needs a clean boot // // g_pBSPArgs->bCleanBootFlag = TRUE; } else if (g_DownloadImage) { rc = BL_DOWNLOAD; } return(rc); } //------------------------------------------------------------------------------ // // Function: OEMLaunch // // This function launches the run-time image. It is the last one called by // the BLCOMMON framework. // // Parameters: // dwImageStart // [in] Starting address of OS image. // // dwImageLength // [in] Length, in bytes, of the OS image. // // dwLaunchAddr // [in] First instruction of the OS image. // // pRomHdr // [out] Pointer to the ROM header structure. // // Returns: // None. //------------------------------------------------------------------------------ void OEMLaunch (DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr, const ROMHDR *pRomHdr) { UINT32 PhysAddress; // Remove-W4: Warning C4100 workaround UNREFERENCED_PARAMETER(pRomHdr); switch(g_BootCFG.autoDownloadImage) { case BOOT_CFG_AUTODOWNLOAD_NK_NOR: // Set launch address for NOR OS image. OS executes-in-place from NOR. PhysAddress = IMAGE_BOOT_NKIMAGE_NOR_PA_START; break; case BOOT_CFG_AUTODOWNLOAD_NK_NAND: // Set launch address for NAND/SDHC OS image. OS is copied into RAM for execution. PhysAddress = IMAGE_BOOT_NKIMAGE_RAM_PA_START; break; case BOOT_CFG_AUTODOWNLOAD_IPL_NAND: // Set launch address for NAND IPL image. IPL is copied into RAM for execution. PhysAddress = IMAGE_BOOT_IPLIMAGE_RAM_START; break; default: // If a launch address wasn't specified - use the last known good address. // if (!dwLaunchAddr) { dwLaunchAddr = g_BootCFG.dwLaunchAddr; } else { if (g_BootCFG.dwLaunchAddr != dwLaunchAddr || g_BootCFG.dwPhysStart != dwImageStart || g_BootCFG.dwPhysLen != dwImageLength) { g_BootCFG.dwLaunchAddr = dwLaunchAddr; g_BootCFG.dwPhysStart = dwImageStart; g_BootCFG.dwPhysLen = dwImageLength; StoreBootCFG(&g_BootCFG); } } // Translate the image start address (virtual address) to a physical address. // PhysAddress = (UINT32) OALVAtoPA((VOID *)dwLaunchAddr); break; } KITLOutputDebugString("Download successful! Jumping to image at 0x%x (physical 0x%x)...\r\n", dwLaunchAddr, PhysAddress); // Wait for PB connection... // if (g_DownloadImage) { GetLaunchInfo (); } // Jump to the image we just downloaded. // KITLOutputDebugString("\r\n\r\n\r\n"); OEMWriteDebugLED(0, 0x00FF); Launch(PhysAddress); // Should never get here... // SpinForever(); } //------------------------------------------------------------------------------ // // Function: OEMMultiBINNotify // // Receives/processes download file manifest. // // Parameters: // pInfo // [in] Download manifiest provided by BLCOMMON framework. // // Returns: // void //------------------------------------------------------------------------------ void OEMMultiBINNotify(const PMultiBINInfo pInfo) { CHAR szFileName[MAX_PATH]; int i, key, fileExtPos; if (!pInfo) return; KITLOutputDebugString("INFO: OEMMultiBINNotify (dwNumRegions = %d, dwRegionStart = 0x%x).\r\n", pInfo->dwNumRegions, pInfo->Region[0].dwRegionStart); // Only inspect manifest if this is a monolithic .nb0 or diskimage file if (pInfo->dwNumRegions != 1) return; // NBO and DIO files will have start address of zero if (pInfo->Region[0].dwRegionStart == 0) { // Convert the file name to lower case i = 0; fileExtPos = 0; while ((pInfo->Region[0].szFileName[i] != '\0') && (i < MAX_PATH)) { szFileName[i] = (CHAR)tolower(pInfo->Region[0].szFileName[i]); // Keep track of file extension position if (szFileName[i] == '.') { fileExtPos = i; } i++; } // Check for NAND XLDR update if (strncmp(szFileName, XLDR_NB0_FILE, XLDR_NB0_FILE_LEN) == 0) { // Remap the start address to the NAND XLDR region pInfo->Region[0].dwRegionStart = (DWORD) OALPAtoCA(IMAGE_BOOT_XLDRIMAGE_NAND_PA_START); KITLOutputDebugString("INFO: XLDR NB0 remapped to 0x%x.\r\n", pInfo->Region[0].dwRegionStart); } // Check for EBOOT/SBOOT update else if ( (strncmp(szFileName, EBOOT_NB0_FILE, EBOOT_NB0_FILE_LEN) == 0) || (strncmp(szFileName, SBOOT_NB0_FILE, SBOOT_NB0_FILE_LEN) == 0) ) { // Remap the start address to the region specified by the user KITLOutputDebugString("Specify destination for EBOOT/SBOOT NB0 [1 = NOR, 2 = NAND]: "); do { key = OEMReadDebugByte(); } while ((key != '1') && (key != '2')); KITLOutputDebugString("\r\n"); switch (key) { case '1': pInfo->Region[0].dwRegionStart = (DWORD) OALPAtoCA(IMAGE_BOOT_BOOTIMAGE_NOR_PA_START); break; case '2': pInfo->Region[0].dwRegionStart = (DWORD) OALPAtoCA(IMAGE_BOOT_BOOTIMAGE_NAND_PA_START); break; default: return; } KITLOutputDebugString("\r\nINFO: EBOOT/SBOOT NB0 remapped to 0x%x.\r\n", pInfo->Region[0].dwRegionStart); } // If file to be downloaded has an NB0 extension, assume it is an NK NB0 image else if (fileExtPos && (strncmp(&szFileName[fileExtPos], ".nb0", 4) == 0)) { // Remap the start address to the region specified by the user KITLOutputDebugString("Specify destination for NK NB0 [0 = RAM, 1 = NOR, 2 = NAND,]: "); do { key = OEMReadDebugByte(); } while ((key != '0') && (key != '1') && (key != '2')); KITLOutputDebugString("\r\n"); switch (key) { case '0': pInfo->Region[0].dwRegionStart = (DWORD) OALPAtoCA(IMAGE_BOOT_NKIMAGE_RAM_PA_START); break; case '1': pInfo->Region[0].dwRegionStart = (DWORD) OALPAtoCA(IMAGE_BOOT_NKIMAGE_NOR_PA_START); break; case '2': pInfo->Region[0].dwRegionStart = (DWORD) OALPAtoCA(IMAGE_BOOT_NKIMAGE_NAND_PA_START); break; default: return; } KITLOutputDebugString("\r\nINFO: NK NB0 remapped to 0x%x.\r\n", pInfo->Region[0].dwRegionStart); } // Notify user of unsupported format else { KITLOutputDebugString("\r\nWARNING: Unsupported binary format. Image not remapped.\r\n"); } } // If this is a Windows Mobile disk image BIN, then dwRegionStart will // be offset into NAND. else if (pInfo->Region[0].dwRegionStart < IMAGE_BOOT_RAMDEV_RAM_PA_START) { g_ImageType = IMAGE_TYPE_BINDIO; g_ImageMemory = IMAGE_MEMORY_NAND; KITLOutputDebugString("\r\nINFO: DIO image with starting address 0x%x.\r\n", pInfo->Region[0].dwRegionStart); } return; } //------------------------------------------------------------------------------ // // Function: OEMReportError // // Error reporting function provided by BLCOMMON framework. // // Parameters: // dwReason // [in] Reason for error // // dwReserved // [in] Reserved parameter // // Returns: // void //------------------------------------------------------------------------------ BOOL OEMReportError (DWORD dwReason, DWORD dwReserved) { // Remove-W4: Warning C4100 workaround UNREFERENCED_PARAMETER(dwReserved); KITLOutputDebugString("INFO: OEMReportError Reason 0x%x\r\n", dwReason); return TRUE; } //----------------------------------------------------------------------------- // // Function: OEMVerifyMemory // // This function verifies that the address provided is in valid memory, // and sets globals to describe the image region being updated. // // Parameters: // dwStartAddr // [in] Address to be verified. // // dwLength // [in] Length of the address, in bytes. // // Returns: // TRUE indicates success. FALSE indicates failure. // //----------------------------------------------------------------------------- BOOL OEMVerifyMemory(DWORD dwStartAddr, DWORD dwLength) { BOOL rc = TRUE; DWORD dwPhysVerifyStart; DWORD dwPhysVerifyEnd; // First check for DIO image flagged by OEMMultiBINNotify if (g_ImageType == IMAGE_TYPE_BINDIO) { KITLOutputDebugString("INFO: Downloading DIO NAND image.\r\n"); return (TRUE); } dwPhysVerifyStart = (DWORD) OALVAtoPA((void *)dwStartAddr); dwPhysVerifyEnd = dwPhysVerifyStart + dwLength - 1; KITLOutputDebugString("INFO: OEMVerifyMemory (CA = 0x%x, PA = 0x%x, length = 0x%x)\r\n", dwStartAddr, dwPhysVerifyStart, dwLength); if ((dwPhysVerifyStart >= IMAGE_BOOT_XLDRIMAGE_NAND_PA_START) && (dwPhysVerifyEnd <= IMAGE_BOOT_XLDRIMAGE_NAND_PA_END)) { KITLOutputDebugString("INFO: Downloading XLDR NAND image.\r\n"); g_ImageType = IMAGE_TYPE_XLDR; g_ImageMemory = IMAGE_MEMORY_NAND; } else if ((dwPhysVerifyStart >= IMAGE_BOOT_BOOTIMAGE_NAND_PA_START) && (dwPhysVerifyEnd <= IMAGE_BOOT_BOOTIMAGE_NAND_PA_END)) { KITLOutputDebugString("INFO: Downloading EBOOT/SBOOT NAND image.\r\n"); g_ImageType = IMAGE_TYPE_BOOT; g_ImageMemory = IMAGE_MEMORY_NAND; } else if ((dwPhysVerifyStart >= IMAGE_BOOT_IPLIMAGE_NAND_PA_START) && (dwPhysVerifyEnd <= IMAGE_BOOT_IPLIMAGE_NAND_PA_END)) { KITLOutputDebugString("INFO: Downloading IPL NAND image.\r\n"); g_ImageType = IMAGE_TYPE_IPL; g_ImageMemory = IMAGE_MEMORY_NAND; } // DIO and NK share this start address else if ((dwPhysVerifyStart >= IMAGE_BOOT_NKIMAGE_NAND_PA_START) && (dwPhysVerifyEnd <= IMAGE_BOOT_NKIMAGE_NAND_PA_END)) { KITLOutputDebugString("INFO: Downloading NK NAND image.\r\n"); g_ImageType = IMAGE_TYPE_NK; g_ImageMemory = IMAGE_MEMORY_NAND; } else if ((dwPhysVerifyStart >= IMAGE_BOOT_BOOTIMAGE_NOR_PA_START) && (dwPhysVerifyEnd <= IMAGE_BOOT_BOOTIMAGE_NOR_PA_END)) { KITLOutputDebugString("INFO: Downloading EBOOT/SBOOT NOR image.\r\n"); g_ImageType = IMAGE_TYPE_BOOT; g_ImageMemory = IMAGE_MEMORY_NOR; } else if ((dwPhysVerifyStart >= IMAGE_BOOT_NKIMAGE_NOR_PA_START) && (dwPhysVerifyEnd <= IMAGE_BOOT_NKIMAGE_NOR_PA_END)) { KITLOutputDebugString("INFO: Downloading NK NOR image.\r\n"); g_ImageType = IMAGE_TYPE_NK; g_ImageMemory = IMAGE_MEMORY_NOR; } else if ((dwPhysVerifyStart >= IMAGE_BOOT_NORDEV_NOR_PA_START) && (dwPhysVerifyEnd <= IMAGE_BOOT_NORDEV_NOR_PA_END)) { KITLOutputDebugString("INFO: Downloading NK NOR image.\r\n"); KITLOutputDebugString("WARNING: NK image will overwrite EBOOT reserved space \r\n"); g_ImageType = IMAGE_TYPE_NK; g_ImageMemory = IMAGE_MEMORY_NOR; } else if ((dwPhysVerifyStart >= IMAGE_BOOT_RAMDEV_RAM_PA_START) && (dwPhysVerifyEnd <= IMAGE_BOOT_RAMDEV_RAM_PA_END)) { KITLOutputDebugString("INFO: Downloading NK RAM image.\r\n"); g_ImageType = IMAGE_TYPE_NK; g_ImageMemory = IMAGE_MEMORY_RAM; } else { KITLOutputDebugString("ERROR: Invalid address range.\r\n"); rc = FALSE; } return(rc); } //------------------------------------------------------------------------------ // // Function: StoreBootCFG // // Stores bootloader configuration information (menu settings, etc.) in flash. // // Parameters: // BootCfg // [in] Points to bootloader configuration to be stored. // // Returns: // TRUE indicates success. FALSE indicates failure. // //----------------------------------------------------------------------------- BOOL StoreBootCFG(BOOT_CFG *BootCfg) { if (!FlashStoreBootCFG((BYTE*) BootCfg, sizeof(BOOT_CFG))) { KITLOutputDebugString("ERROR: StoreBootCFG: failed to write configuration.\r\n"); return(FALSE); } return(TRUE); } //------------------------------------------------------------------------------ // // Function: LoadBootCFG // // Retrieves bootloader configuration information (menu settings, etc.) from // flash. // // Parameters: // BootCfg // [out] Points to bootloader configuration that will be filled with // loaded data. // // Returns: // TRUE indicates success. FALSE indicates failure. // //----------------------------------------------------------------------------- BOOL LoadBootCFG(BOOT_CFG *BootCfg) { if (!FlashLoadBootCFG((BYTE*) BootCfg, sizeof(BOOT_CFG))) { KITLOutputDebugString("ERROR: LoadBootCFG: failed to load configuration.\r\n"); return(FALSE); } // Is the CFG data valid? Check for the magic number that was written the last time // the CFG block was updated. If Eboot has never been run, there will be no configuration // information, so the magic number will likely not be found. In this case, setup the // factory defaults and store them into Flash. // if (BootCfg->ConfigMagicNumber != OEMGetMagicNumber()) { KITLOutputDebugString("ERROR: LoadBootCFG: ConfigMagicNumber not correct. Expected = 0x%x ; Actual = 0x%x.\r\n", OEMGetMagicNumber(), BootCfg->ConfigMagicNumber); ResetDefaultBootCFG(BootCfg); } g_DefaultRamAddress = (PUCHAR)g_BootCFG.dwLaunchAddr; return(TRUE); }