blcommon.c
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:16k
源码类别:

Windows CE

开发平台:

Windows_Unix

  1. //
  2. // Copyright (c) Microsoft Corporation.  All rights reserved.
  3. //
  4. //
  5. // Use of this source code is subject to the terms of the Microsoft end-user
  6. // license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
  7. // If you did not accept the terms of the EULA, you are not authorized to use
  8. // this source code. For a copy of the EULA, please see the LICENSE.RTF on your
  9. // install media.
  10. //
  11. /*++
  12. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  13. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  14. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  15. PARTICULAR PURPOSE.
  16. Module Name:
  17.     blcommon.c
  18. Abstract:
  19.     Bootloader common main module. This file contains the C BootloaderMain
  20.     function for the boot loader.    NOTE: The firmware "entry" point (the real
  21.     entry point is _EntryPoint in init assembler file.
  22.     The Windows CE boot loader is the code that is executed on a Windows CE
  23.     development system at power-on reset and loads the Windows CE
  24.     operating system. The boot loader also provides code that monitors
  25.     the behavior of a Windows CE platform between the time the boot loader
  26.     starts running and the time the full operating system debugger is
  27.     available. Windows CE OEMs are supplied with sample boot loader code
  28.     that runs on a particular development platform and CPU.
  29. Functions:
  30. Notes:
  31. --*/
  32. #include <windows.h>
  33. #include <halether.h>
  34. #include <blcommon.h>
  35. #ifdef SIMULATOR
  36. extern void CleanExit(DWORD dwExitCode);
  37. #define SPIN_FOREVER        CleanExit(42)
  38. #else
  39. #define SPIN_FOREVER        while (1)
  40. #endif
  41. ROMHDR * volatile const pTOC = (ROMHDR *)-1;     // Gets replaced by RomLoader with real address
  42. static ROMHDR romhdr;
  43. static MultiBINInfo g_MultiBINInfo;
  44. static BOOL KernelRelocate (ROMHDR *const pTOC);
  45. static BOOL DownloadImage (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr);
  46. static BOOL IsKernelRegion(DWORD dwRegionStart, DWORD dwRegionLength);
  47. #define CURRENT_VERSION_MAJOR       1
  48. #define CURRENT_VERSION_MINOR       0
  49. const unsigned char NKSignon[] = {
  50.     "nMicrosoft Windows CE Ethernet Bootloader Common Library Version %d.%d Built "
  51.         __DATE__ " " __TIME__ "rn"
  52.     "Copyright (c) 2000-2001  Microsoft Corporationrn"
  53. };
  54. DWORD g_dwROMOffset;
  55. PFN_OEMVERIFYMEMORY    g_pOEMVerifyMemory;
  56. PFN_OEMREPORTERROR     g_pOEMReportError;
  57. PFN_OEMCHECKSIGNATURE  g_pOEMCheckSignature;
  58. PFN_OEMMULTIBINNOTIFY    g_pOEMMultiBINNotify;
  59. static void HALT (DWORD dwReason)
  60. {
  61.     if (g_pOEMReportError) {
  62.         g_pOEMReportError (dwReason, 0);
  63.     }
  64.     SPIN_FOREVER;
  65. }
  66. void BootloaderMain (void)
  67. {
  68.     ROMHDR *pRomHdr = NULL;  // pTOC for NK image. MUST COPY IT OR CLEANBOOT may erase it
  69.     DWORD dwAction, dwpToc;
  70.     DWORD dwImageStart = 0, dwImageLength = 0, dwLaunchAddr = 0;
  71.     BOOL bDownloaded = FALSE;
  72. #ifndef SIMULATOR
  73.     // relocate globals to RAM
  74.     if (!KernelRelocate (pTOC)) {
  75.         // spin forever
  76.         HALT (BLERR_KERNELRELOCATE);
  77.     }
  78. #endif
  79.     // (1) Init debug support. We can use OEMWriteDebugString afterward.
  80.     if (!OEMDebugInit ()) {
  81.         // spin forever
  82.         HALT (BLERR_DBGINIT);
  83.     }
  84.     // output banner
  85.     EdbgOutputDebugString (NKSignon, CURRENT_VERSION_MAJOR, CURRENT_VERSION_MINOR);
  86.     // (3) initialize platform (clock, drivers, transports, etc)
  87.     if (!OEMPlatformInit ()) {
  88.         // spin forever
  89.         HALT (BLERR_PLATINIT);
  90.     }
  91.     // system ready, preparing for download
  92.     EdbgOutputDebugString ("System ready!rnPreparing for download...rn");
  93.     // (4) call OEM specific pre-download function
  94.     switch (dwAction = OEMPreDownload ()) {
  95.     case BL_DOWNLOAD:
  96.         // (5) download image
  97.         if (!DownloadImage (&dwImageStart, &dwImageLength, &dwLaunchAddr)) {
  98.             // error already reported in DownloadImage
  99.             SPIN_FOREVER;
  100.         }
  101.         bDownloaded = TRUE;
  102. if (dwImageStart) {
  103. // Check for pTOC signature ("CECE") here, after image in place
  104. if (*(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE) {
  105. EdbgOutputDebugString("Found pTOC signature.n");
  106. } else {
  107. EdbgOutputDebugString ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rn");
  108. EdbgOutputDebugString ("! ERROR: Did not find pTOC signature.  ABORTING. !rn");
  109. EdbgOutputDebugString ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!rn");
  110. // If no signature, we're going to fail anyway, so loop forever
  111. HALT (BLERR_SIGNATURE);
  112. }
  113. dwpToc = *(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG));
  114. // need to map the content again since the pointer is going to be in a fixup address
  115. dwpToc = (DWORD) OEMMapMemAddr (dwImageStart, dwpToc);
  116. // NOTE: MUST COPY or a CLEAN_BOOT flag will erase it
  117. memcpy (pRomHdr = &romhdr, (LPVOID) dwpToc, sizeof(ROMHDR));
  118. EdbgOutputDebugString ("ROMHDR at Address %Xhrn", dwImageStart + ROM_SIGNATURE_OFFSET + sizeof (DWORD)); // right after signature
  119. EdbgOutputDebugString ("RomHdr.ulRAMStart=%Xh RomHdr.physfirst=%Xh.rn", romhdr.ulRAMStart, romhdr.physfirst);
  120. }
  121.         // fall through
  122.     case BL_JUMP:
  123.         // Before jumping to the image, optionally check the image signature.
  124.         if (g_pOEMCheckSignature && dwImageStart)
  125.         {
  126.             if (!g_pOEMCheckSignature(dwImageStart, g_dwROMOffset, dwLaunchAddr, bDownloaded))
  127.                 HALT(BLERR_WHQL_SIGNATURE);
  128.         }
  129.         // (5) final call to launch the image. never returned
  130.         OEMLaunch (dwImageStart, dwImageLength, dwLaunchAddr, pRomHdr);
  131.         // should never return
  132.         // fall through
  133.     default:
  134.         // ERROR! spin forever
  135.         HALT (BLERR_INVALIDCMD);
  136.     }
  137. }
  138. //
  139. // KernelRelocate: move global variables to RAM
  140. //
  141. static BOOL KernelRelocate (ROMHDR *const pTOC)
  142. {
  143.     ULONG loop;
  144.     COPYentry *cptr;
  145.     if (pTOC == (ROMHDR *const) -1) {
  146.         return FALSE; // spin forever!
  147.     }
  148.     // This is where the data sections become valid... don't read globals until after this
  149.     for (loop = 0; loop < pTOC->ulCopyEntries; loop++) {
  150.         cptr = (COPYentry *)(pTOC->ulCopyOffset + loop*sizeof(COPYentry));
  151.         if (cptr->ulCopyLen)
  152.             memcpy((LPVOID)cptr->ulDest,(LPVOID)cptr->ulSource,cptr->ulCopyLen);
  153.         if (cptr->ulCopyLen != cptr->ulDestLen)
  154.             memset((LPVOID)(cptr->ulDest+cptr->ulCopyLen),0,cptr->ulDestLen-cptr->ulCopyLen);
  155.     }
  156.     return TRUE;
  157. }
  158. static BOOL VerifyChecksum (DWORD cbRecord, LPBYTE pbRecord, DWORD dwChksum)
  159. {
  160.     // Check the CRC
  161.     DWORD dwCRC = 0;
  162.     DWORD i;
  163.     for (i = 0; i < cbRecord; i++)
  164.         dwCRC += *pbRecord ++;
  165.     if (dwCRC != dwChksum)
  166.         EdbgOutputDebugString ("ERROR: Checksum failure (expected=0x%x  computed=0x%x)rn", dwChksum, dwCRC);
  167.     return dwCRC == dwChksum;
  168. }
  169. #define BL_HDRSIG_SIZE 7
  170. static BOOL DownloadImage (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr)
  171. {
  172.     BYTE hdr[BL_HDRSIG_SIZE];
  173.     DWORD dwRecLen, dwRecChk, dwRecAddr;
  174.     BOOL fIsFlash;
  175.     LPBYTE lpDest;
  176.     int nPkgNum = 0;
  177. BYTE nNumRegions = 1;
  178. DWORD dwImageStart, dwImageLength;
  179. *pdwImageStart = *pdwImageLength = *pdwLaunchAddr = 0;
  180. do
  181. {
  182. // read the 7 byte "magic number"
  183. if (!OEMReadData (BL_HDRSIG_SIZE, hdr)) {
  184. EdbgOutputDebugString ("rnUnable to read image signature.rn");
  185. HALT (BLERR_MAGIC);
  186. return FALSE;
  187. }
  188. // check for multi-bin information packet.
  189. if (!memcmp (hdr, "X000FFx0A", BL_HDRSIG_SIZE)) {
  190. // determine number of BIN files to be downloaded.
  191. if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk)) {
  192. EdbgOutputDebugString("rnUnable to read BIN region checksum.rn");
  193. HALT (BLERR_MAGIC);
  194. return FALSE;
  195. }
  196. // read BIN region descriptions (start address and length).
  197. if (!OEMReadData (sizeof (DWORD), (LPBYTE) &g_MultiBINInfo.dwNumRegions)
  198.     || !OEMReadData ((g_MultiBINInfo.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_MultiBINInfo.Region[0])) {
  199. EdbgOutputDebugString("rnUnable to read BIN region descriptors.rn");
  200. HALT (BLERR_MAGIC);
  201. return FALSE;
  202. }
  203. // verify the packet checksum.
  204. if (!VerifyChecksum((g_MultiBINInfo.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_MultiBINInfo.Region, dwRecChk)) {
  205. EdbgOutputDebugString ("rnBIN region descriptor packet failed checksum.rn");
  206. HALT (BLERR_CHECKSUM);
  207. return FALSE;
  208. }
  209. // provide the region information to the OEM.
  210. if (g_pOEMMultiBINNotify) {
  211. g_pOEMMultiBINNotify((const PMultiBINInfo)&g_MultiBINInfo);
  212. }
  213. // look for next download...
  214. nNumRegions = (BYTE)(g_MultiBINInfo.dwNumRegions + 1); // +1 to account for this packet.
  215. continue;
  216. }
  217. else {
  218. // make sure it is a standard BIN file.
  219. if (memcmp (hdr, "B000FFx0A", BL_HDRSIG_SIZE)) {
  220. EdbgOutputDebugString ("rnThis is not a .BIN file %x %x %x %x %x %x %xrn",
  221. hdr[0], hdr[1], hdr[2], hdr[3], hdr[4], hdr[5], hdr[6]);
  222. HALT (BLERR_MAGIC);
  223. return FALSE;
  224. }
  225. }
  226. // read image start/length
  227. if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageStart)
  228. || !OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageLength)) {
  229. EdbgOutputDebugString ("Unable to read image start/lengthrn");
  230. HALT (BLERR_MAGIC);
  231. return FALSE;
  232. }
  233. // if this is a single-bin download, record the bin file information and notify the OEM.
  234. if (!g_MultiBINInfo.dwNumRegions) {
  235. g_MultiBINInfo.dwNumRegions             = 1;
  236. g_MultiBINInfo.Region[0].dwRegionStart  = dwImageStart;
  237. g_MultiBINInfo.Region[0].dwRegionLength = dwImageLength;
  238. // provide the region information to the OEM.
  239. if (g_pOEMMultiBINNotify) {
  240. g_pOEMMultiBINNotify((const PMultiBINInfo)&g_MultiBINInfo);
  241. }
  242. }
  243. // give the OEM a chance to verify memory
  244. if (g_pOEMVerifyMemory && !g_pOEMVerifyMemory (dwImageStart, dwImageLength)) {
  245. EdbgOutputDebugString ("!OEMVERIFYMEMORY: Invalid imagern");
  246. HALT (BLERR_OEMVERIFY);
  247. return FALSE;
  248. }
  249. // check for flash image. Start erasing if it is.
  250. if ((fIsFlash = OEMIsFlashAddr (dwImageStart))
  251. && !OEMStartEraseFlash (dwImageStart, dwImageLength)) {
  252. EdbgOutputDebugString ("Invalid Flash Address/Lengthrn");
  253. HALT (BLERR_FLASHADDR);
  254. return FALSE;
  255. }
  256. // read records (start with address, length, and checksum)
  257. while (OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecAddr)
  258. && OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecLen)
  259. && OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk)) {
  260. RETAILMSG(1, (_T("DownloadImage RecAddr: 0x%xrn"), dwRecAddr));
  261. RETAILMSG(1, (_T("DownloadImage RecLen:  0x%xrn"), dwRecLen));
  262. RETAILMSG(1, (_T("DownloadImage RecChk:  0x%xrn"), dwRecChk));
  263. // check for last record
  264. if (!dwRecAddr && !dwRecChk) {
  265. // if this is the kernel region, update launch address
  266. if (IsKernelRegion(dwImageStart, dwImageLength)) {
  267. *pdwImageStart  = dwImageStart;
  268. *pdwImageLength = dwImageLength;
  269. *pdwLaunchAddr  = dwRecLen;
  270.          RETAILMSG(1, (_T("dwImageStart : 0x%xrn"), dwImageStart));
  271.          RETAILMSG(1, (_T("dwImageLength: 0x%xrn"), dwImageLength));
  272.          RETAILMSG(1, (_T("LaunchAddr   : 0x%xrn"), dwRecLen));
  273. }
  274. // write to flash if it's flash image
  275. if (fIsFlash) {
  276. // finish the flash erase
  277. if (!OEMFinishEraseFlash ()) {
  278. HALT (BLERR_FLASH_ERASE);
  279. return FALSE;
  280. }
  281. // Before writing the image to flash, optionally check the image signature.
  282. if (g_pOEMCheckSignature)
  283. {
  284. if (!g_pOEMCheckSignature(dwImageStart, g_dwROMOffset, *pdwLaunchAddr, TRUE))
  285. HALT(BLERR_WHQL_SIGNATURE);
  286. }
  287. }
  288. // On to the next (possible) BIN file...
  289. break;
  290. }
  291. // map the record address (FLASH data is cached, for example)
  292. lpDest = OEMMapMemAddr (dwImageStart, dwRecAddr);
  293. // read data block
  294. if (!OEMReadData (dwRecLen, lpDest)) {
  295. EdbgOutputDebugString ("****** Data record %d corrupted, ABORT!!! ******rn", nPkgNum);
  296. HALT (BLERR_CORRUPTED_DATA);
  297. return FALSE;
  298. }
  299. if (!VerifyChecksum (dwRecLen, lpDest, dwRecChk)) {
  300. EdbgOutputDebugString ("****** Checksum failure on record %d, ABORT!!! ******rn", nPkgNum);
  301. HALT (BLERR_CHECKSUM);
  302. return FALSE;
  303. }
  304. // Look for ROMHDR to compute ROM offset.  NOTE: romimage guarantees that the record containing
  305. // the TOC signature and pointer will always come before the record that contains the ROMHDR contents.
  306. //
  307. if (dwRecLen == sizeof(ROMHDR) && (*(LPDWORD) OEMMapMemAddr(dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE))
  308. {
  309. DWORD dwTempOffset = (dwRecAddr - *(LPDWORD)OEMMapMemAddr(dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG)));
  310. ROMHDR *pROMHdr = (ROMHDR *)lpDest;
  311. // Check to make sure this record really contains the ROMHDR.
  312. //
  313. if ((pROMHdr->physfirst == (dwImageStart - dwTempOffset)) &&
  314. (pROMHdr->physlast  == (dwImageStart - dwTempOffset + dwImageLength)) &&
  315. (DWORD)(HIWORD(pROMHdr->dllfirst << 16) <= pROMHdr->dlllast) &&
  316. (DWORD)(LOWORD(pROMHdr->dllfirst << 16) <= pROMHdr->dlllast))
  317. {
  318. g_dwROMOffset = dwTempOffset;
  319. EdbgOutputDebugString("rom_offset=0x%x.rn", g_dwROMOffset);
  320. }
  321. }
  322. // verify partial checksum
  323. OEMShowProgress (nPkgNum ++);
  324. if (fIsFlash) {
  325. OEMContinueEraseFlash ();
  326. }
  327. }
  328. }
  329. while (--nNumRegions);
  330. if (fIsFlash) {
  331. nNumRegions = (BYTE)g_MultiBINInfo.dwNumRegions;
  332. while (nNumRegions--) {
  333. if (!OEMWriteFlash (g_MultiBINInfo.Region[nNumRegions].dwRegionStart, g_MultiBINInfo.Region[nNumRegions].dwRegionLength)) {
  334. HALT (BLERR_FLASH_WRITE);
  335. return FALSE;
  336. }
  337. }
  338. }
  339.     return TRUE;
  340. }
  341. /*
  342.     @func   BOOLEAN | IsKernelRegion | Determines if the expanded BIN file provided contains the kernel image.
  343.     @rdesc  TRUE if the region contains the kernel image, FALSE if it doesn't.
  344.     @comm   <l Download Image>
  345.     @xref
  346. @notes  dwCurrentBase is the base address where the BIN records are currently stored (this can be a RAM, a RAM
  347.         file cache, or flash).  dwImageStoreBase is the images base storage address (this is the base address of potentially
  348. multiple BIN regions and can be in RAM or flash) and is used to translate addresses to the file cache area.
  349. dwROMOffset is the difference between the address where the BIN records are stored versus where they're fixed-up
  350. to run from (for example, an image may be stored in flash, but fixed-up to run in RAM).
  351. */
  352. static BOOL IsKernelRegion(DWORD dwRegionStart, DWORD dwRegionLength)
  353. {
  354. DWORD dwCacheAddress = 0;
  355. ROMHDR *pROMHeader;
  356. DWORD dwNumModules = 0;
  357. TOCentry *pTOC;
  358. if (dwRegionStart == 0 || dwRegionLength == 0)
  359. return(FALSE);
  360. if (*(LPDWORD) OEMMapMemAddr (dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET) != ROM_SIGNATURE)
  361. return FALSE;
  362. // A pointer to the ROMHDR structure lives just past the ROM_SIGNATURE (which is a longword value).  Note that
  363. // this pointer is remapped since it might be a flash address (image destined for flash), but is actually cached
  364. // in RAM.
  365. //
  366. dwCacheAddress = *(LPDWORD) OEMMapMemAddr (dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG));
  367. pROMHeader     = (ROMHDR *) OEMMapMemAddr (dwRegionStart, dwCacheAddress);
  368. // Make sure sure are some modules in the table of contents.
  369. //
  370. if ((dwNumModules = pROMHeader->nummods) == 0)
  371. return FALSE;
  372. // Locate the table of contents and search for the kernel executable and the TOC immediately follows the ROMHDR.
  373. //
  374.     pTOC = (TOCentry *)(pROMHeader + 1);
  375. while(dwNumModules--) {
  376. LPBYTE pFileName = OEMMapMemAddr(dwRegionStart, (DWORD)pTOC->lpszFileName);
  377. if (!strcmp(pFileName, "nk.exe")) {
  378. return TRUE;
  379. }
  380. ++pTOC;
  381. }
  382. return FALSE;
  383. }