Uboot compile

  • 了解uboot 编译流程

1.uboot编译流程

1.1.编译生成文件
在这里插入图片描述

1.2.编译整体流程
在这里插入图片描述
2.编译流程分析

  编译时一般执行 make 或者 make all 命令进行编译。一般在根目录的 Makefile 中定义相应的编译命令。

1).入口分析

all:        $(ALL-y)
# Always append ALL so that arch config.mk's can add custom ones
ALL-y += u-boot.srec u-boot.bin u-boot.sym System.map binary_size_check
...
ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin 
ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.img
ALL-$(CONFIG_OF_HOSTFILE) += u-boot.dtb
ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb.img

2).u-boot.bin依赖关系

else ifeq ($(CONFIG_OF_SEPARATE),y)
u-boot-dtb.bin: u-boot-nodtb.bin dts/dt.dtb FORCE
    $(call if_changed,cat)

u-boot.bin: u-boot-dtb.bin FORCE
    $(call if_changed,copy)
else
u-boot.bin: u-boot-nodtb.bin FORCE
    $(call if_changed,copy)
endif

  如上所示,u-boot-dtb.bin是由命令cat将u-boot-nodtb.bin和dts/dt.dtb拼接而成,即

cat u-boot-nodtb.bin dts/dt.dtb > u-boot.dtb.bin

而u-boot.bin 是u-boot-nodtb.bin的拷贝。

3).u-boot-nodtb.bin依赖关系

u-boot-nodtb.bin: u-boot FORCE
        $(call if_changed,objcopy)
        $(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))
        $(BOARD_SIZE_CHECK)

4).u-boot 依赖关系

u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds FORCE
        $(call if_changed,u-boot__)
        
## $(call if_changed,u-boot__)对应cmd_u-boot__命令

  如上,u-boot依赖于$(u-boot-init) 、$(u-boot-main)和u-boot.lds,并且最终调用cmd_u-boot__来生成u-boot。 cmd_u-boot__实现如下 :

# Rule to link u-boot 
# May be overridden by arch/$(ARCH)/config.mk
quiet_cmd_u-boot__ ?= LD      $@                                                                            
      cmd_u-boot__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_u-boot) -o $@ \
      -T u-boot.lds $(u-boot-init)                             \
      --start-group $(u-boot-main) --end-group                 \
      $(PLATFORM_LIBS) -Map u-boot.map;                        \
      $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)

展开分析一下,在开头添加#,然后编译u-boot,输出如下:

u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds FORCE
    #+$(call if_changed,u-boot__) 
