http://blog.csdn.net/ooonebook/article/details/52949584
以下例子都以project X項目tiny210(s5pv210平台,armv7架構)為例
[uboot] uboot流程系列:
[project X] tiny210(s5pv210)上電啟動流程(BL0-BL2)
建議先看《[project X] tiny210(s5pv210)上電啟動流程(BL0-BL2)》,根據例子了解一下上電之后的BL0\BL1\BL2階段,以及各個階段的運行位置,功能。
=================================================================================
一、uboot-spl編譯和生成文件
spl的編譯是編譯uboot的一部分,和uboot.bin走的是兩條編譯流程,這個要重點注意。
正常來說,會先編譯主體uboot,也就是uboot.bin.再編譯uboot-spl,也就是uboot-spl.bin,雖然編譯命令是一起的,但是編譯流程是分開的。
1、編譯方法
在project X項目中,所有鏡像,包括uboot、kernel、rootfs都是放在build目錄下進行編譯的。具體去參考該項目build的Makefile的實現。
假設config已經配置完成,在build編譯命令如下:
make uboot
Makefile中對應的命令如下:
BUILD_DIR=$(shell pwd) OUT_DIR=$(BUILD_DIR)/out UBOOT_OUT_DIR=$(OUT_DIR)/u-boot UBOOT_DIR=$(BUILD_DIR)/../u-boot uboot: mkdir -p $(UBOOT_OUT_DIR) make -C $(UBOOT_DIR) CROSS_COMPILE=$(CROSS_COMPILE) KBUILD_OUTPUT=$(UBOOT_OUT_DIR) $(BOARD_NAME)_defconfig make -C $(UBOOT_DIR) CROSS_COMPILE=$(CROSS_COMPILE) KBUILD_OUTPUT=$(UBOOT_OUT_DIR) ## -C $(UBOOT_DIR) 指定了要在../uboot,也就是uboot的代碼根目錄下執行make ## CROSS_COMPILE=$(CROSS_COMPILE) 指定了交叉編譯器 ## KBUILD_OUTPUT=$(UBOOT_OUT_DIR) 指定了最終編譯的輸出目錄是build/out/u-boot.
最終,相當於進入了uboot目錄執行了make動作。
也就是說spl的編譯是編譯uboot的一部分,和uboot.bin走的是兩條編譯流程,這個要重點注意。
正常來說,會先編譯主體uboot,也就是uboot.bin.再編譯uboot-spl,也就是uboot-spl.bin,雖然編譯命令是一起的,但是編譯流程是分開的。
2、生成文件
最終編譯完成之后,會在project-x/build/out/u-boot/spl下生成如下文件:
arch common dts include u-boot-spl u-boot-spl.cfg u-boot-spl.map board drivers fs tiny210-spl.bin u-boot-spl.bin u-boot-spl.lds u-boot-spl-nodtb.bin
其中,arch、common、dts、include、board、drivers、fs是對應代碼的編譯目錄,各個目錄下都會生成相應的built.o,是由同目錄下的目標文件連接而成。
重點說一下以下幾個文件:
文件 | 說明 |
---|---|
u-boot-spl | 初步鏈接后得到的spl文件 |
u-boot-spl-nodtb.bin | 在u-boot-spl的基礎上,經過objcopy去除符號表信息之后的可執行程序 |
u-boot-spl.bin | 在不需要dtb的情況下,直接由u-boot-spl-nodtb.bin復制而來,也就是編譯spl的最終目標 |
tiny210-spl.bin | 由s5pv210平台決定,需要在u-boot-spl.bin的基礎上加上16B的header用作校驗 |
u-boot-spl.lds | spl的連接腳本 |
u-boot-spl.map | 連接之后的符號表文件 |
u-boot-spl.cfg | 由spl配置生成的文件 |
二、uboot-spl編譯流程
1、編譯整體流程
根據零、2生成的文件說明可知簡單流程如下:
(1)各目錄下built-in.o的生成
對應二、2(5)的實現
(2)由所有built-in.o以u-boot-spl.lds為連接腳本通過連接來生成u-boot-spl
對應二、2(4)的實現
(3)由u-boot-spl生成u-boot-spl-nodtb.bin
對應二、2(3)的實現
(4)由u-boot-spl-nodtb.bin生成u-boot-spl.bin,也就是spl的bin文件
對應二、2(2)的實現
后續的編譯的核心過程就是按照上述的四個編譯流程就是按照上述四個步驟來的。
2、具體編譯流程分析
我們直接從make uboot命令分析,也就是從uboot下的Makefile的依賴關系來分析整個編譯流程。
注意,這個分析順序和上述的整體編譯流程的順序是反着的。
- (1)入口分析
在project-x/u-boot/Makefile中
all: $(ALL-y)
ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin
## 當配置了CONFIG_SPL,make的時候就會執行spl/u-boot-spl.bin這個目標 spl/u-boot-spl.bin: spl/u-boot-spl @: spl/u-boot-spl: tools prepare $(if $(CONFIG_OF_SEPARATE),dts/dt.dtb) $(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all ## obj=spl 會在out/u-boot目錄下生成spl目錄 ## -f $(srctree)/scripts/Makefile.spl 說明執行的Makefile文件是scripts/Makefile.spl ## $(MAKE) all 相當於make的目標是all
綜上,由CONFIG_SPL來決定是否需要編譯出spl文件,也就是BL1。
后續相當於執行了 “make -f u-boot/scripts/Makefile.spl obj=spl all” 命令。
在project-x/u-boot/scripts/Makefile.spl中,
SPL_BIN := u-boot-spl
ALL-y += $(obj)/$(SPL_BIN).bin $(obj)/$(SPL_BIN).cfg
## 所以最終目標是spl/u-boot-spl.bin和spl/u-boot-spl.cfg
在project-x/u-boot/scripts/Makefile.spl中建立了spl/u-boot-spl.bin的依賴關系,后續make過程的主體都是在Makefile.spl中。
- (2)spl/u-boot-spl.bin的依賴關系
在project-x/u-boot/scripts/Makefile.spl中
$(obj)/$(SPL_BIN).bin: $(obj)/$(SPL_BIN)-nodtb.bin FORCE
$(call if_changed,copy) ## $(obj)/$(SPL_BIN).bin依賴於$(obj)/$(SPL_BIN)-nodtb.bin。 ## $(call if_changed,copy)表示當依賴文件發生變化時,直接把依賴文件復制為目標文件,即直接把$(obj)/$(SPL_BIN)-nodtb.bin復制為$(obj)/$(SPL_BIN).bin
如上述Makefile代碼spl/u-boot-spl.bin依賴於spl/u-boot-spl-nodtb.bin,並且由spl/u-boot-spl-nodtb.bin復制而成。
對應於上述二、1(4)流程。
- (3)spl/u-boot-spl-nodtb.bin的依賴關系
在project-x/u-boot/scripts/Makefile.spl中
$(obj)/$(SPL_BIN)-nodtb.bin: $(obj)/$(SPL_BIN) FORCE
$(call if_changed,objcopy) $(obj)/$(SPL_BIN)-nodtb.bin依賴於$(obj)/$(SPL_BIN)。也就是spl/u-boot-spl-nodtb.bin依賴於spl/u-boot-spl. ## $(call if_changed,objcopy)表示當依賴文件發生變化時,將依賴文件經過objcopy處理之后得到目標文件。 ## 也就是通過objcopy把spl/u-boot-spl的符號信息以及一些無用信息去掉之后,得到了spl/u-boot-spl-nodtb.bin。
如上述Makefile代碼spl/u-boot-spl-nodtb.bin依賴於spl/u-boot-spl,並且由spl/u-boot-spl經過objcopy操作之后得到。
對應於上述二、1(3)流程。
- (4)spl/u-boot-spl的依賴關系
在project-x/u-boot/scripts/Makefile.spl中
$(obj)/$(SPL_BIN): $(u-boot-spl-init) $(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
$(call if_changed,u-boot-spl) ## $(call if_changed,u-boot-spl)來生成目標 ## $(call if_changed,u-boot-spl)對應cmd_u-boot-spl命令
如上,spl/u-boot-spl依賴於$(u-boot-spl-init) 、$(u-boot-spl-main)和spl/u-boot-spl.ld,並且最終會調用cmd_u-boot-spl來生成spl/u-boot-spl。
cmd_u-boot-spl實現如下:
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)) --end-group \ $(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN)
將cmd_u-boot-spl通過echo命令打印出來之后得到如下(拆分出來看的):
cmd_u-boot-spl=(
cd spl && /build/arm-none-linux-gnueabi-4.8/bin/arm-none-linux-gnueabi-ld -T u-boot-spl.lds --gc-sections -Bstatic --gc-sections arch/arm/cpu/armv7/start.o --start-group arch/arm/mach-s5pc1xx/built-in.o arch/arm/cpu/armv7/built-in.o arch/arm/cpu/built-in.o arch/arm/lib/built-in.o board/samsung/tiny210/built-in.o board/samsung/common/built-in.o common/init/built-in.o drivers/built-in.o dts/built-in.o fs/built-in.o --end-group arch/arm/lib/eabi_compat.o -L /home/disk3/xys/temp/project-x/build/arm-none-linux-gnueabi-4.8/bin/../lib/gcc/arm-none-linux-gnueabi/4.8.3 -lgcc -Map u-boot-spl.map -o u-boot-spl)
可以看出上述是一條連接命令,以spl/u-boot-spl.ld為鏈接腳本,把$(u-boot-spl-init) 、$(u-boot-spl-main)的指定的目標文件連接到u-boot-spl中。
連接很重要的東西就是連接標識,也就是 $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)的定義。
嘗試把$(LD) \$(LDFLAGS) \$(LDFLAGS_\$(@F)) 打印出來,結果如下:
LD=/home/disk3/xys/temp/project-x/build/arm-none-linux-gnueabi-4.8/bin/arm-none-linux-gnueabi-ld LDFLAGS= LDFLAGS_u-boot-spl=-T u-boot-spl.lds --gc-sections -Bstatic --gc-sections ## $(LDFLAGS_$(@F)對應於LDFLAGS_u-boot-spl
也就是說在LDFLAGS_u-boot-spl中指定了鏈接腳本。
重點關注$(LDFLAGS_$(@F))的由來
## @F是一個自動化變量,提取目標的文件名,比如目標是$(obj)/$(SPL_BIN),也就是spl/u-boot-spl,那么@F就是u-boot-spl。 ## 所以LDFLAGS_$(@F)就是LDFLAGS_u-boot-spl ## 定義如下 LDFLAGS_$(SPL_BIN) += -T u-boot-spl.lds $(LDFLAGS_FINAL) ifneq ($(CONFIG_SPL_TEXT_BASE),) LDFLAGS_$(SPL_BIN) += -Ttext $(CONFIG_SPL_TEXT_BASE) endif ## 當指定CONFIG_SPL_TEXT_BASE時,會配置連接地址。在tiny210項目中,因為spl是地址無關代碼設計,故沒有設置連接地址。 ## $(LDFLAGS_FINAL)在如下幾個地方定義了 ## ./config.mk:19:LDFLAGS_FINAL := ## ./config.mk:80:LDFLAGS_FINAL += -Bstatic ## ./arch/arm/config.mk:16:LDFLAGS_FINAL += --gc-sections ## ./scripts/Makefile.spl:43:LDFLAGS_FINAL += --gc-sections ## 綜上:最后LDFLAGS_u-boot-spl=-T u-boot-spl.lds --gc-sections -Bstatic --gc-sections就可以理解了。 ## 對應於上述二、1(2)流程。
- (5)u-boot-spl-init & u-boot-spl-main依賴關系(代碼是如何被編譯的)
先看一下這兩個值打印出來的
u-boot-spl-init=spl/arch/arm/cpu/armv7/start.o
u-boot-spl-main= spl/arch/arm/mach-s5pc1xx/built-in.o spl/arch/arm/cpu/armv7/built-in.o spl/arch/arm/cpu/built-in.o spl/arch/arm/lib/built-in.o spl/board/samsung/tiny210/built-in.o spl/board/samsung/common/built-in.o spl/common/init/built-in.o spl/drivers/built-in.o spl/dts/built-in.o spl/fs/built-in.o
可以觀察到是一堆目標文件的路徑。這些目標文件最終都要被連接到u-boot-spl中。
u-boot-spl-init & u-boot-spl-main的定義如下代碼:
project-x/u-boot/scripts/Makefile.spl
u-boot-spl-init := $(head-y)
head-y := $(addprefix $(obj)/,$(head-y))
## 加spl路徑 ## ./arch/arm/Makefile定義了如下: ## head-y := arch/arm/cpu/$(CPU)/start.o u-boot-spl-main := $(libs-y) libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/) libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/ libs-$(CONFIG_SPL_FRAMEWORK) += common/spl/ libs-y += common/init/ libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/ cmd/ libs-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/ libs-y += drivers/ libs-y += dts/ libs-y += fs/ libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/ libs-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/ libs-$(CONFIG_SPL_NET_SUPPORT) += net/ libs-y := $(addprefix $(obj)/,$(libs-y)) ## 加spl路徑 u-boot-spl-dirs := $(patsubst %/,%,$(filter %/, $(libs-y))) ## 這里注意一下,u-boot-spl-dir是libs-y沒有加built-in.o后綴的時候被定義的。 libs-y := $(patsubst %/, %/built-in.o, $(libs-y)) ## 加built-in.o文件后綴
那么u-boot-spl-init & u-boot-spl-main是如何生成的呢?
需要看一下對應的依賴如下:
$(sort $(u-boot-spl-init) $(u-boot-spl-main)): $(u-boot-spl-dirs) ;
## 也就是說$(u-boot-spl-init) $(u-boot-spl-main)依賴於$(u-boot-spl-dirs) ## sort函數根據首字母進行排序並去除掉重復的。 ## u-boot-spl-dirs := $(patsubst %/,%,$(filter %/, $(libs-y))) ## $(filter %/, $(libs-y)過濾出'/'結尾的字符串,注意,此時$(libs-y)的內容還沒有加上built-in.o文件后綴 ## patsubst去掉字符串中最后的'/'的字符。 ## 最后u-boot-spl-dirs打印出來如下: ## u-boot-spl-dirs=spl/arch/arm/mach-s5pc1xx spl/arch/arm/cpu/armv7 spl/arch/arm/cpu spl/arch/arm/lib spl/board/samsung/tiny210 spl/board/samsung/common spl/common/init spl/drivers spl/dts spl/fs ## 也就是從libs-y改造而來的。 ## $(u-boot-spl-dirs) 的依賴規則如下: $(u-boot-spl-dirs): $(Q)$(MAKE) $(build)=$@
也就是會對每一個目標文件依次執行make $(build)=目標文件
$(build)定義如下:
project-x/u-boot/scripts/Kbuild.include
build := -f $(srctree)/scripts/Makefile.build obj
以arch/arm/mach-s5pc1xx為例
“$(MAKE) $(build)=$@”展開后格式如下
make -f ~/code/temp/project-x/u-boot/scripts/Makefile.build obj=spl/arch/arm/mach-s5pc1xx。
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 ## 以obj=spl/arch/arm/mach-s5pc1xx為例,那么builtin-target就是spl/arch/arm/mach-s5pc1xx/built-in.o. ## 依賴關系如下: $(builtin-target): $(obj-y) FORCE $(call if_changed,link_o_target) ## $(call if_changed,link_o_target)將所有依賴連接到$(builtin-target),也就是相應的built-in.o中了。 ## 具體實現可以查看cmd_link_o_target的實現,這里不詳細說明了。 ## 那么$(obj-y)是從哪里來的呢?是從相應目錄下的Makefile中include得到的。 # 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) ## 當obj=spl/arch/arm/mach-s5pc1xx時,得到對應的kbuild-file=u-boot/arch/arm/mach-s5pc1xx/Makefile ## 而在u-boot/arch/arm/mach-s5pc1xx/Makefile中定義了obj-y如下: ## obj-y = cache.o ## obj-y += reset.o ## obj-y += clock.o ## 對應obj-y對應一些目標文件,由C文件編譯而來,這里就不說明了。
對應於上述二、1(1)流程。
- (6)spl/u-boot-spl.lds依賴關系
這里主要是為了找到一個匹配的連接文件。
$(obj)/u-boot-spl.lds
$(obj)/u-boot-spl.lds: $(LDSCRIPT) FORCE
$(call if_changed_dep,cpp_lds) ## 依賴於$(LDSCRIPT),$(LDSCRIPT)定義了連接腳本所在的位置, ## 然后把鏈接腳本經過cpp_lds處理之后復制到$(obj)/u-boot-spl.lds中,也就是spl/u-boot-spl.lds中。 ## cpp_lds處理具體實現看cmd_cpu_lds定義,具體是對應連接腳本里面的宏定義進行展開。 ## $(LDSCRIPT)定義如下 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 ifeq ($(wildcard $(LDSCRIPT)),) $(error could not find linker script) endif ## 也就是說依次從board/板級目錄、cpudir目錄、arch/架構/cpu/目錄下去搜索u-boot-spl.lds文件。 ## 例如,tiny210(s5vp210 armv7)最終會在./arch/arm/cpu/下搜索到u-boot-spl.lds
綜上,最終指定了project-X/u-boot/arch/arm/cpu/u-boot-spl.lds作為連接腳本。
三、一些重點定義
-
1、CONFIG_SPL
在二、2(1)中說明。
用於指定是否需要編譯SPL,也就是是否需要編譯出uboot-spl.bin文件 -
2、連接腳本的位置
在二、2(6)中說明。
對於tiny210(s5pv210 armv7)來說,連接腳本的位置在
project-x/u-boot/arch/arm/cpu/u-boot-spl.lds -
3、CONFIG_SPL_TEXT_BASE
在二、2(4)中說明。
用於指定SPL的連接地址,可以定義在板子對應的config文件中。 -
4、CONFIG_SPL_BUILD
在編譯spl過程中,會配置
project-x/scripts/Makefile.spl中定義了如下
KBUILD_CPPFLAGS += -DCONFIG_SPL_BUILD
也就是說在編譯uboot-spl.bin的過程中,CONFIG_SPL_BUILD這個宏是被定義的。
四、uboot-spl鏈接腳本說明
1、連接腳本整體分析
相對比較簡單,直接看連接腳本的內容project-x/u-boot/arch/arm/cpu/u-boot-spl.lds
前面有一篇分析連接腳本的文章了《[kernel 啟動流程] 前篇——vmlinux.lds分析》,可以參考一下。
ENTRY(_start)
//定義了地址為_start的地址,所以我們分析代碼就是從這個函數開始分析的!!! SECTIONS { . = 0x00000000; //以下定義文本段 . = ALIGN(4); .text : { __image_copy_start = .; //定義__image_copy_start這個標號地址為當前地址 *(.vectors) //所有目標文件的vectors段,也就是中斷向量表連接到這里來 CPUDIR/start.o (.text*) //start.o文件的.text段鏈接到這里來 *(.text*) //所有目標文件的.text段鏈接到這里來 } //以下定義只讀數據段 . = ALIGN(4); .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } //以下定義數據段 . = ALIGN(4); .data : { *(.data*) //所有目標文件的.data段鏈接到這里來 } //以下定義u_boot_list段,具體功能未知 . = ALIGN(4); .u_boot_list : { KEEP(*(SORT(.u_boot_list*))); } . = ALIGN(4); __image_copy_end = .; //定義__image_copy_end符號的地址為當前地址 //從__image_copy_start 到__image_copy_end的區間,包含了代碼段和數據段。 //以下定義rel.dyn段,這個段用於uboot資源重定向的時候使用,后面會說明 .rel.dyn : { __rel_dyn_start = .; //定義__rel_dyn_start 符號的地址為當前地址,后續在代碼中會使用到 *(.rel*) __rel_dyn_end = .; //定義__rel_dyn_end 符號的地址為當前地址,后續在代碼中會使用到 //從__rel_dyn_start 到__rel_dyn_end 的區間,應該是在代碼重定向的過程中會使用到,后續遇到再說明。 } .end : { *(.__end) } _image_binary_end = .; //定義_image_binary_end 符號的地址為當前地址 //以下定義bss段 .bss __rel_dyn_start (OVERLAY) : { __bss_start = .; *(.bss*) . = ALIGN(4); __bss_end = .; } __bss_size = __bss_end - __bss_start; .dynsym _image_binary_end : { *(.dynsym) } .dynbss : { *(.dynbss) } .dynstr : { *(.dynstr*) } .dynamic : { *(.dynamic*) } .hash : { *(.hash*) } .plt : { *(.plt*) } .interp : { *(.interp*) } .gnu : { *(.gnu*) } .ARM.exidx : { *(.ARM.exidx*) } }
2、符號表中需要注意的符號
project-x/build/out/u-boot/spl/u-boot-spl.map
Linker script and memory map
.text 0x00000000 0xd10 0x00000000 __image_copy_start = . *(.vectors) 0x00000000 _start 0x00000020 _undefined_instruction 0x00000024 _software_interrupt 0x00000028 _prefetch_abort 0x0000002c _data_abort 0x00000030 _not_used 0x00000034 _irq 0x00000038 _fiq ... 0x00000d10 __image_copy_end = . .rel.dyn 0x00000d10 0x0 0x00000d10 __rel_dyn_start = . *(.rel*) .rel.iplt 0x00000000 0x0 arch/arm/cpu/armv7/start.o 0x00000d10 __rel_dyn_end = . .end *(.__end) 0x00000d10 _image_binary_end = . .bss 0x00000d10 0x0 0x00000d10 __bss_start = . *(.bss*) 0x00000d10 . = ALIGN (0x4) 0x00000d10 __bss_end = .
重點關注
* __image_copy_start & __image_copy_end
界定了代碼的位置,用於重定向代碼的時候使用,后面碰到了再分析。
* _start
在u-boot-spl.lds中ENTRY(_start),也就規定了代碼的入口函數是_start。所以后續分析代碼的時候就是從這里開始分析。
* __rel_dyn_start & __rel_dyn_end
* _image_binary_end
五、tiny210(s5pv210)的額外操作
1、為什么tiny210的spl需要額外操作?需要什么額外操作?
建議先參考《[project X] tiny210(s5pv210)上電啟動流程(BL0-BL2)》一文。
tiny210只支持SD啟動的方式和NAND FLASH啟動的方式。
從《[project X] tiny210(s5pv210)上電啟動流程(BL0-BL2)》一文中,我們已經得知了當使用SD啟動的方式和NAND FLASH啟動的方式,也就是BL1鏡像存放在SD上或者nand flash上時,s5pv210中固化的BL0,都需要對BL1的前16B的header做校驗。BL1就是我們所說的uboot-spl.bin,但是默認編譯出來的uboot-spl.bin就是一個純粹的可執行文件,並沒有加上特別的header。
因此,我們需要在生成uboot-spl.bin之后,再為其加上16B的header后生成tiny210-spl.bin。
16B的header格式如下:
地址 | 數據 |
---|---|
0xD002_0000 | BL1鏡像包括header的長度 |
0xD002_0004 | 保留,設置為0 |
0xD002_0008 | BL1鏡像除去header的校驗和 |
0xD002_000c | 保留,設置為0 |
2、如何生成header?(如何生成tiny210-spl.bin)
project-x/u-boot/scripts/Makefile.spl
ifdef CONFIG_SAMSUNG
ALL-y += $(obj)/$(BOARD)-spl.bin
endif
## 當平台是SAMSUNG平台的時候,也就是CONFIG_SAMSUNG被定義的時候,就需要生成對應的板級spl.bin文件,例如tiny210的話,就應該生成對應的spl/tiny210-spl.bin文件。 ifdef CONFIG_S5PC110 $(obj)/$(BOARD)-spl.bin: $(obj)/u-boot-spl.bin $(objtree)/tools/mks5pc1xxspl $< $@ ## 如果是S5PC110系列的cpu的話,則使用如上方法打上header。tiny210的cpu是s5pv210的,屬於S5PC110系列,所以走的是這路。 ## $(objtree)/tools/mks5pc1xxspl對應於編譯uboot時生成的build/out/u-boot/tools/mks5pc1xxspl ## 其代碼路徑位於u-boot/tools/mks5pc1xxspl.c,會根據s5pc1xx系列的header規則為輸入bin文件加上16B的header,具體參考代碼。 ## 這里就構成了u-boot-spl.bin到tiny210-spl.bin的過程了。 else $(obj)/$(BOARD)-spl.bin: $(obj)/u-boot-spl.bin $(if $(wildcard $(objtree)/spl/board/samsung/$(BOARD)/tools/mk$(BOARD)spl),\ $(objtree)/spl/board/samsung/$(BOARD)/tools/mk$(BOARD)spl,\ $(objtree)/tools/mkexynosspl) $(VAR_SIZE_PARAM) $< $@ endif endif
這里就構成了u-boot-spl.bin到tiny210-spl.bin的過程了。
綜上,spl的編譯就完成了。