Update user guide further to linker scripts changes
This patch updates the user guide section about the memory layout. - Explain the verifications that the linker scripts does on the global memory layout. - Refer to the new linker symbols. - Describe the linker symbols exported to the trusted firmware code. Change-Id: I033ab2b867e8b9776deb4185b9986bcb8218f286
This commit is contained in:
parent
65f546a14f
commit
cd29b0a60c
|
@ -26,6 +26,20 @@ Detailed changes since last release
|
||||||
|
|
||||||
* Build products are now created in a separate build directory tree.
|
* Build products are now created in a separate build directory tree.
|
||||||
|
|
||||||
|
* Analyze at link-time whether bootloader images will fit in memory and won't
|
||||||
|
overlap each other at run time. If it is not the case then image linking
|
||||||
|
will now fail.
|
||||||
|
|
||||||
|
* Reduce the size of the bootloader images by cutting some sections out of
|
||||||
|
their disk images and allocating them at load time, whenever possible.
|
||||||
|
|
||||||
|
* Properly initialise the C runtime environment. C code can now safely assume
|
||||||
|
that global variables are initialised to 0 and that initialised data holds
|
||||||
|
the correct value.
|
||||||
|
|
||||||
|
* General changes on the memory layout: some sections have been moved, some of
|
||||||
|
them have been merged together, and some alignment constraints on sections
|
||||||
|
have changed.
|
||||||
|
|
||||||
ARM Trusted Firmware - version 0.2
|
ARM Trusted Firmware - version 0.2
|
||||||
==================================
|
==================================
|
||||||
|
|
|
@ -164,11 +164,12 @@ constants defined. In the ARM FVP port, this file is found in
|
||||||
* **#define : BL2_BASE**
|
* **#define : BL2_BASE**
|
||||||
|
|
||||||
Defines the base address in secure RAM where BL1 loads the BL2 binary image.
|
Defines the base address in secure RAM where BL1 loads the BL2 binary image.
|
||||||
|
Must be aligned on a page-size boundary.
|
||||||
|
|
||||||
* **#define : BL31_BASE**
|
* **#define : BL31_BASE**
|
||||||
|
|
||||||
Defines the base address in secure RAM where BL2 loads the BL3-1 binary
|
Defines the base address in secure RAM where BL2 loads the BL3-1 binary
|
||||||
image.
|
image. Must be aligned on a page-size boundary.
|
||||||
|
|
||||||
|
|
||||||
### Other mandatory modifications
|
### Other mandatory modifications
|
||||||
|
|
|
@ -883,15 +883,133 @@ world software image at the highest available Exception Level (EL2 if
|
||||||
available, otherwise EL1).
|
available, otherwise EL1).
|
||||||
|
|
||||||
|
|
||||||
### Memory layout on Base FVP
|
### Memory layout on FVP platforms
|
||||||
|
|
||||||
|
On FVP platforms, we use the Trusted ROM and Trusted SRAM to store the trusted
|
||||||
|
firmware binaries. BL1 is originally sitting in the Trusted ROM. Its read-write
|
||||||
|
data are relocated at the base of the Trusted SRAM at runtime. BL1 loads BL2
|
||||||
|
image near the top of the the trusted SRAM. BL2 loads BL3-1 image between BL1
|
||||||
|
and BL2. This memory layout is illustrated by the following diagram.
|
||||||
|
|
||||||
|
Trusted SRAM
|
||||||
|
+----------+ 0x04040000
|
||||||
|
| |
|
||||||
|
|----------|
|
||||||
|
| BL2 |
|
||||||
|
|----------|
|
||||||
|
| |
|
||||||
|
|----------|
|
||||||
|
| BL31 |
|
||||||
|
|----------|
|
||||||
|
| |
|
||||||
|
|----------|
|
||||||
|
| BL1 (rw) |
|
||||||
|
+----------+ 0x04000000
|
||||||
|
|
||||||
|
Trusted ROM
|
||||||
|
+----------+ 0x04000000
|
||||||
|
| BL1 (ro) |
|
||||||
|
+----------+ 0x00000000
|
||||||
|
|
||||||
|
Each bootloader stage image layout is described by its own linker script. The
|
||||||
|
linker scripts export some symbols into the program symbol table. Their values
|
||||||
|
correspond to particular addresses. The trusted firwmare code can refer to these
|
||||||
|
symbols to figure out the image memory layout.
|
||||||
|
|
||||||
|
Linker symbols follow the following naming convention in the trusted firmware.
|
||||||
|
|
||||||
|
* `__<SECTION>_START__`
|
||||||
|
|
||||||
|
Start address of a given section named `<SECTION>`.
|
||||||
|
|
||||||
|
* `__<SECTION>_END__`
|
||||||
|
|
||||||
|
End address of a given section named `<SECTION>`. If there is an alignment
|
||||||
|
constraint on the section's end address then `__<SECTION>_END__` corresponds
|
||||||
|
to the end address of the section's actual contents, rounded up to the right
|
||||||
|
boundary. Refer to the value of `__<SECTION>_UNALIGNED_END__` to know the
|
||||||
|
actual end address of the section's contents.
|
||||||
|
|
||||||
|
* `__<SECTION>_UNALIGNED_END__`
|
||||||
|
|
||||||
|
End address of a given section named `<SECTION>` without any padding or
|
||||||
|
rounding up due to some alignment constraint.
|
||||||
|
|
||||||
|
* `__<SECTION>_SIZE__`
|
||||||
|
|
||||||
|
Size (in bytes) of a given section named `<SECTION>`. If there is an
|
||||||
|
alignment constraint on the section's end address then `__<SECTION>_SIZE__`
|
||||||
|
corresponds to the size of the section's actual contents, rounded up to the
|
||||||
|
right boundary. In other words, `__<SECTION>_SIZE__ = __<SECTION>_END__ -
|
||||||
|
_<SECTION>_START__`. Refer to the value of `__<SECTION>_UNALIGNED_SIZE__`
|
||||||
|
to know the actual size of the section's contents.
|
||||||
|
|
||||||
|
* `__<SECTION>_UNALIGNED_SIZE__`
|
||||||
|
|
||||||
|
Size (in bytes) of a given section named `<SECTION>` without any padding or
|
||||||
|
rounding up due to some alignment constraint. In other words,
|
||||||
|
`__<SECTION>_UNALIGNED_SIZE__ = __<SECTION>_UNALIGNED_END__ -
|
||||||
|
__<SECTION>_START__`.
|
||||||
|
|
||||||
|
Some of the linker symbols are mandatory as the trusted firmware code relies on
|
||||||
|
them to be defined. They are listed in the following subsections. Some of them
|
||||||
|
must be provided for each bootloader stage and some are specific to a given
|
||||||
|
bootloader stage.
|
||||||
|
|
||||||
|
The linker scripts define some extra, optional symbols. They are not actually
|
||||||
|
used by any code but they help in undertanding the bootloader images' memory
|
||||||
|
layout as they are easy to spot in the link map files.
|
||||||
|
|
||||||
|
#### Common linker symbols
|
||||||
|
|
||||||
|
Early setup code needs to know the extents of the BSS section to zero-initialise
|
||||||
|
it before executing any C code. The following linker symbols are defined for
|
||||||
|
this purpose:
|
||||||
|
|
||||||
|
* `__BSS_START__` This address must be aligned on a 16-byte boundary.
|
||||||
|
* `__BSS_SIZE__`
|
||||||
|
|
||||||
|
Similarly, the coherent memory section must be zero-initialised. Also, the MMU
|
||||||
|
setup code needs to know the extents of this section to set the right memory
|
||||||
|
attributes for it. The following linker symbols are defined for this purpose:
|
||||||
|
|
||||||
|
* `__COHERENT_RAM_START__` This address must be aligned on a page-size boundary.
|
||||||
|
* `__COHERENT_RAM_END__` This address must be aligned on a page-size boundary.
|
||||||
|
* `__COHERENT_RAM_UNALIGNED_SIZE__`
|
||||||
|
|
||||||
|
#### BL1's linker symbols
|
||||||
|
|
||||||
|
BL1's early setup code needs to know the extents of the .data section to
|
||||||
|
relocate it from ROM to RAM before executing any C code. The following linker
|
||||||
|
symbols are defined for this purpose:
|
||||||
|
|
||||||
|
* `__DATA_ROM_START__` This address must be aligned on a 16-byte boundary.
|
||||||
|
* `__DATA_RAM_START__` This address must be aligned on a 16-byte boundary.
|
||||||
|
* `__DATA_SIZE__`
|
||||||
|
|
||||||
|
BL1's platform setup code needs to know the extents of its read-write data
|
||||||
|
region to figure out its memory layout. The following linker symbols are defined
|
||||||
|
for this purpose:
|
||||||
|
|
||||||
|
* `__BL1_RAM_START__` This is the start address of BL1 RW data.
|
||||||
|
* `__BL1_RAM_END__` This is the end address of BL1 RW data.
|
||||||
|
|
||||||
|
#### BL2's and BL3-1's linker symbols
|
||||||
|
|
||||||
|
Both BL2 and BL3-1 need to know the extents of their read-only section to set
|
||||||
|
the right memory attributes for this memory region in their MMU setup code. The
|
||||||
|
following linker symbols are defined for this purpose:
|
||||||
|
|
||||||
|
* `__RO_START__`
|
||||||
|
* `__RO_END__`
|
||||||
|
|
||||||
|
#### How to choose the right base address for each bootloader stage image
|
||||||
|
|
||||||
The current implementation of the image loader has some limitations. It is
|
The current implementation of the image loader has some limitations. It is
|
||||||
designed to load images dynamically, at a load address chosen to minimize memory
|
designed to load images dynamically, at a load address chosen to minimize memory
|
||||||
fragmentation. The chosen image location can be either at the top or the bottom
|
fragmentation. The chosen image location can be either at the top or the bottom
|
||||||
of free memory. However, until this feature is fully functional, the code also
|
of free memory. However, until this feature is fully functional, the code also
|
||||||
contains support for loading images at a link-time fixed address. The code that
|
contains support for loading images at a link-time fixed address.
|
||||||
dynamically calculates the load address is bypassed and the load address is
|
|
||||||
specified statically by the platform.
|
|
||||||
|
|
||||||
BL1 is always loaded at address `0x0`. BL2 and BL3-1 are loaded at specified
|
BL1 is always loaded at address `0x0`. BL2 and BL3-1 are loaded at specified
|
||||||
locations in Trusted SRAM. The lack of dynamic image loader support means these
|
locations in Trusted SRAM. The lack of dynamic image loader support means these
|
||||||
|
@ -899,42 +1017,79 @@ load addresses must currently be adjusted as the code grows. The individual
|
||||||
images must be linked against their ultimate runtime locations.
|
images must be linked against their ultimate runtime locations.
|
||||||
|
|
||||||
BL2 is loaded near the top of the Trusted SRAM. BL3-1 is loaded between BL1
|
BL2 is loaded near the top of the Trusted SRAM. BL3-1 is loaded between BL1
|
||||||
and BL2. As a general rule, the following constraints must always be enforced:
|
and BL2. All three images are resident concurrently in Trusted RAM during boot
|
||||||
|
so overlaps are not permitted.
|
||||||
|
|
||||||
1. `BL2_MAX_ADDR <= (<Top of Trusted SRAM>)`
|
The image end addresses can be determined from the link map files of the
|
||||||
2. `BL31_BASE >= BL1_MAX_ADDR`
|
different images. These are the `build/<platform>/<build-type>/bl<x>/bl<x>.map`
|
||||||
3. `BL2_BASE >= BL31_MAX_ADDR`
|
files, with `<x>` the stage bootloader.
|
||||||
|
|
||||||
Constraint 1 is enforced by BL2's linker script. If it is violated then the
|
* `bl1.map` link map file provides `__BL1_RAM_END__` address.
|
||||||
|
* `bl2.map` link map file provides `__BL2_END__` address.
|
||||||
|
* `bl31.map` link map file provides `__BL31_END__` address.
|
||||||
|
|
||||||
|
To prevent images from overlapping each other, the following constraints must be
|
||||||
|
enforced:
|
||||||
|
|
||||||
|
1. `__BL1_RAM_END__ <= BL31_BASE`
|
||||||
|
2. `__BL31_END__ <= BL2_BASE`
|
||||||
|
3. `__BL2_END__ <= (<Top of Trusted SRAM>)`
|
||||||
|
|
||||||
|
This is illustrated by the following memory layout diagram:
|
||||||
|
|
||||||
|
+----------+ 0x04040000
|
||||||
|
| |
|
||||||
|
|----------| __BL2_END__
|
||||||
|
| BL2 |
|
||||||
|
|----------| BL2_BASE
|
||||||
|
| |
|
||||||
|
|----------| __BL31_END__
|
||||||
|
| BL31 |
|
||||||
|
|----------| BL31_BASE
|
||||||
|
| |
|
||||||
|
|----------| __BL1_RAM_END__
|
||||||
|
| BL1 (rw) |
|
||||||
|
+----------+ 0x04000000
|
||||||
|
|
||||||
|
Overlaps are detected during image linking as follows.
|
||||||
|
|
||||||
|
Constraint 1 is enforced by BL1's linker script. If it is violated then the
|
||||||
|
linker will report an error while building BL1 to indicate that it doesn't
|
||||||
|
fit:
|
||||||
|
|
||||||
|
aarch64-none-elf-ld: BL31 image overlaps BL1 image.
|
||||||
|
|
||||||
|
This error means that the BL3-1 base address needs to be incremented. Ensure
|
||||||
|
that the new memory layout still obeys all constraints.
|
||||||
|
|
||||||
|
Constraint 2 is enforced by BL3-1's linker script. If it is violated then the
|
||||||
|
linker will report an error while building BL3-1 to indicate that it doesn't
|
||||||
|
fit:
|
||||||
|
|
||||||
|
aarch64-none-elf-ld: BL31 image overlaps BL2 image.
|
||||||
|
|
||||||
|
This error can either mean that the BL3-1 base address needs to be decremented
|
||||||
|
or that BL2 base address needs to be incremented. Ensure that the new memory
|
||||||
|
layout still obeys all constraints.
|
||||||
|
|
||||||
|
Constraint 3 is enforced by BL2's linker script. If it is violated then the
|
||||||
linker will report an error while building BL2 to indicate that it doesn't
|
linker will report an error while building BL2 to indicate that it doesn't
|
||||||
fit. For example:
|
fit. For example:
|
||||||
|
|
||||||
aarch64-none-elf-ld: address 0x40400c8 of bl2.elf section `.bss' is not
|
aarch64-none-elf-ld: address 0x40400c8 of bl2.elf section `.bss' is not
|
||||||
within region `RAM'
|
within region `RAM'
|
||||||
|
|
||||||
This error means that the BL2 base address needs to be moved down. Be sure that
|
This error means that the BL2 base address needs to be decremented. Ensure that
|
||||||
the new BL2 load address still obeys constraint 3.
|
the new memory layout still obeys all constraints.
|
||||||
|
|
||||||
Constraints 2 & 3 must currently be checked by hand. To ensure they are
|
Since constraint checks are scattered across linker scripts, it is required to
|
||||||
enforced, first determine the maximum addresses used by BL1 and BL3-1. This can
|
`make clean` prior to building to ensure that all possible overlapping scenarios
|
||||||
be deduced from the link map files of the different images.
|
are checked.
|
||||||
|
|
||||||
The BL1 link map file (`bl1.map`) gives these 2 values:
|
The current implementation of the image loader can result in wasted space
|
||||||
|
because of the simplified data structure used to represent the extents of free
|
||||||
* `FIRMWARE_RAM_COHERENT_START`
|
memory. For example, to load BL2 at address `0x0402D000`, the resulting memory
|
||||||
* `FIRMWARE_RAM_COHERENT_SIZE`
|
layout should be as follows:
|
||||||
|
|
||||||
The maximum address used by BL1 can then be easily determined:
|
|
||||||
|
|
||||||
BL1_MAX_ADDR = FIRMWARE_RAM_COHERENT_START + FIRMWARE_RAM_COHERENT_SIZE
|
|
||||||
|
|
||||||
The BL3-1 link map file (`bl31.map`) gives the following value:
|
|
||||||
|
|
||||||
* `BL31_DATA_STOP`. This is the the maximum address used by BL3-1.
|
|
||||||
|
|
||||||
The current implementation can result in wasted space because a simplified
|
|
||||||
`meminfo` structure represents the extents of free memory. For example, to load
|
|
||||||
BL2 at address `0x04020000`, the resulting memory layout should be as follows:
|
|
||||||
|
|
||||||
------------ 0x04040000
|
------------ 0x04040000
|
||||||
| | <- Free space (1)
|
| | <- Free space (1)
|
||||||
|
|
Loading…
Reference in New Issue