uboot的主makefile的分析1
1、uboot的版本号:分为三个级别:
VERSION = 1 //uboot的主版本号
PATCHLEVEL = 3 //此版本号
SUBLEVEL = 4 //再次版本号
EXTRAVERSION = //另外附加的版本信息
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) //构成了uboot的版本号
U_BOOT_VERSION 这个变量构成了我们uboot的版本信息。
include/version_autogenerated.h 这个文件是我们配置uboot编译后生成的,没配置编译之前我们是找不到的,它里面的内容是一个宏,这个宏就是我们uboot中配置的版本号
2、HOSTARCH、HOSTOS、两个环境变量
因为被export 导出了。
在makefile中引用一个命令时 可以让反引号将这个命令引起来去赋值给一个变量,在去用$解析这个变量就可以执行这个命令。
如: var = 'pwd'
all:
echo $(var)
也可以用shell -name的形式,去将这个命令赋值给一个变量
如:
var = $(shell pwd)
all:
echo $(var)
HOSTARCH := $(shell uname -m | \
sed -e s/i.86/i386/ \
-e s/sun4u/sparc64/ \
-e s/arm.*/arm/ \
-e s/sa110/arm/ \
-e s/powerpc/ppc/ \
-e s/ppc64/ppc/ \
-e s/macppc/ppc/)
shell uname -m 中的uname -m 是打印计算机的CPU的版本号,我的是i686
就是你当前的电脑执行这条命令后,出来的是你这台电脑CPU的版本号
| 是一种管道,意思就是将|前面的结果的值输出的值,做为|后面的输入值
sed是一个用于字符串的工具(和函数一样),-e s目的是将/i.86/i386/ i.86替换成i386 .的是匹配符。在我们这里就会将我们的i686这个值替换成i386
HOSTARCH:名字的解析,host是主机的意思,arch是架构这个单词的缩写,意思就是主机的架构
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
sed -e 's/\(cygwin\).*/cygwin/')
HOSTOS :就是主机的操作系统
tr '[:upper:]' '[:lower:]'就是转换成小写的。
uboot的主makefile的分析2
1、静默编译(50-54行)
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO = echo
else
XECHO = :
endif
所以我们使用方法就是make -s 这样我们在make的时候就不会打印出来make中信息,但会有编译器编译的信息
2、2种编译方法(原地编译和单独输出文件夹编译)
在默认的情况下,我们make时,编译.c .S等文件时,编译后的.o文件是在被编译的文件所在的目录下的,叫原地编译。
单独输出文件夹 编译:就是让我们要编译的文件,编译后生成的东西,全部放在一个单独的文件夹下。这样我们的源目录下就不会受到极大的污染(就是在.c .S等文件和生成.o等其他文件放在一起)。这样输出目录就承载了我们本次编译配置的输出结果。
这样做的好处就是,如果我们的一套源代码遇到了三种不同配置的情况下,就是一套源代码有好几个项目同时要用到,并且没一个项目的配置是不一样的,我们就可以建立三个输出目录,将我们的源代码分别按照三种不同的配置去配置并且进行编译,编译后输出的结果放在了三个单独的输出文件夹下,这样做就会非常的好。
具体用法:在默认的情况下,我们的编译就原地进行编译的,如果想要将编译后的结果输出到指定的文件夹下,则有两种指定的方法。
第一种:make O=输出的目录
第二种:导出环境变量,将跟编译后输出到指定目录的那个环境变量的值改成我们想要的目录即可
export BUILD_DIR=输出目录 然后再make 就可以达到我们要的效果了
如果这两种情况同时被指定了,则make O=输出的目录 具有更高的优先级。
makefile的关于这两种方法的使用在56-76行
关于这两种方法的实现在78-122行(实际上就是第二种方法的实现)
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
解析这段:ifdef O 的意思就是,如果我们在命令下输入了 make O 有O的话,这个ifdef就成立了
成立以后
$(origin O) 就是解析这个O 就我们在命令行下输入 make O=XX XX的内容就会被解析出去,就相当于O是一个变量了
BUILD_DIR := $(O) 就是将这个O的值赋值给了BUILD_DIR这个变量,这个不就是我们的那个跟编译后输出到指定目录的那个环境变量的环境变量嘛。
uboot的主makefile的分析3
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE := $(CURDIR)
TOPDIR := $(SRCTREE)
LNDIR := $(OBJTREE)
OBJTREE:就是编译出的.o文件存放的目录的根目录
默认情况下,OBJTREE中的值是我们编译的那个文件所在的目录,
在我们设置后OBJTREE,编译后的输出的目录就是我们设置的那个目录
SRCTREE:源码根目录
TOPDIR: 顶层目录,就是我们源码的目录
MKCONFIG := $(SRCTREE)/mkconfig //源码根目录下的mkconfig mkconfig就是我们的脚本,uboot配置阶段的配置脚本
MKCONFIG 是一变量,这个变量的值就是源码目录下的mkconfig
include $(obj)include/config.mk(133行) 意思是包含obj这个目录下的include下的config.mk,obj的值在makefile中的值是OBJTREE他的值。如果OBJTREE和SRCTREE的值不相等的话,也就是在我们make O=XX的时候,OBJTREE的值就和SRCTREE的值不相等了,这时编译要输出的目录就是XX了,OBJTREE的值就是这个要输出的目录,所以include $(obj)include/config.mk 就是将这个目录下的include下的config.mk包含进来,原地展开,include/config.mk 不是源码自带的,而是在配置的过程中(在make x210_sd_config时),才会出现这个include/config.mk ,它里面的值是我们配置相关的值,在配置后生成的值。
我们配置好后这个里面的值是: ARCH = arm //arm 架构的
CPU = s5pc11x
BOARD = x210
VENDOR = samsung //生产商 三星
SOC = s5pc110
这几个值来自于,uboot主makefile中的2589行,在调用MKCONFIG这个变量指引的脚本时,给这个脚本传递的参数就是arm s5pc11x等这5个值,只要把这几个参数的值改掉,那么我们的配置生成的在config.mk中的信息就会变
2、ARCH
arch是一个环境变量在134行被导出的,它的值是在配置的过程中得到的。arch这个值是什么,会影响CROSS_COMPILE,arch的值就是说明当前的编译目标,uboot是给什么架构的目标cpu用的。
3、CROSS_COMPILE 136行到182行
CROSS_COMPILE是定义我们交叉工具链前缀的,定义这个变量后,我们只在用后面要用(加上不同的后缀,使用不同的交叉编译工具链中的工具),在不同的arch中,也就是不同的架构中,我们使用的交叉编译工具链只是前缀不同,后缀是相同的,所以我们用arch中的值,arch的值不同,我们前缀就也是不同的,所以arch的值会影响我们cross_compile中的值
ifndef CROSS_COMPILE
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE =
else
ifeq ($(ARCH),ppc)
CROSS_COMPILE = ppc_8xx-
endif
.
.
.
.
从中可以看出 第一行的意思就是没有定义CROSS_COMPILE则执行下面的语句
也就是说我们使用make的时候,如果给make CROSS_COMPILE=xxx 那么就相当于定义了CROSS_COMPILE这个,并且他的值是xxx,就会选择用xxx这个前缀的交叉编译工具进行编译,并且这个值可以覆盖我们makefile中的CROSS_COMPILE的值,就是make CROSS_COMPILE=xxx的优先级要高于makefile中的设置
144行
#CROSS_COMPILE = arm-linux-
147行
CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
为什么144行的和147行的不同,如果我们装的交叉编译工具链的根目录导出到了环境变量PATH中,export PATH = /usr/local/arm/arm-2009q3/bin/: $PATH
并且我们将arm-none-linux-gnueabi-的工具符号连接成了arm-linux-,那么我们就可以在makefile中将让CROSS_COMPILE = arm-linux- 这个了,这样我们在make的时候,makefile就会找到了这个交叉工具链了
如果我们没有将交叉编译工具链的路径导出到环境变量中,也没有建议符号链接,那么就只能用147行的那个,才能让makefile找到我们用的交叉编译工具连
uboot的主makefile的分析4
1、TOPDIR (主makefile的185行) TOPDIR上面讲到过,值也是源码的目录
include $(TOPDIR)/config.mk 包含了这个源码录下的config.mk,接下来就开始分析一下这个config.mk
2、编译工具的定义97行-107行
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
LDR = $(CROSS_COMPILE)ldr
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB = $(CROSS_COMPILE)RANLIB
3、包含了开发板的配置项目(TOPDIR目录下的config.mk中的112行)
sinclude $(OBJTREE)/include/autoconf.mk
autoconf.mk文件不是我们源码中提供的,是我们在配置的过程中自动生成的,肯定是有原材料使他生成的
(1)这个文件的作用就是指导我们uboot的整个编译过程,这个文件中的内容都是很多个CONFIG_开头的宏(或者叫做变量)什么什么=y或者等于一个什么其他的值,这些宏或者变量的值会影响我们uboot的整个走向(原理就是条件编译),在uboot的代码中,有很多用条件编译进行编写,这个条件编译就会使我们的uboot像不同的方向发展的,用来实现可移植性的。
也就是说,如果我们在配置的时候,将我们的项目配置成了另一个方式,那么这些宏或者变量的值就会变,那么我们在uboot中用条件编译进行编写代码时,就会像不同的方向去发展,所以同一个uboot中的代码是拼凑起来的,意思就是同一个uboot代码中,包含很多开发板适用的代码,用条件编译进行区别
(2)这个文件的来源:这个文件不是凭空产生的,就算是配置文件产生的,那么也是需要原材料进行加工生成的,在这个原材料来源于我们的源码目录下的/include/configs/xxx,在我们的x210开发板中,这个原材料就来源于我们源码目录下的/include/configs/x210_sd.h
这个x210_sd.h(针对于我们x210的iNand的移植)中的内容全是一些宏定义。这些宏定义是我们当前开发板的移植,每一个开发板的移植都对应于这个目录下的一个头文件。这个头文件中的每一个宏定义都非常的重要,这个配置中的宏定义就是我们移植uboot的关键所在。
当前的总结:我们在移植uboot的时候,在uboot的主makefile中,
1、开始是uboot版本号相关的东西如:
VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 4
EXTRAVERSION = so_care_about_you
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h
前四个变量就是uboot的版本号的各个部分,
第五个变量就是整体的uboot的版本号,由前面四个变量组成的
最后一个变量包含了一个路径下的头文件,这个路径就是我们的目标目录,就是我们输出配置编译结果的目录,里面的那个头文件时我们在配置编译的过程中产生的,里面的内容就是一个宏,这个宏记录了我们上面四个变量的版本号,这个宏就是上面变量的第五个,只是用宏的方式定义了,以便于我们在c代码中去用。
2、接着就是主机的架构和操作系统的的信息。
3、接着就是关于静默编译的
4、接着就是关于将编译输出结果到一个单独的目录下的,用make O=xx 的方式,或者用导出环境变量改这个变量的值的方式
5、接着就是关于我们给不同的架构设备去编译时用到的不同的交叉编译工具链。前缀和后缀给分开了,前缀的值放在了CROSS_COMPILE中
6、接着就包含了我们源码目录(TOPDIR)下的config.mk配置文件,也就是加载了这个配置文件。,这个配置文件其实也是一个makefile,这个文件的97行到107行,就是将我们的交叉编译的后缀加上,并且赋值给了一些变量。
7、接着在源码目录(TOPDIR)下的config.mk中,112行,就又加载了开发板的配置文件
sinclude $(OBJTREE)/include/autoconf.mk
,这个配置文件是由我们的源码目录下的include/configs/x210_sd.h的原材料加工出来的。这个目录下的configs中是一些不同开发板的头文件,这些头文件中全是宏,宏的值跟我们移植uboot非常相关,很重要。由这个头文件作为原材料生成的autoconf.mk配置文件,这个文件也全是一些宏或者变量,他们会影响uboot的走向,在uboot代码的条件编译那些代码中,决定了uboot的走向。所以导致了一个uboot可以移植适用很多个开发板,这里的原因很大。
uboot的主makefile的分析5
链接脚本的导入(config.mk 142-149行)
1、在config.mk中(源码目录下的config.mk),144行-就用到了我们上面那个由x210_sd.h加工成的autoconf.mk中的那些宏或者叫做变量。
ifeq ($(CONFIG_NAND_U_BOOT),y)
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds
else
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
endif
如果autuconf.mk中的CONFIG_NAND_U_BOOT的值等于了y 就让LDSCRIPT变量的值等于$(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds
因为我们的开发板用的iNand所以在autuconf.mk中就没有配置生成CONFIG_NAND_U_BOOT = y,应该和x210_sd.h有关。
否则就让LDSCRIPT等于$(TOPDIR)/board/$(BOARDDIR)/u-boot.lds,所以基于我们210的开发板这个变量的值应该是这个。这变量的值就是我们u-boot.lds这个链接脚本。我们用的链接脚本就是这个。
2、TEXT_BASE(config.mk中156行到158行)
这个环境变量是在我们的配置过程中,在主makefile中的2589行
x210_sd_config : unconfig
@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110
@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk
在使用x210_sd_config 进行配置时在$(obj)board/samsung/x210/目录下创建了一个配置文件,将TEXT_BASE = 0xc3e00000 写入到了里面。编译配置时生成的
这个变量在我们的config.mk中的128-130行被包含加载进来
ifdef BOARD
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk # include board specific rules
endif
所以在config.mk中的156行到158行就可以用这个变量了。
ifneq ($(TEXT_BASE),)
CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
endif
TEXT_BASE的值是将来我们整个uboot链接时指定的链接地址,因为我们的uboot启动了虚拟地址映射,所以这个0xc3e00000地址就是0x23e00000地址(也可能是其他的地址,具体的要看uboot中做的虚拟地址映射关系。)。
199 -201 行
ifneq ($(TEXT_BASE),)
LDFLAGS += -Ttext $(TEXT_BASE)
endif
这就是链接时的地址 -Ttext xxx 我们以前自己用的makefile中的那个东西
3、自动推到规则(config.mk 239 - 256行 )
$@ 自动变量,规则目标
$< 自动变量 规则依赖
还有个$^ 依赖的文件集合
uboot的主makefile的分析6
剩下部分的makefile
291行出现了我们第一个目标all
x210_sd_config : unconfig
@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110
@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk
这个目标是x210_sd_config 依赖是unconfig unconfig在后面也是一个目标,是为了让我们在配置好了一次后,还可以在进行配置
@$(MKCONFIG) MKCONFIG是一个脚本,是源目录下的mkconfig,静默编译,完了引用了这个脚本,并且带了六个参数后面。接下来就要这个脚本在运行时传这六个参数有什么作用了。
uboot配置过程详解1:
MKCONFIG在被主makefile的make x210_sd_config 这个目标时用到了,这是一个脚本,脚本时mkconfig传进去了六个参数
1、mkconfig脚本的六个参数
$(@:_config=)
arm
s5pc11x
x210
samsung
s5pc110
重要的是第一个参数、$(@:_config=)
我们知道$@结合起来是一个自动变量,是目标,所以是x210_sd_config这个东西,$(@:_config=) 意思就是将x210_sd_config 的_config替换成等号右面的东西,也就是替换成空,变成x210_sd
所以x210_sd是实际上的第一个参数
所以这个mkconfig脚本的参数
$1 x210_sd
$2 arm
$3 s5pc11x
$4 x210
$5 samsung
$6 s5pc110
所以$#=6,因为一共传了六个有效参数,$0是无效的参数,$0就是执行这个shell脚本。
2、分析mkconfig脚本(shell脚本就是打开一看就知了)
(1)其中14行-21行什么都没有做。
while [ $# -gt 0 ] ; do
case "$1" in
--) shift ; break ;;
-a) shift ; APPEND=yes ;;
-n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
*) break ;;
esac
done
因为我们的$1是x210_sd ,和*匹配上了,直接break跳出了while循环。
(2)23行
[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
因为脚本中BOARD_NAME这个变量开始定义为空,所以执行了BOARD_NAME="$1"这句话,所以BOARD_NAME变量等于x210_sd了
(3)25行和26行
[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1
我们的传参个数不小于4,也不大于6 所以都不执行exit 1(意思mkconfig脚本返回1 不在继续执行了)
所以mkconfig脚本传进去的参数必须是4个5个6个,如果不是,就不能继续执行这个脚本了
(4)执行到28行
echo "Configuring for ${BOARD_NAME} board..."
打印Configuring for x210_sd board...
(5)33行到49行
if [ "$SRCTREE" != "$OBJTREE" ] ; then
mkdir -p ${OBJTREE}/include
mkdir -p ${OBJTREE}/include2
cd ${OBJTREE}/include2
rm -f asm
ln -s ${SRCTREE}/include/asm-$2 asm
LNPREFIX="../../include2/asm/"
cd ../include
rm -rf asm-$2
rm -f asm
mkdir asm-$2
ln -s asm-$2 asm
else
cd ./include
rm -f asm
ln -s asm-$2 asm
fi
解析:
如果源目录和我们的编译输出目录不相等的话,级联创建文件夹,创建我们要输出到的目录,和目录下的两个inc
然后cd进去include2 文件夹中把asm文件夹删掉
然后将源目录下的include中的asm-arm 用符号链接成asm放在这个cd进来的目录(输出目标目录的include2下)
LNPREFIX这个变量赋值为../../include2/asm/
然后cd ../include 回到输出目标目录下进到include目录下
rm -rf asm-$2 强制删掉 asm-arm 文件夹
rm -f asm 删掉asm
mkdir asm-$2 创建 asm-arm文件
ln -s asm-$2 asm 将asm-arm文件符号链接成 asm
如果源目录和我们的输出目标目录相等的话
cd ./include 进到源目录下的include目录下
rm -f asm 删掉asm文件夹
ln -s asm-$2 asm 将asm-arm符号链接成asm
(6)49行到118行(和33行-49行的都是类似的)
都是创建符号链接一些相关的,包括mkconfig后面的很长的一部分都是跟创建符号链接相关的。
为什么要创建符号链接呢?这些符号链接的存在就我们配置过程的核心,这些符号链接(文件夹)的主要作用就是给头文件包含等过程提供指向性链接,根本目的是为了实现uboot的可移植性
(7)创建符号链接
在默认make的时候,源目录和输出目录是相同的情况下,
1)创建了第一个符号链接asm(46行到48行) 指向asm-arm目录 在源目录的include目录下
2)创建的第二个符号链接asm-arm目录下的arch符号链接 指向${LNPREFIX}arch-s5pc110 第56行(87行删掉了)
3)创建的第三个符号链接ln -s $6.h regs.h 第86行 regs.h指向s5pc110.h
4)创建的第四个符号链接ln -s arch-$3 asm-$2/arch 第88行 asm-arm/arch 指向arch-s5pc11x
5)创建的第五个符号链接ln -s ${LNPREFIX}proc-armv asm-$2/proc 第109行 asm-arm/proc指向proc-armv
总结:实际上创建了四个符号链接:1、源目录下的asm,指向源目录下的asm-arm
2、include/asm-arm/arch 指向include/asm-arm/arch-s5pc11x
3、include/regs.h 指向include/s5pc110.h
4、include/asm-arm/proc 指向include/asm-arm/proc-armv
这四个符号链接在将来头文件包含时非常有用,譬如:#include
uboot配置过程详解2:
1、第123行-129行 创建include/config.mk文件,
echo "ARCH = $2" > config.mk
echo "CPU = $3" >> config.mk
echo "BOARD = $4" >> config.mk
[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk
[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk
写入相关信息到config.mk中。
创建这个文件的作用是为了让主makefile在第133行包含进去这些信息,就是包含config.mk中的变量与值
2、134行到143行
if [ "$APPEND" = "yes" ] # Append to existing config file
then
echo >> config.h
else
> config.h # Create new config file
fi
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include
exit 0
如果APPEND不等于yes创建一个config.h文件。
在这里个文件中追加内容/* Automatically generated - do not edit */
和#include
这个x210_sd.h就是我们x210开发板移植时,宏定义配置文件。非常重要
x210_sd.h文件会生成一个autoconfig.mk文件,这个autoconfig.mk文件又会被我们主makefile引入,指导我们整个的编译过程,这个autoconfig.mk文件中的宏会影响我们整个uboot中大部分.c文件中的条件编译。这就是uboot可移植性的所在之处。这些宏是我们uboot中.c文件条件编译的开关,这些宏的值是在我们x210_sd.h中去设置的
超前的总结:uboot的配置应该就是为编译做准备,让一些配置先进行,和在配置过程中生成的值,将来在编译时会被用到。因为我们用的开发板是Inand版本的,所以移植的uboot是用make x210_sd_config进行配置的,先配置后在去编译。
总结:uboot的编译和配置的配合:配置是为了生成一些类似与ARCH=arm CPU=XXX 等相关信息的变量,这些变量的值将会指导我们uboot的编译,配置阶段就是为了给编译阶段提供这些变量。
uboot的链接脚本:($(TOPDIR)/board/$(BOARDDIR)/u-boot.lds)
1、OUTPUT_ARCH(arm) 架构是arm架构的
2、ENTRY(_start) 整个程序的入口地址,意思就是整个uboot开始时是从这个_start地址处开始运行的。
3、指定程序的链接地址有两种方法,一种是在我们makefile中的ld的flags用-Ttext 0x20000000来指定,
另一种方法就是在链接脚本中的SECTIONS开头的用 .=0x20000000来指定,两种方法都可以,但是当两种方法都存在的时候,都有的时候,-Ttext 指定的链接地址,会覆盖我们sections中的链接地址,所以u-bott.lds中的链接地址是0x00000000,因为我们之前的那个TEXT_BASE的值是我们链接地址,我们在用ld工具的flags时,会指定这链接地址,会覆盖链接脚本中的链接地址
4、
. = ALIGN(4); 链接地址强制成四字节对齐
5、
.text 代码段
在代码段中必须注意排列顺序,因为在我们启动过程中,uboot的前16KB是先被加载运行的,用来初始化一些东西。这个排列顺序放的代码就是uboot的那前16KB代码。
这里指定的排列顺序的文件,就是必须在uboot的中前16KB要做的任务的文件。这些文件中的函数会在uboot的前16KB被调用也就是被称为BL1代码的部分
而在第二部分(16KB以后的代码),文件的先后顺序就没有关系了,所以用*.(text)去匹配。也就是BL2代码的部分。
5、
.rodata 只读数据段
6、
.got 自定义的段
7、 .u_boot_cmd 自定义的段
8、 .mmudata 自定义的段
uboot的链接脚本中除了我们.text .data .rodata .bss 段,这些编译工具自带的段外,还允许我们自定义段
如:uboot链接脚本中的.u_boot_cmd 段就是定义段,很重要,后面会清楚