这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » [原创]试论bootrom的拷贝地址

共11条 1/2 1 2 跳转至

[原创]试论bootrom的拷贝地址

菜鸟
2003-04-09 19:25:42     打赏
上周看了小容儿的那篇《bootROM竟然被copy 到RAM_LOW_ADRS的地方去了!》文章,第一反应是--不可能!结果自己一试果然是这样!可vxworks的各资料上明明说是bootrom被拷贝到RAM_HIGH_ADRS而vxworks映象是down到RAM_LOW_ADRS的呀!百思不得其解,只好自己来研究bootInit.c了,最后总算找到了答案。   先说说bootrom的类型。bootrom有三种类型:ROM_RESIDENT、UMCOMPRESS和COMPRESS。第一种是一直运行在rom中的映象,只把data段拷贝到ram里面;第二种是非压缩方式的映象,data段和text段都要拷贝到ram里面,并在ram里面运行;第三种是压缩方式的映象,生成的时候编译器会把除掉romInit.s和bootInit.c之外的目标文件压缩并“汇编”成一个bootrom.Z.s,最后和romInit.o,bootInit.o,version.o进行链接,生成bootrom映象。所以它也是要全部拷贝到ram中,且必须要进行压缩的工作。而这些工作基本上都是在bootInit.c中进行的。   bootInit.c里面主要就是romStart()这个函数,让我们来分析一下它。它的入口参数是startType,是一个启动类型标志,如BOOT_CLEAR、BOOT_NORMAL等,这在后面清内存时会用到。函数一开始定义了一个函数指针变量absEntry,它最后指向的就是ursInit()或compressedEntry()函数。接下来就是对三种bootrom映象类型进行不同的操作,下面我们以arm为例来分别说明。   1。ROM_RESIDENT:它要拷贝的只是data段。直接调用“ copyLongs ((UINT *)(etext + 4), (UINT *) RESIDENT_DATA, ((UINT) edata - (UINT) RESIDENT_DATA) / sizeof (long));”来实现。这时系统是运行在rom上的,链接器把所有的函数都定位在rom空间上,所以调用copyLongs时没有计算偏移,而拷贝的目标地址是RESIDENT_DATA,对于arm而言RESIDENT_DATA就是sdata,这是在romInit.s中定义的。通过objdumparm这个工具可以看到sdata定位在RAM_HIGH_ADRS+0x4这个位置上。而etext + 4则是rom上data段的起始地址。这样,完成data段的拷贝。然后如果startType为冷启动,那么清零SYS_MEM_BOTTOM到栈底(RESIDENT_DATA - STACK_SAVE)以及data段结束之后(edata到SYS_MEM_TOP)的内存空间。然后将函数开始定义的指针absEntry指向usrInit(在rom中):absEntry = (FUNCPTR)usrInit;并带上startType跳过去运行:(absEntry)(startType),完成。 2。UMCOMPRESS:一开始它将text段和data段都拷贝到ram中:((FUNCPTR)ROM_OFFSET(copyLongs))(ROM_TEXT_ADRS, (UINT)romInit, ROM_COPY_SIZE / sizeof (long))。这时的ROM_TEXT_ADRS就是代码段在rom上的开始位置,而romInit则是由链接器定位到了RAM_HIGH_ADRS的地址上,所以这时的确是按我们常规的思路拷贝的。并且由于copyLongs函数是定位到ram空间的,所以要计算它在rom上的偏移ROM_OFFSET(copyLongs)。然后象ROM_RESIDENT一样,它也要清零栈底(romInit - STACK_SAVE)以下和映象之上(SYS_MEM_TOP - (romInit + ROM_COPY_SIZE))的内存空间。然后将函数开始定义的指针absEntry指向usrInit(在ram中):absEntry = (FUNCPTR)usrInit;并带上startType跳过去运行:(absEntry)(startType),完成。 3。COMPRESS:开始的时候把从ROM_TEXT_ADRS起始的长度为romInit到binArrayStart的内容拷贝到romInit位置上。注意,由于romInit被链接器定位到RAM_LOW_ADRS的位置上,这时相当于把romInit.o、bootInit.o和version.o的内容拷贝到了RAM_LOW_ADRS上。然后和UMCOMPRESS一样清零栈底(romInit - STACK_SAVE)以下的内存空间,不同之处是它接下来清除binArrayStart之上(SYS_MEM_TOP - binArrayStart)的内存空间:fillLongs ((UINT *)binArrayStart, ((UINT)SYS_MEM_TOP - (UINT)binArrayStart) / sizeof (long), 0)。然后调用解压程序inflate将在rom上的(binArrayEnd - binArrayStart)之间的内容解压到RAM_DST_ADRS(RAM_HIGH_ADRS)的位置上:binArrayStart(absUncompress) ((UCHAR *)ROM_OFFSET(binArrayStart),(UCHAR *)RAM_DST_ADRS, &binArrayEnd - binArrayStart)。这样,解完压后函数compressedEntry()刚好就在RAM_DST_ADRS(RAM_HIGH_ADRS)的位置上,所以接下来将指针absEntry指向它:absEntry = (FUNCPTR)RAM_DST_ADRS。最后带上startType跳过去运行:(absEntry)(startType),完成。 所以我敢肯定小容儿的bootrom是COMPRESS类型的。有些细节地方我还没有仔细研究,欢迎各位大牛讨论!



