SMDK2440A 5.0BSP之eboot流程(作者:wogoyixikexie@gliet)

来源:互联网 发布:好用的linux系统 编辑:程序博客网 时间:2024/05/17 03:13

SMDK2440A 5.0BSP之eboot流程(作者:wogoyixikexie@gliet

      这两天为了搞明白bootloader的binfs分区功能,看了大量代码,觉得有必要把整个eboot流程疏理一下。至于binfs分区以及MBR等相关信息,请看http://topic.csdn.net/u/20081203/11/6d0f940c-03e1-487b-a922-e08cc980908d.html这个帖子吧,我贴了好多代码,我想应该可以看出他们的工作原理了。

      好,投入正题,bootloader是裸奔的,所以一定会有main函数,所以我们就从这个main函数开始吧。

  1. /*
  2.     @func   void | main | Samsung bootloader C routine entry point.
  3.     @rdesc  N/A.
  4.     @comm    
  5.     @xref   
  6.     @裸奔时候的main函数
  7. */
  8. void main(void)
  9. {
  10.     
  11.     // Clear LEDs.
  12.     //   
  13.     OEMWriteDebugLED(0, 0x3);
  14.     
  15.     // Common boot loader (blcommon) main routine.
  16.     //C:/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BLCOMMON/blcommon.c 
  17.     //BootloaderMain函数调用eboot中的函数,完成eboot功能
  18.     BootloaderMain();
  19.     // Should never get here.
  20.     // 
  21.     SpinForever();
  22. }

 

显然这个BootloaderMain函数是主角了,现在再来看看它做了什么吧。

  1. void BootloaderMain (void)
  2. {
  3.     DWORD dwAction;   
  4.     DWORD dwpToc = 0;
  5.     DWORD dwImageStart = 0, dwImageLength = 0, dwLaunchAddr = 0;
  6.     BOOL bDownloaded = FALSE;
  7.     // relocate globals to RAM为了共享变量
  8.     if (!KernelRelocate (pTOC))
  9.     {
  10.         // spin forever
  11.         HALT (BLERR_KERNELRELOCATE);
  12.     }
  13.     // (1) Init debug support. We can use OEMWriteDebugString afterward.
  14.     if (!OEMDebugInit ())
  15.     {
  16.         // spin forever
  17.         HALT (BLERR_DBGINIT);
  18.     }
  19.     // output banner
  20.     EdbgOutputDebugString (NKSignon, CURRENT_VERSION_MAJOR, CURRENT_VERSION_MINOR);
  21.     // (3) initialize platform (clock, drivers, transports, etc)
  22.     if (!OEMPlatformInit ())
  23.     {
  24.         // spin forever
  25.         HALT (BLERR_PLATINIT);
  26.     }
  27.     // system ready, preparing for download
  28.     EdbgOutputDebugString ("System ready!/r/nPreparing for download.../r/n");
  29.     // (4) call OEM specific pre-download function
  30.     switch (dwAction = OEMPreDownload ())
  31.     {
  32.     case BL_DOWNLOAD:
  33.         // (5) download image
  34.         if (!DownloadImage (&dwImageStart, &dwImageLength, &dwLaunchAddr))
  35.         {
  36.             // error already reported in DownloadImage
  37.             SPIN_FOREVER;
  38.         }
  39.         bDownloaded = TRUE;
  40.         // Check for pTOC signature ("CECE") here, after image in place
  41.         if (*(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE)
  42.         {
  43.             dwpToc = *(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG));
  44.             // need to map the content again since the pointer is going to be in a fixup address
  45.             dwpToc = (DWORD) OEMMapMemAddr (dwImageStart, dwpToc + g_dwROMOffset);
  46.             EdbgOutputDebugString ("ROMHDR at Address %Xh/r/n", dwImageStart + ROM_SIGNATURE_OFFSET + sizeof (DWORD)); // right after signature
  47.         }
  48.         // fall through 注意这里并没有break,这个用的很巧妙。
  49.     case BL_JUMP:
  50.         // Before jumping to the image, optionally check the image signature.
  51.         // NOTE: if we haven't downloaded the image by now, we assume that it'll be loaded from local storage in OEMLaunch (or it
  52.         // already resides in RAM from an earlier download), and in this case, the image start address might be 0.  This means 
  53.         // that the image signature routine will need to find the image in storage or in RAM to validate it.  Since the OEM"s 
  54.         // OEMLaunch function will need to do this anyways, we trust that it's within their abilities to do it here.
  55.         //
  56.         if (g_bBINDownload && g_pOEMCheckSignature)
  57.         {
  58.             if (!g_pOEMCheckSignature(dwImageStart, g_dwROMOffset, dwLaunchAddr, bDownloaded))
  59.                 HALT(BLERR_CAT_SIGNATURE);
  60.         }
  61.         // (5) final call to launch the image. never returned
  62.         OEMLaunch (dwImageStart, dwImageLength, dwLaunchAddr, (const ROMHDR *)dwpToc);
  63.         // should never return
  64.         // fall through
  65.     default:
  66.         // ERROR! spin forever
  67.         HALT (BLERR_INVALIDCMD);
  68.     }
  69. }

上面很多函数,都是在eboot中实现的。

下面这个函数,俺水平有限,都不知道是如何实现原理

 

    1. //
    2. // KernelRelocate: move global variables to RAM
    3. //
    4. static BOOL KernelRelocate (ROMHDR *const pTOC)
    5. {
    6.     ULONG loop;
    7.     COPYentry *cptr;
    8.     if (pTOC == (ROMHDR *const) -1)
    9.     {
    10.         return (FALSE); // spin forever!
    11.     }
    12.     // This is where the data sections become valid... don't read globals until after this
    13.     for (loop = 0; loop < pTOC->ulCopyEntries; loop++)
    14.     {
    15.         cptr = (COPYentry *)(pTOC->ulCopyOffset + loop*sizeof(COPYentry));
    16.         if (cptr->ulCopyLen)
    17.             memcpy((LPVOID)cptr->ulDest,(LPVOID)cptr->ulSource,cptr->ulCopyLen);
    18.         if (cptr->ulCopyLen != cptr->ulDestLen)
    19.             memset((LPVOID)(cptr->ulDest+cptr->ulCopyLen),0,cptr->ulDestLen-cptr->ulCopyLen);
    20.     }
    21.     return (TRUE);
    22. }
    /*
  1.     @func   DWORD | OEMPreDownload | Complete pre-download tasks - get IP address, initialize TFTP, etc.
  2.     @rdesc  BL_DOWNLOAD = Platform Builder is asking us to download an image, BL_JUMP = Platform Builder is requesting we jump to an existing image, BL_ERROR = Failure.
  3.     @comm    
  4.     @xref   
  5. */
  6. DWORD OEMPreDownload(void)
  7. {
  8.     BOOL  bGotJump = FALSE;
  9.     DWORD dwDHCPLeaseTime = 0;
  10.     PDWORD pdwDHCPLeaseTime = &dwDHCPLeaseTime;
  11.     DWORD dwBootFlags = 0;
  12.     OALMSG(OAL_FUNC, (TEXT("+OEMPreDownload./r/n")));
  13.     // Create device name based on Ethernet address (this is how Platform Builder identifies this device).
  14.     //
  15.     OALKitlCreateName(BSP_DEVICE_PREFIX, pBSPArgs->kitl.mac, pBSPArgs->deviceId);
  16.     OALMSG(OAL_INFO, (L"INFO: *** Device Name '%hs' ***/r/n", pBSPArgs->deviceId));
  17.     if ( g_bUSBDownload == FALSE )
  18.     {
  19.         // If the user wants to use a static IP address, don't request an address 
  20.         // from a DHCP server.  This is done by passing in a NULL for the DHCP 
  21.         // lease time variable.  If user specified a static IP address, use it (don't use DHCP).
  22.         //
  23.         if (!(g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DHCP))
  24.         {
  25.             // Static IP address.
  26.             pBSPArgs->kitl.ipAddress  = g_pBootCfg->EdbgAddr.dwIP;
  27.             pBSPArgs->kitl.ipMask     = g_pBootCfg->SubnetMask;
  28.             pBSPArgs->kitl.flags     &= ~OAL_KITL_FLAGS_DHCP;
  29.             pdwDHCPLeaseTime = NULL;
  30.             OALMSG(OAL_INFO, (TEXT("INFO: Using static IP address %s./r/n"), inet_ntoa(pBSPArgs->kitl.ipAddress))); 
  31.             OALMSG(OAL_INFO, (TEXT("INFO: Using subnet mask %s./r/n"),       inet_ntoa(pBSPArgs->kitl.ipMask))); 
  32.         }
  33.         else
  34.         {
  35.             pBSPArgs->kitl.ipAddress = 0;
  36.             pBSPArgs->kitl.ipMask    = 0;
  37.         }
  38.         if ( !g_bDownloadImage)
  39.         {
  40.             return(BL_JUMP);
  41.         }
  42.         // Initialize the the TFTP transport.
  43.         //
  44.         g_DeviceAddr.dwIP = pBSPArgs->kitl.ipAddress;
  45.         memcpy(g_DeviceAddr.wMAC, pBSPArgs->kitl.mac, (3 * sizeof(UINT16)));
  46.         g_DeviceAddr.wPort = 0;
  47.         if (!EbootInitEtherTransport(&g_DeviceAddr,
  48.                                      &pBSPArgs->kitl.ipMask,
  49.                                      &bGotJump,
  50.                                      pdwDHCPLeaseTime,
  51.                                      EBOOT_VERSION_MAJOR,
  52.                                      EBOOT_VERSION_MINOR,
  53.                                      BSP_DEVICE_PREFIX,
  54.                                      pBSPArgs->deviceId,
  55.                                      EDBG_CPU_ARM720,
  56.                                      dwBootFlags))
  57.         {
  58.             OALMSG(OAL_ERROR, (TEXT("ERROR: OEMPreDownload: Failed to initialize Ethernet connection./r/n")));
  59.             return(BL_ERROR);
  60.         }
  61.         // If the user wanted a DHCP address, we presumably have it now - save it for the OS to use.
  62.         //
  63.         if (g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DHCP)
  64.         {
  65.             // DHCP address.
  66.             pBSPArgs->kitl.ipAddress  = g_DeviceAddr.dwIP;
  67.             pBSPArgs->kitl.flags     |= OAL_KITL_FLAGS_DHCP;
  68.         }
  69.         
  70.         OALMSG(OAL_FUNC, (TEXT("_OEMPreDownload./r/n")));
  71.     }
  72.     else
  73.     {
  74.         OALMSG(TRUE, (TEXT("Please send the Image through USB./r/n"))); 
  75.     }
  76.     return(bGotJump ? BL_JUMP : BL_DOWNLOAD);
  77. }

 

这些函数都有详细的注释,非常明了,我就不注释了。

  1. /*
  2.     @func   BOOL | OEMPlatformInit | Initialize the Samsung SMD2440 platform hardware.
  3.     @rdesc  TRUE = Success, FALSE = Failure.
  4.     @comm    
  5.     @xref   
  6. */
  7. BOOL OEMPlatformInit(void)
  8. {
  9.     ULONG BootDelay;
  10.     UINT8 KeySelect;
  11.     UINT32 dwStartTime, dwPrevTime, dwCurrTime;
  12.     BOOLEAN bResult = FALSE;
  13.     FlashInfo flashInfo;
  14.     OALMSG(OAL_FUNC, (TEXT("+OEMPlatformInit./r/n")));
  15.     EdbgOutputDebugString("Microsoft Windows CE Bootloader for the Samsung SMDK2440 Version %d.%d Built %s/r/n/r/n"
  16.                           EBOOT_VERSION_MAJOR, EBOOT_VERSION_MINOR, __DATE__);
  17.     // Initialize the display.
  18.     //
  19.     InitDisplay();
  20.     // Initialize the BSP args structure.
  21.     //
  22.     memset(pBSPArgs, 0, sizeof(BSP_ARGS));
  23.     pBSPArgs->header.signature       = OAL_ARGS_SIGNATURE;
  24.     pBSPArgs->header.oalVersion      = OAL_ARGS_VERSION;
  25.     pBSPArgs->header.bspVersion      = BSP_ARGS_VERSION;
  26.     pBSPArgs->kitl.flags             = OAL_KITL_FLAGS_ENABLED | OAL_KITL_FLAGS_VMINI;
  27.     pBSPArgs->kitl.devLoc.IfcType    = Internal;
  28.     pBSPArgs->kitl.devLoc.BusNumber  = 0;
  29.     pBSPArgs->kitl.devLoc.LogicalLoc = BSP_BASE_REG_PA_CS8900A_IOBASE;
  30.     // For USB Download functon
  31.     //
  32.     if (!InitUSB())
  33.     {
  34.         DEBUGMSG(1, (TEXT("OEMPlatformInit: Failed to initialize USB./r/n")));
  35.         return(FALSE);
  36.     }
  37.     Isr_Init();
  38.     // This should not change unless reserved blocks are added/removed;
  39.     // made global to do the calc only once.
  40.     g_dwImageStartBlock = IMAGE_START_BLOCK;
  41.     // Try to initialize the boot media block driver and BinFS partition.
  42.     //
  43.     OALMSG(TRUE, (TEXT("BP_Init/r/n")));
  44.     if ( !BP_Init((LPBYTE)BINFS_RAM_START, BINFS_RAM_LENGTH, NULL, NULL, NULL) )
  45.     {
  46.         OALMSG(OAL_WARN, (TEXT("WARNING: OEMPlatformInit failed to initialize Boot Media./r/n")));
  47.         g_bBootMediaExist = FALSE;
  48.     }
  49.     else
  50.         g_bBootMediaExist = TRUE;
  51.     // Get flash info
  52.     if (!FMD_GetInfo(&flashInfo)) {
  53.         OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: "
  54.             L"FMD_GetInfo call failed/r/n"
  55.         ));
  56.     }
  57.     wNUM_BLOCKS = flashInfo.dwNumBlocks;
  58.     RETAILMSG(1, (TEXT("wNUM_BLOCKS : %d(0x%x) /r/n"), wNUM_BLOCKS, wNUM_BLOCKS));
  59.     // Try to retrieve TOC (and Boot config) from boot media
  60.     //
  61.     if ( !TOC_Read( ) ) 
  62.     {
  63.         // use default settings
  64.         TOC_Init(DEFAULT_IMAGE_DESCRIPTOR, (IMAGE_TYPE_RAMIMAGE), 0, 0, 0);
  65.     }
  66.     // Display boot message - user can halt the autoboot by pressing any key on the serial terminal emulator.
  67.     //
  68.     BootDelay = g_pBootCfg->BootDelay;
  69.     if (g_pBootCfg->ConfigFlags & BOOT_TYPE_DIRECT)
  70.     {
  71.         OALMSG(TRUE, (TEXT("Press [ENTER] to launch image stored on boot media, or [SPACE] to enter boot monitor./r/n")));
  72.         OALMSG(TRUE, (TEXT("/r/nInitiating image launch in %d seconds. "),BootDelay--));
  73.     }
  74.     else
  75.     {
  76.         OALMSG(TRUE, (TEXT("Press [ENTER] to download image stored on boot media, or [SPACE] to enter boot monitor./r/n")));
  77.         OALMSG(TRUE, (TEXT("/r/nInitiating image download in %d seconds. "),BootDelay--));
  78.     }
  79.     dwStartTime = OEMEthGetSecs();
  80.     dwPrevTime  = dwStartTime;
  81.     dwCurrTime  = dwStartTime;
  82.     KeySelect   = 0;
  83.     // Allow the user to break into the bootloader menu.
  84.     //
  85.     while((dwCurrTime - dwStartTime) < g_pBootCfg->BootDelay)
  86.     {
  87.         KeySelect = OEMReadDebugByte();
  88.         if ((KeySelect == 0x20) || (KeySelect == 0x0d))
  89.             break;
  90.         dwCurrTime = OEMEthGetSecs();
  91.         if (dwCurrTime > dwPrevTime)
  92.         {
  93.             int i, j;
  94.             // 1 Second has elapsed - update the countdown timer.
  95.             dwPrevTime = dwCurrTime;
  96.             if (BootDelay < 9)
  97.                 i = 11;
  98.             else if (BootDelay < 99)
  99.                 i = 12;
  100.             else if (BootDelay < 999)
  101.                 i = 13;
  102.             for(j = 0; j < i; j++)
  103.                 OEMWriteDebugByte((BYTE)0x08); // print back space
  104.             EdbgOutputDebugString ( "%d seconds. ", BootDelay--);
  105.         }
  106.     }
  107.     OALMSG(OAL_INFO, (TEXT("/r/n")));
  108.     // Boot or enter bootloader menu.
  109.     //
  110.     switch(KeySelect)
  111.     {
  112.     case 0x20: // Boot menu.
  113.         g_bDownloadImage = MainMenu(g_pBootCfg);
  114.         break;
  115.     case 0x00: // Fall through if no keys were pressed -or-
  116.     case 0x0d: // the user cancelled the countdown.
  117.     default:
  118.         if (g_pBootCfg->ConfigFlags & BOOT_TYPE_DIRECT)
  119.         {
  120.             OALMSG(TRUE, (TEXT("/r/nLaunching image from boot media ... /r/n")));
  121.             g_bDownloadImage = FALSE;
  122.         }
  123.         else
  124.         {
  125.             OALMSG(TRUE, (TEXT("/r/nStarting auto-download ... /r/n")));
  126.             g_bDownloadImage = TRUE;
  127.         }
  128.         break;
  129.     }
  130.     if ( !g_bDownloadImage )
  131.     {
  132.         // User doesn't want to download image - load it from the boot media.
  133.         // We could read an entire nk.bin or nk.nb0 into ram and jump.
  134.         if ( !VALID_TOC(g_pTOC) ) {
  135.             OALMSG(OAL_ERROR, (TEXT("OEMPlatformInit: ERROR_INVALID_TOC, can not autoboot./r/n")));
  136.             return FALSE;
  137.         }
  138.         switch (g_ImageType) {
  139.             case IMAGE_TYPE_STEPLDR:
  140.                 OALMSG(TRUE, (TEXT("Don't support launch STEPLDR.bin/r/n")));
  141.                 break;
  142.             
  143.             case IMAGE_TYPE_LOADER:
  144.                 OALMSG(TRUE, (TEXT("Don't support launch EBOOT.bin/r/n")));
  145.                 break;
  146.             case IMAGE_TYPE_RAMIMAGE:
  147.                 OALMSG(TRUE, (TEXT("OEMPlatformInit: IMAGE_TYPE_RAMIMAGE/r/n")));
  148.                 if ( !ReadOSImageFromBootMedia( ) ) 
  149.                 {
  150.                     OALMSG(OAL_ERROR, (TEXT("OEMPlatformInit ERROR: Failed to load kernel region into RAM./r/n")));
  151.                     return FALSE;
  152.                 }
  153.                 break;
  154.             default:
  155.                 OALMSG(OAL_ERROR, (TEXT("OEMPlatformInit ERROR: unknown image type: 0x%x /r/n"), g_ImageType));
  156.                 return FALSE;
  157.         }
  158.     }
  159.     // Configure Ethernet controller.
  160.     //
  161.     if ( g_bDownloadImage && (g_bUSBDownload == FALSE) )
  162.     {
  163.         if (!InitEthDevice(g_pBootCfg))
  164.         {
  165.             OALMSG(OAL_ERROR, (TEXT("ERROR: OEMPlatformInit: Failed to initialize Ethernet controller./r/n")));
  166.             goto CleanUp;
  167.         }
  168.     }
  169.     bResult = TRUE;
  170. CleanUp:
  171.     OALMSG(OAL_FUNC, (TEXT("_OEMPlatformInit./r/n")));
  172.     return(bResult);
  173. }

