作者 主題: 有關bootloader的链接的memory layout的疑惑  (閱讀 5887 次)

0 會員 與 1 訪客 正在閱讀本文。

aaronwong

  • 可愛的小學生
  • *
  • 文章數: 6
    • 檢視個人資料
    • http://aquarius.cublog.cn
最近想研究一下bootloader,我們都知道bootloader的memory layout是要通過一個自己攥寫的鏈接腳本(linker script)來指定的。我的開發板的linker script檔案boot.lds如下:
代碼: [選擇]

OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS {
. = 0xa3f00000;
__boot_start = .;
.start ALIGN(4) : {
*(.text.start)
}

.setup ALIGN(4) : {
setup_block = .;
*(.setup)
setup_block_end = .;
}

.text ALIGN(4) : {
*(.text)
}

.rodata ALIGN(4) : {
*(.rodata)
}

.data ALIGN(4) : {
*(.data)
}

.got ALIGN(4) : {
*(.got)
}
__boot_end = .;

.bss ALIGN(16) : {
bss_start = .;
*(.bss)
*(COMMON)
bss_end = .;


stack_point = __boot_start + 0x00100000;
loader_size = __boot_end - __boot_start;
setup_size  = setup_block_end - setup_block;
}

上面的地址0xa3f00000是SDRAM的(TOP ADDRESS-1MB)
而第一個啟動程式start.S的代碼如下:
代碼: [選擇]

#include <config.h>
#include <hardware.h>
#define eth_base 0x0c00030e

.section .text.start
.global _start
_start :
b start

.section .text
start :
bl define_gpio
bl clock_enable
bl setup_memory @ setup static and dynamic memory

@ copy bootloader to dynamic memory area
ldr r0, =0x00
ldr r1, =__boot_start
ldr r2, =__boot_end
 1: ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r1, r2
blt 1b

@ clear bss area
mov r3, #0x00
mov r4, #0x00
mov r5, #0x00
mov r6, #0x00
ldr r0, =bss_start
ldr r1, =bss_end
 1: stmia r0!, {r3-r6}
cmp r0, r1
blt 1b

        ldr r0, =eth_base
        ldr r1, [r0]


@ set stack point
ldr sp, =stack_point-4

@ jump to c code
ldr pc, =main

我們知道,ARM的第一條指令是從地址0x0開始執行的,那么_start所標記的第一條指令所在的section .text.start應當被relocate到地址0x0(ROM地址空間),而在linker script中卻被指定到地址0xa3f00000(SDRAM address space),那么所得到的executable image檔中,第一條指令的地址就是0xa3f00000,使用objdump和readelf可得到如下信息:
代碼: [選擇]

[aaronwong@localhost src]$ objdump -h boot.elf32 | grep ".start"
  0 .start        00000004  a3f00000  a3f00000  00008000  2**0
[aaronwong@localhost src]$ readelf -s boot.elf32 | grep "_start"
   142: a3f04364   352 FUNC    LOCAL  DEFAULT    3 tftp_start
   263: a3f00000     0 NOTYPE  GLOBAL DEFAULT  ABS __boot_start
   279: a3f00000     0 NOTYPE  GLOBAL DEFAULT    1 _start
   290: a3f09390     0 NOTYPE  GLOBAL DEFAULT   13 bss_start

也就是說,第一條指令的地址被標記為0xa3f00000,其他的label symbol也都是相對于它而言的,這樣的boot image如果download到FLASH MEMORY,怎么能正常執行呢?還是說我理解錯了呢?謝謝指點!

hanlin

  • 可愛的小學生
  • *
  • 文章數: 3
    • 檢視個人資料
有關bootloader的链接的memory layout的疑惑
« 回覆 #1 於: 2007-07-27 19:46 »
我最近也在看有关bootloader的code,不过我的平台是mips而不是arm,我想应该差不多吧,!你的疑惑我也存在,不过我认为,
download to flash,应该能正常运行!连接的地址只是告诉cpu在向ram拷贝自己的时候应该放到ram的哪里!?以及在跳转到c环境的时候,c_main()已被连接到ram address,so it can run normally!I think?

aaronwong

  • 可愛的小學生
  • *
  • 文章數: 6
    • 檢視個人資料
    • http://aquarius.cublog.cn
有關bootloader的链接的memory layout的疑惑
« 回覆 #2 於: 2007-08-17 17:02 »
引述: "hanlin"
连接的地址只是告诉cpu在向ram拷贝自己的时候应该放到ram的哪里!?以及在跳转到c环境的时候,c_main()已被连接到ram address,so it can run normally!

謝謝。問題已解決。你上面的理解是正确的。linker script中指定的是VMA。bootloader把自己拷貝到所指定的VMA所在的RAM空間,是對自身的一個重定位過程。

不過最關鍵的是bootloader最開始的那一部分code,因為他們的運行時地址也是被分配到RAM中的,但是上電之后處理器是從ROM中取指令的,也就是說,bootloader最開始的一段代碼是在ROM中執行的,即:這段代碼實際運行時的地址与在鏈接時所分配的地址不一樣。

這是因為最開始的一段代碼遵循了位置無關的程式設計方法,是一段位置無關代碼(position-independent code),可以參考ARM程式設計中的ROPI和RWPI的ATPCS。這种代碼使用了PC-relative的symbol reference mode,所以与symbol的實際地址無關,可以在任意memory地址空間正确執行。例如使用B/BL相對跳轉指令。

而最后使用“ldr pc, =main”
跳轉到main函數,是使用main的絕對地址來跳轉的,這時RAM中對應的地址處已有一份main函數的拷貝,所以跳轉到RAM中繼續運行。