终于把uboot两个阶段的所有代码都通读了一遍。总体的感觉是uboot的代码确实非常巧妙,读好的代码就如同读一本好书,反复读,认真思考,及时总结,这才是王道!
好了,废话不多说,下面来总结我读uboot的经验,主要是给自己留个笔记,高手看到这篇文章完全可以飘过了~不送啊,谢谢~
uboot启动是从哪里开始的呢?必须要看看lds文件,就是链接文件,这个文件用于指导gcc的链接器如何链接我们程序的各个组成文件中的各个段(section)。因为我学习的是smdk2410开发板,uboot.lds文件就在board/smdk2410/目录下。uboot.lds文件如下:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") //指定默认的输出文件格式为elf格式,32位arm指令,小端。括号中第二和三个为当用户使用命令行选项-EB //和-EL时的文件格式
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)//输出文件的执行平台为arm
ENTRY(_start)//指定输出可执行文件的代码段入口点
SECTIONS//定义一个section块,链接器将为每个section块分配加载地址
{
. = 0x00000000; //地址计数器,指定当前地址为0
. = ALIGN(4);//四字节对齐,因为这是arm指令,是32为指令集
.text ://定义代码段
{
cpu/arm920t/start.o(.text)//将start.o文件放在代码段的最前面,其中的_start为入口点
*(.text)//将所有其他文件的text段都依次放在start.o后面
}
. = ALIGN(4);//依然四字节对齐
.rodata : { *(.rodata) }//定义只读数据段,应该是保存一些常量吧(猜的),所有输入文件的rodata段都依次放在这里
. = ALIGN(4);
.data : { *(.data) }//定义数据段,所有输入文件的data段都依次放在这里
. = ALIGN(4);
.got : { *(.got) }//定义got段,这个段不知道干啥滴~
. = .;
__u_boot_cmd_start = .;//将当前地址计数器中记录的地址值保存到__u_boot_cmd_start中,在代码第二阶段,这个段用于保存uboot指令,通过这个符号,就可以找到该段// 位置
.u_boot_cmd : { *(.u_boot_cmd) } 将所有输入文件的u_boot_cmd段放在这里。*为通配符,表示每一个文件
__u_boot_cmd_end = .;