uboot移植之前期準備篇1
uboot移植之init_sequence_f函數數組分析(番外篇)
uboot移植之源碼流程分析篇3(超詳細!)
uboot移植之修改支援SDRAM篇4
uboot移植之修改支援NorFlash篇5
uboot移植之修改支援NandFlash識别篇6(超詳細)
分析uboot,先要分析頂層Makefile,熟悉整體的編譯流程。
1、make smdk2410_config
smdk2410_config是Makefile檔案中定義的目标之一。當執行make smdk2410_config,會按順序讀取比對Makefile中的規則,并找到對應的目标,根據其依賴關系,決定哪些目标需要更新,根據規則鍊不斷地重複這個過程,直到找到最原始的依賴關系,并最終生成.config配置檔案,供頂層Makefile讀取。
定位目标:

% 符号為通配符,%config表明所有以 config 結尾的目标,其依賴于scripts_basic outputmakefile FORCE三者。但是,該規則置于ifeq中,需分析config-targets變量,發現于
make 的環境變量叫“MAKECMDGOALS”,這個變量中會存放你所指定的終極目标的清單,如果在指令行上,你沒有指定目标,那麼,這個變量是空值。比如make smdk2410_config,那個MAKECMDGOALS的值等于smdk2410_config。
$(filter $(no-dot-config-targets), $(MAKECMDGOALS))表示調用Makefile的filter函數,過濾掉 $(MAKECMDGOALS)中所有不符合$(no-dot-config-targets)模式的單詞。比如 $(filter %.c %.s, foo.c bar.c bax.s uar.h),結果為 bax.s uar.h。而filter-out函數的作用則剛好相反,去除所有符合的單詞。
執行ifneq後,過濾後為空,空==空,是以ifneq分支不執行。dot-config還等于1,查找 KBUILD_EXTMOD 變量定義位置
由注釋可知,由于我們make時并沒有傳入參數指定路徑,是以,SUBDIRS變量為空;$(origin M):origin 函數通過傳回一個字元串來告訴你 M 變量的定義情況。(file:在Makefile中定義;command line:在指令行中定義;undefined:從來沒有定義....)不過,我們并沒有以 make M=dir 的方式編譯,是以此處ifeq也不執行。KBUILD_EXTMOD變量為空。
是以440行的條件判斷成立,$(filter config %config,$(MAKECMDGOALS))結果還是smdk2410_config,不為空,config-targets := 1,至此,已經确定466行分支條件成立。(words函數傳回值是$(MAKECMDGOALS)變量的單詞數目,是以,不執行ifneq)
在478行,Q = @ MAKE=make 。@就是控制指令的輸出流資訊,比如:
A:=abc @echo $(A) 輸出結果:abc
A:=abc echo $(A) 輸出結果:echo abc abc
編譯的時候可以通過輸入參數V=1決定,詳情:https://blog.csdn.net/qwaszx523/article/details/53218014
編譯的時候定義了很多預設變量,MAKE變量的定義可以通過指令檢視:
至于build變量,在目前Makefile中并沒有找到其定義,何不妨搜尋一下,看看是否包含在其他頭檔案中?
後面的不用看,撐死了最大範圍也就目前行(478),到include scripts/Kbuild.include找,果真發現
build := -f $(srctree)/scripts/Makefile.build obj
是以make smdk2410_config最終要478行,即:
make -f ./scripts/Makefile.build obj=scripts/kconfig smdk2410_config
但是該目标依賴于scripts_basic outputmakefile FORCE三者,後兩者為空,scripts_basic目标依賴于:
将其展開即為:
make -f ./scripts/Makefile.build obj=scripts/basic
rm -f .tmp_quiet_recordmcount
在bash中輸入編譯指令,校驗分析結果:
2、make
當我們make但并沒有指定生成目标的時候,那麼預設是生成_all,從頭往下找,發現_all被定義為僞目标:
129 # That's our default target when none is given on the command line
130 PHONY := _all
131 _all:
僞目标又稱為假象目标,僅僅是一個标簽,并不會在編譯的過程中産生目标檔案,而且僞目标一般沒有依賴檔案,是以目标被認為是最新的。但是,也可以為僞目标指定所依賴的對象。比如:
all: first second third
.PHONY: all
first: XXX
second: XXX
third: XXX
上述的all目标依賴于first second third,由于僞目标的特性是總會被執行的,是以其依賴的三個目标就總是不如all這個目标新,每次都會檢查依賴的目标是否最新。
195 # If building an external module we do not care about the all: rule
196 # but instead _all depend on modules
197 PHONY += all
198 ifeq ($(KBUILD_EXTMOD),)
199 _all: all
200 else
201 _all: modules
202 endif
由1分析我們已經可以知道,$(KBUILD_EXTMOD)為空,是以僞目标 _all 依賴于 all ,而all又依賴于$(ALL-y)。
804 all: $(ALL-y)
是以,最終統攬全檔案的重任就落到$(ALL-y)手上了,根據ALL-$(valiable)決定對應的檔案是否編譯進終極檔案。
還有把各種庫檔案打包,比如驅動,裝置樹,net等等
最後,把所有生成的目标檔案連結在一起,連接配接過程如下:
直接執行make V=1指令,在最後的輸出資訊很容易找到其詳細連結過程:
兩個橫框之間的就是組成輸出-o uboot 的原材料,也就是各種的obj檔案。通過連結腳本u-boot.lds和連結位址 -Ttext 0x0 可以知道u-boot代碼的組織排放,也就是各種段,還有檔案先後的排放次序。
也就是說,後面的text段,data段等等,都放在(目前位址 .=0x0 + 連結位址-Ttext 0x0的位置) 0x0 ,因為 . =0x0這隻是個代碼位址偏移值,真正的起始位址是由編譯時指定的。
最開始排放的是代碼段中的*(.__image_copy_start) ,*(.vectors)以及arch/arm/cpu/arm920t/start.o (.text*)。
通常,在調用代碼重定位的時候,就是要把__image_copy_start到__image_copy_end之間的資料進行拷貝,放到連結位址,關于連結位址本篇暫不讨論。而*(.vectors)存放的是中斷向量表。
很明顯,要想分析啟動流程,應從arch/arm/cpu/arm920t/start.o入手,也就是該目錄下的start.s彙編源碼。
請戳連結:uboot移植之源碼流程分析篇3
水準有限,草草分析,很多地方都沒有深入去探究,有什麼分析的不恰當,還望告知。
關于make過程更詳盡的分析請看:https://blog.csdn.net/q_z_r_s/article/details/80719298
參考資料:
《ARM9嵌入式系統設計與應用開發》 熊茂華 楊震倫 主編
《嵌入式Linux應用開發完全手冊》 韋東山著