(2)Main函数代码分析
BLCOMMON的实现代码在/WINCE420/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/
BLCOMMON目录下的blcommon.c文件中。
void BootloaderMain (void)
{
ROMHDR *pRomHdr = NULL; // 镜像文件的PTOC
DWORD dwAction, dwpToc;
DWORD dwImageStart = 0, dwImageLength = 0, dwLaunchAddr = 0;
BOOL bDownloaded = FALSE;
if (!KernelRelocate (pTOC)) {
HALT (BLERR_KERNELRELOCATE);
}
//初始化debug支持,然后就可以用OEMWriteDebugString了
if (!OEMDebugInit ()) {
HALT (BLERR_DBGINIT);
}
//输出版本
EdbgOutputDebugString (NKSignon, CURRENT_VERSION_MAJOR, CURRENT_
VERSION_MINOR);
//初始化平台(时钟、驱动等)
if (!OEMPlatformInit ()) {
HALT (BLERR_PLATINIT);
}
//准备下载
EdbgOutputDebugString ("System ready!/r/nPreparing for download.../r/n");
//调用OEM指定的pre-download函数
switch (dwAction = OEMPreDownload ()) {
case BL_DOWNLOAD:
//下载映像
if (!DownloadImage (&dwImageStart, &dwImageLength, &dwLaunchAddr))
{
//报告DownloadImage的错误
SPIN_FOREVER;
}
bDownloaded = TRUE;
//检查pToc信号("CECE")
if (*(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart +
ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE) {
EdbgOutputDebugString("Found pTOC signature./n");
}
else
{
EdbgOutputDebugString
("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!/r/n");
EdbgOutputDebugString
("!! ERROR: Unable to find a table of contents in the downloaded image. If !!/r/n");
EdbgOutputDebugString
("!! this is a multi-region image, move the chain file region to an address !!/r/n");
EdbgOutputDebugString
("!! following the kernel region. Aborting.!/r/n");
EdbgOutputDebugString ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!/r/n");
//如果没有信号,将永远循环下去
HALT (BLERR_SIGNATURE);
}
dwpToc = *(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart +
ROM_SIGNATURE_OFFSET + sizeof(ULONG));
// 为了修正指针,需要再次映射一次
dwpToc = (DWORD) OEMMapMemAddr (dwImageStart, dwpToc + g_dwROMOffset);
//注意:必须复制或删除CLEAN_BOOT标志
memcpy (pRomHdr = &romhdr, (LPVOID) dwpToc, sizeof(ROMHDR));
EdbgOutputDebugString ("ROMHDR at Address %Xh/r/n", dwImageStart +
ROM_SIGNATURE_OFFSET + sizeof (DWORD)); // right after signature
EdbgOutputDebugString ("RomHdr.ulRAMStart=%Xh RomHdr.physfirst=%Xh./r/n",
romhdr.ulRAMStart, romhdr.physfirst);
//失败
case BL_JUMP:
//跳到映像之前,可以选择检查映像信号
//注意:如果现在没有下载的映像,那么在OEMLaunch中将假定从本地存储装载
//是RAM中残留的以前的下载,这种情况下,.映像启动地址必须是0.
//也就是映像信号程序将需要在存储或者RAM中寻找映像进行验证.
//因此OEM的OEMLaunch函数始终需要这样做.
//
if (g_pOEMCheckSignature)
{
if (!g_pOEMCheckSignature(dwImageStart, g_dwROMOffset, dwLaunchAddr, bDownloaded))
HALT(BLERR_WHQL_SIGNATURE);
}
//最后启动镜像,从不返回
OEMLaunch (dwImageStart, dwImageLength, dwLaunchAddr, pRomHdr);
// 从不返回
default:
HALT (BLERR_INVALIDCMD);
}
}
(3)FLASH操作代码分析
由于FLASH操作函数比较多,在此我们分析其中的几个有代表性的函数。
BOOL OEMIsFlashAddr (DWORD dwAddr)
{
//特殊处理Eboot,Eboot是为RAM创建,但存在于flash中
if (fileType & BOOTLOADER)
{
return(TRUE);
}
if ((dwAddr & 0xF0000000) == 0x90000000 || (dwAddr & 0xF0000000) == 0xB0000000)
{
return(TRUE);
}
return(FALSE);
}
static UINT16 FlashErase(DWORD dwStartBlock, DWORD dwNumBlocks)
{
BlockLockInfo BlockLockInfo;
if (dwStartBlock >= g_FlashInfo.dwNumBlocks || (dwStartBlock + dwNumBlocks - 1) >= g_FlashInfo.dwNumBlocks)
{
EdbgOutputDebugString("FlashErase: block number outside valid range./r/n");
return(-1);
}
//Unlock全部需要删除的块
EdbgOutputDebugString("FlashErase: Unlocking flash block(s) [0x%x, 0x%x] (please wait): ", dwStartBlock, (dwStartBlock + dwNumBlocks - 1));
BlockLockInfo.StartBlock = dwStartBlock;
BlockLockInfo.NumBlocks = dwNumBlocks;
if (!FMD_OEMIoControl(IOCTL_FMD_UNLOCK_BLOCKS, (PBYTE)&BlockLockInfo, sizeof(BlockLockInfo), NULL, 0, NULL))
{
EdbgOutputDebugString("/r/nWARNING: Unable to unlock all flash blocks!/r/n");
}
else
{
EdbgOutputDebugString("Done./r/n");
}
EdbgOutputDebugString("Erasing flash block(s) [0x%x, 0x%x] (please wait): ", dwStartBlock, (dwStartBlock + dwNumBlocks - 1));
while (dwNumBlocks--)
{
if (!FMD_EraseBlock(dwStartBlock))
{
EdbgOutputDebugString("/r/nFlashErase: unable to erase block (0x%x)./r/n", dwStartBlock);
return(-1);
}
++dwStartBlock;
EdbgOutputDebugString(".");
}
EdbgOutputDebugString("Done./r/n");
return(0);
}