歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> u-boot-2014.04運行過程記錄

u-boot-2014.04運行過程記錄

日期:2017/3/1 9:10:11   编辑:Linux編程

u-boot啟動流程分析,針對S5PV210

BL1階段,SPL,u-boot-spl.bin

1、首先運行arch/arm/cpu/armv7/start.S 裡面的_start函數,進行異常向量表設置,然後跳轉到reset復位處理函數,設置處理器SVC模式,關閉IRQ和FIQ中斷。設置cp15協處理器

  的SCTRL寄存器V(bit13)為0,設置異常向量表在0x00000000-0x0000001C,設置異常向量表地址為_start。跳轉到cpu_init_cp15初始化協處理器,清除TLB,關閉cache,

  關閉MMU,如果沒有定義CONFIG_SYS_ICACHE_OFF則打開icache。繼續執行cpu_init_crit,跳轉到board/samsung/tiny210/lowlevel_init.S裡面的lowlevel_init,

  進行時鐘初始化,DDR初始化。

2、跳轉到arch\arm\lib\crt0.S裡面的_main,調用copy_bl2_to_ram把BL2從SD卡或是nand flash拷貝到SDRAM的0x20000000,然後跳轉到SDRAM開始運行BL2。


BL2階段,u-boot.bin

1、還是運行arch/arm/cpu/armv7/start.S 裡面的_start函數,然後是reset,再次設置異常向量表地址,設置cp15,跳轉到cpu_init_crit,調用lowlevel_init,

  但沒做任何時事情,因為BL1已經做了初始化,然後跳轉到_main,設置sp,預留空間給全局變量gd,gd在sp之上,gd指針保存在r9裡面,跳轉到board_init_f執行。

2、執行arch\arm\lib\board.c裡面的board_init_f,清空gd,設置gd裡面變量mon_len為uboot大小,執行init_sequence裡面的初始化序列函數,初始化定時器, 

  串口,環境變量,設置dram banks等等。繼續gd的初始化,如果定義了宏CONFIG_SYS_MEM_TOP_HIDE則預留CONFIG_SYS_MEM_TOP_HIDE ram隱藏空間,

  如果定義了CONFIG_LOGBUFFER,則預留LOGBUFF_RESERVE空間給kernel logbuffer,設置TLB大小和空間,如果定義了CONFIG_LCD則預留fb,

  設置TOTAL_MALLOC_LEN大小為malloc空間,預留空間給bd,預留空間給gd,得到addr_sp為棧指針,addr為uboot起始地址。設置波特率,

  設置dram地址地址和大小,設置uboot重定位地址為addr,起始棧指針為addr_sp,設置重定位偏移,把gd數據由當前r9處拷貝到新的gd空間。

3、設置新的gd地址到r9,計算重定位後here的地址保存在lr,這樣在執行relocate_code進行uboot重定位之後返回時,直接跳轉到重定位後的uboot繼續執行。

  設置r0為重定位地址,調用relocate_code進行uboot重定位。

4、執行arch\arm\lib\relocater.S裡面的relocate_code進行uboot重定位。uboot中ld使用-pie而cc沒有使用-fPIC或-fPIE,目標文件中就不會生成GOT。

  首先拷貝__image_copy_start和__image_copy_end之間的代碼到重定位地址空間,在調整.rel.dyn段裡面的地址,對__rel_dyn_start和__rel_dyn_end

  之間類型為R_ARM_RELATIVE(23)的entry加上偏移進行調整。

5、重定位代碼後清零bss段,設置r0為r9,即r0指向gd,r1為重定位地址,然後調用board_init_r。


6、執行arch\arm\lib\board.c裡面的board_init_r繼續初始化,設置gd標志為GD_FLG_RELOC,使能ceche,調用board\samsung\tiny210\tiny210.c裡面的board_init初始化

  sromc設置機器類型和啟動參數地址,調用serial_initialize注冊串口設備,初始化malloc,初始化nand flash,執行env_relocate設置環境變量,

  設置中斷,初始化網卡,最後跳轉到main_loop死循環,在main_loop中會調用process_boot_delay檢測啟動階段有沒有鍵按下,如果有就進入uboot命令行,

  如果沒有就默認加載kernel,如果加載失敗也會進入uboot命令行。

對於代碼重定位的一些說明

  需要注意的是,在uboot的整個relocate_code中rel.dyn不僅沒有拷貝,也沒有修改,修改只是針對rel.dyn中值+offset為地址上的值!查閱網上資料,compiler在cc時加入-fPIC或-fPIE選項,會在目標文件中生成GOT(global offset table),將需要relocate的值存放在GOT中,函數尾部的 Label來存儲GOT的offset以及其中變量的offset,變量尋址首先根據尾部Label相對尋址找到GOT地址,以及變量地址在GOT中的位置,從而確定變量地址,這樣對於目標文件統一修改GOT中的值,就修改了變量地址的offset,完成了relocation。ld時加入-pie選項,就會將GOT並入到rel.dyn段中,uboot在relocate_code中統一根據rel.dyn段修改需要relocation的數值。uboot中ld使用-pie而cc沒有使用-fPIC或-fPIE,目標文件中就不會生成GOT,函數中尋址還是在尾部Label中直接存儲變量的絕對地址,但這個Label同樣存在rel.dyn中,uboot根據rel.dyn段修改Label上的值,就完成了relocation。這樣不僅節省了每個目標文件的GOT段,而且不需要去相對尋址GOT,直接修改函數尾部Label所存儲的變量地址就可以了。

Copyright © Linux教程網 All Rights Reserved