【原创】关于WinCE中bootloader:nboot/eboot的那点事儿
2009-12-18 23:50
417 查看
预备文章:
//-----------------------------------------------------------------------//
《S3C2410&&WINCE6.0&&NBOOT》
《WinCE6.0的EBOOT概要》
By:cnblogs-HJB
//-----------------------------------------------------------------------//
《nk.bin和nk.nb0文件格式分析》
By:Gooogleman
//-----------------------------------------------------------------------//
《wince2秒快速启动TOC分析》
By:gliethttp
//-----------------------------------------------------------------------//
《eboot,TOC,NK地址跳转的问题》
By:CSDN-fan227
//-----------------------------------------------------------------------//
《Wincebootloader和内核定制》
By:kernel
//-----------------------------------------------------------------------//
《2440从NANDFlash启动之bootloader运行以前》
By:rightsoft
//-----------------------------------------------------------------------//
《NBOOT不能加载CE系统》
By:驱动开发网-fishly_0
//-----------------------------------------------------------------------//
《Nboot程序详细分析》
《Nboot和Eboot中的虚拟地址与物理地址的关系》
By:昔日之ID:formerman
//-----------------------------------------------------------------------//
《【原创】关于WinCE中config.bib的问题》
By:Mercury
//-----------------------------------------------------------------------//
好了,下面进入正文。昨天我们一起先看了下config.bib。于是我们就想更进一步。来在仔细研究下到底bootloader是有哪些事儿呢?
于是我们就找了上面的一些文章来看看。首先我们看HJB大牛的文章。文章很清晰的告诉了我们wince6.0下如何操作bootloader,下面我们再说一次,本人非常笨,不多说两边记不住,所以大家就忍受吧。首先系统要运行,需要一个引导程序,在以前有NORflash,友善系列的开发板就是带NOR这个东东,然后伴随的是有一个vivisuper的loader,这里我们不去细谈这个,现在主流是nandflash,所以,对应的有一个nandflash的boot,我们叫他nboot,那我们再来看ARM,我们拿Samsung这个arm来做例子,在HJB大牛的文章中提及了,ARM自身有一个4K的空间来存储应到程序,所以在上电之后通过一系列的配置,将nboot加载到ARM4k的空间里去执行,nboot就开始对系统的nandflash,内存,USB等等只要是你想初始化的设备进行一个初始化,这里的初始化程度就看你自己写的初始化程序了,按需所设计。接下来是nboot的重要使命,去叫eboot或者直接叫nk,然后结束自己的生命周期。
这里要特别说的是,在上一篇文章完结后,有个朋友问我nboot怎么去找到nk或者eboot在nandflash里的地址啊?这个问题一下也把我问懵了。百思不得其解,看nboot的程序里面到处都是什么loadaddress,或者是jumpaddress之类的东西,以为那个就是,后来根据以上一些文章的阅读发现,其实那些地址只是SDRAM和ARM直接一个虚拟和实际物理地址。根本不是nandflash里的地址。
那如何去从nandflash里面找到我们要的eboot或者image呢?这个时候被我们忽略的TOC蹦出来了,大叫道那些东西都是我扒的。这个时候我们就仔细来看看gliethttp的文章,关于winceTOC启动的文章,这里gliethttp给我们详细介绍了两个结构体:TOC和_IMAGE_DESCRIPTOR,具体这两个结构体的分析我们这里也贴出来,给这两扒东西的留个纪念,并给出一些注释,注释来自gliethttp,具体如下:
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这两个相依为命的结构体是扒eboot和image的罪魁祸首。他们到底是怎么扒的呢,在gliethttp文中介绍道:并不需要一次性将所有nk.nb0数据都加载到内存,应该按需加载,那就是ce的镜像文件image“按需加载”[“段式加载”]方式,TOC就是用来描述ce内核镜像文件image的xipkernel段核心结构体,我们只需加载核文件xipkernel就能正常启动进入wince界面。
好了,到此为止我们搞清楚了原理了,那内存SDRAM和ARM之间的地址又回到了重要的位置,我们怎么去设定这个地址呢?首先我们可以看下最新的mini2440nboot的写法,首先是给出几个固定的地址,也就是原始的物理地址和起始地址,一般的情况下大家可以在oemaddrtab_cfg.inc中的对照表中找到SDRAM的地址映射,一般情况下是类似如下的描述:
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
好了,这完成了第一步,第二步我们来写个比较简单的小程序,如何把虚拟地址转换成实际物理地址呢,这里又回到mini2440的最新5.0代码或者6.0代码中,有一句这样的话,写的很好:
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这里作出了一个判断,保证了地址的大小。同时也转换了地址。
这样一来我们知道如何在两个地址之间转换了,不过这个事情其实是在内存管理单元没有工作的情况下要用一下。当MMU工作了这个事情按照常理是交给MMU处理了.这些都是后话,我们继续看,有了TOC有了地址转换的工具,那地址到底在哪里呢?
现在我们在来看看gooogleman的文章,做wince开发驱动的应该都会用pb自带的一个命令行,这个是很好用的,有的时候makeimg啊,notepad一个什么文件什么的,很方便,这里gooogleman带我们回忆了一个非常重要,但是又往往被我们忽略的一个命令:viewbin,有了这个东东,我们可以仔细的看看我们要引导的eboot.bin或者nk.bin的起始地址是多少了。方法很简单,直接viewbinnk.bin或者viewbineboot.bin就可以了。起始地址,长度以及开始位置都列的很清晰,而这些个信息我们在TOC扒的时候已经全然送到他们该送的地方去了,系统自己该JUMP的也就JUMP过去,该Lunch的也就去Lunch过去,最新的会自己Run过去,呵呵这个完全看自己写的了。都是一样,无非是用一个指针指去那个地址,下面给个参考例子,我们就RUN过去,首先定义下怎么个run法:
首先初始化一下我们的run
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
然后我们通过TOC给run加速,一般是在charReadImageFromNand(unsignedintdwEntry)这个函数中
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
最后我们要在main函数里run起来
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这句话说的很好听,如果想跑你就跑吧。
好了。到此为止该run到eboot了就去runeboot了,该runimage就去runimage了。
这里补充下,其实eboot也是一样,eboot起来也就是去runimage,这个看设计的要求来定,理论是一样的。
其他的文章对nboot+eboot+image模式进行了详细的阐述,大家可以自己阅读,这里不对说了。
祝贺大家run的愉快。
//-----------------------------------------------------------------------//
《
《
By:cnblogs-HJB
//-----------------------------------------------------------------------//
《
By:Gooogleman
//-----------------------------------------------------------------------//
《
By:gliethttp
//-----------------------------------------------------------------------//
《
By:CSDN-
//-----------------------------------------------------------------------//
《
By:kernel
//-----------------------------------------------------------------------//
《
By:rightsoft
//-----------------------------------------------------------------------//
《
By:驱动开发网-
//-----------------------------------------------------------------------//
《
《
By:昔日之ID:
//-----------------------------------------------------------------------//
《
By:Mercury
//-----------------------------------------------------------------------//
好了,下面进入正文。昨天我们一起先看了下config.bib。于是我们就想更进一步。来在仔细研究下到底bootloader是有哪些事儿呢?
于是我们就找了上面的一些文章来看看。首先我们看HJB大牛的文章。文章很清晰的告诉了我们wince6.0下如何操作bootloader,下面我们再说一次,本人非常笨,不多说两边记不住,所以大家就忍受吧。首先系统要运行,需要一个引导程序,在以前有NORflash,友善系列的开发板就是带NOR这个东东,然后伴随的是有一个vivisuper的loader,这里我们不去细谈这个,现在主流是nandflash,所以,对应的有一个nandflash的boot,我们叫他nboot,那我们再来看ARM,我们拿Samsung这个arm来做例子,在HJB大牛的文章中提及了,ARM自身有一个4K的空间来存储应到程序,所以在上电之后通过一系列的配置,将nboot加载到ARM4k的空间里去执行,nboot就开始对系统的nandflash,内存,USB等等只要是你想初始化的设备进行一个初始化,这里的初始化程度就看你自己写的初始化程序了,按需所设计。接下来是nboot的重要使命,去叫eboot或者直接叫nk,然后结束自己的生命周期。
这里要特别说的是,在上一篇文章完结后,有个朋友问我nboot怎么去找到nk或者eboot在nandflash里的地址啊?这个问题一下也把我问懵了。百思不得其解,看nboot的程序里面到处都是什么loadaddress,或者是jumpaddress之类的东西,以为那个就是,后来根据以上一些文章的阅读发现,其实那些地址只是SDRAM和ARM直接一个虚拟和实际物理地址。根本不是nandflash里的地址。
那如何去从nandflash里面找到我们要的eboot或者image呢?这个时候被我们忽略的TOC蹦出来了,大叫道那些东西都是我扒的。这个时候我们就仔细来看看gliethttp的文章,关于winceTOC启动的文章,这里gliethttp给我们详细介绍了两个结构体:TOC和_IMAGE_DESCRIPTOR,具体这两个结构体的分析我们这里也贴出来,给这两扒东西的留个纪念,并给出一些注释,注释来自gliethttp,具体如下:
typedefstruct_TOC
{
//和CSW中的认证域类似,只用来验证接下去内容的合法
DWORDdwSignature;
//包含image的索引(我的是1)、启动delay时间、ip地址、MAC地址和掩码等
BOOT_CFGBootCfg;
//用来描述3个之多的ce内核image数组,我用的是id[1]
IMAGE_DESCRIPTORid[MAX_TOC_DESCRIPTORS];
CHAININFOchainInfo;
}TOC,*PTOC;//512字节
typedefstruct_IMAGE_DESCRIPTOR
{
DWORDdwVersion;//编译时的版本号
DWORDdwSignature;//“EBOOT”或“CFSH”等
UCHARucString[IMAGE_STRING_LEN];
//描述字符串:如"eboot.nb0"之类
DWORDdwImageType;//image的类型nk.nb0为0x04
DWORDdwTtlSectors;//image文件用到的NAND的扇区总数
DWORDdwLoadAddress;//image加载时的虚拟地址
DWORDdwJumpAddress;//image加载完成后的跳转地址
SG_SECTORsgList[MAX_SG_SECTORS];
//image的段描述,包括起始扇区号和所需扇区数目
ULONGdwStoreOffset;
}IMAGE_DESCRIPTOR,*PIMAGE_DESCRIPTOR;
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这两个相依为命的结构体是扒eboot和image的罪魁祸首。他们到底是怎么扒的呢,在gliethttp文中介绍道:并不需要一次性将所有nk.nb0数据都加载到内存,应该按需加载,那就是ce的镜像文件image“按需加载”[“段式加载”]方式,TOC就是用来描述ce内核镜像文件image的xipkernel段核心结构体,我们只需加载核文件xipkernel就能正常启动进入wince界面。
好了,到此为止我们搞清楚了原理了,那内存SDRAM和ARM之间的地址又回到了重要的位置,我们怎么去设定这个地址呢?首先我们可以看下最新的mini2440nboot的写法,首先是给出几个固定的地址,也就是原始的物理地址和起始地址,一般的情况下大家可以在oemaddrtab_cfg.inc中的对照表中找到SDRAM的地址映射,一般情况下是类似如下的描述:
DCD0x80000000,0x30000000,64
;64MBDRAMBANK6
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
好了,这完成了第一步,第二步我们来写个比较简单的小程序,如何把虚拟地址转换成实际物理地址呢,这里又回到mini2440的最新5.0代码或者6.0代码中,有一句这样的话,写的很好:
#defineVIRTUAL_TO_PHYSICAL(va)(((va>0x8c000000)?(va-0xc000000):(va))-VA_BASE+_RAM_STARTADDRESS)
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这里作出了一个判断,保证了地址的大小。同时也转换了地址。
这样一来我们知道如何在两个地址之间转换了,不过这个事情其实是在内存管理单元没有工作的情况下要用一下。当MMU工作了这个事情按照常理是交给MMU处理了.这些都是后话,我们继续看,有了TOC有了地址转换的工具,那地址到底在哪里呢?
现在我们在来看看gooogleman的文章,做wince开发驱动的应该都会用pb自带的一个命令行,这个是很好用的,有的时候makeimg啊,notepad一个什么文件什么的,很方便,这里gooogleman带我们回忆了一个非常重要,但是又往往被我们忽略的一个命令:viewbin,有了这个东东,我们可以仔细的看看我们要引导的eboot.bin或者nk.bin的起始地址是多少了。方法很简单,直接viewbinnk.bin或者viewbineboot.bin就可以了。起始地址,长度以及开始位置都列的很清晰,而这些个信息我们在TOC扒的时候已经全然送到他们该送的地方去了,系统自己该JUMP的也就JUMP过去,该Lunch的也就去Lunch过去,最新的会自己Run过去,呵呵这个完全看自己写的了。都是一样,无非是用一个指针指去那个地址,下面给个参考例子,我们就RUN过去,首先定义下怎么个run法:
首先初始化一下我们的run
#defineDOWNLOAD_ADDRESS0x30138000
void(*run)(void)=(void(*)(void))(DOWNLOAD_ADDRESS);
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
然后我们通过TOC给run加速,一般是在charReadImageFromNand(unsignedintdwEntry)这个函数中
run=(void(*)(void))(pToc->id[dwEntry].dwJumpAddress?VIRTUAL_TO_PHYSICAL(pToc->id[dwEntry].dwJumpAddress):
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
最后我们要在main函数里run起来
if(run)run();
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这句话说的很好听,如果想跑你就跑吧。
好了。到此为止该run到eboot了就去runeboot了,该runimage就去runimage了。
这里补充下,其实eboot也是一样,eboot起来也就是去runimage,这个看设计的要求来定,理论是一样的。
其他的文章对nboot+eboot+image模式进行了详细的阐述,大家可以自己阅读,这里不对说了。
祝贺大家run的愉快。
相关文章推荐
- 【原创】关于WinCE中bootloader:nboot/eboot的那点事儿
- 【转】关于WinCE中bootloader:nboot/eboot的那点事儿
- 【原创】回复:关于wince使用16C554/16C552 等外扩串口芯片的问题
- 【原创】回答网友关于ARM9 S3C2440 wince6.0 内存 128M的使用问题
- 【原创】关于wince驱动中CDEFINES的一些认识(作者:gooogleman)
- 关于EBoot和NBoot及.bin文件和.nb0文件的差别
- 关于EBoot和NBoot及.bin文件和.nb0文件的差别 12K Nboot-->4K
- 关于EBoot和NBoot及.bin文件和.nb0文件的差别
- 【原创】关于wince OS开发面试问题的总结系列之Bootloader
- 【原创】关于wince OS开发面试问题的总结系列之Bootloader
- 关于EBoot和NBoot的区别
- 关于bootloader,eboot,uboot,norflash,nandflash。
- [原创] 关于 AlphaBlend 函数
- (转)关于BSP,BIOS,和bootloader
- wince开发有感(作者原创,支持原创)
- 原创---关于实现comparable接口的排序例子
- 关于Qwebkit与Html之间的那点破事儿
- 关于wince下I2C控制的参考代码
- [原创]关于垃圾短信检测的几点看法
- [原创]java WEB学习笔记35:java WEB 中关于绝对路径 和相对路径问题