>#+ @set -e;  echo '  LD      u-boot'; aarch64-linux-gnu-ld.bfd   -pie  --gc-sections -Bstatic  --no-dynamic-linker ***-Ttext 0x00200000*** -o u-boot -T u-boot.lds arch/arm/cpu/armv8/start.o --start-group  arch/arm/cpu/built-in.o  arch/arm/cpu/armv8/built-in.o  arch/arm/lib/built-in.o  arch/arm/mach-rockchip/built-in.o  board/rockchip/evb_rk3399/built-in.o  cmd/built-in.o  common/built-in.o  disk/built-in.o  drivers/built-in.o  drivers/dma/built-in.o  drivers/gpio/built-in.o  drivers/i2c/built-in.o  drivers/mtd/built-in.o  drivers/mtd/onenand/built-in.o  drivers/mtd/spi/built-in.o  drivers/net/built-in.o  drivers/net/phy/built-in.o  drivers/power/built-in.o  drivers/power/battery/built-in.o  drivers/power/domain/built-in.o  drivers/power/fuel_gauge/built-in.o  drivers/power/mfd/built-in.o  drivers/power/pmic/built-in.o  drivers/power/regulator/built-in.o  drivers/serial/built-in.o  drivers/spi/built-in.o  drivers/usb/common/built-in.o  drivers/usb/dwc3/built-in.o  drivers/usb/emul/built-in.o  drivers/usb/eth/built-in.o  drivers/usb/host/built-in.o  drivers/usb/musb-new/built-in.o  drivers/usb/musb/built-in.o  drivers/usb/phy/built-in.o  drivers/usb/ulpi/built-in.o  env/built-in.o  fs/built-in.o  lib/built-in.o  net/built-in.o --end-group -L /home/zhaoxiao/Documents/work/tools/cross_tool_chain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1 -lgcc -Map u-boot.map;  true; printf '%s\n' 'cmd_u-boot := aarch64-linux-gnu-ld.bfd   -pie  --gc-sections -Bstatic  --no-dynamic-linker -Ttext 0x00200000 -o u-boot -T u-boot.lds arch/arm/cpu/armv8/start.o --start-group  arch/arm/cpu/built-in.o  arch/arm/cpu/armv8/built-in.o  arch/arm/lib/built-in.o  arch/arm/mach-rockchip/built-in.o  board/rockchip/evb_rk3399/built-in.o  cmd/built-in.o  common/built-in.o  disk/built-in.o  drivers/built-in.o  drivers/dma/built-in.o  drivers/gpio/built-in.o  drivers/i2c/built-in.o  drivers/mtd/built-in.o  drivers/mtd/onenand/built-in.o  drivers/mtd/spi/built-in.o  drivers/net/built-in.o  drivers/net/phy/built-in.o  drivers/power/built-in.o  drivers/power/battery/built-in.o  drivers/power/domain/built-in.o  drivers/power/fuel_gauge/built-in.o  drivers/power/mfd/built-in.o  drivers/power/pmic/built-in.o  drivers/power/regulator/built-in.o  drivers/serial/built-in.o  drivers/spi/built-in.o  drivers/usb/common/built-in.o  drivers/usb/dwc3/built-in.o  drivers/usb/emul/built-in.o  drivers/usb/eth/built-in.o  drivers/usb/host/built-in.o  drivers/usb/musb-new/built-in.o  drivers/usb/musb/built-in.o  drivers/usb/phy/built-in.o  drivers/usb/ulpi/built-in.o  env/built-in.o  fs/built-in.o  lib/built-in.o  net/built-in.o --end-group -L /home/zhaoxiao/Documents/work/tools/cross_tool_chain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1 -lgcc -Map u-boot.map;  true' > ./.u-boot.cmd

  可以看出上述是一条连接命令,以u-boot.lds为链接脚本,把$(u-boot-init) 、$(u-boot-main)的指定的目标文件连接到u-boot中,并且已经指定输出文件为u-boot。

  链接地址是由CONFIG_SYS_TEXT_BASE(configs/xxx_defconfig)定义的,该变量指定text segment的起始链接地址。即 -Ttext 0x00200000。

5).u-boot-init & u-boot-main依赖关系

u-boot-init=arch/arm/cpu/armv8/start.o
u-boot-main= arch/arm/cpu/built-in.o arch/arm/cpu/armv7/built-in.o arch/arm/lib/built-in.o arch/arm/mach-s5pc1xx/built-in.o board/samsung/common/built-in.o board/samsung/tiny210/built-in.o cmd/built-in.o common/built-in.o disk/built-in.o drivers/built-in.o drivers/dma/built-in.o drivers/gpio/built-in.o drivers/i2c/built-in.o drivers/mmc/built-in.o drivers/mtd/built-in.o drivers/mtd/onenand/built-in.o drivers/mtd/spi/built-in.o drivers/net/built-in.o drivers/net/phy/built-in.o drivers/pci/built-in.o drivers/power/built-in.o drivers/power/battery/built-in.o drivers/power/fuel_gauge/built-in.o drivers/power/mfd/built-in.o drivers/power/pmic/built-in.o drivers/power/regulator/built-in.o drivers/serial/built-in.o drivers/spi/built-in.o drivers/usb/common/built-in.o drivers/usb/dwc3/built-in.o drivers/usb/emul/built-in.o drivers/usb/eth/built-in.o drivers/usb/gadget/built-in.o drivers/usb/gadget/udc/built-in.o drivers/usb/host/built-in.o drivers/usb/musb-new/built-in.o drivers/usb/musb/built-in.o drivers/usb/phy/built-in.o drivers/usb/ulpi/built-in.o fs/built-in.o lib/built-in.o net/built-in.o test/built-in.o test/dm/built-in.o

  如上所示都是一堆目标文件的路径,这些目标文件最终都要被连接到u-boot中。
