[PATCH 2/2] efi/zboot: arm64: Grab kernel code size from zboot payload
Mark Rutland
mark.rutland at arm.com
Wed Apr 26 08:57:42 PDT 2023
On Wed, Apr 26, 2023 at 03:20:43PM +0100, Ard Biesheuvel wrote:
> On Wed, 26 Apr 2023 at 15:11, Ard Biesheuvel <ardb at kernel.org> wrote:
> >
> > Instead of relying on a dodgy dd hack to copy the image code size from
> > the uncompressed image's PE header to the end of the compressed image,
>
>
> > let's grab the code size from the text_offset field of the arm64 image
> > header after decompression, which is where the arm64 specific EFI zboot
> > make rules will poke the code size when generating the zboot specific
> > version of the binary Image payload.
> >
>
> Apologies, I failed to update the above when I changed the actual
> patch. It should read:
>
> "let's grab the code size from the symbol that is injected into the
> ELF by the Kbuild rules that generate the compressed payload".
With the corrected wording:
Acked-by: Mark Rutland <mark.rutland at arm.com>
Mark.
>
>
> > Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
> > ---
> > drivers/firmware/efi/libstub/Makefile.zboot | 14 +++-----------
> > drivers/firmware/efi/libstub/arm64.c | 19 +++++++++++++------
> > drivers/firmware/efi/libstub/efistub.h | 3 +--
> > drivers/firmware/efi/libstub/zboot.c | 15 ++++-----------
> > 4 files changed, 21 insertions(+), 30 deletions(-)
> >
> > diff --git a/drivers/firmware/efi/libstub/Makefile.zboot b/drivers/firmware/efi/libstub/Makefile.zboot
> > index 1b101d9076fd49e5..89ef820f3b34483a 100644
> > --- a/drivers/firmware/efi/libstub/Makefile.zboot
> > +++ b/drivers/firmware/efi/libstub/Makefile.zboot
> > @@ -24,21 +24,13 @@ comp-type-$(CONFIG_KERNEL_ZSTD) := zstd22
> > # causing the original tools to complain when checking image integrity.
> > # So disregard it when calculating the payload size in the zimage header.
> > zboot-method-y := $(comp-type-y)_with_size
> > -zboot-size-len-y := 12
> > +zboot-size-len-y := 4
> >
> > zboot-method-$(CONFIG_KERNEL_GZIP) := gzip
> > -zboot-size-len-$(CONFIG_KERNEL_GZIP) := 8
> > -
> > -# Copy the SizeOfHeaders and SizeOfCode fields from the payload to the end of
> > -# the compressed image. Note that this presupposes a PE header offset of 64
> > -# bytes, which is what arm64, RISC-V and LoongArch use.
> > -quiet_cmd_compwithsize = $(quiet_cmd_$(zboot-method-y))
> > - cmd_compwithsize = $(cmd_$(zboot-method-y)) && ( \
> > - dd status=none if=$< bs=4 count=1 skip=37 ; \
> > - dd status=none if=$< bs=4 count=1 skip=23 ) >> $@
> > +zboot-size-len-$(CONFIG_KERNEL_GZIP) := 0
> >
> > $(obj)/vmlinuz: $(obj)/vmlinux.bin FORCE
> > - $(call if_changed,compwithsize)
> > + $(call if_changed,$(zboot-method-y))
> >
> > OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) $(EFI_ZBOOT_OBJCOPY_FLAGS) \
> > --rename-section .data=.gzdata,load,alloc,readonly,contents
> > diff --git a/drivers/firmware/efi/libstub/arm64.c b/drivers/firmware/efi/libstub/arm64.c
> > index 8aad8c49d43f18e0..446e35eaf3d9434c 100644
> > --- a/drivers/firmware/efi/libstub/arm64.c
> > +++ b/drivers/firmware/efi/libstub/arm64.c
> > @@ -9,6 +9,7 @@
> >
> > #include <linux/efi.h>
> > #include <asm/efi.h>
> > +#include <asm/image.h>
> > #include <asm/memory.h>
> > #include <asm/sysreg.h>
> >
> > @@ -88,9 +89,10 @@ 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,
> > - unsigned long code_size)
> > + unsigned long alloc_size)
> > {
> > u32 ctr = read_cpuid_effective_cachetype();
> > u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr,
> > @@ -98,16 +100,21 @@ 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;
> > +
> > do {
> > - asm("dc " DCTYPE ", %0" :: "r"(image_base));
> > - image_base += lsize;
> > - code_size -= lsize;
> > - } while (code_size >= lsize);
> > + asm("dc " DCTYPE ", %0" :: "r"(base));
> > + base += lsize;
> > + size -= lsize;
> > + } while (size >= lsize);
> > }
> >
> > 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 148013bcb5f89fdd..67d5a20802e0b7c6 100644
> > --- a/drivers/firmware/efi/libstub/efistub.h
> > +++ b/drivers/firmware/efi/libstub/efistub.h
> > @@ -1066,8 +1066,7 @@ struct screen_info *__alloc_screen_info(void);
> > void free_screen_info(struct screen_info *si);
> >
> > void efi_cache_sync_image(unsigned long image_base,
> > - unsigned long alloc_size,
> > - unsigned long code_size);
> > + unsigned long alloc_size);
> >
> > struct efi_smbios_record {
> > u8 type;
> > diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
> > index 63ece480090032c1..e5d7fa1f1d8fd160 100644
> > --- a/drivers/firmware/efi/libstub/zboot.c
> > +++ b/drivers/firmware/efi/libstub/zboot.c
> > @@ -50,8 +50,7 @@ static unsigned long alloc_preferred_address(unsigned long alloc_size)
> > }
> >
> > void __weak efi_cache_sync_image(unsigned long image_base,
> > - unsigned long alloc_size,
> > - unsigned long code_size)
> > + unsigned long alloc_size)
> > {
> > // Provided by the arch to perform the cache maintenance necessary for
> > // executable code loaded into memory to be safe for execution.
> > @@ -66,7 +65,7 @@ asmlinkage efi_status_t __efiapi
> > efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
> > {
> > unsigned long compressed_size = _gzdata_end - _gzdata_start;
> > - unsigned long image_base, alloc_size, code_size;
> > + unsigned long image_base, alloc_size;
> > efi_loaded_image_t *image;
> > efi_status_t status;
> > char *cmdline_ptr;
> > @@ -91,13 +90,9 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
> > efi_info("Decompressing Linux Kernel...\n");
> >
> > // SizeOfImage from the compressee's PE/COFF header
> > - alloc_size = round_up(get_unaligned_le32(_gzdata_end - 12),
> > + alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),
> > EFI_ALLOC_ALIGN);
> >
> > - // SizeOfHeaders and SizeOfCode from the compressee's PE/COFF header
> > - code_size = get_unaligned_le32(_gzdata_end - 4) +
> > - get_unaligned_le32(_gzdata_end - 8);
> > -
> > // If the architecture has a preferred address for the image,
> > // try that first.
> > image_base = alloc_preferred_address(alloc_size);
> > @@ -140,9 +135,7 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
> > goto free_image;
> > }
> >
> > - efi_cache_sync_image(image_base, alloc_size, code_size);
> > -
> > - efi_remap_image(image_base, alloc_size, code_size);
> > + efi_cache_sync_image(image_base, alloc_size);
> >
> > status = efi_stub_common(handle, image, image_base, cmdline_ptr);
> >
> > --
> > 2.39.2
> >
More information about the linux-arm-kernel
mailing list