UBoot配置编译及Makefile分析
一、 UBoot配置编译初步分析
1. UBoot源码结构
(1)UBoot工程项目中的文件可以分为3类
① 第1类目录:与处理器体系结构或开发板硬件直接相关
② 第2类目录:一些通用的函数或驱动程序
③ 第3类目录:UBoot的应用程序、工具或文档
2. UBoot的配置编译
make <board_name>_config
make
3. UBoot的配置编译初步分析
(1)顶层目下的Makefile:每一种开发板在顶层Makefile中都有自己的配置规则
mini2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t mini2440 samsung s3c24x0
(2)执行make mini2440_config命令,将通过UBoot顶层目录下的mkconfig脚本生成配置文件include/config.mk
ARCH = arm
CPU = arm920t
BOARD = mini2440
VENDOR = samsung
SOC = s3c24x0
(3)而顶层目录的Makefile则包含了include/config.mk文件
# load ARCH, BOARD, and CPU configuration
include $(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC
(4)Makefile的编译选项和规则
① 各种体系结构通用的规则直接在顶层目录的config.mk文件中,通过ARCH、CPU、BOARD、SOC等变量为不同平台定义不同选项。
② 不同体系结构的规则分别包含在各自的lib_xxx目录下的config.mk文件中
(5)开发板配置头文件:移植时为开发板定义配置选项及参数,文件名为include/configs/<board_name>.h
#define CONFIG_ARM920T /* This is an ARM920T Core */
#define CONFIG_S3C24X0 /* in a SAMSUNG S3C24X0 SoC */
(6)编译结果
① 根据对Makefile的分析,编译分为两步:第1步配置,如make mini2440_config;第2步编译,执行make命令
② 编译完成后可得到UBoot的各种格式的映像文件和符号表
System.map:
u-boot:
u-boot.bin:
u-boot.srec:
(7)UBoot常用工具:编译完成后在tools目录下会生成一些常用工具
① bmp_logo
② img2srec
③ envcrc
④ mkimage
⑤ gen_eth_addr
⑥ updater
二、UBoot配置编译详细分析
1. 主机构建环境配置过程:顶层Makefile
(1)定义主机系统架构:HOSTARCH:=i386
HOSTARCH := $(shell uname -m | \
sed -e s/i./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/)
① “sed -e s/abc/def/”:表示从标准输入中查找内容为“abc”的字符串,然后替换为def。其中“abc”中可以用“.”作为通配符
② uname -m:输出主机CPU架构类型
(2)定义主机操作系统类型:HOSTOS:=linux
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
sed -e 's/\(cygwin\).*/cygwin/')
(3)定义脚本解释器:SHELL:=/bin/bash
SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
else if [ -x /bin/bash ]; then echo /bin/bash; \
else echo sh; fi; fi)
(4)设定编译输出目录:BUILD_DIR:=./
① 执行“make O=/tmp/build”命令可以将输出目录设置为特定目录
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
② 与UBoot源码目录和输出目录相关的变量
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE := $(CURDIR)
TOPDIR := $(SRCTREE)
LNDIR := $(OBJTREE)
2. 目标机相关配置过程
(1)顶层Makefie中与具体开发板相关的配置规则
mini2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t mini2440 samsung s3c24x0
其中依赖“unconfig”的定义如下
unconfig:
@rm -f $(obj)include/config.h $(obj)include/config.mk \
$(obj)board/*/config.tmp $(obj)board/*/*/config.tmp \
$(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep
unconfig的作用是清除上次执行make *_config命令产生的配置文件
(2)将具体开发板相关的配置规则替换变量后
./mkconfig mini2440 arm arm920t mini2440 samsung s3c24x0
也就是以“mini2440 arm arm920t mini2440 samsung s3c24x0”为参数执行mkconfig脚本
(3)mkconfig的用法
# Parameters: Target Architecture CPU Board [VENDOR] [SOC]
① 确定开发板名称:BOARD_NAME:=mini2440
while [ $# -gt ] ; do
case "$1" in
--) shift ; break ;;
-a) shift ; APPEND=yes ;;
-n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
-t) shift ; TARGETS="`echo $1 | sed 's:_: :g'` ${TARGETS}" ; shift ;;
*) break ;;
esac
done [ "${BOARD_NAME}" ] || BOARD_NAME="$1"
② 检查参数合法性
[ $# -lt ] && exit
[ $# -gt ] && exit if [ "${ARCH}" -a "${ARCH}" != "$2" ]; then
echo "Failed: \$ARCH=${ARCH}, should be '$2' for ${BOARD_NAME}" >&
exit
fi
③ 创建到目标板相关目录的链接
if [ "$SRCTREE" != "$OBJTREE" ] ; then
mkdir -p ${OBJTREE}/include
mkdir -p ${OBJTREE}/include2
cd ${OBJTREE}/include2
rm -f asm
ln -s ${SRCTREE}/include/asm-$ asm
LNPREFIX="../../include2/asm/"
cd ../include
rm -rf asm-$
rm -f asm
mkdir asm-$
ln -s asm-$ asm
else
cd ./include
rm -f asm
ln -s asm-$ asm
fi rm -f asm-$2/arch if [ -z "$6" -o "$6" = "NULL" ] ; then
ln -s ${LNPREFIX}arch-$3 asm-$2/arch
else
ln -s ${LNPREFIX}arch-$6 asm-$2/arch
fi if [ "$2" = "arm" ] ; then
rm -f asm-$2/proc
ln -s ${LNPREFIX}proc-armv asm-$2/proc
fi
④ 构建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
⑤ 构建include/config.h文件
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 for i in ${TARGETS} ; do
echo "#define CONFIG_MK_${i} 1" >>config.h ;
done cat << EOF >> config.h
#define CONFIG_BOARDDIR board/$BOARDDIR
#include <config_defaults.h>
#include <configs/$.h>
#include <asm/config.h>
EOF exit
(4)总结"make mini2440_config"的执行结果
① 创建到目标板相关文件的链接
ln -s asm-arm asm
ln -s arch-s3c24x0 asm-arm/arch
ln -s proc-armv asm-arm/proc
② 创建include/config.mk文件
ARCH = arm
CPU = arm920t
BOARD = mini2440
VENDOR = samsung
SOC = s3c24x0
③ 创建与目标板相关的头文件include/config.h
#define CONFIG_BOARDDIR board/samsung/mini2440
#include <config_defaults.h>
#include <configs/mini2440.h>
#include <asm/config.h>
3. make命令执行过程
(1)include/autoconf.mk生成过程
主Makefile开始部分,会包含如下头文件
sinclude $(obj)include/autoconf.mk.dep
sinclude $(obj)include/autoconf.mk
① include/autoconf.mk文件是与开发板相关的一些宏定义,在Makefile执行过程中,需要根据某些宏来确定执行哪些操作
② include/autoconf.mk的生成规则
$(obj)include/autoconf.mk: $(obj)include/config.h
@$(XECHO) Generating $@ ; \
set -e ; \
: Extract the config macros ; \
$(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \
sed -n -f tools/scripts/define2mk.sed > $@.tmp && \
mv $@.tmp $@
* 根据上面的规则,编译器提取额include/common.h中定义的宏,然后输出给tools/scripts/define2mk.sed脚本处理,处理的结果是生成include/autoconf.mk文件
* include/common.h中包含include/config,h文件,而include/config.h文件包含configs/mini2440、asm/config.h等文件
(2)config.mk执行过程:
主Makefile中接着将由make mini2440_config生成的config.mk文件包含进来
# load ARCH, BOARD, and CPU configuration
include $(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC
① 设置obj与src
ifneq ($(OBJTREE),$(SRCTREE))
ifeq ($(CURDIR),$(SRCTREE))
dir :=
else
dir := $(subst $(SRCTREE)/,,$(CURDIR))
endif obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/)
src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/) $(shell mkdir -p $(obj))
else
obj :=
src :=
endif
② 设置编译选项:下面3个变量表示交叉编译选项
PLATFORM_RELFLAGS =
PLATFORM_CPPFLAGS =
PLATFORM_LDFLAGS =
* 变量CC和CFLAGS将会在后面的代码中定义。
* 函数cc-option用于检查编译器CC是否支持某选项,定义如下
cc-option = $(shell if $(CC) $(CFLAGS) $() -S -o /dev/null -xc /dev/null \
> /dev/null >&; then echo "$(1)"; else echo "$(2)"; fi ;)
* 函数cc-option使用示例
FLAGS += $(call cc-option, option1, option2)
③ 指定交叉编译工具
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
* 对于arm开发板,CROSS_COMPILE定义于lib_arm/config.mk文件中
CROSS_COMPILE ?= arm-linux-
④ 包含与开发板相关的配置文件
* 包含文件lib_arm/config.mk:该文件中指定了交叉编译前缀,添加了一些与CPU架构相关的编译选项,最后还指定了UBoot的连接器脚本cpu/arm920t/u-boot.lds
ifdef ARCH
sinclude $(TOPDIR)/lib_$(ARCH)/config.mk # include architecture dependend rules
endif
* 包含文件cpu/arm920t/config.mk
* 包含文件cpu/arm920t/s3c24x0/config.mk
* 包含文件board/samsung/mini2440/config.mk:TEXT_BASE定义于此文件中
⑤ 指定隐含的编译规则:
# Allow boards to use custom optimize flags on a per dir/file basis
BCURDIR := $(notdir $(CURDIR))
$(obj)%.s: %.S
$(CPP) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $<
$(obj)%.o: %.S
$(CC) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $< -c
$(obj)%.o: %.c
$(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
$(obj)%.i: %.c
$(CPP) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
$(obj)%.s: %.c
$(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c -S
4. UBoot镜像生成过程
(1)顶层Makefile定义了LIBS变量,用以指明UBoot需要的库文件
LIBS = lib_generic/libgeneric.a
LIBS += lib_generic/lzma/liblzma.a
LIBS += lib_generic/lzo/liblzo.a
(2)下面的代码定义了Makefile第一个目标all的依赖
# Always append ALL so that arch config.mk's can add custom ones
ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND) all: $(ALL) $(obj)u-boot.hex: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ $(obj)u-boot.srec: $(obj)u-boot
$(OBJCOPY) -O srec $< $@ $(obj)u-boot.bin: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
(3)uboot文件的生成规则
$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
$(GEN_UBOOT)
ifeq ($(CONFIG_KALLSYMS),y)
smap=`$(call SYSTEM_MAP,u-boot) | \
awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "\\\\000"}'` ; \
$(CC) $(CFLAGS) -DSYSTEM_MAP="\"$${smap}\"" \
-c common/system_map.c -o $(obj)common/system_map.o
$(GEN_UBOOT) $(obj)common/system_map.o
endif
① depend 依赖:
② (SUBDIRS)依赖:
③ (OBJS)依赖
④ (LIBBOARD)依赖
⑤ (LIBS)依赖
⑥ (LDSCRIPT)依赖
⑦ (obj)u-boot.lds依赖
(4)编译生成u-boot镜像的命令GEN_UBOOT
GEN_UBOOT = \
UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
-Map u-boot.map -o u-boot
① 第一部分:
UNDEF_SYM=`arm-linux-objdump -x board/samsung/mini2440/libmini2449.a... | \
sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
替换相应变量后
UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
将编译u-boot所生成的库中包含__u_boot_cmd_的所有标号,替换为-u__u_boot_cmd_形式的标号,排序(sort),并保证唯一(uniq),然后将所有这样的标号组成的字符串赋值给UNDEF_SYM
②第二部分:
cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
-Map u-boot.map -o u-boot
替换相应变量后
cd $(OBJTREE) && arm-linux-ld -Bstatic -T u-boot.lds -Ttext 0x33F80000 $UNDEF_SYM
cpu/arm920t/start.o --start-group lib_generic/libgeneric.a ... board/samsung/
mini2440/libmini2440.a --end-group ... -Map u-boot.map -o u-boot
(5)从ELF文件u-boot中提取二进制文件u-boot.bin
$(obj)u-boot.bin: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
替换变量后
$(obj)u-boot.bin: $(obj)u-boot
arm-linux-objcopy --gap-fill=0xff -O binary u-boot uboot.bin
后记:以上分析基于uboot2010.03版本,后续版本中的Makefile组织可能会略有不同
UBoot配置编译及Makefile分析的更多相关文章
- (九)uboot配置编译、源码分析
一.X210官方uboot配置编译实践1.找到官方移植好的uboot(BSP概念)(1)源头的源代码是uboot官网下载的.这个下载的源代码可能没有你当前使用的开发板的移植,甚至找不到当前开发板使用的 ...
- uboot主Makefile分析(t配置和编译过程详解)
1.编译uboot前需要三次make make distcleanmake x210_sd_configmake -j4 make distclean为清楚dist文件. make x210_sd_c ...
- Linux内核配置、编译及Makefile简述
Hi,大家好!我是CrazyCatJack.最近在学习Linux内核的配置.编译及Makefile文件.今天总结一下学习成果,分享给大家^_^ 1.解压缩打补丁 首先是解压缩你获取到的Linux内核. ...
- 嵌入式Linux驱动学习之路(三)u-boot配置分析
u-boot配置流程分析 执行make tiny4412_config后,将会对u-boot进行一些列的配置,以便于后面的编译. 打开顶层目录下的Makefile,查找对于的规则tiny4412_co ...
- U-Boot Makefile分析(5)主控Makefile分析
这次分析源码根目录下的Makefile,它负责读入配置过的信息,通过OBJS.LIBS等变量设置能够参与镜像链接的目标文件,设定编译的目标等等. HOSTARCH := $(shell uname - ...
- uboot主Makefile分析
VERSION = 1 PATCHLEVEL = 3 SUBLEVEL = 4 EXTRAVERSION = U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(S ...
- u-boot剖析(一)----Makefile分析
由于u-boot比较庞大,所以我们分开来分析,对于一个大型的项目我们想快速的了解其代码架构和内容,最方便的方法就是分析Makefile,所以我们今天以三星的s3c2440来分析Makefile.我们今 ...
- TQ210 —— S5PV210 uboot顶层Makefile分析
转自:http://blog.csdn.net/wqx521/article/details/52469759 # (C) Copyright 2000-2008 # Wolfgang Denk, D ...
- uboot配置和编译过程详解【转】
本文转载自:http://blog.csdn.net/czg13548930186/article/details/53434566 uboot主Makefile分析1 1.uboot version ...
随机推荐
- Flutter不能做什么:局限性
老孟导读:您在网络上一定看过很多Flutter如何优秀的.如何完美的文章,而这篇文章将会告诉你Flutter不能做什么,注意并不是Flutter的缺点,比如第三方插件少.Dart不流行等,在我看来这都 ...
- python迭代器,生成器
1. 迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器的一大 ...
- python函数总结,你值得拥有
目录 函数总结 函数定义与结构 函数名的使用 函数的参数 名称空间与作用域 名称空间 作用域 函数嵌套 内置函数(globals( ),locals( )) global+nonlocal 可迭代对象 ...
- 【scrapy运行姿势】scrapy.cmdline.execute
scrapy.cmdline.execute scrapy的cmdline命令 1.启动爬虫的命令为:scrapy crawl (爬虫名) 2.还可以通过以下方式来启动爬虫 方法一:创建一个.py文件 ...
- 【NLP】老司机带你入门自然语言处理
自然语言处理是一门用于理解人类语言.情感和思想的技术,被称为是人工智能皇冠上的明珠. 随着深度学习发展,自然语言处理技术近年来发展迅速,在技术上表现为BERT.GPT等表现极佳的模型:在应用中表现为c ...
- AspectJ JoinPoint及ProceedingJoinPoint 简要api文档
AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点 ...
- ATX-UI自动化环境搭建
基础环境准备(以下都是在Mac机上搭建的) 1.android sdk安装&配置 很完美的一个资源下载网:tools.android-studio.org,下载所需的包(我下的zip包直接解压 ...
- Bank5
Account: package banking5; //账户 public class Account { protected double balance; public Account(doub ...
- Pytorch写CNN
用Pytorch写了两个CNN网络,数据集用的是FashionMNIST.其中CNN_1只有一个卷积层.一个全连接层,CNN_2有两个卷积层.一个全连接层,但训练完之后的准确率两者差不多,且CNN_1 ...
- 用Python做词云可视化带你分析海贼王、火影和死神三大经典动漫
对于动漫爱好者来说,海贼王.火影.死神三大动漫神作你肯定肯定不陌生了.小编身边很多的同事仍然深爱着这些经典神作,可见"中毒"至深.今天小编利用Python大法带大家分析一下这些神作 ...