u-boot-init & u-boot-main的定义如下:

u-boot-init := $(head-y)                                                                                    
u-boot-main := $(libs-y)

arch/xxx/Makefile:
head-y := arch/arm/cpu/$(CPU)/start.o

libs-y += lib/
libs-y += fs/
libs-y += net/
libs-y += disk/
libs-y += drivers/
libs-y += drivers/dma/
libs-y += drivers/gpio/
libs-y += drivers/i2c/
...

u-boot-dirs     := $(patsubst %/,%,$(filter %/, $(libs-y))) tools examples
## 过滤出路径之后,加上tools目录和example目录

libs-y          := $(patsubst %/, %/built-in.o, $(libs-y)) 
## 先加上后缀built-in.o

u-boot-main := $(libs-y)

u-boot-init & u-boot-main生成依赖于u-boot-dirs:

$(sort $(u-boot-init) $(u-boot-main)): $(u-boot-dirs) ;

u-boot-dirs依赖规则如下:

PHONY += $(u-boot-dirs)
$(u-boot-dirs): prepare scripts
( Q ) (Q) (Q)(MAKE) ( b u i l d ) = (build)= (build)=@

对每一个目标文件依次执行make $(build)=目标文件 ,$(build)定义如下:

scripts/Kbuild.include
build := -f $(srctree)/scripts/Makefile.build obj

  scripts/Makefile.build定义built-in.o、.lib以及目标文件.o的生成规则。这个Makefile文件生成了子目录的.lib、built-in.o以及目标文件.o。Makefile.build第一个编译目标是__build,如下所示:

PHONY := __build
__build:

## 直接编译执行__build这个目标,其依赖如下:
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
         $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
         $(subdir-ym) $(always)
        @:
        
## 和built-in.o相关的是依赖builtin-target
builtin-target := $(obj)/built-in.o

$(builtin-target): $(obj-y) FORCE
        $(call if_changed,link_o_target)

目标文件的编译流程:

./scripts/Makefile.build:
# Built-in and composite module parts
$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
## 调用cmd_cc_o_c对.c文件进行编译

## cmd_cc_o_c格式如下:
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<

6).u-boot.lds依赖关系

u-boot.lds: $(LDSCRIPT) prepare FORCE
        $(call if_changed_dep,cpp_lds)
        
ifndef LDSCRIPT
        ifeq ($(wildcard $(LDSCRIPT)),)
                LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot.lds
        endif
        ifeq ($(wildcard $(LDSCRIPT)),)
                LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot.lds
        endif
        ifeq ($(wildcard $(LDSCRIPT)),)
                LDSCRIPT := $(srctree)/arch/$(ARCH)/cpu/u-boot.lds
        endif
endif

  依次从board/板级目录、cpudir目录、arch/架构/cpu/目录下去搜索u-boot.lds文件。

7). dts/dt.dtb依赖关系
  该依赖关系的主要目的是生成dtb文件,dt.dtb对应的命令如下,执行make dtbs 产生dtb文件。

Makefile:
PHONY += dtbs                                                                                               
dtbs: dts/dt.dtb
    @:
dts/dt.dtb: u-boot
    $(Q)$(MAKE) $(build)=dts dtbs

展开该命令:
@make -f ./scripts/Makefile.build obj=dts dtbs

如上所示:
  Make进入由参数-f指定的Make文件scripts/Makefile.build,并传入参数obj=build_dir 和argv。

  • $(MAKE) = make -f (-f mean read file as a makefile)
  • $(build) = ./scripts/Makefile.build obj = dts
  • $@ = dtbs

  此时./scripts/Makefile.build文件中src变量等于obj传入的值dts,然后include dts/Makefile.

src := $(patsubst $(prefix)/%,%,$(obj))

# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)

dts/Makefile:

DEVICE_TREE ?= $(CONFIG_DEFAULT_DEVICE_TREE:"%"=%)

  变量CONFIG_DEFAULT_DEVICE_TREE是在配置文件configs/xxx_defconfig中指定设备数镜像文件名。

CONFIG_DEFAULT_DEVICE_TREE="rk3399-firefly"

目标dtbs生成命令:

dts/Makefile
ifneq ($(EXT_DTB),)
DTB := $(EXT_DTB)
else
DTB := arch/$(ARCH)/dts/$(DEVICE_TREE).dtb
endif

$(obj)/dt-spl.dtb: $(DTB) $(objtree)/tools/fdtgrep FORCE
    $(call if_changed,fdtgrep)

$(obj)/dt.dtb: $(DTB) FORCE
    $(call if_changed,shipped)

targets += dt.dtb dt-spl.dtb

  如上所示,obj就是dts目录,生成dt.dtb和dt-spl.dtb分别调用命令:shipped和fdtgrep,这两个命令定义在./scripts/Makefile.lib文件中:

quiet_cmd_shipped = SHIPPED $@
cmd_shipped = cat $< > $@

$(obj)/%: $(src)/%_shipped
    $(call cmd,shipped)  

quiet_cmd_fdtgrep = FDTGREP $@
      cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \
        -n /chosen -n /config -O dtb | \
    $(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
        -P u-boot,dm-pre-reloc -P u-boot,dm-spl -P u-boot,dm-tpl \
        $(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))

shipped执行展开:

cat arch/arm/dts/rk3399-firefly.dtb > dts/dt.dtb

fdtgrep执行展开:

对arch/arm/dts/rk3399-firefly.dtb进行裁剪,然后输出到dts/dt-spl.dtb.

接下来看看生成dtb需要的依赖文件:

$(DTB): (dtb_depends)
ifeq ($(EXT_DTB),)
		$(Q)$(MAKE) $(build)=$(ARCH_PATH) dtbs
...
arch-dtbs:
    $(Q)$(MAKE) $(build)=$(ARCH_PATH) dtbs

通过如下设置,可以将此行展开,执行make dtbs 即可。

 #$(MAKE) $(build)=$(ARCH_PATH) dtbs

展开如下:

@make -f ./scripts/Makefile.build obj=arch/arm/dts arch/arm/dts/rk3399-firefly.dtb

其中dtb_depends为arch/arm/dts/rk3399-firefly.dts,ARCH_PATH为arch/arm/dts。最后arch/arm/dts/Makefile通过如下所示被include,该文件中定义了dtbs的目标。

arch-dtbs:                                                                                                                                                
    $(Q)$(MAKE) $(build)=arch/$(ARCH)/dts dtbs

而在scripts/Makefile.lib文件中定义dtb生成:

$(obj)/%.dtb: $(src)/%.dts FORCE                                                                            
    $(call if_changed_dep,dtc)

进入arch/arm/dts/Makefile,如下所示:

arch/arm/dts/Makefile:
dtb-$(CONFIG_S5PC110) += s5pc1xx-goni.dtb
dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \
        exynos5250-snow.dtb \
        exynos5250-spring.dtb \
        exynos5250-smdk5250.dtb \
        exynos5420-smdk5420.dtb \
        exynos5420-peach-pit.dtb \
        exynos5800-peach-pi.dtb \
        exynos5422-odroidxu3.dtb
dtb-$(CONFIG_TARGET_TINY210) += \
        s5pv210-tiny210.dtb
        
## 填充选择dtb-y
targets += $(dtb-y)

# Add any required device tree compiler flags here
DTC_FLAGS +=
## 用于添加DTC编译选项

PHONY += dtbs
dtbs: $(addprefix $(obj)/, $(dtb-y))     
        @:                               //表示什么都不做

3.SPL(u-boot-spl.bin) 编译流程

  The object files for SPL are built separately and placed in the “spl” directory. The final binaries which are generated are u-boot-spl, u-boot-spl.bin and u-boot-spl.map.

  A config option named CONFIG_SPL_BUILD is enabled by Kconfig for SPL.Source files can therefore be compiled for SPL with different settings.(doc/README.SPL)

3.1.编译生成文件
在这里插入图片描述

3.2.uboot-spl编译流程
在这里插入图片描述

  u-boot-spl.bin编译是编译uboot的一部分,和uboot.bin走的是两条编译流程。首先编译uboot.bin,再编译uboot-spl.bin,虽然编译命令是一起的,但是编译流程是分开的。通过CONFIG_SPL_BUILD宏来进行区分的:

