Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] efi: Expose loaded image properties via info struct
@ 2026-11-06 14:19 Ard Biesheuvel
  2026-11-06 14:19 ` [PATCH 1/5] efi/libstub: Make efi_remap_image() return efi_status_t Ard Biesheuvel
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2026-11-06 14:19 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-arm-kernel, mark.rutland, will, catalin.marinas,
	Ard Biesheuvel, Jason Gunthorpe

From: Ard Biesheuvel <ardb@kernel.org>

Clean up the arm64 build script and linker hacks that zboot uses to
obtain properties of the loaded image (which it cannot access directly
via a relative reference like the ordinary EFI stub).

Instead, define a struct efi_image_info (whose contents are arch
specific), and expose its offset in the loaded image via the arm64 image
header, so that zboot can access it after decompressing the image.

Cc: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/all/0-v2-989a18390eb1+486-arm64_drtm_jgg@nvidia.com/

Ard Biesheuvel (5):
  efi/libstub: Make efi_remap_image() return efi_status_t
  efi/libstub: Pass a struct efi_image_info to efi_stub_common()
  efi/zboot: Disentangle efi_remap_image() from efi_cache_sync_image()
  efi/arm64: Expose struct efi_image_info via the image header
  efi/arm64: Drop build and linker script hacks to obtain image code
    size

 Documentation/arch/arm64/booting.rst           |  3 +-
 arch/arm64/boot/Makefile                       |  3 --
 arch/arm64/include/asm/efi.h                   | 11 ++++++
 arch/arm64/include/asm/image.h                 |  4 ++-
 arch/arm64/kernel/efi-header.S                 |  6 ++++
 arch/arm64/kernel/head.S                       |  3 +-
 arch/arm64/kernel/image-vars.h                 |  4 ---
 drivers/firmware/efi/libstub/arm64-stub.c      | 16 +++++++++
 drivers/firmware/efi/libstub/arm64.c           | 13 ++++---
 drivers/firmware/efi/libstub/efi-stub-entry.c  |  8 ++++-
 drivers/firmware/efi/libstub/efi-stub-helper.c | 13 ++++---
 drivers/firmware/efi/libstub/efi-stub.c        |  3 +-
 drivers/firmware/efi/libstub/efistub.h         | 16 +++++++--
 drivers/firmware/efi/libstub/zboot.c           | 36 ++++++++++++++++++--
 drivers/firmware/efi/libstub/zboot.lds         |  7 ----
 15 files changed, 112 insertions(+), 34 deletions(-)


base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
-- 
2.56.0.455.g6c5a503b38-goog



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] efi/libstub: Make efi_remap_image() return efi_status_t
  2026-11-06 14:19 [PATCH 0/5] efi: Expose loaded image properties via info struct Ard Biesheuvel
@ 2026-11-06 14:19 ` Ard Biesheuvel
  2026-11-06 14:19 ` [PATCH 2/5] efi/libstub: Pass a struct efi_image_info to efi_stub_common() Ard Biesheuvel
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2026-11-06 14:19 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-arm-kernel, mark.rutland, will, catalin.marinas,
	Ard Biesheuvel, Jason Gunthorpe

From: Ard Biesheuvel <ardb@kernel.org>

efi_remap_image() uses the EFI Memory Attributes Protocol to remap code
and data regions with the appropriate permissions. This could fail for a
variety of regions, all of which are currently ignored.

So relay the failure status code if any occur when invoking the
protocol. Locating the protocol itself is allowed to fail, as remapping
the image is likely unnecessary in the first place if the protocol does
not exist.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/efi/libstub/efi-stub-helper.c | 13 ++++++++-----
 drivers/firmware/efi/libstub/efistub.h         |  4 ++--
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 8e43eb3f418b..b2ad081cf324 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -698,8 +698,8 @@ efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key)
  * read-write/non-executable. The code region is assumed to start at the base
  * of the image, and will therefore cover the PE/COFF header as well.
  */
-void efi_remap_image(unsigned long image_base, unsigned alloc_size,
-		     unsigned long code_size)
+efi_status_t efi_remap_image(unsigned long image_base, unsigned alloc_size,
+			     unsigned long code_size)
 {
 	static efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
 	efi_memory_attribute_protocol_t *memattr;
@@ -710,10 +710,12 @@ void efi_remap_image(unsigned long image_base, unsigned alloc_size,
 	 * If the firmware implements the EFI_MEMORY_ATTRIBUTE_PROTOCOL, let's
 	 * invoke it to remap the text/rodata region of the decompressed image
 	 * as read-only and the data/bss region as non-executable.
+	 * Don't bother if the protocol does not exist: it means all memory is
+	 * read-write-exec anyway.
 	 */
 	status = efi_bs_call(locate_protocol, &guid, NULL, (void **)&memattr);
 	if (status != EFI_SUCCESS)
-		return;
+		return EFI_SUCCESS;
 
 	// Get the current attributes for the entire region
 	status = memattr->get_memory_attributes(memattr, image_base,
@@ -721,7 +723,7 @@ void efi_remap_image(unsigned long image_base, unsigned alloc_size,
 	if (status != EFI_SUCCESS) {
 		efi_warn("Failed to retrieve memory attributes for image region: 0x%lx\n",
 			 status);
-		return;
+		return status;
 	}
 
 	// Mark the code region as read-only
@@ -729,7 +731,7 @@ void efi_remap_image(unsigned long image_base, unsigned alloc_size,
 						EFI_MEMORY_RO);
 	if (status != EFI_SUCCESS) {
 		efi_warn("Failed to remap code region read-only\n");
-		return;
+		return status;
 	}
 
 	// If the entire region was already mapped as non-exec, clear the
@@ -749,4 +751,5 @@ void efi_remap_image(unsigned long image_base, unsigned alloc_size,
 		if (status != EFI_SUCCESS)
 			efi_warn("Failed to remap data region non-executable\n");
 	}
+	return status;
 }
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index f5eec8c12894..b09d6c535ab5 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1241,8 +1241,8 @@ struct efi_smbios_type4_record {
 const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
 				  const u8 *offset);
 
-void efi_remap_image(unsigned long image_base, unsigned alloc_size,
-		     unsigned long code_size);
+efi_status_t efi_remap_image(unsigned long image_base, unsigned alloc_size,
+			     unsigned long code_size);
 efi_status_t efi_kaslr_relocate_kernel(unsigned long *image_addr,
 				       unsigned long *reserve_addr,
 				       unsigned long *reserve_size,
-- 
2.56.0.455.g6c5a503b38-goog



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/5] efi/libstub: Pass a struct efi_image_info to efi_stub_common()
  2026-11-06 14:19 [PATCH 0/5] efi: Expose loaded image properties via info struct Ard Biesheuvel
  2026-11-06 14:19 ` [PATCH 1/5] efi/libstub: Make efi_remap_image() return efi_status_t Ard Biesheuvel
@ 2026-11-06 14:19 ` Ard Biesheuvel
  2026-11-06 14:19 ` [PATCH 3/5] efi/zboot: Disentangle efi_remap_image() from efi_cache_sync_image() Ard Biesheuvel
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2026-11-06 14:19 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-arm-kernel, mark.rutland, will, catalin.marinas,
	Ard Biesheuvel, Jason Gunthorpe

From: Ard Biesheuvel <ardb@kernel.org>

Pass a struct efi_image_info pointer to efi_stub_common() so that
architectures can expose properties of the image being loaded in a
consistent manner for both the uncompressed kernel and the EFI zboot
image.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 drivers/firmware/efi/libstub/efi-stub-entry.c |  8 +++++++-
 drivers/firmware/efi/libstub/efi-stub.c       |  3 ++-
 drivers/firmware/efi/libstub/efistub.h        |  8 +++++++-
 drivers/firmware/efi/libstub/zboot.c          | 15 +++++++++++++--
 4 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-entry.c b/drivers/firmware/efi/libstub/efi-stub-entry.c
index efa3ab8ad1c6..ff559708dfe7 100644
--- a/drivers/firmware/efi/libstub/efi-stub-entry.c
+++ b/drivers/firmware/efi/libstub/efi-stub-entry.c
@@ -27,6 +27,11 @@ struct sysfb_display_info *alloc_primary_display(void)
 	return NULL;
 }
 
