u-boot配置和编译过程详解

备注:分析的是OK210开发板自带的uboot_smdkv210,可能有些部分和其他版本不太一样,但是原理都类似。

编译u-boot的步骤

make forlinx_linux_config
make

首先生成配置文件,然后编译源码,依次看看这些命令都干了些什么事情

配置过程

#forlinx add
forlinx_linux_config :  unconfig
    @$(MKCONFIG) $(@:_config=) arm s5pc11x smdkc110 samsung s5pc110 linux
    @echo "TEXT_BASE = 0xcc800000" > $(obj)board/samsung/smdkc110/config.mk

清除上一次配置的文件

此目标依赖unconfig目标,因此先调用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         $(obj)board/$(VENDOR)/$(BOARD)/config.mk

执行的操作主要是删除上一次配置生成的配置文件。

开始配置操作

在Makefile中以@开头的命令表示,在命令执行的时候不在终端上打印信息。

$(MKCONFIG)变量在Makefile的101行有定义,如下:

MKCONFIG    := $(SRCTREE)/mkconfig
export MKCONFIG

$(@:_config=)这句话的意思是将 forlinx_linux_config的_config用空白代替只剩下forlinx_linux,

其中$(srcfiles:xxx=ccc)是Makefile的规则,用等号后边的ccc替代srcfiles中等号前边的xxx,

$(@) = [email protected] 代表目标,即在命令行输入的make forlinx_linux_config中的forlinx_linux_config。

因此@$(MKCONFIG) $(@:_config=) arm s5pc11x smdkc110 samsung s5pc110 linux

的意思就是调用u-boot根目录的mkconfig脚本并将 forlinx_linux arm s5pc11x smdkc110 samsung s5pc110 linux作为参数传递给脚本。

mkconfig文件

在文件的头部的注释已经交代了文件的作用和调用的格式

# Script to create header files and links to configure
# U-Boot for a specific board.
#
# Parameters:  Target  Architecture  CPU  Board [VENDOR] [SOC]
#

$0 = mkconfig (脚本文件名)
$1 = Target (目标) forlinx_linux
$2 = Architecture  (架构) arm
$3 = CPU   (CPU型号)s5pc11x
$4 = Board  (开发板名)smdkc110
$5 = VENDOR (生产商)samsung
$6 = SOC (芯片名)s5pc110 

最后一个linux是OK210的工程师自己添加的用于区别android版本的内核和linux的内核,没有什么实质用途。(个人猜测)

APPEND=no   # Default: Create new config file
BOARD_NAME=""   # Name to print in make output

while [ $# -gt 0 ] ; do
    case "$1" in
    --) shift ; break ;;
    -a) shift ; APPEND=yes ;;
    -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
    *)  break ;;
    esac
done

接下来定义了两个变量为后边配置过程做准备,用途注释已经写的很清楚,APPEND=no是表示需要重新创建配置文件的标志。

再然后循环:如果参数个数大于零就执行循环,然后再循环里判断第一个参数(脚本可以有参数选项),很明显都不符合,所以直接跳出循环。

[ "${BOARD_NAME}" ] || BOARD_NAME="$1"

[ $# -lt 4 ] && exit 1
[ $# -gt 7 ] && exit 1

echo "Configuring for ${BOARD_NAME} board..."

将BOARD_NAME赋值为forlinx_linux,然后判断参数个数,小于4大于7(一般情况为大于6应该还是OK210的工程师修改了)就直接退出脚本,放弃执行。

创建软连接

接下来创建很多链接文件,这些操作是mkconfig脚本的主要工作,主要创建的链接文件如下:

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

./include/asm --> asm-$2 (asm-arm)

# create link for s5pc11x SoC
if [ "$3" = "s5pc11x" ] ; then
        rm -f regs.h
        ln -s $6.h regs.h
        rm -f asm-$2/arch
        ln -s arch-$3 asm-$2/arch
fi

regs.h --> $6.h (s5pc110.h)

asm-$2/arch --> arch-$3(arch-s5pc11x)

u-boot支持很多种开发板,很多种类型的CPU,所以要有一种通用得配置方式来方便移植;
u-boot甚至linux内核都采用了这种方式:针对不同的处理器或者板子都有自己的头文件和文件夹,但是真正的编译过程却不直接使用,而是在配置阶段创建这些头文件或者文件夹的软连接,并命名为一种通用的名字。在编译的时候通过这些软连接访问真正需要的文件。
例如,在u-boot的include目录下有一个asm的目录,此目录就是在配置完后生成的一个软连接,当配置的是arm架构时,此文件是asm-arm的软连接。

创建make时用到的包含文件 config.mk

#
# Create include file for Make
#
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.h

#
# Create board specific header file
#
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

#forlinx add
if [ "$7" = "linux" ]
then
    echo "#define CONFIG_LINUX_FORLINX  1" >>config.h
else
    echo "#define CONFIG_ANDROID_FORLINX 1" >>config.h
fi

#echo "#include <configs/$1.h>" >>config.h
#forlinx change  for linux and android
echo "#include <configs/smdkv210single.h>" >>config.h

因为上边已经把APPEND设置为NO,所以执行> config.h 即创建config.h头文件,并向config.h中写入

/* Automatically generated - do not edit */

"#define CONFIG_LINUX_FORLINX 1

以及#include <configs/smdkv210single.h>

同样是OK210的工程师加入的

#include <configs/$1.h>#include <configs/forlinx_linux.h>

注意:创建软连接的操作全都是在u-boot根目录的include子目录中执行的。

配置脚本mkconfig结束。

mkconfig脚本小结

一共创建了三个连接文件,

./include/asm --> asm-$2 (asm-arm)

regs.h --> $6.h (s5pc110.h)

asm-$2/arch --> arch-$3(asm-arm -> arch-s5pc11x)

以及include/config.mk和include/config.h,其中include/config.mk文件中记录着u-boot的版本信息,include/config.h中包含了 configs/$1.h,此文件里记录着是很多很多以CONFIG_开头的宏,是开发板u-boot的主配置信息。

主Makefile

版本号相关

VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 4
EXTRAVERSION =
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h

Makefile刚开始的时候仍然是定义当前使用的u-boot的版本,此版本和linux内核版本类似都由多个字段组成,各字段意义如下:

VERSION : 主版本号

PATCHLEVEL :次版本号

SUBLEVEL : 修正版本号

EXTRAVERSION:扩展版本号 (可以自己定义,用于区别自己移植的版本号 )

U_BOOT_VERSION 就是以上几个字段的组合字符串。

VERSION_FILE 保存的是u-boot版本号的文件,其中obj变量在后边定义。version_autogenerated.h文件也在后边生成(此文件不是u-boot源码目录本身有的文件,是由配置过程自动生成的),其内容如下:

#define U_BOOT_VERSION "U-Boot 1.3.4"

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/)

HOSTOS := $(shell uname -s | tr ‘[:upper:]‘ ‘[:lower:]‘ |         sed -e ‘s/\(cygwin\).*/cygwin/‘)

export  HOSTARCH HOSTOS

这一段话是检测编译时主机的架构和操作系统,其中使用了sed工具进行了相应的处理,

sed -e s/i.86/i386/ 意思就是不管是i686\i386还是i586,都用i386替代。

tr ‘[:upper:]‘ ‘[:lower:]‘的意思是将操作系统名字中可能存在的大写字母全部转换为小写字母。

笔者用的是i686的Linux操作系统,因此执行的结果是 HOSTARCH=i386, HOSTOS=linux,

最后调用export导出为环境变量供其他地方使用。

静默编译

所谓静默编译就是在编译的时候不打印任何信息(错误和警告信息除外)。

# Allow for silent builds
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO = echo
else
XECHO = :
endif

这段代码的意思是,在执行make时输入的参数中搜索’s’,如果有的话就给XECHO赋值为echo,否则就赋值为空,然后在其他地方用XECHO来打印信息,就实现了是否启用静默编译。

make -s就启用了静默编译。

指定目录编译

u-boot除了支持静默编译外还支持在不同目录进行编译,即将配置过程生成的文件以及编译产生的中间文件全都输出到一个指定的目录,从而避免污染源码目录。

从56-76的注释中可以看出有两种方式指定

1、在命令行通过make O=/tmp/build 指定输出目录为/tmp/build

2、指定BUILD_DIR=/tmp/build环境变量

注意:通过阅读根目录下的README文件,如果要在其他目录进行编译,在配置阶段和编译阶段都要指定输出的目录位置,如下:

1. Add O= to the make command line invocations:

    make O=/tmp/build distclean
    make O=/tmp/build NAME_config
    make O=/tmp/build all

2. Set environment variable BUILD_DIR to point to the desired location:

    export BUILD_DIR=/tmp/build
    make distclean
    make NAME_config
    make all

Makefile中的78-93行完成工作就是,如果指定了O参数,就判断O后边指定的目录存在不存在,如果不存在就创建,并把指定的路径赋值给BUILD_DIR变量 ——

然后就是给几个下边变量赋值

OBJTREE     := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))    //输出目录
SRCTREE     := $(CURDIR)                                                            //源码目录
TOPDIR      := $(SRCTREE)                                                                //顶层目录(源码根目录)
LNDIR       := $(OBJTREE)                                                                //链接目录
export  TOPDIR SRCTREE OBJTREE                                               //导出为环境变量

