Skip to content

Commit bca2f3a

Browse files
committed
efi/zboot: Add BSS padding before compression
We don't really care about the size of the decompressed image - what matters is how much space needs to be allocated for the image to execute, and this includes space for BSS that is not part of the loadable image and so it is not accounted for in the decompressed size. So let's add some zero padding to the end of the image: this compresses well, and it ensures that BSS is accounted for, and as a bonus, it will be zeroed before launching the image. Since all architectures that implement support for EFI zboot carry this value in the header in the same location, we can just grab it from the binary that is being compressed. Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
1 parent 8358098 commit bca2f3a

3 files changed

Lines changed: 31 additions & 13 deletions

File tree

drivers/firmware/efi/libstub/Makefile.zboot

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,40 @@
33
# to be include'd by arch/$(ARCH)/boot/Makefile after setting
44
# EFI_ZBOOT_PAYLOAD, EFI_ZBOOT_BFD_TARGET and EFI_ZBOOT_MACH_TYPE
55

6+
quiet_cmd_copy_and_pad = PAD $@
7+
cmd_copy_and_pad = cp $< $@ && \
8+
truncate -s $(shell hexdump -s16 -n4 -e '"%u"' $<) $@
9+
10+
# Pad the file to the size of the uncompressed image in memory, including BSS
11+
$(obj)/vmlinux.bin: $(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE
12+
$(call if_changed,copy_and_pad)
13+
614
comp-type-$(CONFIG_KERNEL_GZIP) := gzip
715
comp-type-$(CONFIG_KERNEL_LZ4) := lz4
816
comp-type-$(CONFIG_KERNEL_LZMA) := lzma
917
comp-type-$(CONFIG_KERNEL_LZO) := lzo
1018
comp-type-$(CONFIG_KERNEL_XZ) := xzkern
1119
comp-type-$(CONFIG_KERNEL_ZSTD) := zstd22
1220

13-
# Copy the SizeOfHeaders, SizeOfCode and SizeOfImage fields from the payload to
14-
# the end of the compressed image. Note that this presupposes a PE header
15-
# offset of 64 bytes, which is what arm64, RISC-V and LoongArch use.
16-
quiet_cmd_compwithsize = $(quiet_cmd_$(comp-type-y))
17-
cmd_compwithsize = $(cmd_$(comp-type-y)) && ( \
21+
# in GZIP, the appended le32 carrying the uncompressed size is part of the
22+
# format, but in other cases, we just append it at the end for convenience,
23+
# causing the original tools to complain when checking image integrity.
24+
# So disregard it when calculating the payload size in the zimage header.
25+
zboot-method-y := $(comp-type-y)_with_size
26+
zboot-size-len-y := 12
27+
28+
zboot-method-$(CONFIG_KERNEL_GZIP) := gzip
29+
zboot-size-len-$(CONFIG_KERNEL_GZIP) := 8
30+
31+
# Copy the SizeOfHeaders and SizeOfCode fields from the payload to the end of
32+
# the compressed image. Note that this presupposes a PE header offset of 64
33+
# bytes, which is what arm64, RISC-V and LoongArch use.
34+
quiet_cmd_compwithsize = $(quiet_cmd_$(zboot-method-y))
35+
cmd_compwithsize = $(cmd_$(zboot-method-y)) && ( \
1836
dd status=none if=$< bs=4 count=1 skip=37 ; \
19-
dd status=none if=$< bs=4 count=1 skip=23 ; \
20-
dd status=none if=$< bs=4 count=1 skip=36 ) >> $@
37+
dd status=none if=$< bs=4 count=1 skip=23 ) >> $@
2138

22-
$(obj)/vmlinuz: $(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE
39+
$(obj)/vmlinuz: $(obj)/vmlinux.bin FORCE
2340
$(call if_changed,compwithsize)
2441

2542
OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) \
@@ -29,6 +46,7 @@ $(obj)/vmlinuz.o: $(obj)/vmlinuz FORCE
2946

3047
AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE) \
3148
-DZBOOT_EFI_PATH="\"$(realpath $(obj)/vmlinuz.efi.elf)\"" \
49+
-DZBOOT_SIZE_LEN=$(zboot-size-len-y) \
3250
-DCOMP_TYPE="\"$(comp-type-y)\""
3351

3452
$(obj)/zboot-header.o: $(srctree)/drivers/firmware/efi/libstub/zboot-header.S FORCE
@@ -44,4 +62,4 @@ OBJCOPYFLAGS_vmlinuz.efi := -O binary
4462
$(obj)/vmlinuz.efi: $(obj)/vmlinuz.efi.elf FORCE
4563
$(call if_changed,objcopy)
4664

47-
targets += zboot-header.o vmlinuz vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
65+
targets += zboot-header.o vmlinux.bin vmlinuz vmlinuz.o vmlinuz.efi.elf vmlinuz.efi

drivers/firmware/efi/libstub/zboot-header.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ __efistub_efi_zboot_header:
1717
.long MZ_MAGIC
1818
.ascii "zimg" // image type
1919
.long __efistub__gzdata_start - .Ldoshdr // payload offset
20-
.long __efistub__gzdata_size - 12 // payload size
20+
.long __efistub__gzdata_size - ZBOOT_SIZE_LEN // payload size
2121
.long 0, 0 // reserved
2222
.asciz COMP_TYPE // compression type
2323
.org .Ldoshdr + 0x38

drivers/firmware/efi/libstub/zboot.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
9191
efi_info("Decompressing Linux Kernel...\n");
9292

9393
// SizeOfImage from the compressee's PE/COFF header
94-
alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),
94+
alloc_size = round_up(get_unaligned_le32(_gzdata_end - 12),
9595
EFI_ALLOC_ALIGN);
9696

9797
// SizeOfHeaders and SizeOfCode from the compressee's PE/COFF header
98-
code_size = get_unaligned_le32(_gzdata_end - 8) +
99-
get_unaligned_le32(_gzdata_end - 12);
98+
code_size = get_unaligned_le32(_gzdata_end - 4) +
99+
get_unaligned_le32(_gzdata_end - 8);
100100

101101
// If the architecture has a preferred address for the image,
102102
// try that first.

0 commit comments

Comments
 (0)