Memory Management
Note
This information is outdated and needs to be updated.
U-Boot runs in system state and uses physical addresses, i.e. the MMU is not used either for address mapping nor for memory protection.
The available memory is mapped to fixed addresses using the memory-controller. In this process, a contiguous block is formed for each memory type (Flash, SDRAM, SRAM), even when it consists of several physical-memory banks.
U-Boot is installed in XIP flash memory, or may be loaded into a lower region of RAM by a secondary program loader (SPL). After booting and sizing and initialising DRAM, the code relocates itself to the upper end of DRAM. Immediately below the U-Boot code some memory is reserved for use by malloc() [see CONFIG_SYS_MALLOC_LEN configuration setting]. Below that, a structure with global Board-Info data is placed, followed by the stack (growing downward).
Additionally, some exception handler code may be copied to the low 8 kB of DRAM (0x00000000 … 0x00001fff).
So a typical memory configuration with 16 MB of DRAM could look like this:
0x0000 0000 Exception Vector code
:
0x0000 1fff
0x0000 2000 Free for Application Use
:
:
:
:
0x00fb ff20 Monitor Stack (Growing downward)
0x00fb ffac Board Info Data and permanent copy of global data
0x00fc 0000 Malloc Arena
:
0x00fd ffff
0x00fe 0000 RAM Copy of Monitor Code
... eventually: LCD or video framebuffer
... eventually: pRAM (Protected RAM - unchanged by reset)
0x00ff ffff [End of RAM]
System RAM Utilization in U-Boot in ARM
Let us break down the relevant parts of the execution sequence where system RAM comes into play. Please note that these are individual pieces of the entire boot sequence. It is not exhaustive, rather it aims to show only the pieces where the system RAM is modified. See arch/arm/lib/crt0* to understand the complete execution sequence.
Also note that the below sequence is not a hard and fast rule on how DRAM usage would be and an architecture and board specific analysis is required for the exact flow.
SPL Flow
Pre-DRAM
Prior to setting up of the DRAM, the stack, malloc is defined as below possibly sitting on a smaller readily available memory (SRAM etc.):
![]()
Please see CONFIG_SPL_EARLY_BSS if BSS initialization is needed prior to entering board_init_f().
DRAM Initialization
This is typically triggered by board_init_f prior to relocating the stack and the GD (optionally) to the system RAM. DRAM drivers reside in drivers/ram/. Their probe/configuration can be done either via placing the logic in dram_init() or wherever deemed applicable within board_init_f.
Post board_init_f, spl_relocate_stack_gd() is called to relocate the stack and the GD to the newly initialized DRAM. If CONFIG_SPL_SYS_MALLOC_SIMPLE is set it is also possible to use some amount of this DRAM stack as memory pool for malloc_simple.
Both of which are an optional move at this point in the sequence. This is still an intermediate environment.
Final Environment Set Up
The final environment is setup and the system RAM now looks like this:
![]()
Again stack and gd are an optional move and may still remain in the available RAM (SRAM, locked cache etc.)
U-Boot Proper Flow
TODO: this section is still under progress
DRAM Initialization
This follows the same as in SPL flow. In board_init_f(), a part of memory is reserved at the end of RAM (see reserve_* functions in init_sequence_f)
Code Relocation
relocate_code() is called which relocates U-Boot code from the current location into the relocation destination in system RAM. Typically it is relocated to the upper portion of the memory. So DRAM now has: * stack * gd * code
The code relocation happens to the upper portion of the memory after certain portion of memory is reserved. This is memory that is intended to not be “touched” by U-Boot.
Final Environment Set Up
At this stage we are completely running out of the system RAM with: * stack * gd * code * bss * initialized non-const data * initialized const data
It is better to do a complete analysis to visualize the layers the system RAM is composed of at the end of this flow. This is entirely dependent on CPU/SoC architecture.
Getting information about system RAM
At boot:
The prints given by announce_dram_init() and show_dram_config() come up in the boot banner like so:
DRAM: 2 GiB (total 32 GiB)U-Boot supports addressing upto 39-bit. To avoid trying to access higher addresses in systems with > 39-bit addresses, U-Boot caps itself (gd->ram_size) to the first bank. This is also inline with philosophy that U-Boot is a bootloader and not a full-fledged operating system. The first value represents this memory that is available for U-Boot while the “total” value represents the total system RAM available on the device.
Getting the most basic information on how system RAM has been set up is by running bdinfo at U-Boot prompt:
=> bdinfo boot_params = 0x0000000000000000 DRAM bank = 0x0000000000000000 -> start = 0x0000000080000000 -> size = 0x0000000080000000 DRAM bank = 0x0000000000000001 -> start = 0x0000000880000000 -> size = 0x0000000780000000 flashstart = 0x0000000000000000 flashsize = 0x0000000000000000 flashoffset = 0x0000000000000000 baudrate = 115200 bps relocaddr = 0x00000000ffec1000 reloc off = 0x000000007f6c1000 Build = 64-bit current eth = ethernet@46000000port@1 ethaddr = 3c:e0:64:62:4b:4e IP addr = <NULL> fdt_blob = 0x00000000fde7df60 lmb_dump_all: memory.count = 0x1 memory[0] [0x80000000-0xffffffff], 0x80000000 bytes flags: none reserved.count = 0x2 reserved[0] [0x9e800000-0xabffffff], 0x0d800000 bytes flags: no-map reserved[1] [0xfce79f50-0xffffffff], 0x031860b0 bytes flags: no-overwrite devicetree = separate serial addr = 0x0000000002880000 width = 0x0000000000000000 shift = 0x0000000000000002 offset = 0x0000000000000000 clock = 0x0000000002dc6c00 arch_number = 0x0000000000000000 TLB addr = 0x00000000ffff0000 irq_sp = 0x00000000fde7df50 sp start = 0x00000000fde7df50 Early malloc usage: 3288 / 8000Here you are able to see the banks of DDR that have been set up in DRAM bank -> start and -> size as well as the reserved memories in lmb_dump_all.
Testing Memory
Please see doc/README.memory-test