MKCONFIG    := $(SRCTREE)/mkconfig                                               //mkconfig配置脚本的路径
export MKCONFIG                                                                                   //导出为环境变量

然后是编译要用的$(obj) 和$(src)

# $(obj) and (src) are defined in config.mk but here in main Makefile
# we also need them before config.mk is included which is the case for
# some targets like unconfig, clean, clobber, distclean, etc.
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src

如果编译输出目录和源码目录不是通一个目录,就将源码目录的路径赋值给$(src),将输出的路径赋值给$(obj)。

否则就置空。

确定目标架构和交叉编译工具

从124行开始一直到182行都是在确定要使用的交叉编译工具。

其中在133行的时候导入了一个配置文件

# load ARCH, BOARD, and CPU configuration
include $(obj)include/config.mk
export  ARCH CPU BOARD VENDOR SOC

$(obj)include/config.mk此文件在执行mkconfig脚本的时候生成,里边保存着开发板以及CPU的型号和架构信息

ARCH   = arm
CPU    = s5pc11x
BOARD  = smdkc110
VENDOR = samsung
SOC    = s5pc110

然后再将这些信息导出为环境变量。

ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux-
endif
export  CROSS_COMPILE

再然后就是指定交叉编译工具,并将CROSS_COMPILE导出为环境变量了。

此外

在185行导入了U-boot根目录下的config.mk文件

# load other configuration
include $(TOPDIR)/config.mk

此文件主要完成以下工作

1、定义交叉编译工具,例如 CC=arm-linux-gcc, LD=arm-linux-ld等等。

2、导入配置文件

$(OBJTREE)/include/autoconf.mk

$(TOPDIR)/$(ARCH)_config.mk

$(TOPDIR)/cpu/$(CPU)/config.mk

$(TOPDIR)/cpu/$(CPU)/$(SOC)/config.mk

$(VENDOR)/$(BOARD)

$(TOPDIR)/board/$(BOARDDIR)/config.mk

3、编译选项相关的一大坨,一般不用管

4、make的自动推导规则

定义u-boot编译的目标

OBJS是编译时的目标

LIBS是依赖的库

此外还有GCC的库等等

ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND) $(obj)u-boot.dis
ifeq ($(ARCH),blackfin)
ALL += $(obj)u-boot.ldr

第一个目标all

all:        $(ALL)
时间: 2024-11-06 03:55:40

u-boot配置和编译过程详解的相关文章

uboot主Makefile分析(t配置和编译过程详解)