+const struct efi_image_info * __weak efistub_get_image_info(void)
+{
+	return NULL;
+}
+
 /*
  * EFI entry point for the generic EFI stub used by ARM, arm64, RISC-V and
  * LoongArch. This is the entrypoint that is described in the PE/COFF header
@@ -80,7 +85,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
 
 	kernel_image_offset = image_addr - (unsigned long)image->image_base;
 
-	status = efi_stub_common(handle, image, image_addr, cmdline_ptr);
+	status = efi_stub_common(handle, image, image_addr, cmdline_ptr,
+				 efistub_get_image_info());
 
 	efi_free(image_size, image_addr);
 	efi_free(reserve_size, reserve_addr);
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index 6db10590f89b..ee5931eed59c 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c
@@ -161,7 +161,8 @@ efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
 efi_status_t efi_stub_common(efi_handle_t handle,
 			     efi_loaded_image_t *image,
 			     unsigned long image_addr,
-			     char *cmdline_ptr)
+			     char *cmdline_ptr,
+			     const struct efi_image_info *image_info)
 {
 	struct sysfb_display_info *dpy;
 	efi_status_t status;
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index b09d6c535ab5..1955cdb5139a 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1148,11 +1148,17 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
 				 efi_loaded_image_t *image,
 				 efi_handle_t image_handle);
 
+struct efi_image_info;
+
+const struct efi_image_info *zboot_get_image_info(unsigned long image_base);
+const struct efi_image_info *efistub_get_image_info(void);
+
 /* shared entrypoint between the normal stub and the zboot stub */
 efi_status_t efi_stub_common(efi_handle_t handle,
 			     efi_loaded_image_t *image,
 			     unsigned long image_addr,
-			     char *cmdline_ptr);
+			     char *cmdline_ptr,
+			     const struct efi_image_info *image_info);
 
 efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr);
 
diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
index 4a5ffe164873..97ae706c034a 100644
--- a/drivers/firmware/efi/libstub/zboot.c
+++ b/drivers/firmware/efi/libstub/zboot.c
@@ -31,6 +31,11 @@ struct sysfb_display_info *alloc_primary_display(void)
 	return __alloc_primary_display();
 }
 
+const struct efi_image_info * __weak zboot_get_image_info(unsigned long image_base)
+{
+	return NULL;
+}
+
 asmlinkage efi_status_t __efiapi
 efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
 {
@@ -93,9 +98,15 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
 	}
 
 	// Decompress the payload into the newly allocated buffer
-	status = efi_zboot_decompress((void *)image_base, alloc_size) ?:
-	         efi_stub_common(handle, image, image_base, cmdline_ptr);
+	status = efi_zboot_decompress((void *)image_base, alloc_size);
+	if (status != EFI_SUCCESS)
+		goto error;
+
+	auto image_info = zboot_get_image_info(image_base);
+	status = efi_stub_common(handle, image, image_base, cmdline_ptr,
+				 image_info);
 
+error:
 	efi_free(alloc_size, image_base);
 	return status;
 }
-- 
2.56.0.455.g6c5a503b38-goog



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/5] efi/zboot: Disentangle efi_remap_image() from efi_cache_sync_image()
  2026-11-06 14:19 [PATCH 0/5] efi: Expose loaded image properties via info struct Ard Biesheuvel
  2026-11-06 14:19 ` [PATCH 1/5] efi/libstub: Make efi_remap_image() return efi_status_t Ard Biesheuvel
  2026-11-06 14:19 ` [PATCH 2/5] efi/libstub: Pass a struct efi_image_info to efi_stub_common() Ard Biesheuvel
@ 2026-11-06 14:19 ` Ard Biesheuvel
  2026-11-06 14:19 ` [PATCH 4/5] efi/arm64: Expose struct efi_image_info via the image header Ard Biesheuvel
  2026-11-06 14:19 ` [PATCH 5/5] efi/arm64: Drop build and linker script hacks to obtain image code size Ard Biesheuvel
  4 siblings, 0 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2026-11-06 14:19 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-arm-kernel, mark.rutland, will, catalin.marinas,
	Ard Biesheuvel, Jason Gunthorpe

From: Ard Biesheuvel <ardb@kernel.org>

Refactor efi_cache_sync_image() so that it is not in charge of calling
efi_remap_image(), which is really the wrong way around.

Instead, call efi_remap_image() from the primary zboot procedure, where
it is more straight-forward to obtain the code size from the loaded
image.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/include/asm/efi.h           |  3 +++
 drivers/firmware/efi/libstub/arm64.c   |  2 --
 drivers/firmware/efi/libstub/efistub.h |  4 ++++
 drivers/firmware/efi/libstub/zboot.c   | 23 +++++++++++++++++++-
 4 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index e8a9783235cb..da6afd4a7a27 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -151,4 +151,7 @@ efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f);
 
 void efi_icache_sync(unsigned long start, unsigned long end);
 
+// temporary resolution for efistub_get_code_size()
+#define efistub_get_code_size(image_info) ({ extern u32 code_size; code_size; })
+
 #endif /* _ASM_EFI_H */
diff --git a/drivers/firmware/efi/libstub/arm64.c b/drivers/firmware/efi/libstub/arm64.c
index e57cd3de0a00..7ab634e37cf1 100644
--- a/drivers/firmware/efi/libstub/arm64.c
+++ b/drivers/firmware/efi/libstub/arm64.c
@@ -112,8 +112,6 @@ void efi_cache_sync_image(unsigned long image_base,
 	asm("ic ialluis");
 	dsb(ish);
 	isb();
-
-	efi_remap_image(image_base, alloc_size, code_size);
 }
 
 unsigned long __weak primary_entry_offset(void)
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 1955cdb5139a..89cd2ae57a3c 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1270,4 +1270,8 @@ void arch_accept_memory(phys_addr_t start, phys_addr_t end);
 efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size);
 efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen);
 
+#ifndef efistub_get_code_size
+#define efistub_get_code_size(image_info)	0
+#endif
+
 #endif
diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
index 97ae706c034a..27f6661253c0 100644
--- a/drivers/firmware/efi/libstub/zboot.c
+++ b/drivers/firmware/efi/libstub/zboot.c
@@ -36,6 +36,26 @@ const struct efi_image_info * __weak zboot_get_image_info(unsigned long image_ba
 	return NULL;
 }
 
+static efi_status_t efi_zboot_remap_image(const struct efi_image_info *image_info,
+					  unsigned long image_base,
+					  unsigned long image_size)
+{
+	unsigned long code_size = efistub_get_code_size(image_info);
+	efi_status_t status;
+
+	if (code_size) {
+		efi_cache_sync_image(image_base, code_size);
+
+		status = efi_remap_image(image_base, image_size, code_size);
+		if (status != EFI_SUCCESS)
+			return status;
+	} else {
+		efi_cache_sync_image(image_base, image_size);
+	}
+
+	return EFI_SUCCESS;
+}
+
 asmlinkage efi_status_t __efiapi
 efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
 {
@@ -103,7 +123,8 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
 		goto error;
 
 	auto image_info = zboot_get_image_info(image_base);
-	status = efi_stub_common(handle, image, image_base, cmdline_ptr,
+	status = efi_zboot_remap_image(image_info, image_base, alloc_size) ?:
+	         efi_stub_common(handle, image, image_base, cmdline_ptr,
 				 image_info);
 
 error:
-- 
2.56.0.455.g6c5a503b38-goog



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/5] efi/arm64: Expose struct efi_image_info via the image header
  2026-11-06 14:19 [PATCH 0/5] efi: Expose loaded image properties via info struct Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2026-11-06 14:19 ` [PATCH 3/5] efi/zboot: Disentangle efi_remap_image() from efi_cache_sync_image() Ard Biesheuvel
@ 2026-11-06 14:19 ` Ard Biesheuvel
  2026-11-06 14:34   ` Jason Gunthorpe
  2026-11-06 14:19 ` [PATCH 5/5] efi/arm64: Drop build and linker script hacks to obtain image code size Ard Biesheuvel
  4 siblings, 1 reply; 7+ messages in thread
From: Ard Biesheuvel @ 2026-11-06 14:19 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-arm-kernel, mark.rutland, will, catalin.marinas,
	Ard Biesheuvel, Jason Gunthorpe

From: Ard Biesheuvel <ardb@kernel.org>

The zboot compressed kernel and the uncompressed Image both contain a
copy of the EFI stub, and both are tightly coupled to the kernel image.

However, the zboot stub is not linked into vmlinux like the ordinary EFI
stub is, and so it does not have direct access to its symbols. This is
needed today for things like image size and code size, but there are
more cases coming (DRTM) where both stubs need to have a consistent view
of these things.

So add a struct efi_image_info that is built into vmlinux and exposed
via the image header, so that zboot can access it easily.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 Documentation/arch/arm64/booting.rst      |  3 ++-
 arch/arm64/include/asm/efi.h              |  3 +++
 arch/arm64/include/asm/image.h            |  4 +++-
 arch/arm64/kernel/efi-header.S            |  6 ++++++
 arch/arm64/kernel/head.S                  |  3 ++-
 drivers/firmware/efi/libstub/arm64-stub.c | 14 ++++++++++++++
 drivers/firmware/efi/libstub/arm64.c      |  7 +++++++
 7 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/Documentation/arch/arm64/booting.rst b/Documentation/arch/arm64/booting.rst
index dae5ff9fae26..2389558bd389 100644
--- a/Documentation/arch/arm64/booting.rst
+++ b/Documentation/arch/arm64/booting.rst
@@ -84,7 +84,8 @@ The decompressed kernel image contains a 64-byte header as follows::
   u64 flags;			/* kernel flags, little endian */
   u64 res2	= 0;		/* reserved */
   u64 res3	= 0;		/* reserved */
-  u64 res4	= 0;		/* reserved */
+  u32 res4	= 0;		/* reserved */
+  u32 efi_image_info_offset;	/* Offset to struct efi_image_info */
   u32 magic	= 0x644d5241;	/* Magic number, little endian, "ARM\x64" */
   u32 res5;			/* reserved (used for PE COFF offset) */
 
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index da6afd4a7a27..b0c9120b9741 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -154,4 +154,7 @@ void efi_icache_sync(unsigned long start, unsigned long end);
 // temporary resolution for efistub_get_code_size()
 #define efistub_get_code_size(image_info) ({ extern u32 code_size; code_size; })
 
+struct efi_image_info {
+};
+
 #endif /* _ASM_EFI_H */
diff --git a/arch/arm64/include/asm/image.h b/arch/arm64/include/asm/image.h
index 9ba85173f857..10b35521cf28 100644
--- a/arch/arm64/include/asm/image.h
+++ b/arch/arm64/include/asm/image.h
@@ -36,6 +36,7 @@
  * @image_size:		Effective Image size
  * @flags:		kernel flags
  * @reserved:		reserved
+ * @efi_image_offset:	Offset to struct efi_image_info
  * @magic:		Magic number
  * @reserved5:		reserved, or
  *   @pe_header:	  alternatively used for PE COFF offset
@@ -49,7 +50,8 @@ struct arm64_image_header {
 	__le64 flags;
 	__le64 res2;
 	__le64 res3;
-	__le64 res4;
+	__le32 res4;
+	__le32 efi_image_info_offset;
 	__le32 magic;
 	__le32 res5;
 };
diff --git a/arch/arm64/kernel/efi-header.S b/arch/arm64/kernel/efi-header.S
index 329e8df9215f..62061cb0bf21 100644
--- a/arch/arm64/kernel/efi-header.S
+++ b/arch/arm64/kernel/efi-header.S
@@ -7,6 +7,12 @@
 #include <linux/pe.h>
 #include <linux/sizes.h>
 
+#ifdef CONFIG_EFI
+#define EFI_IMAGE_INFO_OFFSET  __efistub_efi_image_info - .L_head
+#else
+#define EFI_IMAGE_INFO_OFFSET	0
+#endif
+
 	.macro	efi_signature_nop
 #ifdef CONFIG_EFI
 .L_head:
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index d6ba3c0af811..f1827e32b0e5 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -65,7 +65,8 @@
 	le64sym	_kernel_flags_le		// Informative flags, little-endian
 	.quad	0				// reserved
 	.quad	0				// reserved
-	.quad	0				// reserved
+       .long   0                               // reserved
+       .long   EFI_IMAGE_INFO_OFFSET           // Offset to struct efi_image_info
 	.ascii	ARM64_IMAGE_MAGIC		// Magic number
 	.long	.Lpe_header_offset		// Offset to the PE header.
 
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index 2c3869356147..8daed681f97d 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -61,3 +61,17 @@ void efi_icache_sync(unsigned long start, unsigned long end)
 {
 	caches_clean_inval_pou(start, end);
 }
+
+extern const struct efi_image_info efi_image_info;
+
+asm("	.section \".rodata\", \"a\", %progbits;			" \
+    "	.align	3;						" \
+    "	.globl	efi_image_info;					" \
+    "efi_image_info:						" \
+    "	.previous						");
+
+
+const struct efi_image_info *efistub_get_image_info(void)
+{
+	return &efi_image_info;
+}
diff --git a/drivers/firmware/efi/libstub/arm64.c b/drivers/firmware/efi/libstub/arm64.c
index 7ab634e37cf1..190cf180bb23 100644
--- a/drivers/firmware/efi/libstub/arm64.c
+++ b/drivers/firmware/efi/libstub/arm64.c
@@ -135,3 +135,10 @@ void __noreturn efi_enter_kernel(unsigned long entrypoint,
 	enter_kernel = (void *)entrypoint + primary_entry_offset();
 	enter_kernel(fdt_addr, 0, 0, 0);
 }
+
+const struct efi_image_info *zboot_get_image_info(unsigned long image_base)
+{
+	auto header = (const struct arm64_image_header *)image_base;
+
+	return (void *)image_base + header->efi_image_info_offset;
+}
-- 
2.56.0.455.g6c5a503b38-goog



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/5] efi/arm64: Drop build and linker script hacks to obtain image code size
  2026-11-06 14:19 [PATCH 0/5] efi: Expose loaded image properties via info struct Ard Biesheuvel
                   ` (3 preceding siblings ...)
  2026-11-06 14:19 ` [PATCH 4/5] efi/arm64: Expose struct efi_image_info via the image header Ard Biesheuvel
@ 2026-11-06 14:19 ` Ard Biesheuvel
  4 siblings, 0 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2026-11-06 14:19 UTC (permalink / raw)
  To: linux-efi
  Cc: linux-arm-kernel, mark.rutland, will, catalin.marinas,
	Ard Biesheuvel, Jason Gunthorpe

From: Ard Biesheuvel <ardb@kernel.org>

Instead of taking vmlinux symbol values at build time and poking them
into the zboot linker script, wire up struct efi_image_info so this
information can be obtained from the code.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/boot/Makefile                  |  3 ---
 arch/arm64/include/asm/efi.h              | 11 ++++++++---
 arch/arm64/kernel/image-vars.h            |  4 ----
 drivers/firmware/efi/libstub/arm64-stub.c |  2 ++
 drivers/firmware/efi/libstub/arm64.c      |  4 +---
 drivers/firmware/efi/libstub/zboot.lds    |  7 -------
 6 files changed, 11 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile
index d42d07667822..509b59518818 100644
--- a/arch/arm64/boot/Makefile
+++ b/arch/arm64/boot/Makefile
@@ -51,7 +51,4 @@ EFI_ZBOOT_BFD_TARGET	:= elf64-littleaarch64
 EFI_ZBOOT_MACH_TYPE	:= ARM64
 EFI_ZBOOT_FORWARD_CFI	:= $(CONFIG_ARM64_BTI_KERNEL)
 
-EFI_ZBOOT_OBJCOPY_FLAGS	= --add-symbol zboot_code_size=0x$$( \
-				$(NM) vmlinux|grep _kernel_codesize|cut -d' ' -f1)
-
 include $(srctree)/drivers/firmware/efi/libstub/Makefile.zboot
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index b0c9120b9741..3194e133a4d5 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -151,10 +151,15 @@ efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f);
 
 void efi_icache_sync(unsigned long start, unsigned long end);
 
-// temporary resolution for efistub_get_code_size()
-#define efistub_get_code_size(image_info) ({ extern u32 code_size; code_size; })
-
 struct efi_image_info {
+	s32 _text_offset;
+	s32 __inittext_end_offset;
 };
 
+static inline u32 efistub_get_code_size(const struct efi_image_info *info)
+{
+	return info->__inittext_end_offset - info->_text_offset;
+}
+#define efistub_get_code_size efistub_get_code_size
+
 #endif /* _ASM_EFI_H */
diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index 19d602e45523..b02234f080b0 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -150,10 +150,6 @@ KVM_NVHE_ALIAS(kvm_protected_mode_initialized);
 
 #endif /* CONFIG_KVM */
 
