[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