Skip to content

Commit 026b857

Browse files
committed
efi/zboot: arm64: Grab code size from ELF symbol in payload
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>
1 parent 45dd403 commit 026b857

File tree

4 files changed

+21
-30
lines changed

4 files changed

+21
-30
lines changed

drivers/firmware/efi/libstub/Makefile.zboot

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,13 @@ comp-type-$(CONFIG_KERNEL_ZSTD) := zstd22
2424
# causing the original tools to complain when checking image integrity.
2525
# So disregard it when calculating the payload size in the zimage header.
2626
zboot-method-y := $(comp-type-y)_with_size
27-
zboot-size-len-y := 12
27+
zboot-size-len-y := 4
2828

2929
zboot-method-$(CONFIG_KERNEL_GZIP) := gzip
30-
zboot-size-len-$(CONFIG_KERNEL_GZIP) := 8
31-
32-
# Copy the SizeOfHeaders and SizeOfCode fields from the payload to the end of
33-
# the compressed image. Note that this presupposes a PE header offset of 64
34-
# bytes, which is what arm64, RISC-V and LoongArch use.
35-
quiet_cmd_compwithsize = $(quiet_cmd_$(zboot-method-y))
36-
cmd_compwithsize = $(cmd_$(zboot-method-y)) && ( \
37-
dd status=none if=$< bs=4 count=1 skip=37 ; \
38-
dd status=none if=$< bs=4 count=1 skip=23 ) >> $@
30+
zboot-size-len-$(CONFIG_KERNEL_GZIP) := 0
3931

4032
$(obj)/vmlinuz: $(obj)/vmlinux.bin FORCE
41-
$(call if_changed,compwithsize)
33+
$(call if_changed,$(zboot-method-y))
4234

4335
OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) $(EFI_ZBOOT_OBJCOPY_FLAGS) \
4436
--rename-section .data=.gzdata,load,alloc,readonly,contents

drivers/firmware/efi/libstub/arm64.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <linux/efi.h>
1111
#include <asm/efi.h>
12+
#include <asm/image.h>
1213
#include <asm/memory.h>
1314
#include <asm/sysreg.h>
1415

@@ -88,26 +89,32 @@ efi_status_t check_platform_features(void)
8889
#define DCTYPE "cvau"
8990
#endif
9091

92+
u32 __weak code_size;
93+
9194
void efi_cache_sync_image(unsigned long image_base,
92-
unsigned long alloc_size,
93-
unsigned long code_size)
95+
unsigned long alloc_size)
9496
{
9597
u32 ctr = read_cpuid_effective_cachetype();
9698
u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr,
9799
CTR_EL0_DminLine_SHIFT);
98100

99101
/* only perform the cache maintenance if needed for I/D coherency */
100102
if (!(ctr & BIT(CTR_EL0_IDC_SHIFT))) {
103+
unsigned long base = image_base;
104+
unsigned long size = code_size;
105+
101106
do {
102-
asm("dc " DCTYPE ", %0" :: "r"(image_base));
103-
image_base += lsize;
104-
code_size -= lsize;
105-
} while (code_size >= lsize);
107+
asm("dc " DCTYPE ", %0" :: "r"(base));
108+
base += lsize;
109+
size -= lsize;
110+
} while (size >= lsize);
106111
}
107112

108113
asm("ic ialluis");
109114
dsb(ish);
110115
isb();
116+
117+
efi_remap_image(image_base, alloc_size, code_size);
111118
}
112119

113120
unsigned long __weak primary_entry_offset(void)

drivers/firmware/efi/libstub/efistub.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,8 +1066,7 @@ struct screen_info *__alloc_screen_info(void);
10661066
void free_screen_info(struct screen_info *si);
10671067

10681068
void efi_cache_sync_image(unsigned long image_base,
1069-
unsigned long alloc_size,
1070-
unsigned long code_size);
1069+
unsigned long alloc_size);
10711070

10721071
struct efi_smbios_record {
10731072
u8 type;

drivers/firmware/efi/libstub/zboot.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ static unsigned long alloc_preferred_address(unsigned long alloc_size)
5050
}
5151

5252
void __weak efi_cache_sync_image(unsigned long image_base,
53-
unsigned long alloc_size,
54-
unsigned long code_size)
53+
unsigned long alloc_size)
5554
{
5655
// Provided by the arch to perform the cache maintenance necessary for
5756
// executable code loaded into memory to be safe for execution.
@@ -66,7 +65,7 @@ asmlinkage efi_status_t __efiapi
6665
efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
6766
{
6867
unsigned long compressed_size = _gzdata_end - _gzdata_start;
69-
unsigned long image_base, alloc_size, code_size;
68+
unsigned long image_base, alloc_size;
7069
efi_loaded_image_t *image;
7170
efi_status_t status;
7271
char *cmdline_ptr;
@@ -91,13 +90,9 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
9190
efi_info("Decompressing Linux Kernel...\n");
9291

9392
// SizeOfImage from the compressee's PE/COFF header
94-
alloc_size = round_up(get_unaligned_le32(_gzdata_end - 12),
93+
alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),
9594
EFI_ALLOC_ALIGN);
9695

97-
// SizeOfHeaders and SizeOfCode from the compressee's PE/COFF header
98-
code_size = get_unaligned_le32(_gzdata_end - 4) +
99-
get_unaligned_le32(_gzdata_end - 8);
100-
10196
// If the architecture has a preferred address for the image,
10297
// try that first.
10398
image_base = alloc_preferred_address(alloc_size);
@@ -140,9 +135,7 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
140135
goto free_image;
141136
}
142137

143-
efi_cache_sync_image(image_base, alloc_size, code_size);
144-
145-
efi_remap_image(image_base, alloc_size, code_size);
138+
efi_cache_sync_image(image_base, alloc_size);
146139

147140
status = efi_stub_common(handle, image, image_base, cmdline_ptr);
148141

0 commit comments

Comments
 (0)