uboot重定位代码分析(转)
概述
重定位(relocate)代碼將BootLoader自身由Flash復制到SDRAM,以便跳轉到SDRAM執行。之所以需要進行重定位是因為在Flash中執行速度比較慢,而系統復位后總是從0x00000000地址取指。
重定位代碼,位于/U-Boot/cpu/s3c44b0/start.S?:
relocate:????????????????
????adr?r0, _start????
????ldr?r1, _TEXT_BASE????
????cmp?????r0, r1????????
????beq?????stack_setup
?
????ldr?r2, _armboot_start
????ldr?r3, _bss_start
????sub?r2, r3, r2????
????add?r2, r0, r2????
?
copy_loop:
????ldmia?r0!, {r3-r10}?????
????stmia?r1!, {r3-r10}?????
????cmp?r0, r2???????????????
????ble?copy_loop
以上代碼首先判斷是否需要進行重定位,如果需要的話首先確定復制的源基址、源大小和目標基址,然后以r3 ~ r13為媒介,將BootLoader復制到SDRAM中。
分析
copy_loop很容易理解,這里主要分析relocate處的前兩條指令:
1.???????adr?r0, _start
adr是一條偽指令,匯編器總是試圖為它產生add/sub這樣的指令,(在這里)以pc為基址裝載目標寄存器。以下是arm-elf-objdump產生的反匯編代碼:
c700048:???e24f0050 ?sub?r0, pc, #80???; 0x50
e24f0050是指令對應的機器碼,c700048是存放該機器碼的地址(十六進制表示)。這個地址是怎么來的呢?在/U-Boot/config.mk中有問題的答案:
LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)
上面的宏指定連接時的命令行參數,-Ttext設定了.text段的地址,而TEXT_BASE在/U-Boot/board/.../config.mk中定義為0x0C700000。這些信息最后都以硬編碼的方式記錄在程序映像文件中,程序的入口_start = TEXT_BASE = 0x0C700000?:
Disassembly of section .text:
0c700000 <_start>:
?c700000:?ea00000a ?b???c700030
?...
但是,程序映像是燒寫到Flash中并開始執行的,而Flash的地址從0x00000000開始。于是,程序映像的第一條指令對齊到0x00000000處。相應的,這條adr指令的地址應對齊到0x00000048處,執行后r0等于0。
2.???????ldr?r1, _TEXT_BASE
以下是arm-elf-objdump產生的反匯編代碼:
c70004c:???e51f1034 ?ldr?r1, [pc, #-52]????; c700020 <_TEXT_BASE>
由此可見,這里的ldr并不是簡單的將_TEXT_BASE地址處的4字節裝載到r1,而同樣是以pc為基址計算得到源地址的。這里的pc = 0x4c + 8 = 0x54,于是該指令把0x54 – 52 = 0x20處的4字節(即TEXT_BASE,亦即0x0C700000)裝載到r1。
3.???????源大小的確定
通過上面的分析,我們已經有了一個概念:程序的實際執行地址與連接時指定的加載地址可能是不一樣的。我們已經得到BootLoader代碼開始的運行時開始地址,存放于r0,還需要計算它的運行時結束地址。運行時結束地址?=?運行時開始地址?+?代碼段大小。代碼段大小由.bss段的期望開始地址?- .text段的期望開始地址獲得。
小結
通過連接時的-Ttext選項,將.text段的地址硬編碼到程序映像中。雖然程序映像在Flash中執行,其實際執行地址與期望執行地址不一致,但在relocate之前,通過以pc為基址進行相對尋址,使得這些代碼的執行與其實際裝載的地址無關。
轉載于:https://www.cnblogs.com/songfeixiang/p/3733781.html
總結
以上是生活随笔為你收集整理的uboot重定位代码分析(转)的全部內容,希望文章能夠幫你解決所遇到的問題。