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函数开始吧。
- /*
- @func void | main | Samsung bootloader C routine entry point.
- @rdesc N/A.
- @comm
- @xref
- @裸奔时候的main函数
- */
- void main(void)
- {
- // Clear LEDs.
- //
- OEMWriteDebugLED(0, 0x3);
- // Common boot loader (blcommon) main routine.
- //C:/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BLCOMMON/blcommon.c
- //BootloaderMain函数调用eboot中的函数,完成eboot功能
- BootloaderMain();
- // Should never get here.
- //
- SpinForever();
- }
显然这个BootloaderMain函数是主角了,现在再来看看它做了什么吧。
- void BootloaderMain (void)
- {
- DWORD dwAction;
- DWORD dwpToc = 0;
- DWORD dwImageStart = 0, dwImageLength = 0, dwLaunchAddr = 0;
- BOOL bDownloaded = FALSE;
- // relocate globals to RAM为了共享变量
- if (!KernelRelocate (pTOC))
- {
- // spin forever
- HALT (BLERR_KERNELRELOCATE);
- }
- // (1) Init debug support. We can use OEMWriteDebugString afterward.
- if (!OEMDebugInit ())
- {
- // spin forever
- HALT (BLERR_DBGINIT);
- }
- // output banner
- EdbgOutputDebugString (NKSignon, CURRENT_VERSION_MAJOR, CURRENT_VERSION_MINOR);
- // (3) initialize platform (clock, drivers, transports, etc)
- if (!OEMPlatformInit ())
- {
- // spin forever
- HALT (BLERR_PLATINIT);
- }
- // system ready, preparing for download
- EdbgOutputDebugString ("System ready!/r/nPreparing for download.../r/n");
- // (4) call OEM specific pre-download function
- switch (dwAction = OEMPreDownload ())
- {
- case BL_DOWNLOAD:
- // (5) download image
- if (!DownloadImage (&dwImageStart, &dwImageLength, &dwLaunchAddr))
- {
- // error already reported in DownloadImage
- SPIN_FOREVER;
- }
- bDownloaded = TRUE;
- // Check for pTOC signature ("CECE") here, after image in place
- if (*(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE)
- {
- dwpToc = *(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG));
- // need to map the content again since the pointer is going to be in a fixup address
- dwpToc = (DWORD) OEMMapMemAddr (dwImageStart, dwpToc + g_dwROMOffset);
- EdbgOutputDebugString ("ROMHDR at Address %Xh/r/n", dwImageStart + ROM_SIGNATURE_OFFSET + sizeof (DWORD)); // right after signature
- }
- // fall through 注意这里并没有break,这个用的很巧妙。
- case BL_JUMP:
- // Before jumping to the image, optionally check the image signature.
- // NOTE: if we haven't downloaded the image by now, we assume that it'll be loaded from local storage in OEMLaunch (or it
- // already resides in RAM from an earlier download), and in this case, the image start address might be 0. This means
- // that the image signature routine will need to find the image in storage or in RAM to validate it. Since the OEM"s
- // OEMLaunch function will need to do this anyways, we trust that it's within their abilities to do it here.
- //
- if (g_bBINDownload && g_pOEMCheckSignature)
- {
- if (!g_pOEMCheckSignature(dwImageStart, g_dwROMOffset, dwLaunchAddr, bDownloaded))
- HALT(BLERR_CAT_SIGNATURE);
- }
- // (5) final call to launch the image. never returned
- OEMLaunch (dwImageStart, dwImageLength, dwLaunchAddr, (const ROMHDR *)dwpToc);
- // should never return
- // fall through
- default:
- // ERROR! spin forever
- HALT (BLERR_INVALIDCMD);
- }
- }
上面很多函数,都是在eboot中实现的。
下面这个函数,俺水平有限,都不知道是如何实现原理
-
- //
- // KernelRelocate: move global variables to RAM
- //
- static BOOL KernelRelocate (ROMHDR *const pTOC)
- {
- ULONG loop;
- COPYentry *cptr;
- if (pTOC == (ROMHDR *const) -1)
- {
- return (FALSE); // spin forever!
- }
- // This is where the data sections become valid... don't read globals until after this
- for (loop = 0; loop < pTOC->ulCopyEntries; loop++)
- {
- cptr = (COPYentry *)(pTOC->ulCopyOffset + loop*sizeof(COPYentry));
- if (cptr->ulCopyLen)
- memcpy((LPVOID)cptr->ulDest,(LPVOID)cptr->ulSource,cptr->ulCopyLen);
- if (cptr->ulCopyLen != cptr->ulDestLen)
- memset((LPVOID)(cptr->ulDest+cptr->ulCopyLen),0,cptr->ulDestLen-cptr->ulCopyLen);
- }
- return (TRUE);
- }
- @func DWORD | OEMPreDownload | Complete pre-download tasks - get IP address, initialize TFTP, etc.
- @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.
- @comm
- @xref
- */
- DWORD OEMPreDownload(void)
- {
- BOOL bGotJump = FALSE;
- DWORD dwDHCPLeaseTime = 0;
- PDWORD pdwDHCPLeaseTime = &dwDHCPLeaseTime;
- DWORD dwBootFlags = 0;
- OALMSG(OAL_FUNC, (TEXT("+OEMPreDownload./r/n")));
- // Create device name based on Ethernet address (this is how Platform Builder identifies this device).
- //
- OALKitlCreateName(BSP_DEVICE_PREFIX, pBSPArgs->kitl.mac, pBSPArgs->deviceId);
- OALMSG(OAL_INFO, (L"INFO: *** Device Name '%hs' ***/r/n", pBSPArgs->deviceId));
- if ( g_bUSBDownload == FALSE )
- {
- // If the user wants to use a static IP address, don't request an address
- // from a DHCP server. This is done by passing in a NULL for the DHCP
- // lease time variable. If user specified a static IP address, use it (don't use DHCP).
- //
- if (!(g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DHCP))
- {
- // Static IP address.
- pBSPArgs->kitl.ipAddress = g_pBootCfg->EdbgAddr.dwIP;
- pBSPArgs->kitl.ipMask = g_pBootCfg->SubnetMask;
- pBSPArgs->kitl.flags &= ~OAL_KITL_FLAGS_DHCP;
- pdwDHCPLeaseTime = NULL;
- OALMSG(OAL_INFO, (TEXT("INFO: Using static IP address %s./r/n"), inet_ntoa(pBSPArgs->kitl.ipAddress)));
- OALMSG(OAL_INFO, (TEXT("INFO: Using subnet mask %s./r/n"), inet_ntoa(pBSPArgs->kitl.ipMask)));
- }
- else
- {
- pBSPArgs->kitl.ipAddress = 0;
- pBSPArgs->kitl.ipMask = 0;
- }
- if ( !g_bDownloadImage)
- {
- return(BL_JUMP);
- }
- // Initialize the the TFTP transport.
- //
- g_DeviceAddr.dwIP = pBSPArgs->kitl.ipAddress;
- memcpy(g_DeviceAddr.wMAC, pBSPArgs->kitl.mac, (3 * sizeof(UINT16)));
- g_DeviceAddr.wPort = 0;
- if (!EbootInitEtherTransport(&g_DeviceAddr,
- &pBSPArgs->kitl.ipMask,
- &bGotJump,
- pdwDHCPLeaseTime,
- EBOOT_VERSION_MAJOR,
- EBOOT_VERSION_MINOR,
- BSP_DEVICE_PREFIX,
- pBSPArgs->deviceId,
- EDBG_CPU_ARM720,
- dwBootFlags))
- {
- OALMSG(OAL_ERROR, (TEXT("ERROR: OEMPreDownload: Failed to initialize Ethernet connection./r/n")));
- return(BL_ERROR);
- }
- // If the user wanted a DHCP address, we presumably have it now - save it for the OS to use.
- //
- if (g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DHCP)
- {
- // DHCP address.
- pBSPArgs->kitl.ipAddress = g_DeviceAddr.dwIP;
- pBSPArgs->kitl.flags |= OAL_KITL_FLAGS_DHCP;
- }
- OALMSG(OAL_FUNC, (TEXT("_OEMPreDownload./r/n")));
- }
- else
- {
- OALMSG(TRUE, (TEXT("Please send the Image through USB./r/n")));
- }
- return(bGotJump ? BL_JUMP : BL_DOWNLOAD);
- }
这些函数都有详细的注释,非常明了,我就不注释了。
- /*
- @func BOOL | OEMPlatformInit | Initialize the Samsung SMD2440 platform hardware.
- @rdesc TRUE = Success, FALSE = Failure.
- @comm
- @xref
- */
- BOOL OEMPlatformInit(void)
- {
- ULONG BootDelay;
- UINT8 KeySelect;
- UINT32 dwStartTime, dwPrevTime, dwCurrTime;
- BOOLEAN bResult = FALSE;
- FlashInfo flashInfo;
- OALMSG(OAL_FUNC, (TEXT("+OEMPlatformInit./r/n")));
- EdbgOutputDebugString("Microsoft Windows CE Bootloader for the Samsung SMDK2440 Version %d.%d Built %s/r/n/r/n",
- EBOOT_VERSION_MAJOR, EBOOT_VERSION_MINOR, __DATE__);
- // Initialize the display.
- //
- InitDisplay();
- // Initialize the BSP args structure.
- //
- memset(pBSPArgs, 0, sizeof(BSP_ARGS));
- pBSPArgs->header.signature = OAL_ARGS_SIGNATURE;
- pBSPArgs->header.oalVersion = OAL_ARGS_VERSION;
- pBSPArgs->header.bspVersion = BSP_ARGS_VERSION;
- pBSPArgs->kitl.flags = OAL_KITL_FLAGS_ENABLED | OAL_KITL_FLAGS_VMINI;
- pBSPArgs->kitl.devLoc.IfcType = Internal;
- pBSPArgs->kitl.devLoc.BusNumber = 0;
- pBSPArgs->kitl.devLoc.LogicalLoc = BSP_BASE_REG_PA_CS8900A_IOBASE;
- // For USB Download functon
- //
- if (!InitUSB())
- {
- DEBUGMSG(1, (TEXT("OEMPlatformInit: Failed to initialize USB./r/n")));
- return(FALSE);
- }
- Isr_Init();
- // This should not change unless reserved blocks are added/removed;
- // made global to do the calc only once.
- g_dwImageStartBlock = IMAGE_START_BLOCK;
- // Try to initialize the boot media block driver and BinFS partition.
- //
- OALMSG(TRUE, (TEXT("BP_Init/r/n")));
- if ( !BP_Init((LPBYTE)BINFS_RAM_START, BINFS_RAM_LENGTH, NULL, NULL, NULL) )
- {
- OALMSG(OAL_WARN, (TEXT("WARNING: OEMPlatformInit failed to initialize Boot Media./r/n")));
- g_bBootMediaExist = FALSE;
- }
- else
- g_bBootMediaExist = TRUE;
- // Get flash info
- if (!FMD_GetInfo(&flashInfo)) {
- OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: "
- L"FMD_GetInfo call failed/r/n"
- ));
- }
- wNUM_BLOCKS = flashInfo.dwNumBlocks;
- RETAILMSG(1, (TEXT("wNUM_BLOCKS : %d(0x%x) /r/n"), wNUM_BLOCKS, wNUM_BLOCKS));
- // Try to retrieve TOC (and Boot config) from boot media
- //
- if ( !TOC_Read( ) )
- {
- // use default settings
- TOC_Init(DEFAULT_IMAGE_DESCRIPTOR, (IMAGE_TYPE_RAMIMAGE), 0, 0, 0);
- }
- // Display boot message - user can halt the autoboot by pressing any key on the serial terminal emulator.
- //
- BootDelay = g_pBootCfg->BootDelay;
- if (g_pBootCfg->ConfigFlags & BOOT_TYPE_DIRECT)
- {
- OALMSG(TRUE, (TEXT("Press [ENTER] to launch image stored on boot media, or [SPACE] to enter boot monitor./r/n")));
- OALMSG(TRUE, (TEXT("/r/nInitiating image launch in %d seconds. "),BootDelay--));
- }
- else
- {
- OALMSG(TRUE, (TEXT("Press [ENTER] to download image stored on boot media, or [SPACE] to enter boot monitor./r/n")));
- OALMSG(TRUE, (TEXT("/r/nInitiating image download in %d seconds. "),BootDelay--));
- }
- dwStartTime = OEMEthGetSecs();
- dwPrevTime = dwStartTime;
- dwCurrTime = dwStartTime;
- KeySelect = 0;
- // Allow the user to break into the bootloader menu.
- //
- while((dwCurrTime - dwStartTime) < g_pBootCfg->BootDelay)
- {
- KeySelect = OEMReadDebugByte();
- if ((KeySelect == 0x20) || (KeySelect == 0x0d))
- break;
- dwCurrTime = OEMEthGetSecs();
- if (dwCurrTime > dwPrevTime)
- {
- int i, j;
- // 1 Second has elapsed - update the countdown timer.
- dwPrevTime = dwCurrTime;
- if (BootDelay < 9)
- i = 11;
- else if (BootDelay < 99)
- i = 12;
- else if (BootDelay < 999)
- i = 13;
- for(j = 0; j < i; j++)
- OEMWriteDebugByte((BYTE)0x08); // print back space
- EdbgOutputDebugString ( "%d seconds. ", BootDelay--);
- }
- }
- OALMSG(OAL_INFO, (TEXT("/r/n")));
- // Boot or enter bootloader menu.
- //
- switch(KeySelect)
- {
- case 0x20: // Boot menu.
- g_bDownloadImage = MainMenu(g_pBootCfg);
- break;
- case 0x00: // Fall through if no keys were pressed -or-
- case 0x0d: // the user cancelled the countdown.
- default:
- if (g_pBootCfg->ConfigFlags & BOOT_TYPE_DIRECT)
- {
- OALMSG(TRUE, (TEXT("/r/nLaunching image from boot media ... /r/n")));
- g_bDownloadImage = FALSE;
- }
- else
- {
- OALMSG(TRUE, (TEXT("/r/nStarting auto-download ... /r/n")));
- g_bDownloadImage = TRUE;
- }
- break;
- }
- if ( !g_bDownloadImage )
- {
- // User doesn't want to download image - load it from the boot media.
- // We could read an entire nk.bin or nk.nb0 into ram and jump.
- if ( !VALID_TOC(g_pTOC) ) {
- OALMSG(OAL_ERROR, (TEXT("OEMPlatformInit: ERROR_INVALID_TOC, can not autoboot./r/n")));
- return FALSE;
- }
- switch (g_ImageType) {
- case IMAGE_TYPE_STEPLDR:
- OALMSG(TRUE, (TEXT("Don't support launch STEPLDR.bin/r/n")));
- break;
- case IMAGE_TYPE_LOADER:
- OALMSG(TRUE, (TEXT("Don't support launch EBOOT.bin/r/n")));
- break;
- case IMAGE_TYPE_RAMIMAGE:
- OALMSG(TRUE, (TEXT("OEMPlatformInit: IMAGE_TYPE_RAMIMAGE/r/n")));
- if ( !ReadOSImageFromBootMedia( ) )
- {
- OALMSG(OAL_ERROR, (TEXT("OEMPlatformInit ERROR: Failed to load kernel region into RAM./r/n")));
- return FALSE;
- }
- break;
- default:
- OALMSG(OAL_ERROR, (TEXT("OEMPlatformInit ERROR: unknown image type: 0x%x /r/n"), g_ImageType));
- return FALSE;
- }
- }
- // Configure Ethernet controller.
- //
- if ( g_bDownloadImage && (g_bUSBDownload == FALSE) )
- {
- if (!InitEthDevice(g_pBootCfg))
- {
- OALMSG(OAL_ERROR, (TEXT("ERROR: OEMPlatformInit: Failed to initialize Ethernet controller./r/n")));
- goto CleanUp;
- }
- }
- bResult = TRUE;
- CleanUp:
- OALMSG(OAL_FUNC, (TEXT("_OEMPlatformInit./r/n")));
- return(bResult);
- }
这个OEMPlatformInit 函数不简单,把菜单啊,分区等的事情都做的相当完美。eboot一系列配置都在这里完成的。
- /*
- @func void | OEMLaunch | Executes the stored/downloaded image.
- @rdesc N/A.
- @comm
- @xref
- C:/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BLCOMMON/blcommon.c(149):
- */
- void OEMLaunch( DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr, const ROMHDR *pRomHdr )
- {
- DWORD dwPhysLaunchAddr;
- EDBG_ADDR EshellHostAddr;
- EDBG_OS_CONFIG_DATA *pCfgData;
- OALMSG(OAL_FUNC, (TEXT("+OEMLaunch./r/n")));
- // If the user requested that a disk image (stored in RAM now) be written to the SmartMedia card, so it now.
- //
- if (g_bDownloadImage && (g_pBootCfg->ConfigFlags & TARGET_TYPE_NAND))
- {
- // Since this platform only supports RAM images, the image cache address is the same as the image RAM address.
- //
- switch (g_ImageType)
- {
- case IMAGE_TYPE_STEPLDR:
- if (!WriteRawImageToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr))
- {
- OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: Failed to store image to Smart Media./r/n")));
- goto CleanUp;
- }
- OALMSG(TRUE, (TEXT("INFO: Step loader image stored to Smart Media. Please Reboot. Halting.../r/n")));
- while(1)
- {
- // Wait...
- }
- break;
- case IMAGE_TYPE_LOADER:
- g_pTOC->id[0].dwLoadAddress = dwImageStart;
- g_pTOC->id[0].dwTtlSectors = FILE_TO_SECTOR_SIZE(dwImageLength);
- if (!WriteRawImageToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr))
- {
- OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: Failed to store image to Smart Media./r/n")));
- goto CleanUp;
- }
- if (dwLaunchAddr && (g_pTOC->id[0].dwJumpAddress != dwLaunchAddr))
- {
- g_pTOC->id[0].dwJumpAddress = dwLaunchAddr;
- if ( !TOC_Write() ) {
- EdbgOutputDebugString("*** OEMLaunch ERROR: TOC_Write failed! Next boot may not load from disk *** /r/n");
- }
- TOC_Print();
- }
- OALMSG(TRUE, (TEXT("INFO: Eboot image stored to Smart Media. Please Reboot. Halting.../r/n")));
- while(1)
- {
- // Wait...
- }
- break;
- case IMAGE_TYPE_RAMIMAGE:
- g_pTOC->id[g_dwTocEntry].dwLoadAddress = dwImageStart;
- g_pTOC->id[g_dwTocEntry].dwTtlSectors = FILE_TO_SECTOR_SIZE(dwImageLength);
- if (!WriteOSImageToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr))
- {
- OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: Failed to store image to Smart Media./r/n")));
- goto CleanUp;
- }
- //---如果设定地址和实际启动地址不符合
- if (dwLaunchAddr && (g_pTOC->id[g_dwTocEntry].dwJumpAddress != dwLaunchAddr))
- {
- g_pTOC->id[g_dwTocEntry].dwJumpAddress = dwLaunchAddr;
- if ( !TOC_Write() ) {
- EdbgOutputDebugString("*** OEMLaunch ERROR: TOC_Write failed! Next boot may not load from disk *** /r/n");
- }
- TOC_Print();
- }
- else
- {
- dwLaunchAddr= g_pTOC->id[g_dwTocEntry].dwJumpAddress;
- EdbgOutputDebugString("INFO: using TOC[%d] dwJumpAddress: 0x%x/r/n", g_dwTocEntry, dwLaunchAddr);
- }
- break;
- }
- }
- else if(g_bDownloadImage)
- {
- switch (g_ImageType)
- {
- case IMAGE_TYPE_STEPLDR:
- OALMSG(TRUE, (TEXT("Stepldr image can't launch from ram./r/n")));
- OALMSG(TRUE, (TEXT("You should program it into flash./r/n")));
- SpinForever();
- break;
- case IMAGE_TYPE_LOADER:
- OALMSG(TRUE, (TEXT("Eboot image can't launch from ram./r/n")));
- OALMSG(TRUE, (TEXT("You should program it into flash./r/n")));
- SpinForever();
- break;
- default:
- break;
- }
- }
- OALMSG(1, (TEXT("waitforconnect/r/n")));
- // Wait for Platform Builder to connect after the download and send us IP and port settings for service
- // connections - also sends us KITL flags. This information is used later by the OS (KITL).
- //
- if (~g_bUSBDownload & g_bDownloadImage & g_bWaitForConnect)
- {
- memset(&EshellHostAddr, 0, sizeof(EDBG_ADDR));
- g_DeviceAddr.dwIP = pBSPArgs->kitl.ipAddress;
- memcpy(g_DeviceAddr.wMAC, pBSPArgs->kitl.mac, (3 * sizeof(UINT16)));
- g_DeviceAddr.wPort = 0;
- if (!(pCfgData = EbootWaitForHostConnect(&g_DeviceAddr, &EshellHostAddr)))
- {
- OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: EbootWaitForHostConnect failed./r/n")));
- goto CleanUp;
- }
- // If the user selected "passive" KITL (i.e., don't connect to the target at boot time), set the
- // flag in the args structure so the OS image can honor it when it boots.
- //
- if (pCfgData->KitlTransport & KTS_PASSIVE_MODE)
- {
- pBSPArgs->kitl.flags |= OAL_KITL_FLAGS_PASSIVE;
- }
- }
- // If a launch address was provided, we must have downloaded the image, save the address in case we
- // want to jump to this image next time. If no launch address was provided, retrieve the last one.
- //
- if (dwLaunchAddr && (g_pTOC->id[g_dwTocEntry].dwJumpAddress != dwLaunchAddr))
- {
- g_pTOC->id[g_dwTocEntry].dwJumpAddress = dwLaunchAddr;
- }
- else
- {
- dwLaunchAddr= g_pTOC->id[g_dwTocEntry].dwJumpAddress;
- OALMSG(OAL_INFO, (TEXT("INFO: using TOC[%d] dwJumpAddress: 0x%x/r/n"), g_dwTocEntry, dwLaunchAddr));
- }
- // Jump to downloaded image (use the physical address since we'll be turning the MMU off)...
- //
- dwPhysLaunchAddr = (DWORD)OALVAtoPA((void *)dwLaunchAddr);
- OALMSG(TRUE, (TEXT("INFO: OEMLaunch: Jumping to Physical Address 0x%Xh (Virtual Address 0x%Xh).../r/n/r/n/r/n"), dwPhysLaunchAddr, dwLaunchAddr));
- // Jump...
- //开始运行wince
- Launch(dwPhysLaunchAddr);
- CleanUp:
- OALMSG(TRUE, (TEXT("ERROR: OEMLaunch: Halting.../r/n")));
- SpinForever();
- }
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)也有。具体还不知道用了哪里,不过方法几乎一样的。
- typedef struct {
- UINT32 CA; // cached virtual address
- UINT32 PA; // physical address
- UINT32 size; // size, in MB bytes
- } OAL_ADDRESS_TABLE, *POAL_ADDRESS_TABLE;
- //------------------------------------------------------------------------------
- //
- // Define: OAL_MEMORY_CACHE_BIT
- //
- // Defines the address bit that determines if an address is cached
- // or uncached, according to the ranges below:
- //
- // 0x80000000 - 0x9FFFFFFF ==> CACHED address
- // 0xA0000000 - 0xBFFFFFFF ==> UNCACHED address
- //
- #define OAL_MEMORY_CACHE_BIT 0x20000000
- //------------------------------------------------------------------------------
- //
- // Extern: g_oalAddressTable
- //
- // This table is used by kernel to establish the virtual to physical address
- // mapping. It is alos used in OALPAtoVA and OALVAtoPA functions to allow
- // get virtual address for physical and vice versa.
- //
- extern OAL_ADDRESS_TABLE g_oalAddressTable[];
- //------------------------------------------------------------------------------
- #define OALCAtoUA(va) (VOID*)(((UINT32)(va))|OAL_MEMORY_CACHE_BIT)
- #define OALUAtoCA(va) (VOID*)(((UINT32)(va))&~OAL_MEMORY_CACHE_BIT)
- #define OALPAtoCA(pa) OALPAtoVA(pa, TRUE)
- #define OALPAtoUA(pa) OALPAtoVA(pa, FALSE)
- VOID* OALPAtoVA(UINT32 pa, BOOL cached);
- UINT32 OALVAtoPA(VOID *va);
- //从这些可以看出物理内存和虚拟内存有什么关系了。