这个OEMPlatformInit 函数不简单,把菜单啊,分区等的事情都做的相当完美。eboot一系列配置都在这里完成的。

 

  1. /*
  2.     @func   void | OEMLaunch | Executes the stored/downloaded image.
  3.     @rdesc  N/A.
  4.     @comm    
  5.     @xref  
  6.     C:/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BLCOMMON/blcommon.c(149):
  7. */
  8. void OEMLaunch( DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr, const ROMHDR *pRomHdr )
  9. {
  10.     DWORD dwPhysLaunchAddr;
  11.     EDBG_ADDR EshellHostAddr;
  12.     EDBG_OS_CONFIG_DATA *pCfgData;    
  13.     OALMSG(OAL_FUNC, (TEXT("+OEMLaunch./r/n")));
  14.     // If the user requested that a disk image (stored in RAM now) be written to the SmartMedia card, so it now.
  15.     //
  16.     if (g_bDownloadImage && (g_pBootCfg->ConfigFlags & TARGET_TYPE_NAND))
  17.     {
  18.         // Since this platform only supports RAM images, the image cache address is the same as the image RAM address.
  19.         //
  20.         switch (g_ImageType) 
  21.         {
  22.             case IMAGE_TYPE_STEPLDR:
  23.                 if (!WriteRawImageToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr))
  24.                 {
  25.                     OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: Failed to store image to Smart Media./r/n")));
  26.                     goto CleanUp;
  27.                 }
  28.                 OALMSG(TRUE, (TEXT("INFO: Step loader image stored to Smart Media.  Please Reboot.  Halting.../r/n")));
  29.                 while(1)
  30.                 {
  31.                     // Wait...
  32.                 }
  33.                 break;
  34.             
  35.             case IMAGE_TYPE_LOADER:
  36.                 g_pTOC->id[0].dwLoadAddress = dwImageStart;
  37.                 g_pTOC->id[0].dwTtlSectors = FILE_TO_SECTOR_SIZE(dwImageLength);
  38.                 if (!WriteRawImageToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr))
  39.                 {
  40.                     OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: Failed to store image to Smart Media./r/n")));
  41.                     goto CleanUp;
  42.                 }
  43.                 if (dwLaunchAddr && (g_pTOC->id[0].dwJumpAddress != dwLaunchAddr))
  44.                 {
  45.                     g_pTOC->id[0].dwJumpAddress = dwLaunchAddr;
  46.                     if ( !TOC_Write() ) {
  47.                         EdbgOutputDebugString("*** OEMLaunch ERROR: TOC_Write failed! Next boot may not load from disk *** /r/n");
  48.                     }
  49.                     TOC_Print();
  50.                 }
  51.                 OALMSG(TRUE, (TEXT("INFO: Eboot image stored to Smart Media.  Please Reboot.  Halting.../r/n")));
  52.                 while(1)
  53.                 {
  54.                     // Wait...
  55.                 }               
  56.                                 
  57.                 break;
  58.             case IMAGE_TYPE_RAMIMAGE:
  59.                 g_pTOC->id[g_dwTocEntry].dwLoadAddress = dwImageStart;
  60.                 g_pTOC->id[g_dwTocEntry].dwTtlSectors = FILE_TO_SECTOR_SIZE(dwImageLength);
  61.                 if (!WriteOSImageToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr))
  62.                 {
  63.                     OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: Failed to store image to Smart Media./r/n")));
  64.                     goto CleanUp;
  65.                 }
  66.                 
  67.                 //---如果设定地址和实际启动地址不符合
  68.                 if (dwLaunchAddr && (g_pTOC->id[g_dwTocEntry].dwJumpAddress != dwLaunchAddr))
  69.                 {
  70.                     g_pTOC->id[g_dwTocEntry].dwJumpAddress = dwLaunchAddr;
  71.                     if ( !TOC_Write() ) {
  72.                         EdbgOutputDebugString("*** OEMLaunch ERROR: TOC_Write failed! Next boot may not load from disk *** /r/n");
  73.                     }
  74.                     TOC_Print();
  75.                 }
  76.                 else
  77.                 {
  78.                     dwLaunchAddr= g_pTOC->id[g_dwTocEntry].dwJumpAddress;
  79.                     EdbgOutputDebugString("INFO: using TOC[%d] dwJumpAddress: 0x%x/r/n", g_dwTocEntry, dwLaunchAddr);
  80.                 }
  81.                                 
  82.                 break;
  83.         }
  84.     }
  85.     else if(g_bDownloadImage)
  86.     {
  87.         switch (g_ImageType) 
  88.         {
  89.             case IMAGE_TYPE_STEPLDR:
  90.                 OALMSG(TRUE, (TEXT("Stepldr image can't launch from ram./r/n")));
  91.                 OALMSG(TRUE, (TEXT("You should program it into flash./r/n")));
  92.                 SpinForever();
  93.                 break;
  94.             case IMAGE_TYPE_LOADER:
  95.                 OALMSG(TRUE, (TEXT("Eboot image can't launch from ram./r/n")));
  96.                 OALMSG(TRUE, (TEXT("You should program it into flash./r/n")));
  97.                 SpinForever();
  98.                 break;
  99.             default:
  100.                 break;
  101.         }
  102.     }
  103.     OALMSG(1, (TEXT("waitforconnect/r/n")));
  104.     // Wait for Platform Builder to connect after the download and send us IP and port settings for service
  105.     // connections - also sends us KITL flags.  This information is used later by the OS (KITL).
  106.     //
  107.     if (~g_bUSBDownload & g_bDownloadImage & g_bWaitForConnect)
  108.     {
  109.         memset(&EshellHostAddr, 0, sizeof(EDBG_ADDR));
  110.         g_DeviceAddr.dwIP  = pBSPArgs->kitl.ipAddress;
  111.         memcpy(g_DeviceAddr.wMAC, pBSPArgs->kitl.mac, (3 * sizeof(UINT16)));
  112.         g_DeviceAddr.wPort = 0;
  113.         if (!(pCfgData = EbootWaitForHostConnect(&g_DeviceAddr, &EshellHostAddr)))
  114.         {
  115.             OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: EbootWaitForHostConnect failed./r/n")));
  116.             goto CleanUp;
  117.         }
  118.         // If the user selected "passive" KITL (i.e., don't connect to the target at boot time), set the
  119.         // flag in the args structure so the OS image can honor it when it boots.
  120.         //
  121.         if (pCfgData->KitlTransport & KTS_PASSIVE_MODE)
  122.         {
  123.             pBSPArgs->kitl.flags |= OAL_KITL_FLAGS_PASSIVE;
  124.         }
  125.     }
  126.     
  127.     // If a launch address was provided, we must have downloaded the image, save the address in case we
  128.     // want to jump to this image next time.  If no launch address was provided, retrieve the last one.
  129.     //
  130.     if (dwLaunchAddr && (g_pTOC->id[g_dwTocEntry].dwJumpAddress != dwLaunchAddr))
  131.     {
  132.         g_pTOC->id[g_dwTocEntry].dwJumpAddress = dwLaunchAddr;
  133.     }
  134.     else
  135.     {
  136.         dwLaunchAddr= g_pTOC->id[g_dwTocEntry].dwJumpAddress;
  137.         OALMSG(OAL_INFO, (TEXT("INFO: using TOC[%d] dwJumpAddress: 0x%x/r/n"), g_dwTocEntry, dwLaunchAddr));
  138.     }
  139.     // Jump to downloaded image (use the physical address since we'll be turning the MMU off)...
  140.     //
  141.     dwPhysLaunchAddr = (DWORD)OALVAtoPA((void *)dwLaunchAddr);
  142.     OALMSG(TRUE, (TEXT("INFO: OEMLaunch: Jumping to Physical Address 0x%Xh (Virtual Address 0x%Xh).../r/n/r/n/r/n"), dwPhysLaunchAddr, dwLaunchAddr));
  143.     // Jump...
  144.     //开始运行wince
  145.     Launch(dwPhysLaunchAddr);
  146. CleanUp:
  147.     OALMSG(TRUE, (TEXT("ERROR: OEMLaunch: Halting.../r/n")));
  148.     SpinForever();
  149. }

 

