uboot-spl编译流程
[uboot] (第二章)uboot流程——uboot-spl編譯流程
2016年10月27日 20:40:47閱讀數:2675以下例子都以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編譯命令如下:
- 1
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)_defconfigmake -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.- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
最終,相當于進入了uboot目錄執行了make動作。?
也就是說spl的編譯是編譯uboot的一部分,和uboot.bin走的是兩條編譯流程,這個要重點注意。?
正常來說,會先編譯主體uboot,也就是uboot.bin.再編譯uboot-spl,也就是uboot-spl.bin,雖然編譯命令是一起的,但是編譯流程是分開的。
2、生成文件?
最終編譯完成之后,會在project-x/build/out/u-boot/spl下生成如下文件:
- 1
- 2
其中,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中
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
綜上,由CONFIG_SPL來決定是否需要編譯出spl文件,也就是BL1。?
后續相當于執行了?“make -f u-boot/scripts/Makefile.spl obj=spl all”?命令。?
在project-x/u-boot/scripts/Makefile.spl中,
- 1
- 2
- 3
在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- 1
- 2
- 3
- 4
如上述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中
- 1
- 2
- 3
- 4
- 5
如上述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中
- 1
- 2
- 3
- 4
如上,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實現如下:
- 1
- 2
- 3
- 4
- 5
將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)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
可以看出上述是一條連接命令,以spl/u-boot-spl.ld為鏈接腳本,把$(u-boot-spl-init) 、$(u-boot-spl-main)的指定的目標文件連接到u-boot-spl中。?
連接很重要的東西就是連接標識,也就是?$(LD)?$(LDFLAGS)?$(LDFLAGS_$(@F)的定義。?
嘗試把$(LD) \$(LDFLAGS) \$(LDFLAGS_\$(@F)) 打印出來,結果如下:
- 1
- 2
- 3
- 4
也就是說在LDFLAGS_u-boot-spl中指定了鏈接腳本。?
重點關注$(LDFLAGS_$(@F))的由來
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- (5)u-boot-spl-init & u-boot-spl-main依賴關系(代碼是如何被編譯的)?
先看一下這兩個值打印出來的
- 1
- 2
- 3
可以觀察到是一堆目標文件的路徑。這些目標文件最終都要被連接到u-boot-spl中。?
u-boot-spl-init & u-boot-spl-main的定義如下代碼:?
project-x/u-boot/scripts/Makefile.spl
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
那么u-boot-spl-init & u-boot-spl-main是如何生成的呢??
需要看一下對應的依賴如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
也就是會對每一個目標文件依次執行make?$(build)=目標文件?
$(build)定義如下:?
project-x/u-boot/scripts/Kbuild.include
- 1
以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,如下
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
對應于上述二、1(1)流程。
- (6)spl/u-boot-spl.lds依賴關系?
這里主要是為了找到一個匹配的連接文件。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
綜上,最終指定了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.lds3、CONFIG_SPL_TEXT_BASE?
在二、2(4)中說明。?
用于指定SPL的連接地址,可以定義在板子對應的config文件中。4、CONFIG_SPL_BUILD?
在編譯spl過程中,會配置?
project-x/scripts/Makefile.spl中定義了如下
- 1
也就是說在編譯uboot-spl.bin的過程中,CONFIG_SPL_BUILD這個宏是被定義的。
四、uboot-spl鏈接腳本說明
1、連接腳本整體分析
相對比較簡單,直接看連接腳本的內容project-x/u-boot/arch/arm/cpu/u-boot-spl.lds?
前面有一篇分析連接腳本的文章了《[kernel 啟動流程] 前篇——vmlinux.lds分析》,可以參考一下。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
2、符號表中需要注意的符號
project-x/build/out/u-boot/spl/u-boot-spl.map
Linker script and memory map .text 0x00000000 0xd100x00000000 __image_copy_start = . *(.vectors)0x00000000 _start0x00000020 _undefined_instruction0x00000024 _software_interrupt0x00000028 _prefetch_abort0x0000002c _data_abort0x00000030 _not_used0x00000034 _irq0x00000038 _fiq ...0x00000d10 __image_copy_end = . .rel.dyn 0x00000d10 0x00x00000d10 __rel_dyn_start = .*(.rel*).rel.iplt 0x00000000 0x0 arch/arm/cpu/armv7/start.o0x00000d10 __rel_dyn_end = . .end*(.__end)0x00000d10 _image_binary_end = ..bss 0x00000d10 0x00x00000d10 __bss_start = .*(.bss*)0x00000d10 . = ALIGN (0x4)0x00000d10 __bss_end = .- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
重點關注?
* __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- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
這里就構成了u-boot-spl.bin到tiny210-spl.bin的過程了。
綜上,spl的編譯就完成了。
總結
以上是生活随笔為你收集整理的uboot-spl编译流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UBOOT 概述
- 下一篇: 1-uboot流程——概述