S3C2450
的整个Bootloader
包括四个部分:
1
):Eboot.Whimory
2
):NBL1.IROM_SD
3
):NBL1.LSB
4
):NBL2
实现功能:生成三个有用的文件:block0img.nb0,Eboot.nb0/Eboot.bin,
以及IROM_SD_EBOOT.nb0
。其中前两个文件用于烧到NAND
的前几个block,
用于初始化整个系统的环境,以及引导NK
。最后面的IROM_SD_EBOOT.nb0
文件,是将第二个Eboot.nb0/Eboot.bin
文件打包得到的文件,用于烧写到SD
卡中,从SD
卡启动。下面针对前面的四个文件逐一说明。
一:NBL2
该文件用于生成block0img.nb0
。用于完成如下功能:
1
):初始化硬件配置,如堆栈,中断向量表,MMU
等。
2
):将后面生成的Eboot.bin
文件拷备到DRAM
中。
3
):打印部分串口信息,表示系统已经启动。
4
):初始化显示设备,输出开机LOGO
。但此时背光没点亮,故肉眼是看不清有开机LOGO
显示的。
5
):初始化NAND FLASH
。
6
):跳转到拷备Eboot.bin
的地址,执行Eboot
程序。
注:执行此段代码的前提是,开机必须是从NAND
启动的。之所以从SD
卡启动时会白屏一下,就是因为从SD
卡启动并没有执行这一段代码,即先点亮了背光,再初始化显示设备。如果从T
卡启动,这段代码没有任何作用。
二:NBL1.LSB
此段代码个人觉得没有任何用处,应该可以直接删除。将该段屏蔽掉后,仍然能从SD
卡启动,但是由于从NAND
启动需要跳线,没做相关实验。但是block0img.nb0
和Eboot.bin
两个文件已经生成。
三:Eboot.Whimory
整个Bootloader
最关键的部分就是这一块了。该部分用于产生Eboot.bin
和Eboot.nb0
文件。
主函数中由三个函数组成:
1
):powerlock_init();
用于软置锁,开机后通过IO
口给电源的使能脚供电,保证系统正常供电。
2
):BootloaderMain();
整个bootloader
的最关键的函数。下面将重点介绍。
3
):SpinForever();
这个函数是不会执行的,在执行第二个函数后,就会跳到NK
的地址启动系统了。如果执行到这个函数,那系统肯定就挂在Eboot
这里了。
整个函数代码如下:
void BootloaderMain
(void)
{
DWORD dwAction;
DWORD dwpToc = 0;
DWORD dwImageStart = 0, dwImageLength = 0, dwLaunchAddr =
0;
BOOL bDownloaded = FALSE;
//
relocate globals to RAM
//
将全局变量在
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
//
打印第一条信息
:
//
Microsoft Windows CE Ethernet Bootloader Common Library Version 1.1
Built Jul 13 2009 00:17:59
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);
}
}
从以上程序可以看出,整个
BootloaderMain()
函数由五大函数组成,分别是:
1
):KernelRelocate (pTOC)
;
用于将全局变量在DRAM
中声明。
2
):OEMDebugInit ()
;
用于初始化串口,给后续代码提供串口打印信息,便于调试。
3
):OEMPlatformInit ()
;
用于初始化硬件平台,如时钟,驱动等。
该函数通过如下子函数完成各硬件平台的初始化:
A
:memset()
:
初始化BSP args
结构;
B
:InitUSB();
初始化USB
接口;
C
:Isr_Init();
初始化中断;
D
:BP_Init();
初始化Nand Flash;
E
:InitDisplay();
初始化显示设备;
F
:ShowLogo();
显示logo;
G
:FMD_GetInfo();
读Flash
信息;
H
:TOC_Read();
读TOC
信息;
I
:OEMEthGetSecs();
读取当前时间,进行5
秒倒计时;同时在这5
秒的时间内检测是否有回车或空格键按下,如果回车,则运行NK
。如果空格,则进入USB
下载的菜单。
J
:backlight_open();
亮背光。
以上是OEMPlatformInit
()
函数的作用,具体每一句如何执行,每个函数是如何工作的,限于篇幅,这里就不详细介绍了。
4
):OEMPreDownload ()
;
该函数用于判断程序是下载映像还是引导映像。执行完该函数后,将根据函数的返回值选择。程序通过一个switch
语句完成。
5
):DownloadImage()
或OEMLaunch()
函数;
在步骤4
中,如果返回值是BL_DOWNLOAD
,则执行DownloadImage()
函数,用于下载映像。如果返回值是BL_JUMP
,则执行OEMLaunch()
函数,用于引导映像,最终启动系统。程序执行到OEMLaunch()
后,整个bootloader
也就完成任务了。
原文地址:http://blog.sina.com.cn/s/blog_455851af0100ecbn.html~type=v5_one&label=rela_nextarticle