记得从去年的三月份开始接触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
小结: (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 = .;
}
总结: