找回密码
 注册
搜索
热搜: 回贴
微赢网络技术论坛 门户 服务器 Linux/BSD 查看内容

U-Boot:Startup Code - Relocation

2009-12-20 13:35| 发布者: admin| 查看: 34| 评论: 0|原作者: 墨元


U-Boot:Startup Code - Relocation
jollen
發表於 February 8, 2007 10:22 PM
延續前一則日記的介紹,我們繼續以 s3c2410 的平臺為例。U-Boot 的 startup code(hardware bring-up code)for s3c2410 位於 cpu/arm920t/start.S,此部份的研究重心如下:



Monitor relocation.

Stack setup.

BSS clearing.

Jump to high-level language.

基本概念分述如後。不過,在開始前,必須具備幾個基本背景知識:



您必須先學會 ARM assembly 後再來閱讀此部份。

必須知道什麼叫「symbol(符號)」以及「memory address」。

能區分 symbol 與 variable 的差異。

一定要能看得懂 symbol table,以 U-Boot 為例,在編譯好 U-Boot 後便會產生檔名為 System.map 的 symbol table。

1. Monitor relocation.
一開始 U-Boot 是在 SMDK2410 的 nor flash 執行,所以 U-Boot 心須把自己由 nor flash 搬到 RAM,才能執行接下來的工作,這個動作就稱為 relocation。相關的程式片斷如下:
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0
程式裡有相當詳細的註解。首先,U-Boot 先把 symbol _start 載到 register r0,再把 symbol _TEXT_BASE 載到 register r1,然後比較 r0 是否等於 r1。如果 r0 等於 r1,表示 U-Boot 目前是在 RAM 裡頭,所以不必做 relocation。
symbol 代表一個記憶體位址(memory address),所以要找出 _start symbol 的 memory address,方式是由 board 的 linker script 來看,所以把 board/smdk2410/u-boot.lds 叫出來瞧瞧:
...
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text)
*(.text)
}
...
}
看懂 linker script 是您的功課,不過這個部份其實很直覺。程式的進入點(ENTRY command)定義為 _start symbol,而程式一開始的 value to current address(看到沒,就是 SECTIONS 後的那個小點點!)為 0x00000000,所以 _start symbol 代表的是 memory address 0x0。請不要用 _start 等於 0x0 的方式來解說,因為 _start 壓根兒就是一個 symbol 並不是 variable。
Linker script 的 "." 稱為 location counter,這是一個指定運算子,也就是「assign value to symbol」的意思。因此,_start symbol 為 address 0x0,且 value to _start symbol 為 0x00000000。
所以,總結來看 "adr r0, _start" 把 symbol _start 的 memory address 放到 r0,adr 是 ARM 的 pseudo-instruction;"ldr r1, _TEXT_BASE" 把 symbol _TEXT_BASE 的值放到 r1,ldr 是 ARM 的 memory addressing 指令,這裡用到的 addressing mode 是 direct addressing。
回頭找一下 symbol _TEXT_BASE,_TEXT_BASE 可就不在 linker script 裡頭了。把 start.S 程式移到開頭,就可以找到 _TEXT_BASE:
_TEXT_BASE:
.word TEXT_BASE
這是一個 symbol 的定義與 GNU assembly 的 variable 宣告語法,所以 symbol _TEXT_BASE 所代表的 memory address 之處,放了一個值(value),其值為 TEXT_BASE。TEXT_BASE 便是一個變數,此變數是 linking 階段(GNU ld)所定義的,以 U-Boot for SMDK2410 為例,便是 0x33F80000(board/smdk2410/config.mk):
TEXT_BASE = 0x33F80000
接下來的程式是:
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2
這裡做的是「計算程式長度」的動作。把 _armboot_start 放到 r2、_bss_start 放到 r3,然後 r2 = r3 - r2 算出要 relocation 的長度,此時 r2 放的便是 U-Boot 後面「要 relocate 到 RAM 的程長度」。下一行做 r2 = r0 r2,很清楚,再把程式尾段的 memory address 算出來,所以 r2 最後放的是「source end address」。
這個時候就要把 symbol table 請出來看了。
先在 start.S 裡找到 _armboot_start:
.globl _armboot_start
_armboot_start:
.word _start
再對照 System.map:
33f80000 t $a
33f80000 T _start
33f80020 t $d
...
不過,_bss_start 可就不是對照 System.map 就能解決的了。概念上,_bss_start 是 linker script 所定義的 symbol,可用來表示程式「實體程式碼」的 end address;概念上來說雖然簡單,不過仍強烈建議了解 ELF 的格式與 .bss section 的整體觀念,畢道這是基本功,不可不練。
可在 U-Boot 程式碼裡頭找到這行宣告:
extern ulong _bss_start; /* code data end == BSS start */
剩下來的部份就容易了,只要以上這些觀念都能確實掌握,startup code 並沒有什麼困難的地方。
延伸閱讀




Executable and Linking Format
: 重要的 ELF 格式介紹


BSS Section Concepts
: .bss section 的基本觀念介紹

--jollen





最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-30 13:15 , Processed in 0.222949 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

返回顶部