moving u-boot in ARM architecture
Here is the whole sequence for a two-step boot process:
- The ROM code reads the SPL (from the
MLO file on the SD card) to the address CONFIG_SPL_TEXT_BASE . This address is usually located in SRAM, which does not need to be initialized to be functional (as opposed to RAM). The ROM code goes to the SPL code. - SPL sets up the RAM, then reads u-boot (from the
u-boot.img on the SD card) to the address CONFIG_SYS_TEXT_BASE RAM (which is usually located at the beginning of RAM) and starts it - u-boot will go to
gd->relocaddr RAM address (which is usually located at the end of RAM) and go to the moved code - Now we are ready to load the kernel
For a one-step download, you do not have an SPL and usually use the u-boot.bin . In this case, you only have steps 3 and 4.
There are two cases regarding relocation (as described in doc / README.arm-relocation ):
CONFIG_SYS_TEXT_BASE != gd->relocaddr : movingCONFIG_SYS_TEXT_BASE == gd->relocaddr : move will not be performed
In your case, you see that the move was done (like CONFIG_SYS_TEXT_BASE != gd->relocaddr ).
So, referring to your question:
Why does U-Boot need these two offsets?
The reason for this move is described in the ARM u-boot reboot task :
... we can measure the actual size of the memory present on the board, and then move the U-Boot to the very end of the RAM, leaving almost all of the RAM as one large contiguous area for the βapplicationsβ like loading the Linux kernel, ramdisk, etc. d.
In fact, if you look at the code, you can see that gd->relocaddr is the end of RAM minus the size of the monitor code (U-Boot):
gd->relocaddr = gd->ram_top; ... gd->relocaddr -= gd->mon_len;
Some additional memory backup may also be performed. For example, on my platform (TI DRA7XX EVM), I see the following functions called:
setup_dest_addr() reserve_round_4k() reserve_mmu() reserve_uboot()
The actual move is done immediately after calling board_init_f() .
arch / arm / Library / crt0.S
bl board_init_f ... b relocate_code
arch / arm / Library / relocate.S
ENTRY(relocate_code)
Now it is easy to answer the following question:
What is the real amount of U-Boot memory?
Before moving, the U-Boot is in CONFIG_SYS_TEXT_BASE . After moving, the U-Boot is in gs->relocaddr .
Regarding your last question:
Where can I put my core in confidence that it will not overwrite something?
Since the U-Boot was moved to the end of RAM, theoretically you can use any RAM address to install the kernel. But look at the definition of CONFIG_EXTRA_ENV_SETTINGS in include/configs/zynq-common.h :
"sdboot=if mmcinfo; then " \ "run uenvboot; " \ "echo Copying Linux from SD to RAM... && " \ "load mmc 0 ${kernel_load_address} ${kernel_image} && " \ "load mmc 0 ${devicetree_load_address} ${devicetree_image} && " \ "load mmc 0 ${ramdisk_load_address} ${ramdisk_image} && " \ "bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; " \ "fi\0" \
From there, you can see that you should load the kernel at ${kernel_load_address} , which is 0x2080000 :
"kernel_load_address=0x2080000\0" \
See the rest of this definition for other constants.
bdinfo team
You can find the bdinfo command useful: the move address and other useful information can be found using the bdinfo from the U-Boot shell. For example, for DRA7XX EVM:
=> bdinfo DRAM bank = 0x00000000 -> start = 0x80000000 -> size = 0x60000000 TLB addr = 0xDFFF0000 relocaddr = 0xDFF5D000 reloc off = 0x5F75D000 irq_sp = 0xDEF3CEE0 sp start = 0xDEF3CED0
From here you can see that:
- RAM starts at
0x80000000 - RAM Size
0x60000000 - ... so the end of RAM (
gd->ram_top ) is 0x80000000 + 0x60000000 = 0xE0000000 - Move Address
0xDFF5D000 - reserved memory for moving -
0xE0000000 - 0xDFF5D000 = 652 KB - The size of the monitor (U-Boot) is approximately
TLB addr - relocaddr = 0xDFFF0000 - 0xDFF5D000 = 588 KB
See also:
[1] u-boot: Moving
[2] what is used SPL (secondary program loader)
[3] commit, which adds support for moving ARM to u-boot