Skip to content

Commit 825a071

Browse files
committed
Merge tag 'efi-next-for-v6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi
Pull EFI updates from Ard Biesheuvel: - relocate the LoongArch kernel if the preferred address is already occupied - implement BTI annotations for arm64 EFI stub and zboot images - clean up arm64 zboot Kbuild rules for injecting the kernel code size * tag 'efi-next-for-v6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi: efi/zboot: arm64: Grab code size from ELF symbol in payload efi/zboot: arm64: Inject kernel code size symbol into the zboot payload efi/zboot: Set forward edge CFI compat header flag if supported efi/zboot: Add BSS padding before compression arm64: efi: Enable BTI codegen and add PE/COFF annotation efi/pe: Import new BTI/IBT header flags from the spec efi/loongarch: Reintroduce efi_relocate_kernel() to relocate kernel
2 parents 17d4ded + 026b857 commit 825a071

File tree

12 files changed

+149
-97
lines changed

12 files changed

+149
-97
lines changed

arch/arm64/boot/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,9 @@ $(obj)/Image.zst: $(obj)/Image FORCE
4242
EFI_ZBOOT_PAYLOAD := Image
4343
EFI_ZBOOT_BFD_TARGET := elf64-littleaarch64
4444
EFI_ZBOOT_MACH_TYPE := ARM64
45+
EFI_ZBOOT_FORWARD_CFI := $(CONFIG_ARM64_BTI_KERNEL)
46+
47+
EFI_ZBOOT_OBJCOPY_FLAGS = --add-symbol zboot_code_size=0x$(shell \
48+
$(NM) vmlinux|grep _kernel_codesize|cut -d' ' -f1)
4549

4650
include $(srctree)/drivers/firmware/efi/libstub/Makefile.zboot

arch/arm64/kernel/efi-header.S

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,47 @@
8181
.quad 0 // CertificationTable
8282
.quad 0 // BaseRelocationTable
8383

84-
#ifdef CONFIG_DEBUG_EFI
84+
#if defined(CONFIG_DEBUG_EFI) || defined(CONFIG_ARM64_BTI_KERNEL)
8585
.long .Lefi_debug_table - .L_head // DebugTable
8686
.long .Lefi_debug_table_size
87+
88+
/*
89+
* The debug table is referenced via its Relative Virtual Address (RVA),
90+
* which is only defined for those parts of the image that are covered
91+
* by a section declaration. Since this header is not covered by any
92+
* section, the debug table must be emitted elsewhere. So stick it in
93+
* the .init.rodata section instead.
94+
*
95+
* Note that the payloads themselves are permitted to have zero RVAs,
96+
* which means we can simply put those right after the section headers.
97+
*/
98+
__INITRODATA
99+
100+
.align 2
101+
.Lefi_debug_table:
102+
#ifdef CONFIG_DEBUG_EFI
103+
// EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
104+
.long 0 // Characteristics
105+
.long 0 // TimeDateStamp
106+
.short 0 // MajorVersion
107+
.short 0 // MinorVersion
108+
.long IMAGE_DEBUG_TYPE_CODEVIEW // Type
109+
.long .Lefi_debug_entry_size // SizeOfData
110+
.long 0 // RVA
111+
.long .Lefi_debug_entry - .L_head // FileOffset
112+
#endif
113+
#ifdef CONFIG_ARM64_BTI_KERNEL
114+
.long 0 // Characteristics
115+
.long 0 // TimeDateStamp
116+
.short 0 // MajorVersion
117+
.short 0 // MinorVersion
118+
.long IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS // Type
119+
.long 4 // SizeOfData
120+
.long 0 // RVA
121+
.long .Lefi_dll_characteristics_ex - .L_head // FileOffset
122+
#endif
123+
.set .Lefi_debug_table_size, . - .Lefi_debug_table
124+
.previous
87125
#endif
88126

89127
// Section table
@@ -119,33 +157,6 @@
119157
.set .Lsection_count, (. - .Lsection_table) / 40
120158

121159
#ifdef CONFIG_DEBUG_EFI
122-
/*
123-
* The debug table is referenced via its Relative Virtual Address (RVA),
124-
* which is only defined for those parts of the image that are covered
125-
* by a section declaration. Since this header is not covered by any
126-
* section, the debug table must be emitted elsewhere. So stick it in
127-
* the .init.rodata section instead.
128-
*
129-
* Note that the EFI debug entry itself may legally have a zero RVA,
130-
* which means we can simply put it right after the section headers.
131-
*/
132-
__INITRODATA
133-
134-
.align 2
135-
.Lefi_debug_table:
136-
// EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
137-
.long 0 // Characteristics
138-
.long 0 // TimeDateStamp
139-
.short 0 // MajorVersion
140-
.short 0 // MinorVersion
141-
.long IMAGE_DEBUG_TYPE_CODEVIEW // Type
142-
.long .Lefi_debug_entry_size // SizeOfData
143-
.long 0 // RVA
144-
.long .Lefi_debug_entry - .L_head // FileOffset
145-
146-
.set .Lefi_debug_table_size, . - .Lefi_debug_table
147-
.previous
148-
149160
.Lefi_debug_entry:
150161
// EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
151162
.ascii "NB10" // Signature
@@ -157,6 +168,10 @@
157168

158169
.set .Lefi_debug_entry_size, . - .Lefi_debug_entry
159170
#endif
171+
#ifdef CONFIG_ARM64_BTI_KERNEL
172+
.Lefi_dll_characteristics_ex:
173+
.long IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT
174+
#endif
160175

161176
.balign SEGMENT_ALIGN
162177
.Lefi_header_end:

arch/arm64/kernel/image-vars.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,8 @@ KVM_NVHE_ALIAS(kvm_protected_mode_initialized);
108108

109109
#endif /* CONFIG_KVM */
110110

111+
#ifdef CONFIG_EFI_ZBOOT
112+
_kernel_codesize = ABSOLUTE(__inittext_end - _text);
113+
#endif
114+
111115
#endif /* __ARM64_KERNEL_IMAGE_VARS_H */

drivers/firmware/efi/libstub/Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
2323
# arm64 uses the full KBUILD_CFLAGS so it's necessary to explicitly
2424
# disable the stackleak plugin
2525
cflags-$(CONFIG_ARM64) += -fpie $(DISABLE_STACKLEAK_PLUGIN) \
26-
-fno-unwind-tables -fno-asynchronous-unwind-tables \
27-
$(call cc-option,-mbranch-protection=none)
26+
-fno-unwind-tables -fno-asynchronous-unwind-tables
2827
cflags-$(CONFIG_ARM) += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
2928
-DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \
3029
-DEFI_HAVE_STRCMP -fno-builtin -fpic \
Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
# SPDX-License-Identifier: GPL-2.0
22

33
# to be include'd by arch/$(ARCH)/boot/Makefile after setting
4-
# EFI_ZBOOT_PAYLOAD, EFI_ZBOOT_BFD_TARGET and EFI_ZBOOT_MACH_TYPE
4+
# EFI_ZBOOT_PAYLOAD, EFI_ZBOOT_BFD_TARGET, EFI_ZBOOT_MACH_TYPE and
5+
# EFI_ZBOOT_FORWARD_CFI
6+
7+
quiet_cmd_copy_and_pad = PAD $@
8+
cmd_copy_and_pad = cp $< $@ && \
9+
truncate -s $(shell hexdump -s16 -n4 -e '"%u"' $<) $@
10+
11+
# Pad the file to the size of the uncompressed image in memory, including BSS
12+
$(obj)/vmlinux.bin: $(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE
13+
$(call if_changed,copy_and_pad)
514

615
comp-type-$(CONFIG_KERNEL_GZIP) := gzip
716
comp-type-$(CONFIG_KERNEL_LZ4) := lz4
@@ -10,26 +19,32 @@ comp-type-$(CONFIG_KERNEL_LZO) := lzo
1019
comp-type-$(CONFIG_KERNEL_XZ) := xzkern
1120
comp-type-$(CONFIG_KERNEL_ZSTD) := zstd22
1221

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)) && ( \
18-
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 ) >> $@
22+
# in GZIP, the appended le32 carrying the uncompressed size is part of the
23+
# format, but in other cases, we just append it at the end for convenience,
24+
# causing the original tools to complain when checking image integrity.
25+
# So disregard it when calculating the payload size in the zimage header.
26+
zboot-method-y := $(comp-type-y)_with_size
27+
zboot-size-len-y := 4
2128

22-
$(obj)/vmlinuz: $(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE
23-
$(call if_changed,compwithsize)
29+
zboot-method-$(CONFIG_KERNEL_GZIP) := gzip
30+
zboot-size-len-$(CONFIG_KERNEL_GZIP) := 0
2431

25-
OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) \
32+
$(obj)/vmlinuz: $(obj)/vmlinux.bin FORCE
33+
$(call if_changed,$(zboot-method-y))
34+
35+
OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) $(EFI_ZBOOT_OBJCOPY_FLAGS) \
2636
--rename-section .data=.gzdata,load,alloc,readonly,contents
2737
$(obj)/vmlinuz.o: $(obj)/vmlinuz FORCE
2838
$(call if_changed,objcopy)
2939

40+
aflags-zboot-header-$(EFI_ZBOOT_FORWARD_CFI) := \
41+
-DPE_DLL_CHAR_EX=IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT
42+
3043
AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE) \
3144
-DZBOOT_EFI_PATH="\"$(realpath $(obj)/vmlinuz.efi.elf)\"" \
32-
-DCOMP_TYPE="\"$(comp-type-y)\""
45+
-DZBOOT_SIZE_LEN=$(zboot-size-len-y) \
46+
-DCOMP_TYPE="\"$(comp-type-y)\"" \
47+
$(aflags-zboot-header-y)
3348

3449
$(obj)/zboot-header.o: $(srctree)/drivers/firmware/efi/libstub/zboot-header.S FORCE
3550
$(call if_changed_rule,as_o_S)
@@ -44,4 +59,4 @@ OBJCOPYFLAGS_vmlinuz.efi := -O binary
4459
$(obj)/vmlinuz.efi: $(obj)/vmlinuz.efi.elf FORCE
4560
$(call if_changed,objcopy)
4661

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

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/loongarch-stub.c

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,16 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
2121
efi_loaded_image_t *image,
2222
efi_handle_t image_handle)
2323
{
24-
int nr_pages = round_up(kernel_asize, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
25-
efi_physical_addr_t kernel_addr = EFI_KIMG_PREFERRED_ADDRESS;
2624
efi_status_t status;
25+
unsigned long kernel_addr = 0;
2726

28-
/*
29-
* Allocate space for the kernel image at the preferred offset. This is
30-
* the only location in memory from where we can execute the image, so
31-
* no point in falling back to another allocation.
32-
*/
33-
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
34-
EFI_LOADER_DATA, nr_pages, &kernel_addr);
35-
if (status != EFI_SUCCESS)
36-
return status;
37-
38-
*image_addr = EFI_KIMG_PREFERRED_ADDRESS;
39-
*image_size = kernel_asize;
27+
kernel_addr = (unsigned long)&kernel_offset - kernel_offset;
28+
29+
status = efi_relocate_kernel(&kernel_addr, kernel_fsize, kernel_asize,
30+
EFI_KIMG_PREFERRED_ADDRESS, efi_get_kimg_min_align(), 0x0);
4031

41-
memcpy((void *)EFI_KIMG_PREFERRED_ADDRESS,
42-
(void *)&kernel_offset - kernel_offset,
43-
kernel_fsize);
32+
*image_addr = kernel_addr;
33+
*image_size = kernel_asize;
4434

4535
return status;
4636
}

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

Lines changed: 33 additions & 18 deletions
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
@@ -78,9 +78,36 @@ __efistub_efi_zboot_header:
7878
.quad 0 // ExceptionTable
7979
.quad 0 // CertificationTable
8080
.quad 0 // BaseRelocationTable
81-
#ifdef CONFIG_DEBUG_EFI
81+
#if defined(PE_DLL_CHAR_EX) || defined(CONFIG_DEBUG_EFI)
8282
.long .Lefi_debug_table - .Ldoshdr // DebugTable
8383
.long .Lefi_debug_table_size
84+
85+
.section ".rodata", "a"
86+
.p2align 2
87+
.Lefi_debug_table:
88+
// EFI_IMAGE_DEBUG_DIRECTORY_ENTRY[]
89+
#ifdef PE_DLL_CHAR_EX
90+
.long 0 // Characteristics
91+
.long 0 // TimeDateStamp
92+
.short 0 // MajorVersion
93+
.short 0 // MinorVersion
94+
.long IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS // Type
95+
.long 4 // SizeOfData
96+
.long 0 // RVA
97+
.long .Lefi_dll_characteristics_ex - .Ldoshdr // FileOffset
98+
#endif
99+
#ifdef CONFIG_DEBUG_EFI
100+
.long 0 // Characteristics
101+
.long 0 // TimeDateStamp
102+
.short 0 // MajorVersion
103+
.short 0 // MinorVersion
104+
.long IMAGE_DEBUG_TYPE_CODEVIEW // Type
105+
.long .Lefi_debug_entry_size // SizeOfData
106+
.long 0 // RVA
107+
.long .Lefi_debug_entry - .Ldoshdr // FileOffset
108+
#endif
109+
.set .Lefi_debug_table_size, . - .Lefi_debug_table
110+
.previous
84111
#endif
85112

86113
.Lsection_table:
@@ -110,23 +137,11 @@ __efistub_efi_zboot_header:
110137

111138
.set .Lsection_count, (. - .Lsection_table) / 40
112139

140+
#ifdef PE_DLL_CHAR_EX
141+
.Lefi_dll_characteristics_ex:
142+
.long PE_DLL_CHAR_EX
143+
#endif
113144
#ifdef CONFIG_DEBUG_EFI
114-
.section ".rodata", "a"
115-
.align 2
116-
.Lefi_debug_table:
117-
// EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
118-
.long 0 // Characteristics
119-
.long 0 // TimeDateStamp
120-
.short 0 // MajorVersion
121-
.short 0 // MinorVersion
122-
.long IMAGE_DEBUG_TYPE_CODEVIEW // Type
123-
.long .Lefi_debug_entry_size // SizeOfData
124-
.long 0 // RVA
125-
.long .Lefi_debug_entry - .Ldoshdr // FileOffset
126-
127-
.set .Lefi_debug_table_size, . - .Lefi_debug_table
128-
.previous
129-
130145
.Lefi_debug_entry:
131146
// EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
132147
.ascii "NB10" // Signature

drivers/firmware/efi/libstub/zboot.c

Lines changed: 3 additions & 10 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;
@@ -94,10 +93,6 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
9493
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 - 8) +
99-
get_unaligned_le32(_gzdata_end - 12);
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)