]> xenbits.xensource.com Git - people/aperard/linux.git/commitdiff
efi/zboot: arm64: Grab code size from ELF symbol in payload
authorArd Biesheuvel <ardb@kernel.org>
Tue, 18 Apr 2023 13:49:52 +0000 (15:49 +0200)
committerArd Biesheuvel <ardb@kernel.org>
Wed, 26 Apr 2023 21:06:48 +0000 (23:06 +0200)
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 symbol that is injected into the ELF
object by the Kbuild rules that generate the compressed payload.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Acked-by: Mark Rutland <mark.rutland@arm.com>
drivers/firmware/efi/libstub/Makefile.zboot
drivers/firmware/efi/libstub/arm64.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/zboot.c

index 1b101d9076fd49e549901aa9b15af3d2eeaa21cf..89ef820f3b34483a55cd6f9b30043910922da75e 100644 (file)
@@ -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
index 8aad8c49d43f18e0903e055ecfbf38740c957fa0..446e35eaf3d9434cd11ee1b858a792a88a7fb8b0 100644 (file)
@@ -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)
index 148013bcb5f89fdd90de221f4d88da83f6e75337..67d5a20802e0b7c6bff01a8da5c083f1768b6e58 100644 (file)
@@ -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;
index 63ece480090032c143dc8c4c01d711ad8d814410..e5d7fa1f1d8fd1602c86e2e39bddfd3fb672ddfa 100644 (file)
@@ -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);