第1阶段——u-boot分析之make指令(2)

通过make 100ask24x0_config 指令配置好芯片选型后,使用make指令来生成uboot.bin文件

本文学习目标: 对Makefile文件进行基本了解,掌握make指令是怎么实现生成uboot.bin的过程

1.接下来开始分析make指令,首先打开u-boot-1.1.6/Makefile文件:

117 include $(OBJTREE)/include/config.mk               //调用config.mk这个文件
118 
...
124 ifeq ($(ARCH),ppc)                                 //判断config.mk这个文件中ARCH是否等于ppc
125 CROSS_COMPILE = powerpc-linux- 
126 endif
127 ifeq ($(ARCH),arm)                                 //判断config.mk这个文件中ARCH是否等于arm
128 CROSS_COMPILE = arm-linux- 
129 endif
...
164 include $(TOPDIR)/config.mk

因为执行了make 100ask24x0_config 后,其中include/config.mk内容为:

ARCH = arm
CPU = arm920t
BOARD = 100ask24x0
SOC = s3c24x0

由于ARCH=arm,所以第127行为真,执行第128行语句使用arm-linux-来制定交叉编译器前缀。 其中第164行的config.mk是属于顶层目录的config,主要通过arm,arm920t,100ask24x0,s3c24x0来确定编译器、编译选项等 2.打开config.mk(主要作用如下几段):

45 PLATFORM_LDFLAGS =
...
88 BOARDDIR = $(BOARD)                                        //$(BOARD)=100ask24x0
...
91 sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk	      //调用 board/100ask24x0/config.mk中第25行"TEXT_BASE=0x33F80000."
...
143 LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds        //LDSCRIPT=.//board/100ask24x0/u-boot.lds
...
189 LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)

如下图,通过grep查找内容指令可以看出u-boot设置的TEXT_BASE地址为0x33F80000(若boot太大或SDRAM太小,可以减小TEXT_BASE基地址)

相当于向LDFLAGS内容中追加了"-T board/100ask24x0/u-boot.lds -Ttext 0x33F80000"字段,(LDFLAGS:属于u-boot第四个依赖文件)

3.继续看makefile:

169 OBJS = cpu/$(CPU)/start.o                                //u-boot需要的目标文件,OBJS等于目标文件cpu/$(CPU)/start.o 
... 
193 LIBS = lib_generic/libgeneric.a                          //u-boot需要的库文件,LIBS等于库文件lib_generic/libgeneric.a  
194 LIBS += board/$(BOARDDIR)/lib$(BOARD).a                  //追加库文件board/100ask24x0/lib100ask24x0.a 
195 LIBS += cpu/$(CPU)/lib$(CPU).a                           //追加库文件cpu/arm920t/libarm920t.a 
...

214 LIBS := $(addprefix $(obj),$(LIBS))                      //addprefix为加前缀函数,其中obj=空,所以LIBS地址不变


...
222 SUBDIRS	= tools \                                  //SUBDIRS伪命令:用来执行tools,examples,post,post\cpu子目录下面的make文件。
223 examples \
224 post \
225 post/cpu
...
239 ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)    //all的依赖文件
240
241 all:	$(ALL)                                                          //使用make命令,相当于执行make all 
...
249 $(obj)u-boot.bin:	$(obj)u-boot                                            //生成u-boot.bin需要elf格式的u-boot,elf也就是通过ld链接文件生成的。
250	$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@                                 //执行:arm-linux-objcopy -O binary u-boot u-boot.bin
...

262 $(obj)u-boot:	depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)      //生成elf格式的u-boot所需要的依赖文件
263	UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
264 cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \                       
265 --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
266 -Map u-boot.map -o u-boot

在第263行和266行翻译出内容如下所示:

UNDEF_SYM=`arm-linux-objdump -x lib_generic/libgeneric.a board/100ask24x0/lib100ask24x0.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.afs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a drivers/nand_legacy/libnand_legacy.a drivers/usb/libusb.a drivers/sk98lin/libsk98lin.a common/libcommon.a

 |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\

cd /work/system/u-boot-1.1.6 && arm-linux-ld -Bstatic -T /work/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds -Ttext 0x33F80000 $UNDEF_SYM cpu/arm920t/start.o \ --start-group lib_generic/libgeneric.a board/100ask24x0/lib100ask24x0.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a drivers/nand_legacy/libnand_legacy.a drivers/usb/libusb.a drivers/sk98lin/libsk98lin.a common/libcommon.a --end-group -L /work/tools/gcc-3.4.5-glibc-2.3.6/lib/gcc/arm-linux/3.4.5 -lgcc \ -Map u-boot.map -o u-boot

在第263行和266行就是在制作elf格式的u-boot, 其中$(LIBS)$(__LIBS)就是库文件,$(LD)为连接选项,$(__OBJS)为目标文件, $(LDFLAGS)指定程序的布局与地址,为"/work/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds -Ttext 0x33F80000 ..."

4.board/100ask24x0/u-boot.lds文件如下所示:

	OUTPUT_ARCH(arm)                        //设置输出文件的体系架构。
	ENTRY(_start)                           //将_start这个全局符号设置成入口地址,进行复位初始化
SECTIONS                                        //输出文件的内容布局
{
. = 0x00000000;                                 //指定地址0x00000000,最终运行地址在0x33F80000+0x00000000

. = ALIGN(4);                                   //代码以4字节对齐
.text :                                         //指定.text section段(位于0x33F80000) 
{
cpu/arm920t/start.o	(.text)                 //添加第一个目标文件cpu/arm920t/start.o里面的.text代码段
board/100ask24x0/boot_init.o (.text)            //添加第二个目标文件board/100ask24x0/boot_init.o里面的.text代码段
*(.text)                                        //*(.data) 表示添加剩下的全部文件的.text代码段
}

. = ALIGN(4);
.rodata : { *(.rodata) }                        //指定.rodata section段(位于0x33F80000+.text section),将所有的.rodata只读数据段合并成一个.rodata只读数据段

. = ALIGN(4);
.data : { *(.data) }                            //指定读写数据段

. = ALIGN(4);
.got : { *(.got) }                             //指定got段,got段是uboot自定义的一个段

. = .;
__u_boot_cmd_start = .;                        //把__u_boot_cmd_start赋值为当前位置, 即起始位置
.u_boot_cmd : { *(.u_boot_cmd) }               // u_boot_cmd段,所有的u-boot命令相关的定义都放在这个位置
__u_boot_cmd_end = .;                          // *u_boot_cmd段结束位置

. = ALIGN(4);
__bss_start = .;                               //把__bss_start赋值为当前位置,即bss段的开始位置
.bss : { *(.bss) }                             //指定bss段,这里NOLOAD的意思是这段不需装载,仅在执行域中才会有这段
_end = .;                                      //把_end赋值为当前位置,即bss段的结束位置
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏LEo的网络日志

python i18n实现

3647
来自专栏Ryan Miao

SpringCloud学习6-如何创建一个服务消费者consumer

3104
来自专栏逆向技术

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

        PE文件格式详解,第二讲,NT头文件格式,以及文件头格式 PS:本篇博客默认你已经有了汇编基础,所以会使用32位汇编编写最小PE进行讲解 今天...

1826
来自专栏Jerry的SAP技术分享

SAP云平台CloudFoundry中的用户自定义变量

CloudFoundry应用的manifest.xml里的env区域,允许用户自定义变量,如下图5个变量所示。

1893
来自专栏大魏分享(微信公众号:david-share)

应用对持久数据的管理 | 从开发角度看应用架构7

当应用程序将数据存储在永久性存储中(例如flat file,XML文件或数据库的持久性数据)时,它被称为数据的持久性。 关系数据库是企业应用程序用来保存数据以供...

1074
来自专栏Android 研究

APK安装流程详解4——安装中关于so库的那些事

不同的Android手机使用不同的CPU,因此支持不同的指令集。CPU与指令集的每种组合都有其自己的应用二进制接口(或ABI)。"ABI"精确定义了"运行时,应...

1621
来自专栏向治洪

Spring Boot入门及整合mybatis

Spring Boot入门 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用...

2325
来自专栏IT技术精选文摘

Spring Boot使用过滤器和拦截器分别实现REST接口简易安全认证

5402
来自专栏技术小讲堂

ASP.NET AJAX(10)__Authentication ServiceAuthentication ServiceAuthentication Service属性Authentication

在通常情况下,如果使用AJAX方式调用WebService,则可能被恶意用户利用,造成性能以及安全性的问题,所以我们需要使用一些验证方式来保护WebServic...

3769
来自专栏猿天地

Spring Boot Async异步执行任务

异步调用就是不用等待结果的返回就执行后面的逻辑,同步调用则需要等带结果再执行后面的逻辑。

1112

扫码关注云+社区