-#ifdef CONFIG_EFI_ZBOOT
-_kernel_codesize = ABSOLUTE(__inittext_end - _text);
-#endif
-
 /*
  * LLD will occasionally error out with a '__init_end does not converge' error
  * if INIT_IDMAP_DIR_SIZE is defined in terms of _end, as this results in a
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index 8daed681f97d..754cb2843967 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -68,6 +68,8 @@ asm("	.section \".rodata\", \"a\", %progbits;			" \
     "	.align	3;						" \
     "	.globl	efi_image_info;					" \
     "efi_image_info:						" \
+    "	.long	_text - efi_image_info;				" \
+    "	.long	__inittext_end - efi_image_info;		" \
     "	.previous						");
 
 
diff --git a/drivers/firmware/efi/libstub/arm64.c b/drivers/firmware/efi/libstub/arm64.c
index 190cf180bb23..da6fa2f6c821 100644
--- a/drivers/firmware/efi/libstub/arm64.c
+++ b/drivers/firmware/efi/libstub/arm64.c
@@ -88,8 +88,6 @@ efi_status_t check_platform_features(void)
 #define DCTYPE	"cvau"
 #endif
 
-u32 __weak code_size;
-
 void efi_cache_sync_image(unsigned long image_base,
 			  unsigned long alloc_size)
 {
@@ -100,7 +98,7 @@ void efi_cache_sync_image(unsigned long image_base,
 	/* only perform the cache maintenance if needed for I/D coherency */
 	if (!(ctr & BIT(CTR_EL0_IDC_SHIFT))) {
 		unsigned long base = image_base;
-		unsigned long size = code_size;
+		unsigned long size = alloc_size;
 
 		do {
 			asm("dc " DCTYPE ", %0" :: "r"(base));
diff --git a/drivers/firmware/efi/libstub/zboot.lds b/drivers/firmware/efi/libstub/zboot.lds
index 367907eb7d86..61714a151766 100644
--- a/drivers/firmware/efi/libstub/zboot.lds
+++ b/drivers/firmware/efi/libstub/zboot.lds
@@ -2,8 +2,6 @@
 
 ENTRY(__efistub_efi_zboot_header);
 
-PROVIDE(zboot_code_size = ABSOLUTE(0));
-
 SECTIONS
 {
 	.head : ALIGN(4096) {
@@ -20,11 +18,6 @@ SECTIONS
 		__efistub_payload_size = . - 4;
 		__efistub__gzdata_end = .;
 		*(.rodata* .init.rodata* .srodata*)
-
-		. = ALIGN(4);
-		__efistub_code_size = .;
-		LONG(zboot_code_size);
-
 		_etext = ALIGN(4096);
 		. = _etext;
 	}
-- 
2.56.0.455.g6c5a503b38-goog



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/5] efi/arm64: Expose struct efi_image_info via the image header
  2026-11-06 14:19 ` [PATCH 4/5] efi/arm64: Expose struct efi_image_info via the image header Ard Biesheuvel
@ 2026-11-06 14:34   ` Jason Gunthorpe
  0 siblings, 0 replies; 7+ messages in thread
From: Jason Gunthorpe @ 2026-11-06 14:34 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-efi, linux-arm-kernel, mark.rutland, will, catalin.marinas,
	Ard Biesheuvel

On Fri, Nov 06, 2026 at 03:19:41PM +0100, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb@kernel.org>
> 
> The zboot compressed kernel and the uncompressed Image both contain a
> copy of the EFI stub, and both are tightly coupled to the kernel image.
> 
> However, the zboot stub is not linked into vmlinux like the ordinary EFI
> stub is, and so it does not have direct access to its symbols. This is
> needed today for things like image size and code size, but there are
> more cases coming (DRTM) where both stubs need to have a consistent view
> of these things.
> 
> So add a struct efi_image_info that is built into vmlinux and exposed
> via the image header, so that zboot can access it easily.

I tried hard to avoid doing this because I didn't want to make the
struct layout ABI. I really see only negatives to that.

Putting it here and documenting it in the rst is going to encourage
other bootloaders to look inside it and try to read the contents. :(

The linker trick to inject the offset into zboot seemed better because
it completely prevents it from being ABI as nothing but the EFI stubs
can ever locate it.

Also, I wanted it to eventually be cross arch and I don't know if
other arches have any spare space like this.

Jason


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-11-06 14:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-06 14:19 [PATCH 0/5] efi: Expose loaded image properties via info struct Ard Biesheuvel
2026-11-06 14:19 ` [PATCH 1/5] efi/libstub: Make efi_remap_image() return efi_status_t Ard Biesheuvel
2026-11-06 14:19 ` [PATCH 2/5] efi/libstub: Pass a struct efi_image_info to efi_stub_common() Ard Biesheuvel
2026-11-06 14:19 ` [PATCH 3/5] efi/zboot: Disentangle efi_remap_image() from efi_cache_sync_image() Ard Biesheuvel
2026-11-06 14:19 ` [PATCH 4/5] efi/arm64: Expose struct efi_image_info via the image header Ard Biesheuvel
2026-11-06 14:34   ` Jason Gunthorpe
2026-11-06 14:19 ` [PATCH 5/5] efi/arm64: Drop build and linker script hacks to obtain image code size Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox