diff options
73 files changed, 2933 insertions, 2685 deletions
diff --git a/Documentation/driver-api/firmware/efi/index.rst b/Documentation/driver-api/firmware/efi/index.rst new file mode 100644 index 000000000000..4fe8abba9fc6 --- /dev/null +++ b/Documentation/driver-api/firmware/efi/index.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============ +UEFI Support +============ + +UEFI stub library functions +=========================== + +.. kernel-doc:: drivers/firmware/efi/libstub/mem.c + :internal: diff --git a/Documentation/driver-api/firmware/index.rst b/Documentation/driver-api/firmware/index.rst index 29da39ec4b8a..57415d657173 100644 --- a/Documentation/driver-api/firmware/index.rst +++ b/Documentation/driver-api/firmware/index.rst @@ -6,6 +6,7 @@ Linux Firmware API introduction core + efi/index request_firmware other_interfaces diff --git a/Documentation/x86/boot.rst b/Documentation/x86/boot.rst index c9c201596c3e..fa7ddc0428c8 100644 --- a/Documentation/x86/boot.rst +++ b/Documentation/x86/boot.rst @@ -490,15 +490,11 @@ Protocol: 2.00+ kernel) to not write early messages that require accessing the display hardware directly. - Bit 6 (write): KEEP_SEGMENTS + Bit 6 (obsolete): KEEP_SEGMENTS Protocol: 2.07+ - - If 0, reload the segment registers in the 32bit entry point. - - If 1, do not reload the segment registers in the 32bit entry point. - - Assume that %cs %ds %ss %es are all set to flat segments with - a base of 0 (or the equivalent for their environment). + - This flag is obsolete. Bit 7 (write): CAN_USE_HEAP diff --git a/MAINTAINERS b/MAINTAINERS index 88bf75088b5a..251e9c3475e5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6363,7 +6363,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git S: Maintained F: Documentation/admin-guide/efi-stub.rst F: arch/*/kernel/efi.c -F: arch/x86/boot/compressed/eboot.[ch] F: arch/*/include/asm/efi.h F: arch/x86/platform/efi/ F: drivers/firmware/efi/ diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S index a5983588f96b..62286da318e7 100644 --- a/arch/arm/boot/compressed/efi-header.S +++ b/arch/arm/boot/compressed/efi-header.S @@ -60,7 +60,7 @@ optional_header: .long __pecoff_code_size @ SizeOfCode .long __pecoff_data_size @ SizeOfInitializedData .long 0 @ SizeOfUninitializedData - .long efi_stub_entry - start @ AddressOfEntryPoint + .long efi_entry - start @ AddressOfEntryPoint .long start_offset @ BaseOfCode .long __pecoff_data_start - start @ BaseOfData @@ -70,8 +70,8 @@ extra_header_fields: .long SZ_512 @ FileAlignment .short 0 @ MajorOsVersion .short 0 @ MinorOsVersion - .short 0 @ MajorImageVersion - .short 0 @ MinorImageVersion + .short LINUX_EFISTUB_MAJOR_VERSION @ MajorImageVersion + .short LINUX_EFISTUB_MINOR_VERSION @ MinorImageVersion .short 0 @ MajorSubsystemVersion .short 0 @ MinorSubsystemVersion .long 0 @ Win32VersionValue diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 088b0a060876..04f77214f050 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -1437,29 +1437,25 @@ __enter_kernel: reloc_code_end: #ifdef CONFIG_EFI_STUB - .align 2 -_start: .long start - . - -ENTRY(efi_stub_entry) - @ allocate space on stack for passing current zImage address - @ and for the EFI stub to return of new entry point of - @ zImage, as EFI stub may copy the kernel. Pointer address - @ is passed in r2. r0 and r1 are passed through from the - @ EFI firmware to efi_entry - adr ip, _start - ldr r3, [ip] - add r3, r3, ip - stmfd sp!, {r3, lr} - mov r2, sp @ pass zImage address in r2 - bl efi_entry - - @ Check for error return from EFI stub. r0 has FDT address - @ or error code. - cmn r0, #1 - beq efi_load_fail - - @ Preserve return value of efi_entry() in r4 - mov r4, r0 +ENTRY(efi_enter_kernel) + mov r7, r0 @ preserve image base + mov r4, r1 @ preserve DT pointer + + mov r0, r4 @ DT start + add r1, r4, r2 @ DT end + bl cache_clean_flush + + mov r0, r7 @ relocated zImage + ldr r1, =_edata @ size of zImage + add r1, r1, r0 @ end of zImage + bl cache_clean_flush + + @ The PE/COFF loader might not have cleaned the code we are + @ running beyond the PoU, and so calling cache_off below from + @ inside the PE/COFF loader allocated region is unsafe unless + @ we explicitly clean it to the PoC. + adr r0, call_cache_fn @ region of code we will + adr r1, 0f @ run with MMU off bl cache_clean_flush bl cache_off @@ -1469,18 +1465,10 @@ ENTRY(efi_stub_entry) mov r0, #0 mov r1, #0xFFFFFFFF mov r2, r4 - - @ Branch to (possibly) relocated zImage that is in [sp] - ldr lr, [sp] - ldr ip, =start_offset - add lr, lr, ip - mov pc, lr @ no mode switch - -efi_load_fail: - @ Return EFI_LOAD_ERROR to EFI firmware on error. - ldr r0, =0x80000001 - ldmfd sp!, {ip, pc} -ENDPROC(efi_stub_entry) + add r7, r7, #(__efi_start - start) + mov pc, r7 @ no mode switch +ENDPROC(efi_enter_kernel) +0: #endif .align diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 44531a69d32b..45e821222774 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -58,13 +58,6 @@ efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...); /* arch specific definitions used by the stub code */ /* - * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from - * start of kernel and may not cross a 2MiB boundary. We set alignment to - * 2MiB so we know it won't cross a 2MiB boundary. - */ -#define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */ - -/* * In some configurations (e.g. VMAP_STACK && 64K pages), stacks built into the * kernel need greater alignment than we require the segments to be padded to. */ @@ -107,9 +100,6 @@ static inline void free_screen_info(struct screen_info *si) { } -/* redeclare as 'hidden' so the compiler will generate relative references */ -extern struct screen_info screen_info __attribute__((__visibility__("hidden"))); - static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) { } diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S index 304d5b02ca67..1a03618df0df 100644 --- a/arch/arm64/kernel/efi-entry.S +++ b/arch/arm64/kernel/efi-entry.S @@ -10,81 +10,35 @@ #include <asm/assembler.h> -#define EFI_LOAD_ERROR 0x8000000000000001 - __INIT - /* - * We arrive here from the EFI boot manager with: - * - * * CPU in little-endian mode - * * MMU on with identity-mapped RAM - * * Icache and Dcache on - * - * We will most likely be running from some place other than where - * we want to be. The kernel image wants to be placed at TEXT_OFFSET - * from start of RAM. - */ -ENTRY(entry) - /* - * Create a stack frame to save FP/LR with extra space - * for image_addr variable passed to efi_entry(). - */ - stp x29, x30, [sp, #-32]! - mov x29, sp - - /* - * Call efi_entry to do the real work. - * x0 and x1 are already set up by firmware. Current runtime - * address of image is calculated and passed via *image_addr. - * - * unsigned long efi_entry(void *handle, - * efi_system_table_t *sys_table, - * unsigned long *image_addr) ; - */ - adr_l x8, _text - add x2, sp, 16 - str x8, [x2] - bl efi_entry - cmn x0, #1 - b.eq efi_load_fail - +SYM_CODE_START(efi_enter_kernel) /* * efi_entry() will have copied the kernel image if necessary and we - * return here with device tree address in x0 and the kernel entry - * point stored at *image_addr. Save those values in registers which - * are callee preserved. - */ - mov x20, x0 // DTB address - ldr x0, [sp, #16] // relocated _text address - ldr w21, =stext_offset - add x21, x0, x21 - - /* - * Calculate size of the kernel Image (same for original and copy). + * end up here with device tree address in x1 and the kernel entry + * point stored in x0. Save those values in registers which are + * callee preserved. */ - adr_l x1, _text - adr_l x2, _edata - sub x1, x2, x1 + ldr w2, =stext_offset + add x19, x0, x2 // relocated Image entrypoint + mov x20, x1 // DTB address /* - * Flush the copied Image to the PoC, and ensure it is not shadowed by + * Clean the copied Image to the PoC, and ensure it is not shadowed by * stale icache entries from before relocation. */ - bl __flush_dcache_area + ldr w1, =kernel_size + bl __clean_dcache_area_poc ic ialluis /* - * Ensure that the rest of this function (in the original Image) is - * visible when the caches are disabled. The I-cache can't have stale - * entries for the VA range of the current image, so no maintenance is - * necessary. + * Clean the remainder of this routine to the PoC + * so that we can safely disable the MMU and caches. */ - adr x0, entry - adr x1, entry_end - sub x1, x1, x0 - bl __flush_dcache_area - + adr x0, 0f + ldr w1, 3f + bl __clean_dcache_area_poc +0: /* Turn off Dcache and MMU */ mrs x0, CurrentEL cmp x0, #CurrentEL_EL2 @@ -109,12 +63,6 @@ ENTRY(entry) mov x1, xzr mov x2, xzr mov x3, xzr - br x21 - -efi_load_fail: - mov x0, #EFI_LOAD_ERROR - ldp x29, x30, [sp], #32 - ret - -entry_end: -ENDPROC(entry) + br x19 +SYM_CODE_END(efi_enter_kernel) +3: .long . - 0b diff --git a/arch/arm64/kernel/efi-header.S b/arch/arm64/kernel/efi-header.S index a7cfacce3e15..914999ccaf8a 100644 --- a/arch/arm64/kernel/efi-header.S +++ b/arch/arm64/kernel/efi-header.S @@ -27,7 +27,7 @@ optional_header: .long __initdata_begin - efi_header_end // SizeOfCode .long __pecoff_data_size // SizeOfInitializedData .long 0 // SizeOfUninitializedData - .long __efistub_entry - _head // AddressOfEntryPoint + .long __efistub_efi_entry - _head // AddressOfEntryPoint .long efi_header_end - _head // BaseOfCode extra_header_fields: @@ -36,8 +36,8 @@ extra_header_fields: .long PECOFF_FILE_ALIGNMENT // FileAlignment .short 0 // MajorOperatingSystemVersion .short 0 // MinorOperatingSystemVersion - .short 0 // MajorImageVersion - .short 0 // MinorImageVersion + .short LINUX_EFISTUB_MAJOR_VERSION // MajorImageVersion + .short LINUX_EFISTUB_MINOR_VERSION // MinorImageVersion .short 0 // MajorSubsystemVersion .short 0 // MinorSubsystemVersion .long 0 // Win32VersionValue diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index 25a2a9b479c2..7f06ad93fc95 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -12,7 +12,9 @@ #ifdef CONFIG_EFI -__efistub_stext_offset = stext - _text; +__efistub_kernel_size = _edata - _text; +__efistub_stext_offset = stext - _text; + /* * The EFI stub has its own symbol namespace prefixed by __efistub_, to @@ -33,7 +35,7 @@ __efistub_strnlen = __pi_strnlen; __efistub_strcmp = __pi_strcmp; __efistub_strncmp = __pi_strncmp; __efistub_strrchr = __pi_strrchr; -__efistub___flush_dcache_area = __pi___flush_dcache_area; +__efistub___clean_dcache_area_poc = __pi___clean_dcache_area_poc; #ifdef CONFIG_KASAN __efistub___memcpy = __pi_memcpy; @@ -45,6 +47,7 @@ __efistub__text = _text; __efistub__end = _end; __efistub__edata = _edata; __efistub_screen_info = screen_info; +__efistub__ctype = _ctype; #endif diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 0a34dcc435c6..f69f3fe0532e 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -45,11 +45,21 @@ #define EFI_DEBUG 0 +#define ESI_TABLE_GUID \ + EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3, \ + 0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4) + +static unsigned long mps_phys = EFI_INVALID_TABLE_ADDR; static __initdata unsigned long palo_phys; +unsigned long __initdata esi_phys = EFI_INVALID_TABLE_ADDR; +unsigned long hcdp_phys = EFI_INVALID_TABLE_ADDR; unsigned long sal_systab_phys = EFI_INVALID_TABLE_ADDR; -static __initdata efi_config_table_type_t arch_tables[] = { +static const efi_config_table_type_t arch_tables[] __initconst = { + {ESI_TABLE_GUID, "ESI", &esi_phys}, + {HCDP_TABLE_GUID, "HCDP", &hcdp_phys}, + {MPS_TABLE_GUID, "MPS", &mps_phys}, {PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, "PALO", &palo_phys}, {SAL_SYSTEM_TABLE_GUID, "SALsystab", &sal_systab_phys}, {NULL_GUID, NULL, 0}, @@ -474,11 +484,10 @@ efi_map_pal_code (void) void __init efi_init (void) { + const efi_system_table_t *efi_systab; void *efi_map_start, *efi_map_end; - efi_char16_t *c16; u64 efi_desc_size; - char *cp, vendor[100] = "unknown"; - int i; + char *cp; set_bit(EFI_BOOT, &efi.flags); set_bit(EFI_64BIT, &efi.flags); @@ -508,42 +517,29 @@ efi_init (void) printk(KERN_INFO "Ignoring memory above %lluMB\n", max_addr >> 20); - efi.systab = __va(ia64_boot_param->efi_systab); + efi_systab = __va(ia64_boot_param->efi_systab); /* * Verify the EFI Table */ - if (efi.systab == NULL) + if (efi_systab == NULL) panic("Whoa! Can't find EFI system table.\n"); - if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) + if (efi_systab_check_header(&efi_systab->hdr, 1)) panic("Whoa! EFI system table signature incorrect\n"); - if ((efi.systab->hdr.revision >> 16) == 0) - printk(KERN_WARNING "Warning: EFI system table version " - "%d.%02d, expected 1.00 or greater\n", - efi.systab->hdr.revision >> 16, - efi.systab->hdr.revision & 0xffff); - - /* Show what we know for posterity */ - c16 = __va(efi.systab->fw_vendor); - if (c16) { - for (i = 0;i < (int) sizeof(vendor) - 1 && *c16; ++i) - vendor[i] = *c16++; - vendor[i] = '\0'; - } - printk(KERN_INFO "EFI v%u.%.02u by %s:", - efi.systab->hdr.revision >> 16, - efi.systab->hdr.revision & 0xffff, vendor); + efi_systab_report_header(&efi_systab->hdr, efi_systab->fw_vendor); palo_phys = EFI_INVALID_TABLE_ADDR; - if (efi_config_init(arch_tables) != 0) + if (efi_config_parse_tables(__va(efi_systab->tables), + efi_systab->nr_tables, + arch_tables) != 0) return; if (palo_phys != EFI_INVALID_TABLE_ADDR) handle_palo(palo_phys); - runtime = __va(efi.systab->runtime); + runtime = __va(efi_systab->runtime); efi.get_time = phys_get_time; efi.set_time = phys_set_time; efi.get_wakeup_time = phys_get_wakeup_time; @@ -1351,3 +1347,12 @@ vmcore_find_descriptor_size (unsigned long address) return ret; } #endif + +char *efi_systab_show_arch(char *str) +{ + if (mps_phys != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "MPS=0x%lx\n", mps_phys); + if (hcdp_phys != EFI_INVALID_TABLE_ADDR) + str += sprintf(str, "HCDP=0x%lx\n", hcdp_phys); + return str; +} diff --git a/arch/ia64/kernel/esi.c b/arch/ia64/kernel/esi.c index cb514126ef7f..4df57c93e0a8 100644 --- a/arch/ia64/kernel/esi.c +++ b/arch/ia64/kernel/esi.c @@ -19,10 +19,6 @@ MODULE_LICENSE("GPL"); #define MODULE_NAME "esi" -#define ESI_TABLE_GUID \ - EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3, \ - 0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4) - enum esi_systab_entry_type { ESI_DESC_ENTRY_POINT = 0 }; @@ -48,27 +44,18 @@ struct pdesc { static struct ia64_sal_systab *esi_systab; +extern unsigned long esi_phys; + static int __init esi_init (void) { - efi_config_table_t *config_tables; struct ia64_sal_systab *systab; - unsigned long esi = 0; char *p; |