* [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments
@ 2026-08-24 7:29 Ahmad Fatoum
2026-08-24 7:29 ` [PATCH 2/4] efi: loader: map code-type page allocations executable Ahmad Fatoum
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Ahmad Fatoum @ 2026-08-24 7:29 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
From: Ahmad Fatoum <a.fatoum@barebox.org>
EFI runtime services support was added before barebox proper was made an
ELF and back then it proved too cumbersome to have two non-adjacent text
areas for each of the boot-time and run-time portions.
Now that barebox proper is an ELF, let's move the EFI runtime data and
text each into its own segment with the appropriate segment flags, so
pbl_mmu_setup_from_elf() can apply the correct protections.
The runtime sections are also moved between rodata and data rather than
at the end of the image: sections in a PT_LOAD must be contiguous, so in
the old position .bss would have had to move into the efirt_data
segment, inflating its p_memsz by all of barebox's bss, which would make
a BSS worth of memory unusable by the running kernel.
This does not yet introduce a functional change:
without ARM_MMU_PERMISSIONS, all cached mappings remain RWX.
Assisted-by: Claude:fable-5
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
arch/arm/lib32/barebox.lds.S | 12 +++++++++---
arch/arm/lib64/barebox.lds.S | 12 +++++++++---
include/asm-generic/barebox.lds.h | 6 ++++--
3 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/arch/arm/lib32/barebox.lds.S b/arch/arm/lib32/barebox.lds.S
index 02db3b9790b7..e5ef2d045218 100644
--- a/arch/arm/lib32/barebox.lds.S
+++ b/arch/arm/lib32/barebox.lds.S
@@ -13,6 +13,10 @@ PHDRS
text PT_LOAD FLAGS(5); /* PF_R | PF_X */
rodata PT_LOAD FLAGS(4); /* PF_R */
dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+#ifdef CONFIG_EFI_RUNTIME
+ efirt_text PT_LOAD FLAGS(5); /* PF_R | PF_X */
+ efirt_data PT_LOAD FLAGS(6); /* PF_R | PF_W */
+#endif
data PT_LOAD FLAGS(6); /* PF_R | PF_W */
}
@@ -63,6 +67,9 @@ SECTIONS
__end_rodata = .;
_etext = .;
+
+ BAREBOX_EFI_RUNTIME
+
_sdata = .;
.data : { *(.data*) } :data
@@ -73,8 +80,6 @@ SECTIONS
_edata = .;
- BAREBOX_EFI_RUNTIME
-
.image_end : { *(.__image_end) } :data
. = ALIGN(4);
@@ -94,4 +99,5 @@ SECTIONS
_barebox_image_size = __bss_start;
}
-NOCROSSREFS_FROM(.efi_runtime)
+NOCROSSREFS_FROM(.efi_runtime.text)
+NOCROSSREFS_FROM(.efi_runtime.data)
diff --git a/arch/arm/lib64/barebox.lds.S b/arch/arm/lib64/barebox.lds.S
index 1dddd6d1a942..a06a078d4142 100644
--- a/arch/arm/lib64/barebox.lds.S
+++ b/arch/arm/lib64/barebox.lds.S
@@ -12,6 +12,10 @@ PHDRS
text PT_LOAD FLAGS(5); /* PF_R | PF_X */
rodata PT_LOAD FLAGS(4); /* PF_R */
dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+#ifdef CONFIG_EFI_RUNTIME
+ efirt_text PT_LOAD FLAGS(5); /* PF_R | PF_X */
+ efirt_data PT_LOAD FLAGS(6); /* PF_R | PF_W */
+#endif
data PT_LOAD FLAGS(6); /* PF_R | PF_W */
}
@@ -43,14 +47,15 @@ SECTIONS
__end_rodata = .;
_etext = .;
+
+ BAREBOX_EFI_RUNTIME
+
_sdata = .;
.data : { *(.data*) } :data
_edata = .;
- BAREBOX_EFI_RUNTIME
-
.image_end : { *(.__image_end) } :data
. = ALIGN(4);
@@ -61,4 +66,5 @@ SECTIONS
_barebox_image_size = __bss_start;
}
-NOCROSSREFS_FROM(.efi_runtime)
+NOCROSSREFS_FROM(.efi_runtime.text)
+NOCROSSREFS_FROM(.efi_runtime.data)
diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h
index 008217e808cb..c672894ad502 100644
--- a/include/asm-generic/barebox.lds.h
+++ b/include/asm-generic/barebox.lds.h
@@ -157,7 +157,7 @@
#ifdef CONFIG_EFI_RUNTIME
#define BAREBOX_EFI_RUNTIME \
. = ALIGN(4096); \
- .efi_runtime : { \
+ .efi_runtime.text : { \
__efi_runtime_start = .; \
__efi_runtime_text_start = .; \
*(.efi_runtime.text*) \
@@ -166,12 +166,14 @@
*(.efi_runtime.rodata*) \
__efi_runtime_rodata_stop = .; \
. = ALIGN(4096); \
+ } :efirt_text \
+ .efi_runtime.data : { \
__efi_runtime_data_start = .; \
*(.efi_runtime.data*) \
*(.efi_runtime.bss*) \
__efi_runtime_data_stop = .; \
__efi_runtime_stop = .; \
- } \
+ } :efirt_data \
. = ALIGN(4096);
#else
#define BAREBOX_EFI_RUNTIME
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/4] efi: loader: map code-type page allocations executable
2026-08-24 7:29 [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments Ahmad Fatoum
@ 2026-08-24 7:29 ` Ahmad Fatoum
2026-08-24 7:29 ` [PATCH 3/4] ARM: allow CONFIG_ARM_MMU_PERMISSIONS together with EFI_RUNTIME Ahmad Fatoum
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Ahmad Fatoum @ 2026-08-24 7:29 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
From: Ahmad Fatoum <a.fatoum@barebox.org>
PE images are loaded into EFI_LOADER_CODE pages allocated from
conventional memory, which mmu_remap_memory_banks() would map
non-executable. The Linux arm64 EFI stub additionally relocates the
kernel into an EFI_LOADER_CODE allocation of its own and jumps to it,
so fixing this up at StartImage time only would not be enough.
Drop the erroneous comment and map executable pages RWX before handing
them out and revert them to regular cached memory when they are freed.
Assisted-by: Claude:fable-5
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
efi/loader/boot.c | 2 --
efi/loader/memory.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/efi/loader/boot.c b/efi/loader/boot.c
index 53c8fc5ff938..d361a71a4dae 100644
--- a/efi/loader/boot.c
+++ b/efi/loader/boot.c
@@ -3132,8 +3132,6 @@ efi_status_t __efi_start_image(efi_handle_t image_handle,
pr_info("Starting EFI payload at %p\n", entry);
- // FIXME: we need the below if we enable CONFIG_ARM_MMU_PERMISSIONS...
- // remap_range(info->image_base, info->image_size, MAP_ARCH(2));
sync_caches_for_execution();
efi_set_variable_usec("LoaderTimeExecUSec", &efi_systemd_vendor_guid,
diff --git a/efi/loader/memory.c b/efi/loader/memory.c
index 8931cd1bab52..d35f124d381e 100644
--- a/efi/loader/memory.c
+++ b/efi/loader/memory.c
@@ -7,14 +7,35 @@
#include <linux/sprintf.h>
#include <efi/loader.h>
#include <efi/error.h>
+#include <efi/mode.h>
#include <init.h>
#include <memory.h>
+#include <mmu.h>
#include <linux/list_sort.h>
#include <linux/sizes.h>
#include <dma.h>
efi_uintn_t efi_memory_map_key;
+/*
+ * EFI images and the code pages they allocate expect to be mapped RWX,
+ * matching the attributes we advertise in the memory map for the code
+ * memory types. The page tables set up from the ELF segments only cover
+ * the barebox image itself, so allocations from conventional memory are
+ * mapped non-executable when ARM_MMU_PERMISSIONS is enabled.
+ */
+static void efi_remap_pages(u64 addr, size_t size, maptype_t map_type)
+{
+ if (!arch_can_remap())
+ return;
+
+ /* EFI_ALLOCATE_ADDRESS may pass through an unaligned address */
+ if (!IS_ALIGNED(addr, PAGE_SIZE) || !IS_ALIGNED(size, PAGE_SIZE))
+ return;
+
+ remap_range((void *)(uintptr_t)addr, size, map_type);
+}
+
static efi_status_t find_pages_max(struct list_head *banks, size_t npages, size_t *page)
{
struct memory_bank *bank;
@@ -199,6 +220,12 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type,
res->flags |= IORESOURCE_EFI_ALLOC;
+ if (memory_type == EFI_LOADER_CODE ||
+ memory_type == EFI_BOOT_SERVICES_CODE ||
+ memory_type == EFI_RUNTIME_SERVICES_CODE)
+ efi_remap_pages(new_addr, npages << EFI_PAGE_SHIFT,
+ MAP_CACHED_RWX);
+
*memory = new_addr;
return EFI_SUCCESS;
}
@@ -301,6 +328,9 @@ efi_status_t efi_free_pages(uint64_t memory, size_t pages)
if (nfreed <= 0)
return EFI_INVALID_PARAMETER;
+ /* Revert a possible executable mapping of code-type allocations */
+ efi_remap_pages(memory, size, MAP_CACHED);
+
++efi_memory_map_key;
return EFI_SUCCESS;
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/4] ARM: allow CONFIG_ARM_MMU_PERMISSIONS together with EFI_RUNTIME
2026-08-24 7:29 [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments Ahmad Fatoum
2026-08-24 7:29 ` [PATCH 2/4] efi: loader: map code-type page allocations executable Ahmad Fatoum
@ 2026-08-24 7:29 ` Ahmad Fatoum
2026-08-24 7:29 ` [PATCH 4/4] test: py: efiloader: test EFI ResetSystem from booted Linux Ahmad Fatoum
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Ahmad Fatoum @ 2026-08-24 7:29 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
From: Ahmad Fatoum <a.fatoum@barebox.org>
The exclusion was added because the MMU permission code could only
handle a single text/rodata section, while EFI_RUNTIME adds a second
set, and because EFI payloads expect RWX mappings.
Both reasons are gone: barebox proper is a proper ELF now and PBL
applies permissions from the PT_LOAD segment flags, which since the
preceding commits include separate segments for the EFI runtime
services code and data, and code-type EFI page allocations are
remapped executable at allocation time.
As ARM_MMU_PERMISSIONS defaults to y, the multi_v8_efiloader and
multi_v8_efi CI configurations start testing W^X together with the
EFI loader with this commit.
Assisted-by: Claude:fable-5
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
arch/arm/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 02580611d9c3..47089df2a0e1 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -468,7 +468,7 @@ config ARM_UNWIND
config ARM_MMU_PERMISSIONS
bool "Map with extended RO/X permissions"
- depends on MMU && !EFI_RUNTIME
+ depends on MMU
default y
help
Enable this option to map readonly sections as readonly, executable
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 4/4] test: py: efiloader: test EFI ResetSystem from booted Linux
2026-08-24 7:29 [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments Ahmad Fatoum
2026-08-24 7:29 ` [PATCH 2/4] efi: loader: map code-type page allocations executable Ahmad Fatoum
2026-08-24 7:29 ` [PATCH 3/4] ARM: allow CONFIG_ARM_MMU_PERMISSIONS together with EFI_RUNTIME Ahmad Fatoum
@ 2026-08-24 7:29 ` Ahmad Fatoum
2026-08-24 12:28 ` [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments Sascha Hauer
2026-08-25 13:49 ` Sascha Hauer
4 siblings, 0 replies; 6+ messages in thread
From: Ahmad Fatoum @ 2026-08-24 7:29 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
From: Ahmad Fatoum <a.fatoum@barebox.org>
arm64 machine_restart() calls efi_reboot() before falling back to
PSCI whenever EFI runtime services are available, so rebooting the
booted Debian kernel calls barebox's ResetSystem implementation,
which lives entirely in the .efi_runtime code section.
This way, we have a test that verifies we can call into efi_runtime
section both at boot and at runtime.
QEMU would restart the VM on a successful reset, so the test expects the
barebox banner to reappear on the console.
Assisted-by: Claude:fable-5
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
test/py/test_linux_efiloader.py | 57 +++++++++++++++++++++++++++++----
1 file changed, 50 insertions(+), 7 deletions(-)
diff --git a/test/py/test_linux_efiloader.py b/test/py/test_linux_efiloader.py
index a76e55a91e52..eae6703e9d49 100644
--- a/test/py/test_linux_efiloader.py
+++ b/test/py/test_linux_efiloader.py
@@ -26,13 +26,7 @@ def get_dmesg(shell, grep=None):
return stdout
-@pytest.mark.lg_feature(['bootable', 'efi', 'testfs'])
-@pytest.mark.parametrize('efiloader', [False, True])
-def test_boot_manual_with_initrd(strategy, barebox, env, efiloader, debian_iso):
- """Test booting Debian kernel directly without GRUB"""
-
- barebox.run_check(f"global.bootm.efi={'required' if efiloader else 'disabled'}")
-
+def configure_bootm(strategy, barebox):
def get_option(strategy, opt):
config = strategy.target.env.config
return config.get_target_option(strategy.target.name, opt)
@@ -57,6 +51,16 @@ def test_boot_manual_with_initrd(strategy, barebox, env, efiloader, debian_iso):
# Speed up subsequent runs a bit
barebox.run_check("global linux.bootargs.noapparmor=apparmor=0")
+
+@pytest.mark.lg_feature(['bootable', 'efi', 'testfs'])
+@pytest.mark.parametrize('efiloader', [False, True])
+def test_boot_manual_with_initrd(strategy, barebox, env, efiloader, debian_iso):
+ """Test booting Debian kernel directly without GRUB"""
+
+ barebox.run_check(f"global.bootm.efi={'required' if efiloader else 'disabled'}")
+
+ configure_bootm(strategy, barebox)
+
# Boot the kernel - it should use EFI stub by default
with strategy.boot_kernel(bootm=True) as shell:
shell.run_check("grep -q apparmor=0 /proc/cmdline")
@@ -127,3 +131,42 @@ def check_efivars_filesystem_not_empty(shell):
assert ret == 0
assert len(stdout), "EFI variables directory is empty"
+
+
+@pytest.mark.lg_feature(['bootable', 'efi', 'testfs'])
+def test_efi_reset_system(strategy, barebox, env, debian_iso):
+ """Test rebooting Linux via barebox's EFI ResetSystem runtime service
+
+ arm64 machine_restart() calls efi_reboot() before falling back to
+ PSCI whenever EFI runtime services are available, so a reboot from
+ the booted kernel calls into the barebox .efi_runtime code section
+ after ExitBootServices.
+ """
+
+ barebox.run_check("global.bootm.efi=required")
+
+ configure_bootm(strategy, barebox)
+
+ with strategy.boot_kernel(bootm=True) as shell:
+ # ensure the kernel did not give up on EFI runtime services
+ check_expected_efi_messages(shell, env)
+ stdout, _, _ = shell.run("dmesg | grep 'Runtime Services are disabled'")
+ assert stdout == [], "kernel disabled EFI runtime services"
+
+ strategy.console.sendline("reboot -f")
+
+ # QEMU reboots the VM on a successful reset, so barebox comes
+ # back up on the same console
+ _, before, _, _ = strategy.console.expect(
+ [r"barebox 2\d{3}"], timeout=120)
+
+ # A faulting ResetSystem would be caught by the kernel, which
+ # then complains and falls back to PSCI. That also reboots, so
+ # check the console log to tell the two apart.
+ before = before.decode("utf-8", errors="replace")
+ for pattern in ["Synchronous exception in EFI runtime service",
+ "Unable to handle kernel",
+ "Internal error",
+ "Runtime Services are disabled"]:
+ assert pattern not in before, \
+ f"kernel reported EFI runtime fault: {pattern}"
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments
2026-08-24 7:29 [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments Ahmad Fatoum
` (2 preceding siblings ...)
2026-08-24 7:29 ` [PATCH 4/4] test: py: efiloader: test EFI ResetSystem from booted Linux Ahmad Fatoum
@ 2026-08-24 12:28 ` Sascha Hauer
2026-08-25 13:49 ` Sascha Hauer
4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2026-08-24 12:28 UTC (permalink / raw)
To: barebox, Ahmad Fatoum; +Cc: Ahmad Fatoum
On Mon, 24 Aug 2026 09:29:51 +0200, Ahmad Fatoum wrote:
> EFI runtime services support was added before barebox proper was made an
> ELF and back then it proved too cumbersome to have two non-adjacent text
> areas for each of the boot-time and run-time portions.
>
> Now that barebox proper is an ELF, let's move the EFI runtime data and
> text each into its own segment with the appropriate segment flags, so
> pbl_mmu_setup_from_elf() can apply the correct protections.
>
> [...]
Applied, thanks!
[1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments
https://git.pengutronix.de/cgit/barebox/commit/?id=38e03bdde67f (link may not be stable)
[2/4] efi: loader: map code-type page allocations executable
https://git.pengutronix.de/cgit/barebox/commit/?id=834b1ba72ede (link may not be stable)
[3/4] ARM: allow CONFIG_ARM_MMU_PERMISSIONS together with EFI_RUNTIME
https://git.pengutronix.de/cgit/barebox/commit/?id=35c6febf6725 (link may not be stable)
[4/4] test: py: efiloader: test EFI ResetSystem from booted Linux
https://git.pengutronix.de/cgit/barebox/commit/?id=10305208ccf8 (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments
2026-08-24 7:29 [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments Ahmad Fatoum
` (3 preceding siblings ...)
2026-08-24 12:28 ` [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments Sascha Hauer
@ 2026-08-25 13:49 ` Sascha Hauer
4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2026-08-25 13:49 UTC (permalink / raw)
To: barebox, Ahmad Fatoum; +Cc: Ahmad Fatoum
On Mon, 24 Aug 2026 09:29:51 +0200, Ahmad Fatoum wrote:
> EFI runtime services support was added before barebox proper was made an
> ELF and back then it proved too cumbersome to have two non-adjacent text
> areas for each of the boot-time and run-time portions.
>
> Now that barebox proper is an ELF, let's move the EFI runtime data and
> text each into its own segment with the appropriate segment flags, so
> pbl_mmu_setup_from_elf() can apply the correct protections.
>
> [...]
Applied, thanks!
[1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments
https://git.pengutronix.de/cgit/barebox/commit/?id=2aae71d068f6 (link may not be stable)
[2/4] efi: loader: map code-type page allocations executable
https://git.pengutronix.de/cgit/barebox/commit/?id=52abcfa25ece (link may not be stable)
[3/4] ARM: allow CONFIG_ARM_MMU_PERMISSIONS together with EFI_RUNTIME
https://git.pengutronix.de/cgit/barebox/commit/?id=9d492e9c03b4 (link may not be stable)
[4/4] test: py: efiloader: test EFI ResetSystem from booted Linux
https://git.pengutronix.de/cgit/barebox/commit/?id=4eb882cebdc1 (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-25 13:50 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-24 7:29 [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments Ahmad Fatoum
2026-08-24 7:29 ` [PATCH 2/4] efi: loader: map code-type page allocations executable Ahmad Fatoum
2026-08-24 7:29 ` [PATCH 3/4] ARM: allow CONFIG_ARM_MMU_PERMISSIONS together with EFI_RUNTIME Ahmad Fatoum
2026-08-24 7:29 ` [PATCH 4/4] test: py: efiloader: test EFI ResetSystem from booted Linux Ahmad Fatoum
2026-08-24 12:28 ` [PATCH 1/4] ARM: lds: place EFI runtime code and data in separate PT_LOAD segments Sascha Hauer
2026-08-25 13:49 ` Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox