免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1159 | 回复: 0
打印 上一主题 下一主题

U-Boot:Startup Code - Relocation [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-10-13 22:30 |只看该作者 |倒序浏览

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_BASETEXT_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 並沒有什麼困難的地方。
延伸閱讀

--jollen


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/82019/showart_1296529.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP