一、uboot編譯和生成文件
說(shuō)明
現(xiàn)在的uboot已經(jīng)做得和kernel很像,最主要的一點(diǎn)是,uboot也使用了dtb的方法,將設(shè)備樹(shù)和代碼分離開(kāi)來(lái)(當(dāng)然可以通過(guò)宏來(lái)控制)。
project-x/u-boot/configs/tiny210_defconfig
CONFIG_OF_CONTROL=y
// 用于表示是否使用了dtb的方式
CONFIG_OF_SEPARATE=y
// 是否將dtb和uboot分離表一
所以在uboot的編譯中,和spl的最大區(qū)別是還要編譯dtb。 (前面我們將的spl是沒(méi)有使用dtb的,當(dāng)然好像也可以使用dtb,只是我沒(méi)有試過(guò))。
U-Boot編譯命令
對(duì)于mini2440開(kāi)發(fā)板,編譯U-Boot需要執(zhí)行如下的命令:
$ make mini2440_config
$ make all
使用上面的命令編譯U-Boot,編譯生成的所有文件都保存在源代碼目錄中。為了保持源代碼目錄的干凈,可以使用如下命令將編譯生成的文件輸出到一個(gè)外部目錄,而不是在源代碼目錄中,下面的2種方法都將編譯生成的文件輸出到 /tmp/build目錄:
$ export BUILD_DIR=/tmp/build
$ make mini2440_config
$ make all
或
$ make O=/tmp/build mini2440_config (注意是字母O,而不是數(shù)字0)
$ make all
為了簡(jiǎn)化分析過(guò)程,方便讀者理解,這里主要針對(duì)第一種編譯方式(目標(biāo)輸出到源代碼所在目錄)進(jìn)行分析。
uboot編譯流程
編譯整體流程
根據(jù)一、2生成的文件說(shuō)明可知簡(jiǎn)單流程如下:
?。?)各目錄下built-in.o的生成
源文件、代碼文件編譯、匯編目標(biāo)文件同目錄目標(biāo)文件連接built-in目標(biāo)文件
(2)由所有built-in.o以u(píng)-boot.lds為連接腳本通過(guò)連接來(lái)生成u-boot
built-in目標(biāo)文件以u(píng)-boot.lds為連接腳本進(jìn)行統(tǒng)一連接u-boot
?。?)由u-boot生成u-boot-nodtb.bin
u-bootobjcopy動(dòng)作去掉符號(hào)信息表u-boot-nodtb.bin
(4)由生成uboot的dtb文件
dts文件dtc編譯、打包dtb文件u-boot.dtb
(5)由u-boot-nodtb.bin和u-boot.dtb生成u-boot-dtb.bin
u-boot-nodtb.bin和u-boot.dtb追加整合兩個(gè)文件u-boot-dtb.bin
?。?)由u-boot-dtb.bin復(fù)制生成u-boot.bin
u-boot-dtb.bin復(fù)制u-boot.bin
U-Boot配置、編譯、連接過(guò)程
U-Boot開(kāi)頭有一些跟主機(jī)軟硬件環(huán)境相關(guān)的代碼,在每次執(zhí)行make命令時(shí)這些代碼都被執(zhí)行一次。
1. U-Boot配置過(guò)程
(1)定義主機(jī)系統(tǒng)架構(gòu)
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/)
“sed –e”表示后面跟的是一串命令腳本,而表達(dá)式“s/abc/def/”表示要從標(biāo)準(zhǔn)輸入中,查找到內(nèi)容為“abc”的,然后替換成“def”。其中“abc”表達(dá)式用可以使用“?!弊鳛橥ㄅ浞?。
命令“uname –m”將輸出主機(jī)CPU的體系架構(gòu)類型。作者的電腦使用Intel Core2系列的CPU,因此“uname–m”輸出“i686”?!癷686”可以匹配命令“sed -e s/i.86/i386/”中的“i.86”,因此在作者的機(jī)器上執(zhí)行Makefile,HOSTARCH將被設(shè)置成“i386” 。
?。?)定義主機(jī)操作系統(tǒng)類型
HOSTOS := $(shell uname -s | tr‘[:upper:]’ ‘[:lower:]’ | \
sed -e ‘s/cygwin.*/cygwin/’)
“uname –s”輸出主機(jī)內(nèi)核名字,作者使用Linux發(fā)行版Ubuntu9.10,因此“uname –s”結(jié)果是“Linux”?!皌r ‘[:upper:]’ ‘[:lower:]’”作用是將標(biāo)準(zhǔn)輸入中的所有大寫(xiě)字母轉(zhuǎn)換為響應(yīng)的小寫(xiě)字母。因此執(zhí)行結(jié)果是將HOSTOS設(shè)置為“l(fā)inux”。
?。?)定義執(zhí)行shell腳本的shell
# Set shell to bash if possible, otherwisefall back to sh
SHELL := $(shell if [ -x“
BASH”];thenecho
BASH; \
elseif [ -x /bin/bash ]; then echo /bin/bash; \
elseecho sh; fi; fi)
“$$BASH”的作用實(shí)質(zhì)上是生成了字符串“$BASH”(前一個(gè)$號(hào)的作用是指明第二個(gè)$是普通的字符)。若執(zhí)行當(dāng)前Makefile的shell中定義了“$BASH”環(huán)境變量,且文件“$BASH”是可執(zhí)行文件,則SHELL的值為“$BASH”。否則,若“/bin/bash”是可執(zhí)行文件,則SHELL值為“/bin/bash”。若以上兩條都不成立,則將“sh”賦值給SHELL變量。
由于作者的機(jī)器安裝了bash shell,且shell默認(rèn)環(huán)境變量中定義了“$BASH”,因此SHELL 被設(shè)置為$BASH 。
?。?)設(shè)定編譯輸出目錄
ifdef O
ifeq (“$(origin O)”,“command line”)
BUILD_DIR := $(O)
endif
endif
函數(shù)$( origin, variable) 輸出的結(jié)果是一個(gè)字符串,輸出結(jié)果由變量variable定義的方式?jīng)Q定,若variable在命令行中定義過(guò),則origin函數(shù)返回值為“command line”。假若在命令行中執(zhí)行了“exportBUILD_DIR=/tmp/build”的命令,則“$(origin O)”值為“command line”,而B(niǎo)UILD_DIR被設(shè)置為“/tmp/build”。
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p${BUILD_DIR})
若${BUILD_DIR}表示的目錄沒(méi)有定義,則創(chuàng)建該目錄。
# Verify if it was successful.
BUILD_DIR := $(shell cd $(BUILD_DIR)&& /bin/pwd)
$(if $(BUILD_DIR),,$(error output directory“$(saved-output)” does not exist))
endif # ifneq ($(BUILD_DIR),)
若$(BUILD_DIR)為空,則將其賦值為當(dāng)前目錄路徑(源代碼目錄)。并檢查$(BUILD_DIR)目錄是否存在。
OBJTREE :=$(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE :=$(CURDIR)
TOPDIR :=$(SRCTREE)
LNDIR :=$(OBJTREE)
… …
MKCONFIG :=$(SRCTREE)/mkconfig
… …
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
CURDIR變量指示Make當(dāng)前的工作目錄,由于當(dāng)前Make在U-Boot頂層目錄執(zhí)行Makefile,因此CURDIR此時(shí)就是U-Boot頂層目錄。
執(zhí)行完上面的代碼后, SRCTREE,src變量就是U-Boot代碼頂層目錄,而OBJTREE,obj變量就是輸出目錄,若沒(méi)有定義BUILD_DIR環(huán)境變量,則SRCTREE,src變量與OBJTREE,obj變量都是U-Boot源代碼目錄。而MKCONFIG則表示U-Boot根目錄下的mkconfig腳本。
評(píng)論
查看更多