[PATCH 2/2] efi/zboot: arm64: Grab kernel code size from zboot payload

Ard Biesheuvel ardb at kernel.org
Wed Apr 26 07:20:43 PDT 2023


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".


> 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