summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Powell <john.powell@arm.com>2026-05-20 16:42:56 -0500
committerJohn Powell <john.powell@arm.com>2026-06-30 14:56:12 +0000
commit769380b33b0a20f6c05b22e6897680a9e28f573d (patch)
tree266fee0f77e19b014a2202d42fcf1a0d11e48a11
parent1a95ccecd33ed1ac13c748461cdd5df5c9a41657 (diff)
downloadarm-trusted-firmware-769380b33b0a20f6c05b22e6897680a9e28f573d.tar.gz
arm-trusted-firmware-769380b33b0a20f6c05b22e6897680a9e28f573d.zip
feat(lfa): bl31 linker file updates for lfa
This patch modifies the BL31 linker script to carve out regions needed by BL31 live activation framework. Change-Id: I8b5f38a62e159bf1cad8dc4ab74cf6a9bb137074 Signed-off-by: John Powell <john.powell@arm.com>
-rw-r--r--bl31/bl31.ld.S86
1 files changed, 84 insertions, 2 deletions
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index bb337f403..d156680b8 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -7,13 +7,20 @@
#include <common/bl_common.ld.h>
#include <lib/per_cpu/per_cpu_defs.h>
#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <platform_def.h>
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
ENTRY(bl31_entrypoint)
MEMORY {
- RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_LIMIT - BL31_BASE
+
+ RAM (rwx): ORIGIN = BL31_BASE, \
+ LENGTH = BL31_LIMIT - BL31_BASE - (ENABLE_LFA_BL31 * (2 * PAGE_SIZE))
+
+#if ENABLE_LFA_BL31
+ LFA (rwx): ORIGIN = BL31_LIMIT - (2 * PAGE_SIZE), LENGTH = (2 * PAGE_SIZE)
+#endif
#if SEPARATE_NOBITS_REGION
NOBITS (rw!a): ORIGIN = BL31_NOBITS_BASE, LENGTH = BL31_NOBITS_LIMIT - BL31_NOBITS_BASE
@@ -50,6 +57,33 @@ SECTIONS {
__TEXT_START__ = .;
*bl31_entrypoint.o(.text*)
+
+#if ENABLE_LFA_BL31
+ /*
+ * When LFA for BL31 is enabled we must group these two subsections
+ * together so they live in a fixed area of the binary that can be
+ * padded to a constant size. This means this section can be replaced
+ * on it's own and expand for new workarounds to be added. Otherwise
+ * the linker is free to do whatever it likes with them in text and
+ * rodata as usual.
+ */
+ . = ALIGN(PAGE_SIZE);
+ __ERRATA_START__ = .;
+ *(.text.errata*)
+ *(.rodata.errata*)
+
+ ASSERT(PLAT_LFA_ERRATA_SECTION_SIZE >= (. - __ERRATA_START__),
+ "Section .errata is too big for PLAT_LFA_ERRATA_SECTION_SIZE!");
+
+ FILL(0x00)
+ . += (( PLAT_LFA_ERRATA_SECTION_SIZE > (. - __ERRATA_START__) )
+ ? ( PLAT_LFA_ERRATA_SECTION_SIZE - (. - __ERRATA_START__) )
+ : 0);
+
+ . = ALIGN(PAGE_SIZE);
+ __ERRATA_END__ = .;
+#endif
+
*(SORT_BY_ALIGNMENT(SORT(.text*)))
*(.vectors)
__TEXT_END_UNALIGNED__ = .;
@@ -91,6 +125,33 @@ SECTIONS {
__RO_START__ = .;
*bl31_entrypoint.o(.text*)
+
+#if ENABLE_LFA_BL31
+ /*
+ * When LFA for BL31 is enabled we must group these two subsections
+ * together so they live in a fixed area of the binary that can be
+ * padded to a constant size. This means this section can be replaced
+ * on it's own and expand for new workarounds to be added. Otherwise
+ * the linker is free to do whatever it likes with them in text and
+ * rodata as usual.
+ */
+ . = ALIGN(PAGE_SIZE);
+ __ERRATA_START__ = .;
+ *(.text.errata*)
+ *(.rodata.errata*)
+
+ ASSERT(PLAT_LFA_ERRATA_SECTION_SIZE >= (. - __ERRATA_START__),
+ "Section .errata is too big for PLAT_LFA_ERRATA_SECTION_SIZE!");
+
+ FILL(0x00)
+ . += (( PLAT_LFA_ERRATA_SECTION_SIZE > (. - __ERRATA_START__) )
+ ? ( PLAT_LFA_ERRATA_SECTION_SIZE - (. - __ERRATA_START__) )
+ : 0);
+
+ . = ALIGN(PAGE_SIZE);
+ __ERRATA_END__ = .;
+#endif
+
*(SORT_BY_ALIGNMENT(.text*))
*(SORT_BY_ALIGNMENT(.rodata*))
@@ -147,6 +208,26 @@ SECTIONS {
. = LOADADDR(.spm_shim_exceptions) + SIZEOF(.spm_shim_exceptions);
#endif /* SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP) */
+#if ENABLE_LFA_BL31
+ .lfa_relocatable : ALIGN(PAGE_SIZE) {
+ __LFA_RELOCATABLE_CODE_START__ = .;
+ KEEP(*(.lfa_relocatable_code*))
+ __LFA_RELOCATABLE_CODE_END__ = .;
+ . = ALIGN(PAGE_SIZE);
+ __LFA_RELOCATABLE_DATA_START__ = .;
+ KEEP(*(.lfa_relocatable_data*))
+ . = ALIGN(PAGE_SIZE);
+ __LFA_RELOCATABLE_DATA_END__ = .;
+ __LFA_RELOCATABLE_LIMIT__ = .;
+ } >LFA AT> RAM
+
+ PROVIDE(__LFA_RELOCATABLE_LMA__ = LOADADDR(.lfa_relocatable));
+
+ . = LOADADDR(.lfa_relocatable) + SIZEOF(.lfa_relocatable);
+ ASSERT(__LFA_RELOCATABLE_LIMIT__ <= BL31_LIMIT, \
+ "__LFA_RELOCATABLE_END__ has exceeded its limit.")
+#endif /* ENABLE_LFA_BL31 */
+
#if SEPARATE_RWDATA_REGION
. = BL31_RWDATA_BASE;
ASSERT(BL31_RWDATA_BASE == ALIGN(PAGE_SIZE),
@@ -193,7 +274,8 @@ SECTIONS {
#endif /* SEPARATE_RWDATA_REGION */
__BL31_END__ = .;
- ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.")
+ ASSERT(. <= BL31_LIMIT - (ENABLE_LFA_BL31 * (2 * PAGE_SIZE)), \
+ "BL31 image has exceeded its limit.")
. = BL31_NOBITS_BASE;