记得从去年的三月份开始接触linux,由于上课和实习的种种原因,断断续续的拖到了十月份学完了韦东山老师的新一期裸机视频,再后来就开始忙毕业设计、毕业论文的事了,直到最近答辩完毕,又重新复习了新一期裸机部分,最后来到了u-boot部分。写此博客,主要记录学习笔记,加深对各个知识点的理解。
补丁打到哪里去?(补丁文件分析 (用notepad打开补丁文件u-boot-1.1.6_jz2440.patch))
diff -urN u-boot-1.1.6/board/100ask24x0/100ask24x0.c u-boot-1.1.6_jz2440_burn_nor_with_nand_uboot/board/100ask24x0/100ask24x0.c --- u-boot-1.1.6/board/100ask24x0/100ask24x0.c 1970-01-01 07:00:00.000000000 +0700 +++ u-boot-1.1.6_jz2440_burn_nor_with_nand_uboot/board/100ask24x0/100ask24x0.c 2014-09-11 22:07:26.623026062 +0800 @@ -0,0 +1,96 @@命令:diff :常用来比较文件,目录,也可以用来制作补丁文件 语法:diff [选项] 原文件 目标文件 选项:-u:表示在比较结果中输出上下文中一些相同的行,这有利于人工定位 -r:表示递归比较各个目录下的文件 -N:将不存在的文件当作空文件 -w:忽略对空格的比较 -B:忽略对空行的比较
diff -urN u-boot-1.1.6/board/100ask24x0/100ask24x0.c u-boot-1.1.6_jz2440_burn_nor_with_nand_uboot/board/100ask24x0/100ask24x0.c所以这段代码的意思是:给源文件u-boot-1.1.6/board/100ask24x0/100ask24x0.c打个补丁。
补丁文件中修改过的代码表示:“- - -” 表示是 原来代码 ; “+++”表示修改后的代码。 “@@ -0,0 +1,96 @@” 其中,“-” 表示没有修改过的代码;“+” 表示修改后的代码 其中,“@@ -34,6 +34,8 @@”表示原来代码的从 34 行始,往下共 6 行。修改之后的代码也是从 34 行始,修改完后是往下8 行。 打补丁的过程: a.下载源码:u-boot-1.1.6.tar.bz2 b.解压缩 :tar xjf u-boot-1.1.6.tar.bz2 c.打补丁 :patch -p1 < …/补丁文件 注:此时打补丁已经进入u-boot-1.1.6目录 参数-p1:表示忽略第一层目录 -p2:表示忽略第一层、第二层目录
当在u-boot-1.1.6目录下make 100ask24x0_config时,会执行u-boot-1.1.6目录下的Makefile的如下语句: 此时,make 100ask24x0_config 相当于执行 @$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0 其中,最左边的@是指 make 时不输出 make 信息。 从u-boot-1.1.6目录下Makefile的92行可知 MKCONFIG := $(SRCTREE)/mkconfig(源码树下的mkconfig文件) $(@:_config=):其中,@表示目标,即100ask24x0_config 即 $(@:_config=) = 100ask24x0 这里涉及到Makefile 的一个函数 $(var:a=b) $(var:a=b) //把变量 “var” 中所有以 “a” 字串结尾的 “a” 替换成 “b” 字串 因此:@ $(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0 替换为: mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0 此时,执行make 100ask24x0_config相当执行下面的脚本 mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0 由此上图可知,mkconfig是一个可执行文件,make 100ask24x0_config 时会执行mkconfig 文件,而100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0 则是传入mkconfig文件的参数。 mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0 $0 $1 $2 $3 $4 $5 $6 对于shell脚本,参数$0为执行的文件名,参数 $1 ~ $6是传入执行文件的第一到第六个参数。 使用notepad打开mkconfig 文件 在文件的开头,可见下图代码 其中, #!/bin/sh 是指此脚本使用/bin/sh来解释执行,#! 是特殊的表示符,其后面跟的是此解释此脚本的shell的路径
接着 由上图可知,while语句先判断mkconfig传入的参数总个数($#代表参数总数)是否大于0,如果传入的参数总个数大于0,然后分析传入的参数 $1是否有 “–” , " -a ", “-n” , " * ", $1 = 100ask24x0,因此,跳过可忽略while…done 这段代码。
[ “${BOARD_NAME}” ] || BOARD_NAME="$1" 如果BOARD_NAME已经定义了,就不执行BOARD_NAME="$1",如果BOARD_NAME没有定义,则执行BOARD_NAME="$1"; 由上图开头的BOARD_NAME=" “,可以看出BOARD_NAME是空的,故执行BOARD_NAME=”$1",即BOARD_NAME = 100ask24x0。
其中, $#表示参数的个数,-lt:表示小于,-gt:表示大于 [ $# -lt 4 ] && exit 1 #如果参数的个数小于4,则退出 [ $# -gt 6 ] && exit 1 #如果参数的个数大于6,则退出
echo “Configuring for ${BOARD_NAME} board…” 执行完上面的代码后,打印出Configuring for 100ask24x0 board…
由上图可知,执行完else语句后,会在u-boot-1.1.6/incluce目录下生成一个名为asm的连接文件。
接着,删除u-boot-1.1.6/incluce/asm-arm/目录下的arch文件 继续往下执行 执行完上面的代码后,会在u-boot-1.1.6/incluce/asm-arm/目录下的生成arch和proc连接文件,分别执向该目录下的arch-s3c24x0和proc-armv目录。 执行完上述代码后,会在include目录下创建一个config.mk文件,文件的内容为: ARCH = arm CPU = arm920t BOARD = 100ask24x0 SOC = s3c24x0
由该mkconfig文的开头可知,APPEND=no,所以执行else分支,在include目录下新建config.h文件,文件的内容为: /* Automatically generated - do not edit */" #include <configs/100ask24x0.h>
小结: (make 100ask24x0_config 做了哪些事) 1. 执行mkconfig文件,并向该文件传入$1~$6 6个参数。 2. 在屏幕上打印 Configuring for 100ask24x0 board… 3. 在include目录下创建asm连接文件,在incluce/asm-arm/目录下arch、proc连接文件 4. 在顶层目录下创建config.mk文件 5. 在include目录下创建开发板相关的config.h头文件
编译:在u-boot-1.1.6目录下直接 make 分析Makefile 从config.mk文件可知ARCH = arm 由上图可知,$(ARCH) = arm ,所以,使用的交叉编译器为 arm-linux- $(CPU) = arm920t,由于 start.S 是启动代码,所以首先编译.OBJ=cpu/arm920t/start.o 这个addprefix是将OBJS赋值给obj
添加静态库 链接 arm-linux-ld -Bstatic -T /home/book/u-boot-1.1.6/board/100ask24x0/u-boot.lds -Ttext 0x33F80000 从上面可以看出,链接脚本是/u-boot-1.1.6/board/100ask24x0/目录下的u-boot.lds,代码段的基地址为0x33F80000
分析链接脚本
SECTIONS { //当前地址等于0,这个0地址会加上0x33F80000, //意即下面的文件会排放在从Ox33f80000开始的地方。 //关于0x33F80000放在 64M SDRAM 的最上边 512K 空间处 //这个地址可以根据u-boot的大小更改 . = 0x00000000; //最先排放cpu/arm920t/start.o这个文件的代码段。 . = ALIGN(4);//4字节对齐 .text : { //(.text)指cpu/arm920t/start.o的代码段 cpu/arm920t/start.o (.text) //接着放board/100ask24x0/boot_init.o的代码段 board/100ask24x0/boot_init.o (.text)//放在uboot最前的两个文件 *(.text)//接着放其他所有文件的代码段 } //接着是.rodata是只读数据段; *(.rodata)是指所有文件的只读数据 . = ALIGN(4); .rodata : { *(.rodata) } //接着放所有文件的数据段 . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); .got : { *(.got) } . = .; __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) }//所有文件的.u_boot_cmd段。 __u_boot_cmd_end = .; //这个段一般文件里不存在。这里是UBOOT定义了这个段。 //接着存放bss段(即存放初始值为0、无初始值的全局变量) . = ALIGN(4); __bss_start = .; .bss : { *(.bss) } _end = .; }总结:
uboot 从 0x33f80000 处开始运行第一个文件 cpu/arm920t/start.S链接地址TEXT_BASE在u-boot-1.1.6/board/100ask24x0 目录下的 config.mk定义 u-boot存放在SDRAM边沿的512kb空间处,下图是uboot存储空间的分布