Skip to content

Commit

Permalink
Merge tag 'efi-next' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/efi/efi into efi/core

Pull EFI updates for v5.7 from Ard Biesheuvel:

This time, the set of changes for the EFI subsystem is much larger than
usual. The main reasons are:

 - Get things cleaned up before EFI support for RISC-V arrives, which will
   increase the size of the validation matrix, and therefore the threshold to
   making drastic changes,

 - After years of defunct maintainership, the GRUB project has finally started
   to consider changes from the distros regarding UEFI boot, some of which are
   highly specific to the way x86 does UEFI secure boot and measured boot,
   based on knowledge of both shim internals and the layout of bootparams and
   the x86 setup header. Having this maintenance burden on other architectures
   (which don't need shim in the first place) is hard to justify, so instead,
   we are introducing a generic Linux/UEFI boot protocol.

Summary of changes:

 - Boot time GDT handling changes (Arvind)

 - Simplify handling of EFI properties table on arm64

 - Generic EFI stub cleanups, to improve command line handling, file I/O,
   memory allocation, etc.

 - Introduce a generic initrd loading method based on calling back into
   the firmware, instead of relying on the x86 EFI handover protocol or
   device tree.

 - Introduce a mixed mode boot method that does not rely on the x86 EFI
   handover protocol either, and could potentially be adopted by other
   architectures (if another one ever surfaces where one execution mode
   is a superset of another)

 - Clean up the contents of struct efi, and move out everything that
   doesn't need to be stored there.

 - Incorporate support for UEFI spec v2.8A changes that permit firmware
   implementations to return EFI_UNSUPPORTED from UEFI runtime services at
   OS runtime, and expose a mask of which ones are supported or unsupported
   via a configuration table.

 - Various documentation updates and minor code cleanups (Heinrich)

 - Partial fix for the lack of by-VA cache maintenance in the decompressor
   on 32-bit ARM. Note that these patches were deliberately put at the
   beginning so they can be used as a stable branch that will be shared with
   a PR containing the complete fix, which I will send to the ARM tree.

Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
Ingo Molnar committed Feb 26, 2020
2 parents c5f8689 + dc235d6 commit e976568
Show file tree
Hide file tree
Showing 66 changed files with 2,718 additions and 2,638 deletions.
8 changes: 2 additions & 6 deletions Documentation/x86/boot.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions arch/arm/boot/compressed/efi-header.S
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
60 changes: 25 additions & 35 deletions arch/arm/boot/compressed/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -1437,30 +1437,28 @@ __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. Let's
@ assume our own zImage relocation code did a better job, and
@ jump into its version of this routine before proceeding.
ldr r1, .Ljmp
sub r1, r7, r1
mov pc, r1 @ no mode switch
0:
bl cache_off

@ Set parameters for booting zImage according to boot protocol
Expand All @@ -1469,18 +1467,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)
b __efi_start
ENDPROC(efi_enter_kernel)
.align 2
.Ljmp: .long start - 0b
#endif

.align
Expand Down
10 changes: 0 additions & 10 deletions arch/arm64/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,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.
Expand Down Expand Up @@ -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)
{
}
Expand Down
86 changes: 17 additions & 69 deletions arch/arm64/kernel/efi-entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -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

ENTRY(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
mov x19, x0 // relocated Image address
mov x20, x1 // DTB address

/*
* Flush the copied Image to the PoC, and ensure it is not shadowed by
* stale icache entries from before relocation.
*/
ldr w1, =kernel_size
bl __flush_dcache_area
ic ialluis
dsb sy

/*
* 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.
* Jump across, into the copy of the image that we just cleaned
* 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

ldr w0, .Ljmp
sub x0, x19, w0, sxtw
br x0
0:
/* Turn off Dcache and MMU */
mrs x0, CurrentEL
cmp x0, #CurrentEL_EL2
Expand All @@ -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)
b stext
ENDPROC(efi_enter_kernel)
.Ljmp: .long _text - 0b
6 changes: 3 additions & 3 deletions arch/arm64/kernel/efi-header.S
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down
5 changes: 4 additions & 1 deletion arch/arm64/kernel/image-vars.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@

#ifdef CONFIG_EFI

__efistub_stext_offset = stext - _text;
__efistub_kernel_size = _edata - _text;


/*
* The EFI stub has its own symbol namespace prefixed by __efistub_, to
Expand Down Expand Up @@ -42,9 +43,11 @@ __efistub___memset = __pi_memset;
#endif

__efistub__text = _text;
__efistub_stext = stext;
__efistub__end = _end;
__efistub__edata = _edata;
__efistub_screen_info = screen_info;
__efistub__ctype = _ctype;

#endif

Expand Down
55 changes: 30 additions & 25 deletions arch/ia64/kernel/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Loading

0 comments on commit e976568

Please sign in to comment.