U-boot Link Analysis
Http://www.rritw.com/a/bianchengyuyan/C__/20130312/279763.html
In a typical embedded system, the bootloader code is placed in nor flash or NAND Flash. After the system is powered on or reset, run this code first. The bootloader code is usually stored in nor flash. NAND Flash cannot be accessed randomly due to hardware reasons, and special hardware support mechanisms are required.
In addition to initialization, the bootloader code is the handler, that is, the address relocate ). Why do we need relocate? This is mainly because of the economic and speed reasons. In terms of economics, the prices of nor flash and NAND Flash vary sharply per megabits. the bootloader code is usually several dozen to several hundred kb in size, and applications are usually large, therefore, they are stored with low-cost NAND Flash. In terms of speed, the execution speed of the program in nor flash is far less than the execution speed in SDRAM. In order to pursue a higher speed, relocate is also required for the program to be executed in SDRAM.
Relocate involves two concepts: loading a domain (VMA) and running a domain (LMA. The loading domain is the sorting order and address arrangement of the program code in ROM and flash, and the running domain is the address arrangement of the runtime code in SRAM and SDRAM. When storing code, the code is stored in Flash according to the loading domain. When running, the code is extracted from flash and run in the ram running domain. The loading domain and storage domain of a piece of code can be different. (For more information, see the relevant chapter in "ARM architecture and programming" by Du chunlei ).
Take smdk2410 as an example, closely related to the two folders/board/smdk2410 and/CPU/ARM920T, which is the core file on the u-boot.lds, config. mk, start. S.
// CPU/ARM920T/u-boot.lds
Output_format ("elf32-littlearm", "elf32-littlearm", "elf32-littlearm ")
Output_arch (ARM)
Entry (_ start)
Sections
{
. = 0x00000000; // starts from 0
. = Align (4 );
. Text:
{
CPU/ARM920T/start. O (. Text)
* (. Text)
}
. = Align (4 );
. Rodata: {* (sort_by_alignment (sort_by_name (. rodata *)))}
. = Align (4 );
. Data: {* (. Data )}
. = Align (4 );
. Got: {* (. Got )}
. = .;
_ U_boot_1__start = .;
. U_boot_cmd: {* (. u_boot_cmd )}
_ U_boot_1__end = .;
. = Align (4 );
_ Bss_start = .;
. BSS (noload): {* (. BSS). = align (4 );}
_ End = .;
}
No LMA is set in the connection script file LDs, but VMA is set. VMA settings are implemented through ldflags In the config. mk file in the top-level directory. text_base is defined as 0x33f80000 (SDRAM address) in/board/smdk2410/config. mk ).
Ldflags + =-bstatic-T $ (OBJ) u-boot.lds $ (platform_ldflags)
Ifneq ($ (text_base ),)
Ldflags + =-ttext $ (text_base)
Endif
View the u-boot.map file where the connection address of the Code starts from 0x33f80000.
167. Text 0x33f80000 0x232c8
168 CPU/ARM920T/start. O (. Text)
169. Text 0x33f80000 0x4a0 CPU/ARM920T/start. o
170 0x33f80048 _ bss_start
171 0x33f8004c _ bss_end
172 0x33f80044 _ armboot_start
173 0x33f80000 _ start
174 board/Samsung/fs2410/lowlevel_init.o (. Text)
175. Text 0x33f804a0 0x64 board/Samsung/fs2410/lowlevel_init.o
176 0x33f804a4 lowlevel_init
177 board/Samsung/fs2410/nand_read.o (. Text)
178. Text 0x33f80504 0xe8 board/Samsung/fs2410/nand_read.o
179 0x33f80504 wait_idle
180 0x33f80518 nand_read_ll
The reason why the bootloader code can be correctly executed after power-on is that the initial bootloader code is address-independent, that is, this image file can be run on any address in the memory.
For address-independent code, addressing is based on the PC value. On the Pc value, +/-an offset is worth reaching the running address, such as the jump command B. After the code is executed, You need to jump to the address-related place for execution, that is, in Ram. Usually Jump to a label, and the address-related code starts to run, such as ldr pc, _ start_armboot.
When the bin image is generated, the _ start_armboot symbol has been bound with the actual address. When the ldr pc, _ start_armboot statement is executed, the program jumps from execution in the Rom to ram, provided that the code is moved. Run ldr pc, _ start_armboot without code handling. Because no correct executable code exists in Ram, the program will fly away immediately. All codes related to absolute addresses cannot be addressed before code handling, the address of the Code that must be executed is irrelevant.
The following code is carried from nor flash to SDRAM:
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
Note that the ADR r0, _ start is a pseudo command, which is generally replaced by sub r0, PC, # offset, do not read the address that complies with the _ start symbol in the table (0x33f80000 ). When power-on is started, the PC starts from 0. Therefore, the R0 value is 0 + offset, not equal to _ text_base (0x33f80000 ). Next we need to use the signed address _ armboot_start (0x33f80044) identified during the link, and set _ start: 0x0 (nor flash. text ,. data Code: 0x33f80000. The SDRAM base address of S3C2410 is 0x3000_0000, because uboot supports this board sdram64m (0x3000_0000-0x3400_0000), so the u-boot.bin is moved to the high-end address of memory. Then jump to the memory for execution, increase the speed.