Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學

U-Boot 第一階段啟動關鍵代碼深度解析

編輯:Linux 系統常見問題解答

鏈接腳本與入口地址

U-Boot 通過鏈接腳本 u-boot.lds 定義內存佈局:

ENTRY(_start)SECTIONS{  . = 0x00000000;  .text : { cpu/arm920t/start.o(.text) *(.text) }  .rodata : { *(.rodata) }  .data : { *(.data) }  .got  : { *(.got) }  __u_boot_cmd_start = .;  .u_boot_cmd : { *(.u_boot_cmd) }  __u_boot_cmd_end = .;  __bss_start = .;  .bss : { *(.bss) }  _end = .;}
  • ENTRY(_start) 指定入口符號。
  • . = 0x00000000 並非真實運行地址,鏈接時會被 TEXT_BASE(如 0x33F80000)替換,所有符號地址均相對 TEXT_BASE 計算。
  • 編譯生成的 u-boot.map 可見符號鏈接地址均為 0x33F8xxxx。

start.S 關鍵符號解析

_TEXT_BASE

_TEXT_BASE: .word TEXT_BASE

定義標號 _TEXT_BASE,其值為該指令的鏈接地址(即 TEXT_BASE),便於位置無關代碼引用基址。

_armboot_start

.globl _armboot_start_armboot_start: .word _start

_armboot_start 存儲 _start 的鏈接地址。u-boot.map 顯示其地址為 0x33F80044,二進制 u-boot.bin 偏移 0x44 處確為 0x33F80000(小端)。

_bss_start / __bss_start

.globl _bss_start_bss_start: .word __bss_start

__bss_start 由鏈接腳本 __bss_start = . 定義,標記 BSS 段起始。_bss_start 處存儲該值(0x33F979D4),用於計算需搬運代碼大小(__bss_start - TEXT_BASE)。

SDRAM 初始化:lowlevel_init.S

ldr r0, =SMRDATALdr r1, _TEXT_BASEsub r0, r0, r1  @ r0 = SMRDATA 相對 TEXT_BASE 的偏移

核心邏輯:代碼尚未搬運至 SDRAM,運行於 Flash(加載地址 0x0),但符號地址基於 TEXT_BASE(鏈接/運行地址)。直接使用符號會導致地址錯誤。通過 SMRDATA - _TEXT_BASE 得到相對偏移,再加上當前 PC 基址,即可正確訪問 Flash 中的數據,實現位置無關代碼(PIC)。

代碼重定位

relocate: adr r0, _start  @ r0 = 當前代碼加載地址(PC 相對)ldr r1, _TEXT_BASE @ r1 = 運行地址 TEXT_BASEcmp r0, r1        @ 比較判斷是否已在正確位置
  • adr 取 PC 相對偏移,得到當前代碼實際加載地址(Flash 基址)。
  • ldr 取絕對值 TEXT_BASE(SDRAM 目標地址)。
  • 若不等,執行搬運循環將 _start ~ __bss_start 範圍複製到 TEXT_BASE,然後跳轉 start_armboot(C 入口)。

此機制確保 U-Boot 能從 Flash 啟動、自動重定位到 SDRAM 高速運行,是嵌入式 Bootloader 的經典設計。

Copyright © Windows教程網 All Rights Reserved