scripts/Makefile.spl:
KBUILD_CPPFLAGS += -DCONFIG_SPL_BUILD

编译u-boot-spl使用脚本scripts/Makefile.spl :

Makefile:
spl/u-boot-spl.bin: spl/u-boot-spl
    @:
spl/u-boot-spl: tools prepare \                                                                             
        $(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb) \
        $(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_TPL_OF_PLATDATA),dts/dt.dtb)
    $(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all

修改为:

#$(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all

编译展开后为:

#@make obj=spl -f ./scripts/Makefile.spl all

类似u-boot.bin编译,ALL-y 包含编译目录:

scripts/Makefile.spl:
SPL_BIN := u-boot-spl

all:    $(ALL-y)
ALL-y   += $(obj)/$(SPL_BIN).bin 

  如下所示,编译u-boot-spl.bin:spl/u-boot-spl依赖于$(u-boot-spl-init) ,$(u-boot-spl-main),spl/u-boot-spl.lds,并且最终调用cmd_u-boot-spl来生成spl/u-boot-spl。

# Rule to link u-boot-spl
# May be overridden by arch/$(ARCH)/config.mk
quiet_cmd_u-boot-spl ?= LD      $@
      cmd_u-boot-spl ?= (cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
               $(patsubst $(obj)/%,%,$(u-boot-spl-init)) --start-group \
               $(patsubst $(obj)/%,%,$(u-boot-spl-main))  \
               $(patsubst $(obj)/%,%,$(u-boot-spl-platdata)) \
               --end-group \
               $(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN))                                          

$(obj)/$(SPL_BIN): $(u-boot-spl-platdata) $(u-boot-spl-init) \
        $(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
    $(call if_changed,u-boot-spl)

下面分别介绍一下这几个依赖关系:

  • u-boot-spl-init := $(head-y)
    • arch/arm/Makefile :head-y := arch/arm/cpu/$(CPU)/start.o
  • u-boot-spl-main := $(libs-y)
  • u-boot-spl.lds

  Because SPL images normally have a different text base, one has to be configured by defining CONFIG_SPL_TEXT_BASE. The linker script has to be defined with CONFIG_SPL_LDSCRIPT.

  • CONFIG_SPL_TEXT_BASE :SPL的入口地址
    • include/configs/xxx.h
  • CONFIG_SPL_LDSCRIPT :SPL的链接脚本

  如下所示,CONFIG_SPL_LDSCRIPT 指定spl链接脚本,定义在configs/xxx_defconfig中,如果没有定义,则依次从board/板级目录、cpudir目录、arch/架构/cpu/目录下去搜索u-boot-spl.lds文件。

configs/taurus_defconfig:
CONFIG_SPL_LDSCRIPT="arch/$(ARCH)/cpu/u-boot-spl.lds"

scripts/Makefiel.spl:
ifneq ($(CONFIG_SPL_LDSCRIPT),)
# need to strip off double quotes
LDSCRIPT := $(addprefix $(srctree)/,$(CONFIG_SPL_LDSCRIPT:"%"=%))
endif
endif

ifeq ($(wildcard $(LDSCRIPT)),)
    LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot-spl.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
    LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot-spl.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
    LDSCRIPT := $(srctree)/arch/$(ARCH)/cpu/u-boot-spl.lds
endif

同理编译u-boot-spl-nodtb.bin,u-boot-spl-dtb.bin。

$(obj)/$(SPL_BIN)-nodtb.bin: $(obj)/$(SPL_BIN) FORCE
    $(call if_changed,objcopy)    

ifneq ($(build_dtb),)
$(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \
        $(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \                                       
        $(FINAL_DTB_CONTAINER)  FORCE
    $(call if_changed,cat)

$(obj)/$(SPL_BIN).bin: $(obj)/$(SPL_BIN)-dtb.bin FORCE
    $(call if_changed,copy)
else
$(obj)/$(SPL_BIN).bin: $(obj)/$(SPL_BIN)-nodtb.bin FORCE
    $(call if_changed,copy)
endif

参考资料:
https://blog.csdn.net/ooonebook/article/details/52949584

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值