1.编译uboot前需要三次make make distcleanmake x210_sd_configmake -j4 make distclean为清楚dist文件. make x210_sd_config  跳转执行mkconfig用来配置并生成config.mk(board/samsung/x210目录下为指定链接地址的与主uboot目录的config.mk不同) autuconfig.mk 2.框图 3.uboot主Makefile分析 3.1.uboot version确定(Make

uboot配置和编译过程详解【转】

本文转载自:http://blog.csdn.net/czg13548930186/article/details/53434566 uboot主Makefile分析1 1.uboot version确定(Makefile的24-29行) Makefile代码部分: [plain] view plain copy VERSION = 1 PATCHLEVEL = 30 SUBLEVEL = 4 EXTRAVERSION = U_BOOT_VERSION = $(VERSION).$(PATCHL

2.4、uboot配置和编译过程详解

2.4.1.uboot主Makefile分析1 2.4.1.1.uboot version分析 (1)uboot版本号分为3个级别: VERSION:主版本号 PATCHLEVEL:次版本号 SUBLEVEL:再次版本号 EXTRAVERSION:另外附加的版本信息 这四个用.隔开共同构成了最终的版本号. (2)Makefile中版本号最终生成了一个变量U_BOOT_VERSION,这个变量记录了Makefile中配置的版本号 (3)include/version_autogenerated.h

uboot配置和编译过程详解

一.uboot主Makefile分析 1.uboot version确定(Makefile的24-29行) include/version_autogenerated.h文件是编译过程中自动生成的一个文件,所以源目录中没有,但是编译过后的uboot中就有了 2.HOSTARCH和HOSTOS HOSTARCH:表示主机的CPU的架构,值会影响后面的CROSS_COMPILE环境变量的值.HOSTOS:主机 3.静默编译(50-54行) 不希望看到这些编译信息,就后台编译即可.这就叫静默编译. 4

反编译过程详解

这段时间在学Android应用开发,在想既然是用Java开发的应该很好反编译从而得到源代码吧,google了一下,确实很简单,以下是我的实践过程. 在此郑重声明,贴出来的目的不是为了去破解人家的软件,完全是一种学习的态度,不过好像通过这种方式也可以去汉化一些外国软件. 一.反编译Apk得到Java源代码首先要下载两个工具:dex2jar和JD-GUI 前者是将apk中的classes.dex转化成Jar文件,而JD-GUI是一个反编译工具,可以直接查看Jar包的源代码. dex2jar和JD-G

Spring Boot 配置加载顺序详解

使用 Spring Boot 会涉及到各种各样的配置,如开发.测试.线上就至少 3 套配置信息了.Spring Boot 可以轻松的帮助我们使用相同的代码就能使开发.测试.线上环境使用不同的配置. 在 Spring Boot 里面,可以使用以下几种方式来加载配置.本章内容基于 Spring Boot 2.0 进行详解. 1.properties文件: 2.YAML文件: 3.系统环境变量: 4.命令行参数: 等等-- 我们可以在 Spring Beans 里面直接使用这些配置文件中加载的值,如:

Linux LVM逻辑卷配置过程详解

Linux LVM逻辑卷配置过程详解 许多Linux使用者安装操作系统时都会遇到这样的困境:如何精确评估和分配各个硬盘分区的容量,如果当初评估不准确,一旦系统分区不够用时可能不得不备份.删除相关数据,甚至被迫重新规划分区并重装操作系统,以满足应用系统的需要. LVM是Linux环境中对磁盘分区进行管理的一种机制,是建立在硬盘和分区之上.文件系统之下的一个逻辑层,可提高磁盘分区管理的灵活性.RHEL5默认安装的分区格式就是LVM逻辑卷的格式,需要注意的是/boot分区不能基于LVM创建,必须独立出

使用HeartBeat实现高可用HA的配置过程详解

使用HeartBeat实现高可用HA的配置过程详解 一.写在前面 HA即(high available)高可用,又被叫做双机热备,用于关键性业务.简单理解就是,有2台机器 A 和 B,正常是 A 提供服务,B 待命闲置,当 A 宕机或服务宕掉,会切换至B机器继续提供服务.常见的实现高可用的开源软件有 heartbeat 和 keepalived. 这样,一台 web 服务器一天24小时提供web服务,难免会存在 web 服务挂掉或服务器宕机宕机的情况,那么用户就访问不了服务了,这当然不是我们期望

Nginx实现集群的负载均衡配置过程详解

Nginx实现集群的负载均衡配置过程详解 Nginx 的负载均衡功能,其实实际上和 nginx 的代理是同一个功能,只是把代理一台机器改为多台机器而已. Nginx 的负载均衡和 lvs 相比,nginx属于更高级的应用层,不牵扯到 ip 和内核的修改,它只是单纯地把用户的请求转发到后面的机器上.这就意味着,后端的 RS 不需要配置公网. 一.实验环境 Nginx 调度器 (public 172.16.254.200 privite 192.168.0.48)RS1只有内网IP (192.168