关键词: 原创     试论     bootrom     拷贝     地址     absEn    

菜鸟
2003-04-11 01:46:00     打赏
2楼
纠正一下:“romInit被编译器定位在RAM_LOW_ADRS处”这个说法是不对的。当映象为COMPRESS时的确是样,当为UMCOMPRESS时则是定位在RAM_HIGH_ADRS处,而当为ROM_RESIDENT时则定位在ROM_TEXT_ADRS处的。   另外,当映象为压缩模式时解压到RAM_HIGH_ADRS处的是函数compressedEntry()的入口,由它调用usrInit(),而不usrRoot()。   我没有仔细去研究Tornado的编译规则,只是采用了“笨”办法:用host/bin目录下的objdump工具来查看生成的bootrom、bootrom_uncmp和bootrom_res三个文件来分析的。这是一个非常有用的工具,它可以反汇编coff、elf之类的文件。你用“objdumpArm -t bootrom”就可以得到symbl表。另外,tornado在编译的时候也会以最后打印出类似“ldarm -X -N -e _romInit -Ttext 00001000”这样的信息,它就是将_romInit定位到x00001000。 但愿有所帮助。

菜鸟
2003-04-11 18:47:00     打赏
3楼
seasoblue说的很明白,我长了见识。 精神可嘉!

菜鸟
2003-04-11 19:15:00     打赏
4楼
能得到大家的肯定,我真是高兴! 希望多多交流,共同进步!![em27][em27]

菜鸟
2006-03-18 03:47:00     打赏
5楼

小弟才看了,非常好的文章,但是我看的现在T2.2的bootInit.c,里面关于bootrom压缩的情况多了下面这段代码,有点不懂,请斑竹赐教。

/*
BINARRAYEND_ROUNDOFF(binArrayEnd)被LD定位到???
BINARRAYEND_ROUNDOFF(binArrayEnd)定义为被压缩的image尾。
(UINT)ROM_TEXT_ADRS + ((UINT)BINARRAYEND_ROUNDOFF - (UINT)romInit)为ROM上的数据段起始地址
wrs_kernel_data_end数据段尾?包括BSS段不?
把ROM上的数据段拷贝到binArrayEnd之后,被定位到RAM的哪里?
*/
((FUNCPTR)ROM_OFFSET(copyLongs))
((UINT *)((UINT)ROM_TEXT_ADRS + ((UINT)BINARRAYEND_ROUNDOFF -
(UINT)romInit)), (UINT *)BINARRAYEND_ROUNDOFF,
((UINT)wrs_kernel_data_end - (UINT)binArrayEnd) / sizeof (long));


菜鸟
2006-03-21 04:51:00     打赏
6楼

楼上的能说明白一点不?IA体系??前面已经拷贝了,后面这段拷贝是什么意思?


菜鸟
2006-03-21 21:04:00     打赏
7楼
以下是引用aloha在2003-11-23 14:50:00的发言:
seasoblue好文章!

也来谈谈偶的理解,请诸位大虾指教.



好,那么我们再考虑一下压缩的情况。假设bootrom是压缩的。首先它是怎么
压缩的呢?它肯定不能完全压缩,而是由一个无压缩的部分加上一个压缩的
部分组成,否则无法自运行。这个无压缩的部分就是romInit.s+bootInit.c,
称为boot strap。一上电时boot strap在flash rom中执行,入口点就是
romInit.s的第一条语句。


原来这就是boot strap

好贴,又多了解了些压缩bootrom


菜鸟
2006-08-26 04:17:00     打赏
8楼

((FUNCPTR)ROM_OFFSET(copyLongs)) (ROM_TEXT_ADRS, (UINT)romInit,

((UINT)binArrayStart - (UINT)romInit)/ sizeof (long));

((FUNCPTR)ROM_OFFSET(copyLongs))

((UINT *)((UINT)ROM_TEXT_ADRS + ((UINT)BINARRAYEND_ROUNDOFF - (UINT)romInit)), (UINT *)BINARRAYEND_ROUNDOFF,

((UINT)wrs_kernel_data_end - (UINT)binArrayEnd) / sizeof (long));

这里前面一句不是已经把没有压缩的romInit romStart,拷贝到RAM_LOW_ADRS了吗?

后面这一句是什么意思?还有,wrs_kernel_data_end 是什么意思?


菜鸟
2006-08-31 05:12:00     打赏
9楼

很有启发


菜鸟
2007-02-06 22:53:00     打赏
10楼

对bsp有了更深的了解。


共11条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]