blcommon.c
资源名称:SMDK2440.rar [点击查看]
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:16k
源码类别:
Windows CE
开发平台:
Windows_Unix
- //
- // 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.
- //
- /*++
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- PARTICULAR PURPOSE.
- Module Name:
- blcommon.c
- Abstract:
- Bootloader common main module. This file contains the C BootloaderMain
- function for the boot loader. NOTE: The firmware "entry" point (the real
- entry point is _EntryPoint in init assembler file.
- The Windows CE boot loader is the code that is executed on a Windows CE
- development system at power-on reset and loads the Windows CE
- operating system. The boot loader also provides code that monitors
- the behavior of a Windows CE platform between the time the boot loader
- starts running and the time the full operating system debugger is
- available. Windows CE OEMs are supplied with sample boot loader code
- that runs on a particular development platform and CPU.
- Functions:
- Notes:
- --*/
- #include <windows.h>
- #include <halether.h>
- #include <blcommon.h>
- #ifdef SIMULATOR
- extern void CleanExit(DWORD dwExitCode);
- #define SPIN_FOREVER CleanExit(42)
- #else
- #define SPIN_FOREVER while (1)
- #endif
- ROMHDR * volatile const pTOC = (ROMHDR *)-1; // Gets replaced by RomLoader with real address
- static ROMHDR romhdr;
- static MultiBINInfo g_MultiBINInfo;
- static BOOL KernelRelocate (ROMHDR *const pTOC);
- static BOOL DownloadImage (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr);
- static BOOL IsKernelRegion(DWORD dwRegionStart, DWORD dwRegionLength);
- #define CURRENT_VERSION_MAJOR 1
- #define CURRENT_VERSION_MINOR 0
- const unsigned char NKSignon[] = {
- "nMicrosoft Windows CE Ethernet Bootloader Common Library Version %d.%d Built "
- __DATE__ " " __TIME__ "rn"
- "Copyright (c) 2000-2001 Microsoft Corporationrn"
- };
- DWORD g_dwROMOffset;
- PFN_OEMVERIFYMEMORY g_pOEMVerifyMemory;
- PFN_OEMREPORTERROR g_pOEMReportError;
- PFN_OEMCHECKSIGNATURE g_pOEMCheckSignature;
- PFN_OEMMULTIBINNOTIFY g_pOEMMultiBINNotify;
- static void HALT (DWORD dwReason)
- {
- if (g_pOEMReportError) {
- g_pOEMReportError (dwReason, 0);
- }
- SPIN_FOREVER;
- }
- void BootloaderMain (void)
- {
- ROMHDR *pRomHdr = NULL; // pTOC for NK image. MUST COPY IT OR CLEANBOOT may erase it
- DWORD dwAction, dwpToc;
- DWORD dwImageStart = 0, dwImageLength = 0, dwLaunchAddr = 0;
- BOOL bDownloaded = FALSE;
- #ifndef SIMULATOR
- // relocate globals to RAM
- if (!KernelRelocate (pTOC)) {
- // spin forever
- HALT (BLERR_KERNELRELOCATE);
- }
- #endif
- // (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!rnPreparing for download...rn");
- // (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;
- if (dwImageStart) {
- // Check for pTOC signature ("CECE") here, after image in place
- if (*(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE) {
- EdbgOutputDebugString("Found pTOC signature.n");
- } else {
- EdbgOutputDebugString ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rn");
- EdbgOutputDebugString ("! ERROR: Did not find pTOC signature. ABORTING. !rn");
- EdbgOutputDebugString ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rn");
- // If no signature, we're going to fail anyway, so loop forever
- HALT (BLERR_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);
- // NOTE: MUST COPY or a CLEAN_BOOT flag will erase it
- memcpy (pRomHdr = &romhdr, (LPVOID) dwpToc, sizeof(ROMHDR));
- EdbgOutputDebugString ("ROMHDR at Address %Xhrn", dwImageStart + ROM_SIGNATURE_OFFSET + sizeof (DWORD)); // right after signature
- EdbgOutputDebugString ("RomHdr.ulRAMStart=%Xh RomHdr.physfirst=%Xh.rn", romhdr.ulRAMStart, romhdr.physfirst);
- }
- // fall through
- case BL_JUMP:
- // Before jumping to the image, optionally check the image signature.
- if (g_pOEMCheckSignature && dwImageStart)
- {
- if (!g_pOEMCheckSignature(dwImageStart, g_dwROMOffset, dwLaunchAddr, bDownloaded))
- HALT(BLERR_WHQL_SIGNATURE);
- }
- // (5) final call to launch the image. never returned
- OEMLaunch (dwImageStart, dwImageLength, dwLaunchAddr, pRomHdr);
- // should never return
- // fall through
- default:
- // ERROR! spin forever
- HALT (BLERR_INVALIDCMD);
- }
- }
- //
- // 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;
- }
- static BOOL VerifyChecksum (DWORD cbRecord, LPBYTE pbRecord, DWORD dwChksum)
- {
- // Check the CRC
- DWORD dwCRC = 0;
- DWORD i;
- for (i = 0; i < cbRecord; i++)
- dwCRC += *pbRecord ++;
- if (dwCRC != dwChksum)
- EdbgOutputDebugString ("ERROR: Checksum failure (expected=0x%x computed=0x%x)rn", dwChksum, dwCRC);
- return dwCRC == dwChksum;
- }
- #define BL_HDRSIG_SIZE 7
- static BOOL DownloadImage (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr)
- {
- BYTE hdr[BL_HDRSIG_SIZE];
- DWORD dwRecLen, dwRecChk, dwRecAddr;
- BOOL fIsFlash;
- LPBYTE lpDest;
- int nPkgNum = 0;
- BYTE nNumRegions = 1;
- DWORD dwImageStart, dwImageLength;
- *pdwImageStart = *pdwImageLength = *pdwLaunchAddr = 0;
- do
- {
- // read the 7 byte "magic number"
- if (!OEMReadData (BL_HDRSIG_SIZE, hdr)) {
- EdbgOutputDebugString ("rnUnable to read image signature.rn");
- HALT (BLERR_MAGIC);
- return FALSE;
- }
- // check for multi-bin information packet.
- if (!memcmp (hdr, "X000FFx0A", BL_HDRSIG_SIZE)) {
- // determine number of BIN files to be downloaded.
- if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk)) {
- EdbgOutputDebugString("rnUnable to read BIN region checksum.rn");
- HALT (BLERR_MAGIC);
- return FALSE;
- }
- // read BIN region descriptions (start address and length).
- if (!OEMReadData (sizeof (DWORD), (LPBYTE) &g_MultiBINInfo.dwNumRegions)
- || !OEMReadData ((g_MultiBINInfo.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_MultiBINInfo.Region[0])) {
- EdbgOutputDebugString("rnUnable to read BIN region descriptors.rn");
- HALT (BLERR_MAGIC);
- return FALSE;
- }
- // verify the packet checksum.
- if (!VerifyChecksum((g_MultiBINInfo.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_MultiBINInfo.Region, dwRecChk)) {
- EdbgOutputDebugString ("rnBIN region descriptor packet failed checksum.rn");
- HALT (BLERR_CHECKSUM);
- return FALSE;
- }
- // provide the region information to the OEM.
- if (g_pOEMMultiBINNotify) {
- g_pOEMMultiBINNotify((const PMultiBINInfo)&g_MultiBINInfo);
- }
- // look for next download...
- nNumRegions = (BYTE)(g_MultiBINInfo.dwNumRegions + 1); // +1 to account for this packet.
- continue;
- }
- else {
- // make sure it is a standard BIN file.
- if (memcmp (hdr, "B000FFx0A", BL_HDRSIG_SIZE)) {
- EdbgOutputDebugString ("rnThis is not a .BIN file %x %x %x %x %x %x %xrn",
- hdr[0], hdr[1], hdr[2], hdr[3], hdr[4], hdr[5], hdr[6]);
- HALT (BLERR_MAGIC);
- return FALSE;
- }
- }
- // read image start/length
- if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageStart)
- || !OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageLength)) {
- EdbgOutputDebugString ("Unable to read image start/lengthrn");
- HALT (BLERR_MAGIC);
- return FALSE;
- }
- // if this is a single-bin download, record the bin file information and notify the OEM.
- if (!g_MultiBINInfo.dwNumRegions) {
- g_MultiBINInfo.dwNumRegions = 1;
- g_MultiBINInfo.Region[0].dwRegionStart = dwImageStart;
- g_MultiBINInfo.Region[0].dwRegionLength = dwImageLength;
- // provide the region information to the OEM.
- if (g_pOEMMultiBINNotify) {
- g_pOEMMultiBINNotify((const PMultiBINInfo)&g_MultiBINInfo);
- }
- }
- // give the OEM a chance to verify memory
- if (g_pOEMVerifyMemory && !g_pOEMVerifyMemory (dwImageStart, dwImageLength)) {
- EdbgOutputDebugString ("!OEMVERIFYMEMORY: Invalid imagern");
- HALT (BLERR_OEMVERIFY);
- return FALSE;
- }
- // check for flash image. Start erasing if it is.
- if ((fIsFlash = OEMIsFlashAddr (dwImageStart))
- && !OEMStartEraseFlash (dwImageStart, dwImageLength)) {
- EdbgOutputDebugString ("Invalid Flash Address/Lengthrn");
- HALT (BLERR_FLASHADDR);
- return FALSE;
- }
- // read records (start with address, length, and checksum)
- while (OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecAddr)
- && OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecLen)
- && OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk)) {
- RETAILMSG(1, (_T("DownloadImage RecAddr: 0x%xrn"), dwRecAddr));
- RETAILMSG(1, (_T("DownloadImage RecLen: 0x%xrn"), dwRecLen));
- RETAILMSG(1, (_T("DownloadImage RecChk: 0x%xrn"), dwRecChk));
- // check for last record
- if (!dwRecAddr && !dwRecChk) {
- // if this is the kernel region, update launch address
- if (IsKernelRegion(dwImageStart, dwImageLength)) {
- *pdwImageStart = dwImageStart;
- *pdwImageLength = dwImageLength;
- *pdwLaunchAddr = dwRecLen;
- RETAILMSG(1, (_T("dwImageStart : 0x%xrn"), dwImageStart));
- RETAILMSG(1, (_T("dwImageLength: 0x%xrn"), dwImageLength));
- RETAILMSG(1, (_T("LaunchAddr : 0x%xrn"), dwRecLen));
- }
- // write to flash if it's flash image
- if (fIsFlash) {
- // finish the flash erase
- if (!OEMFinishEraseFlash ()) {
- HALT (BLERR_FLASH_ERASE);
- return FALSE;
- }
- // Before writing the image to flash, optionally check the image signature.
- if (g_pOEMCheckSignature)
- {
- if (!g_pOEMCheckSignature(dwImageStart, g_dwROMOffset, *pdwLaunchAddr, TRUE))
- HALT(BLERR_WHQL_SIGNATURE);
- }
- }
- // On to the next (possible) BIN file...
- break;
- }
- // map the record address (FLASH data is cached, for example)
- lpDest = OEMMapMemAddr (dwImageStart, dwRecAddr);
- // read data block
- if (!OEMReadData (dwRecLen, lpDest)) {
- EdbgOutputDebugString ("****** Data record %d corrupted, ABORT!!! ******rn", nPkgNum);
- HALT (BLERR_CORRUPTED_DATA);
- return FALSE;
- }
- if (!VerifyChecksum (dwRecLen, lpDest, dwRecChk)) {
- EdbgOutputDebugString ("****** Checksum failure on record %d, ABORT!!! ******rn", nPkgNum);
- HALT (BLERR_CHECKSUM);
- return FALSE;
- }
- // Look for ROMHDR to compute ROM offset. NOTE: romimage guarantees that the record containing
- // the TOC signature and pointer will always come before the record that contains the ROMHDR contents.
- //
- if (dwRecLen == sizeof(ROMHDR) && (*(LPDWORD) OEMMapMemAddr(dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE))
- {
- DWORD dwTempOffset = (dwRecAddr - *(LPDWORD)OEMMapMemAddr(dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG)));
- ROMHDR *pROMHdr = (ROMHDR *)lpDest;
- // Check to make sure this record really contains the ROMHDR.
- //
- if ((pROMHdr->physfirst == (dwImageStart - dwTempOffset)) &&
- (pROMHdr->physlast == (dwImageStart - dwTempOffset + dwImageLength)) &&
- (DWORD)(HIWORD(pROMHdr->dllfirst << 16) <= pROMHdr->dlllast) &&
- (DWORD)(LOWORD(pROMHdr->dllfirst << 16) <= pROMHdr->dlllast))
- {
- g_dwROMOffset = dwTempOffset;
- EdbgOutputDebugString("rom_offset=0x%x.rn", g_dwROMOffset);
- }
- }
- // verify partial checksum
- OEMShowProgress (nPkgNum ++);
- if (fIsFlash) {
- OEMContinueEraseFlash ();
- }
- }
- }
- while (--nNumRegions);
- if (fIsFlash) {
- nNumRegions = (BYTE)g_MultiBINInfo.dwNumRegions;
- while (nNumRegions--) {
- if (!OEMWriteFlash (g_MultiBINInfo.Region[nNumRegions].dwRegionStart, g_MultiBINInfo.Region[nNumRegions].dwRegionLength)) {
- HALT (BLERR_FLASH_WRITE);
- return FALSE;
- }
- }
- }
- return TRUE;
- }
- /*
- @func BOOLEAN | IsKernelRegion | Determines if the expanded BIN file provided contains the kernel image.
- @rdesc TRUE if the region contains the kernel image, FALSE if it doesn't.
- @comm <l Download Image>
- @xref
- @notes dwCurrentBase is the base address where the BIN records are currently stored (this can be a RAM, a RAM
- file cache, or flash). dwImageStoreBase is the images base storage address (this is the base address of potentially
- multiple BIN regions and can be in RAM or flash) and is used to translate addresses to the file cache area.
- dwROMOffset is the difference between the address where the BIN records are stored versus where they're fixed-up
- to run from (for example, an image may be stored in flash, but fixed-up to run in RAM).
- */
- static BOOL IsKernelRegion(DWORD dwRegionStart, DWORD dwRegionLength)
- {
- DWORD dwCacheAddress = 0;
- ROMHDR *pROMHeader;
- DWORD dwNumModules = 0;
- TOCentry *pTOC;
- if (dwRegionStart == 0 || dwRegionLength == 0)
- return(FALSE);
- if (*(LPDWORD) OEMMapMemAddr (dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET) != ROM_SIGNATURE)
- return FALSE;
- // A pointer to the ROMHDR structure lives just past the ROM_SIGNATURE (which is a longword value). Note that
- // this pointer is remapped since it might be a flash address (image destined for flash), but is actually cached
- // in RAM.
- //
- dwCacheAddress = *(LPDWORD) OEMMapMemAddr (dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG));
- pROMHeader = (ROMHDR *) OEMMapMemAddr (dwRegionStart, dwCacheAddress);
- // Make sure sure are some modules in the table of contents.
- //
- if ((dwNumModules = pROMHeader->nummods) == 0)
- return FALSE;
- // Locate the table of contents and search for the kernel executable and the TOC immediately follows the ROMHDR.
- //
- pTOC = (TOCentry *)(pROMHeader + 1);
- while(dwNumModules--) {
- LPBYTE pFileName = OEMMapMemAddr(dwRegionStart, (DWORD)pTOC->lpszFileName);
- if (!strcmp(pFileName, "nk.exe")) {
- return TRUE;
- }
- ++pTOC;
- }
- return FALSE;
- }