📄 blcommon.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.
//
/*++
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 _StartUp 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>
#define SPIN_FOREVER while (1)
ROMHDR * volatile const pTOC = (ROMHDR *)-1; // Gets replaced by RomLoader with real address
static DownloadManifest g_DownloadManifest;
static BOOLEAN g_bBINDownload = TRUE;
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 1
const unsigned char NKSignon[] = {
"\nMicrosoft Windows CE Ethernet Bootloader Common Library Version %d.%d Built "
__DATE__ " " __TIME__ "\r\n"
};
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)
{
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
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);
}
}
//
// 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)\r\n", 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 = FALSE;
LPBYTE lpDest = NULL;
int nPkgNum = 0;
BYTE nNumDownloadFiles = 1;
DWORD dwImageStart = 0;
DWORD dwImageLength = 0;
RegionInfo *pCurDownloadFile;
*pdwImageStart = *pdwImageLength = *pdwLaunchAddr = 0;
do
{
// read the 7 byte "magic number"
//
if (!OEMReadData (BL_HDRSIG_SIZE, hdr))
{
EdbgOutputDebugString ("\r\nUnable to read image signature.\r\n");
HALT (BLERR_MAGIC);
return (FALSE);
}
// An N000FF packet is manufactured by Platform Builder when we're
// downloading multiple files or when we're downloading a .nb0 file.
//
if (!memcmp (hdr, "N000FF\x0A", BL_HDRSIG_SIZE))
{
// read the packet checksum.
//
if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk))
{
EdbgOutputDebugString("\r\nUnable to read download manifest checksum.\r\n");
HALT (BLERR_MAGIC);
return (FALSE);
}
// read BIN region descriptions (start address and length).
//
if (!OEMReadData (sizeof (DWORD), (LPBYTE) &g_DownloadManifest.dwNumRegions) ||
!OEMReadData ((g_DownloadManifest.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_DownloadManifest.Region[0]))
{
EdbgOutputDebugString("\r\nUnable to read download manifest information.\r\n");
HALT (BLERR_MAGIC);
return (FALSE);
}
// verify the packet checksum.
//
if (!VerifyChecksum((g_DownloadManifest.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_DownloadManifest.Region[0], dwRecChk))
{
EdbgOutputDebugString ("\r\nDownload manifest packet failed checksum verification.\r\n");
HALT (BLERR_CHECKSUM);
return (FALSE);
}
// Provide the download manifest to the OEM. This gives the OEM the
// opportunity to provide start addresses for the .nb0 files (which
// don't contain placement information like .bin files do).
//
if (g_pOEMMultiBINNotify)
{
g_pOEMMultiBINNotify((PDownloadManifest)&g_DownloadManifest);
}
// look for next download...
nNumDownloadFiles = (BYTE)(g_DownloadManifest.dwNumRegions + 1); // +1 to account for this packet.
continue;
}
// Is this an old X000FF multi-bin packet header? It's no longer supported.
//
else if (!memcmp (hdr, "X000FF\x0A", BL_HDRSIG_SIZE))
{
EdbgOutputDebugString ("ERROR: The X000FF packet is an old-style multi-bin download manifest and it's no longer supported. \
\r\nPlease update your Platform Builder installation in you want to download multiple files.\r\n");
HALT (BLERR_MAGIC);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -