diff options
Diffstat (limited to 'drivers/firmware/efi')
-rw-r--r-- | drivers/firmware/efi/Kconfig | 24 | ||||
-rw-r--r-- | drivers/firmware/efi/efi.c | 1 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/Makefile | 1 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/Makefile.zboot | 4 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/efi-stub-helper.c | 1 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/x86-5lvl.c | 2 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/x86-mixed.S | 253 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/zboot-header.S | 32 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/zboot.lds | 11 | ||||
-rw-r--r-- | drivers/firmware/efi/memmap.c | 3 | ||||
-rw-r--r-- | drivers/firmware/efi/test/efi_test.c | 4 |
11 files changed, 73 insertions, 263 deletions
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 5fe61b9ab5f9..db8c5c03d3a2 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -281,6 +281,30 @@ config EFI_EMBEDDED_FIRMWARE bool select CRYPTO_LIB_SHA256 +config EFI_SBAT + def_bool y if EFI_SBAT_FILE!="" + +config EFI_SBAT_FILE + string "Embedded SBAT section file path" + depends on EFI_ZBOOT + help + SBAT section provides a way to improve SecureBoot revocations of UEFI + binaries by introducing a generation-based mechanism. With SBAT, older + UEFI binaries can be prevented from booting by bumping the minimal + required generation for the specific component in the bootloader. + + Note: SBAT information is distribution specific, i.e. the owner of the + signing SecureBoot certificate must define the SBAT policy. Linux + kernel upstream does not define SBAT components and their generations. + + See https://github.com/rhboot/shim/blob/main/SBAT.md for the additional + details. + + Specify a file with SBAT data which is going to be embedded as '.sbat' + section into the kernel. + + If unsure, leave blank. + endmenu config UEFI_CPER diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 7309394b8fc9..e57bff702b5f 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -558,6 +558,7 @@ int __efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) extern int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) __weak __alias(__efi_mem_desc_lookup); +EXPORT_SYMBOL_GPL(efi_mem_desc_lookup); /* * Calculate the highest address of an efi memory descriptor. diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index d23a1b9fed75..2f173391b63d 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -85,7 +85,6 @@ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \ lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o lib-$(CONFIG_X86) += x86-stub.o smbios.o -lib-$(CONFIG_EFI_MIXED) += x86-mixed.o lib-$(CONFIG_X86_64) += x86-5lvl.o lib-$(CONFIG_RISCV) += kaslr.o riscv.o riscv-stub.o lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o diff --git a/drivers/firmware/efi/libstub/Makefile.zboot b/drivers/firmware/efi/libstub/Makefile.zboot index 48842b5c106b..92e3c73502ba 100644 --- a/drivers/firmware/efi/libstub/Makefile.zboot +++ b/drivers/firmware/efi/libstub/Makefile.zboot @@ -44,6 +44,10 @@ AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE $(obj)/zboot-header.o: $(srctree)/drivers/firmware/efi/libstub/zboot-header.S FORCE $(call if_changed_rule,as_o_S) +ifneq ($(CONFIG_EFI_SBAT_FILE),) +$(obj)/zboot-header.o: $(CONFIG_EFI_SBAT_FILE) +endif + ZBOOT_DEPS := $(obj)/zboot-header.o $(objtree)/drivers/firmware/efi/libstub/lib.a LDFLAGS_vmlinuz.efi.elf := -T $(srctree)/drivers/firmware/efi/libstub/zboot.lds diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index fd6dc790c5a8..7aa2f9ad2935 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -601,6 +601,7 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image, * @image: EFI loaded image protocol * @soft_limit: preferred address for loading the initrd * @hard_limit: upper limit address for loading the initrd + * @out: pointer to store the address of the initrd table * * Return: status code */ diff --git a/drivers/firmware/efi/libstub/x86-5lvl.c b/drivers/firmware/efi/libstub/x86-5lvl.c index 77359e802181..f1c5fb45d5f7 100644 --- a/drivers/firmware/efi/libstub/x86-5lvl.c +++ b/drivers/firmware/efi/libstub/x86-5lvl.c @@ -62,7 +62,7 @@ efi_status_t efi_setup_5level_paging(void) void efi_5level_switch(void) { - bool want_la57 = IS_ENABLED(CONFIG_X86_5LEVEL) && !efi_no5lvl; + bool want_la57 = !efi_no5lvl; bool have_la57 = native_read_cr4() & X86_CR4_LA57; bool need_toggle = want_la57 ^ have_la57; u64 *pgt = (void *)la57_toggle + PAGE_SIZE; diff --git a/drivers/firmware/efi/libstub/x86-mixed.S b/drivers/firmware/efi/libstub/x86-mixed.S deleted file mode 100644 index e04ed99bc449..000000000000 --- a/drivers/firmware/efi/libstub/x86-mixed.S +++ /dev/null @@ -1,253 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming - * - * Early support for invoking 32-bit EFI services from a 64-bit kernel. - * - * Because this thunking occurs before ExitBootServices() we have to - * restore the firmware's 32-bit GDT and IDT before we make EFI service - * calls. - * - * On the plus side, we don't have to worry about mangling 64-bit - * addresses into 32-bits because we're executing with an identity - * mapped pagetable and haven't transitioned to 64-bit virtual addresses - * yet. - */ - -#include <linux/linkage.h> -#include <asm/desc_defs.h> -#include <asm/msr.h> -#include <asm/page_types.h> -#include <asm/pgtable_types.h> -#include <asm/processor-flags.h> -#include <asm/segment.h> - - .text - .code32 -#ifdef CONFIG_EFI_HANDOVER_PROTOCOL -SYM_FUNC_START(efi32_stub_entry) - call 1f -1: popl %ecx - - /* Clear BSS */ - xorl %eax, %eax - leal (_bss - 1b)(%ecx), %edi - leal (_ebss - 1b)(%ecx), %ecx - subl %edi, %ecx - shrl $2, %ecx - cld - rep stosl - - add $0x4, %esp /* Discard return address */ - movl 8(%esp), %ebx /* struct boot_params pointer */ - jmp efi32_startup -SYM_FUNC_END(efi32_stub_entry) -#endif - -/* - * Called using a far call from __efi64_thunk() below, using the x86_64 SysV - * ABI (except for R8/R9 which are inaccessible to 32-bit code - EAX/EBX are - * used instead). EBP+16 points to the arguments passed via the stack. - * - * The first argument (EDI) is a pointer to the boot service or protocol, to - * which the remaining arguments are passed, each truncated to 32 bits. - */ -SYM_FUNC_START_LOCAL(efi_enter32) - /* - * Convert x86-64 SysV ABI params to i386 ABI - */ - pushl 32(%ebp) /* Up to 3 args passed via the stack */ - pushl 24(%ebp) - pushl 16(%ebp) - pushl %ebx /* R9 */ - pushl %eax /* R8 */ - pushl %ecx - pushl %edx - pushl %esi - - /* Disable paging */ - movl %cr0, %eax - btrl $X86_CR0_PG_BIT, %eax - movl %eax, %cr0 - - /* Disable long mode via EFER */ - movl $MSR_EFER, %ecx - rdmsr - btrl $_EFER_LME, %eax - wrmsr - - call *%edi - - /* We must preserve return value */ - movl %eax, %edi - - call efi32_enable_long_mode - - addl $32, %esp - movl %edi, %eax - lret -SYM_FUNC_END(efi_enter32) - - .code64 -SYM_FUNC_START(__efi64_thunk) - push %rbp - movl %esp, %ebp - push %rbx - - /* Move args #5 and #6 into 32-bit accessible registers */ - movl %r8d, %eax - movl %r9d, %ebx - - lcalll *efi32_call(%rip) - - pop %rbx - pop %rbp - RET -SYM_FUNC_END(__efi64_thunk) - - .code32 -SYM_FUNC_START_LOCAL(efi32_enable_long_mode) - movl %cr4, %eax - btsl $(X86_CR4_PAE_BIT), %eax - movl %eax, %cr4 - - movl $MSR_EFER, %ecx - rdmsr - btsl $_EFER_LME, %eax - wrmsr - - /* Disable interrupts - the firmware's IDT does not work in long mode */ - cli - - /* Enable paging */ - movl %cr0, %eax - btsl $X86_CR0_PG_BIT, %eax - movl %eax, %cr0 - ret -SYM_FUNC_END(efi32_enable_long_mode) - -/* - * This is the common EFI stub entry point for mixed mode. It sets up the GDT - * and page tables needed for 64-bit execution, after which it calls the - * common 64-bit EFI entrypoint efi_stub_entry(). - * - * Arguments: 0(%esp) image handle - * 4(%esp) EFI system table pointer - * %ebx struct boot_params pointer (or NULL) - * - * Since this is the point of no return for ordinary execution, no registers - * are considered live except for the function parameters. [Note that the EFI - * stub may still exit and return to the firmware using the Exit() EFI boot - * service.] - */ -SYM_FUNC_START_LOCAL(efi32_startup) - movl %esp, %ebp - - subl $8, %esp - sgdtl (%esp) /* Save GDT descriptor to the stack */ - movl 2(%esp), %esi /* Existing GDT pointer */ - movzwl (%esp), %ecx /* Existing GDT limit */ - inc %ecx /* Existing GDT size */ - andl $~7, %ecx /* Ensure size is multiple of 8 */ - - subl %ecx, %esp /* Allocate new GDT */ - andl $~15, %esp /* Realign the stack */ - movl %esp, %edi /* New GDT address */ - leal 7(%ecx), %eax /* New GDT limit */ - pushw %cx /* Push 64-bit CS (for LJMP below) */ - pushl %edi /* Push new GDT address */ - pushw %ax /* Push new GDT limit */ - - /* Copy GDT to the stack and add a 64-bit code segment at the end */ - movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) & 0xffffffff, (%edi,%ecx) - movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) >> 32, 4(%edi,%ecx) - shrl $2, %ecx - cld - rep movsl /* Copy the firmware GDT */ - lgdtl (%esp) /* Switch to the new GDT */ - - call 1f -1: pop %edi - - /* Record mixed mode entry */ - movb $0x0, (efi_is64 - 1b)(%edi) - - /* Set up indirect far call to re-enter 32-bit mode */ - leal (efi32_call - 1b)(%edi), %eax - addl %eax, (%eax) - movw %cs, 4(%eax) - - /* Disable paging */ - movl %cr0, %eax - btrl $X86_CR0_PG_BIT, %eax - movl %eax, %cr0 - - /* Set up 1:1 mapping */ - leal (pte - 1b)(%edi), %eax - movl $_PAGE_PRESENT | _PAGE_RW | _PAGE_PSE, %ecx - leal (_PAGE_PRESENT | _PAGE_RW)(%eax), %edx -2: movl %ecx, (%eax) - addl $8, %eax - addl $PMD_SIZE, %ecx - jnc 2b - - movl $PAGE_SIZE, %ecx - .irpc l, 0123 - movl %edx, \l * 8(%eax) - addl %ecx, %edx - .endr - addl %ecx, %eax - movl %edx, (%eax) - movl %eax, %cr3 - - call efi32_enable_long_mode - - /* Set up far jump to 64-bit mode (CS is already on the stack) */ - leal (efi_stub_entry - 1b)(%edi), %eax - movl %eax, 2(%esp) - - movl 0(%ebp), %edi - movl 4(%ebp), %esi - movl %ebx, %edx - ljmpl *2(%esp) -SYM_FUNC_END(efi32_startup) - -/* - * efi_status_t efi32_pe_entry(efi_handle_t image_handle, - * efi_system_table_32_t *sys_table) - */ -SYM_FUNC_START(efi32_pe_entry) - pushl %ebx // save callee-save registers - - /* Check whether the CPU supports long mode */ - movl $0x80000001, %eax // assume extended info support - cpuid - btl $29, %edx // check long mode bit - jnc 1f - leal 8(%esp), %esp // preserve stack alignment - xor %ebx, %ebx // no struct boot_params pointer - jmp efi32_startup // only ESP and EBX remain live -1: movl $0x80000003, %eax // EFI_UNSUPPORTED - popl %ebx - RET -SYM_FUNC_END(efi32_pe_entry) - -#ifdef CONFIG_EFI_HANDOVER_PROTOCOL - .org efi32_stub_entry + 0x200 - .code64 -SYM_FUNC_START_NOALIGN(efi64_stub_entry) - jmp efi_handover_entry -SYM_FUNC_END(efi64_stub_entry) -#endif - - .data - .balign 8 -SYM_DATA_START_LOCAL(efi32_call) - .long efi_enter32 - . - .word 0x0 -SYM_DATA_END(efi32_call) -SYM_DATA(efi_is64, .byte 1) - - .bss - .balign PAGE_SIZE -SYM_DATA_LOCAL(pte, .fill 6 * PAGE_SIZE, 1, 0) diff --git a/drivers/firmware/efi/libstub/zboot-header.S b/drivers/firmware/efi/libstub/zboot-header.S index fb676ded47fa..b6431edd0fc9 100644 --- a/drivers/firmware/efi/libstub/zboot-header.S +++ b/drivers/firmware/efi/libstub/zboot-header.S @@ -4,17 +4,17 @@ #ifdef CONFIG_64BIT .set .Lextra_characteristics, 0x0 - .set .Lpe_opt_magic, PE_OPT_MAGIC_PE32PLUS + .set .Lpe_opt_magic, IMAGE_NT_OPTIONAL_HDR64_MAGIC #else .set .Lextra_characteristics, IMAGE_FILE_32BIT_MACHINE - .set .Lpe_opt_magic, PE_OPT_MAGIC_PE32 + .set .Lpe_opt_magic, IMAGE_NT_OPTIONAL_HDR32_MAGIC #endif .section ".head", "a" .globl __efistub_efi_zboot_header __efistub_efi_zboot_header: .Ldoshdr: - .long MZ_MAGIC + .long IMAGE_DOS_SIGNATURE .ascii "zimg" // image type .long __efistub__gzdata_start - .Ldoshdr // payload offset .long __efistub__gzdata_size - ZBOOT_SIZE_LEN // payload size @@ -25,7 +25,7 @@ __efistub_efi_zboot_header: .long .Lpehdr - .Ldoshdr // PE header offset .Lpehdr: - .long PE_MAGIC + .long IMAGE_NT_SIGNATURE .short MACHINE_TYPE .short .Lsection_count .long 0 @@ -63,7 +63,7 @@ __efistub_efi_zboot_header: .long .Lefi_header_end - .Ldoshdr .long 0 .short IMAGE_SUBSYSTEM_EFI_APPLICATION - .short IMAGE_DLL_CHARACTERISTICS_NX_COMPAT + .short IMAGE_DLLCHARACTERISTICS_NX_COMPAT #ifdef CONFIG_64BIT .quad 0, 0, 0, 0 #else @@ -123,11 +123,29 @@ __efistub_efi_zboot_header: IMAGE_SCN_MEM_READ | \ IMAGE_SCN_MEM_EXECUTE +#ifdef CONFIG_EFI_SBAT + .ascii ".sbat\0\0\0" + .long __sbat_size + .long _sbat - .Ldoshdr + .long __sbat_size + .long _sbat - .Ldoshdr + + .long 0, 0 + .short 0, 0 + .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ + IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_DISCARDABLE + + .pushsection ".sbat", "a", @progbits + .incbin CONFIG_EFI_SBAT_FILE + .popsection +#endif + .ascii ".data\0\0\0" .long __data_size - .long _etext - .Ldoshdr + .long _data - .Ldoshdr .long __data_rawsize - .long _etext - .Ldoshdr + .long _data - .Ldoshdr .long 0, 0 .short 0, 0 diff --git a/drivers/firmware/efi/libstub/zboot.lds b/drivers/firmware/efi/libstub/zboot.lds index 9ecc57ff5b45..c3a166675450 100644 --- a/drivers/firmware/efi/libstub/zboot.lds +++ b/drivers/firmware/efi/libstub/zboot.lds @@ -29,7 +29,17 @@ SECTIONS . = _etext; } +#ifdef CONFIG_EFI_SBAT + .sbat : ALIGN(4096) { + _sbat = .; + *(.sbat) + _esbat = ALIGN(4096); + . = _esbat; + } +#endif + .data : ALIGN(4096) { + _data = .; *(.data* .init.data*) _edata = ALIGN(512); . = _edata; @@ -52,3 +62,4 @@ PROVIDE(__efistub__gzdata_size = PROVIDE(__data_rawsize = ABSOLUTE(_edata - _etext)); PROVIDE(__data_size = ABSOLUTE(_end - _etext)); +PROVIDE(__sbat_size = ABSOLUTE(_esbat - _sbat)); diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c index 34109fd86c55..f1c04d7cfd71 100644 --- a/drivers/firmware/efi/memmap.c +++ b/drivers/firmware/efi/memmap.c @@ -43,7 +43,8 @@ int __init __efi_memmap_init(struct efi_memory_map_data *data) map.map = early_memremap(phys_map, data->size); if (!map.map) { - pr_err("Could not map the memory map!\n"); + pr_err("Could not map the memory map! phys_map=%pa, size=0x%lx\n", + &phys_map, data->size); return -ENOMEM; } diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c index 9e2628728aad..77b5f7ac3e20 100644 --- a/drivers/firmware/efi/test/efi_test.c +++ b/drivers/firmware/efi/test/efi_test.c @@ -361,6 +361,10 @@ static long efi_runtime_get_waketime(unsigned long arg) getwakeuptime.enabled)) return -EFAULT; + if (getwakeuptime.pending && put_user(pending, + getwakeuptime.pending)) + return -EFAULT; + if (getwakeuptime.time) { if (copy_to_user(getwakeuptime.time, &efi_time, sizeof(efi_time_t))) |