OEMLaunch这个函数可以根据eboot菜单的控制决定是何种方式启动都行,包括KITL功能。

================================================================================

DownloadImage这个函数是在C:/WINCE500/PLATFORM/COMMON/SRC/COMMON/BOOT/BLCOMMON/blcommon.c实现的。

有空再分析一下吧。

现在看看这个真正使内核运行的Launch函数是怎么实现的

C:/WINCE500/PLATFORM/SMDK2440A/Src/Bootloader/Eboot/util.s(32): LEAF_ENTRY Launch

----------------------------------------------------------------------------------------------------------------------------

==================Launch(dwPhysLaunchAddr);这个dwPhysLaunchAddr是怎么传递进来的?

   INCLUDE kxarm.h

PHY_RAM_START EQU 0x30000000
VIR_RAM_START EQU 0x80000000

 TEXTAREA

 LEAF_ENTRY  Launch

 ldr r2, = PhysicalStart
 ldr     r3, = (VIR_RAM_START - PHY_RAM_START)虚拟地址和物理地址想减,为什么要这么做呢?

 sub     r2, r2, r3

 mov     r1, #0x0070             ; Disable MMU
 mcr     p15, 0, r1, c1, c0, 0
 nop
 mov     pc, r2                  ; Jump to PStart
 nop

 ; MMU & caches now disabled.

PhysicalStart

 mov     r2, #0
 mcr     p15, 0, r2, c8, c7, 0   ; Flush the TLB
 mov     pc, r0   ; Jump to program we are launching.

 

还有OALVAtoPA函数我也觉得比较有意思。虚拟地址转换为物理地址。

C:/WINCE500/PLATFORM/COMMON/SRC/ARM/COMMON/MEMORY/memory.c(65):UINT32 OALVAtoPA(VOID *pVA)
有些虚拟内存和物理内存转换的函数实现。C:/WINCE500/PLATFORM/SMDK2440A/Src/Inc/oal_memory.h(84):#define OALVAtoPA(va)       (((UINT32)(va))&~0xE0000000)也有。具体还不知道用了哪里,不过方法几乎一样的。

  1. typedef struct {
  2.     UINT32  CA;                         // cached virtual address
  3.     UINT32  PA;                         // physical address
  4.     UINT32  size;                       // size, in MB bytes
  5. } OAL_ADDRESS_TABLE, *POAL_ADDRESS_TABLE;
  6. //------------------------------------------------------------------------------
  7. //
  8. //  Define:  OAL_MEMORY_CACHE_BIT
  9. //
  10. //  Defines the address bit that determines if an address is cached
  11. //  or uncached, according to the ranges below:
  12. //
  13. //      0x80000000 - 0x9FFFFFFF ==> CACHED   address
  14. //      0xA0000000 - 0xBFFFFFFF ==> UNCACHED address
  15. //
  16. #define OAL_MEMORY_CACHE_BIT            0x20000000
  17. //------------------------------------------------------------------------------
  18. //
  19. //  Extern:  g_oalAddressTable 
  20. //
  21. //  This table is used by kernel to establish the virtual to physical address
  22. //  mapping. It is alos used in OALPAtoVA and OALVAtoPA functions to allow
  23. //  get virtual address for physical and vice versa.
  24. //
  25. extern OAL_ADDRESS_TABLE g_oalAddressTable[];
  26. //------------------------------------------------------------------------------
  27. #define OALCAtoUA(va)       (VOID*)(((UINT32)(va))|OAL_MEMORY_CACHE_BIT)
  28. #define OALUAtoCA(va)       (VOID*)(((UINT32)(va))&~OAL_MEMORY_CACHE_BIT)
  29. #define OALPAtoCA(pa)       OALPAtoVA(pa, TRUE)
  30. #define OALPAtoUA(pa)       OALPAtoVA(pa, FALSE)
  31. VOID* OALPAtoVA(UINT32 pa, BOOL cached);
  32. UINT32 OALVAtoPA(VOID *va);
  33. //从这些可以看出物理内存和虚拟内存有什么关系了。
转载请标明:作者wogoyixikexie@gliet.桂林电子科技大学一系科协。如有错误,希望能够留言指出。