Commit f92e3da1 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull EFI updates from Ingo Molnar:
 "The main changes in this cycle were:

   - Transparently fall back to other poweroff method(s) if EFI poweroff
     fails (and returns)

   - Use separate PE/COFF section headers for the RX and RW parts of the
     ARM stub loader so that the firmware can use strict mapping
     permissions

   - Add support for requesting the firmware to wipe RAM at warm reboot

   - Increase the size of the random seed obtained from UEFI so CRNG
     fast init can complete earlier

   - Update the EFI framebuffer address if it points to a BAR that gets
     moved by the PCI resource allocation code

   - Enable "reset attack mitigation" of TPM environments: this is
     enabled if the kernel is configured with
     CONFIG_RESET_ATTACK_MITIGATION=y.

   - Clang related fixes

   - Misc cleanups, constification, refactoring, etc"

* 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  efi/bgrt: Use efi_mem_type()
  efi: Move efi_mem_type() to common code
  efi/reboot: Make function pointer orig_pm_power_off static
  efi/random: Increase size of firmware supplied randomness
  efi/libstub: Enable reset attack mitigation
  firmware/efi/esrt: Constify attribute_group structures
  firmware/efi: Constify attribute_group structures
  firmware/dcdbas: Constify attribute_group structures
  arm/efi: Split zImage code and data into separate PE/COFF sections
  arm/efi: Replace open coded constants with symbolic ones
  arm/efi: Remove pointless dummy .reloc section
  arm/efi: Remove forbidden values from the PE/COFF header
  drivers/fbdev/efifb: Allow BAR to be moved instead of claiming it
  efi/reboot: Fall back to original power-off method if EFI_RESET_SHUTDOWN returns
  efi/arm/arm64: Add missing assignment of efi.config_table
  efi/libstub/arm64: Set -fpie when building the EFI stub
  efi/libstub/arm64: Force 'hidden' visibility for section markers
  efi/libstub/arm64: Use hidden attribute for struct screen_info reference
  efi/arm: Don't mark ACPI reclaim memory as MEMBLOCK_NOMAP
parents 57e88b43 6de47a5e
/* /*
* Copyright (C) 2013-2015 Linaro Ltd * Copyright (C) 2013-2017 Linaro Ltd
* Authors: Roy Franz <roy.franz@linaro.org> * Authors: Roy Franz <roy.franz@linaro.org>
* Ard Biesheuvel <ard.biesheuvel@linaro.org> * Ard Biesheuvel <ard.biesheuvel@linaro.org>
* *
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/pe.h>
#include <linux/sizes.h>
.macro __nop .macro __nop
#ifdef CONFIG_EFI_STUB #ifdef CONFIG_EFI_STUB
@ This is almost but not quite a NOP, since it does clobber the @ This is almost but not quite a NOP, since it does clobber the
...@@ -15,7 +18,7 @@ ...@@ -15,7 +18,7 @@
@ PE/COFF expects the magic string "MZ" at offset 0, while the @ PE/COFF expects the magic string "MZ" at offset 0, while the
@ ARM/Linux boot protocol expects an executable instruction @ ARM/Linux boot protocol expects an executable instruction
@ there. @ there.
.inst 'M' | ('Z' << 8) | (0x1310 << 16) @ tstne r0, #0x4d000 .inst MZ_MAGIC | (0x1310 << 16) @ tstne r0, #0x4d000
#else #else
AR_CLASS( mov r0, r0 ) AR_CLASS( mov r0, r0 )
M_CLASS( nop.w ) M_CLASS( nop.w )
...@@ -37,56 +40,56 @@ ...@@ -37,56 +40,56 @@
.long pe_header - start @ Offset to the PE header. .long pe_header - start @ Offset to the PE header.
pe_header: pe_header:
.ascii "PE\0\0" .long PE_MAGIC
coff_header: coff_header:
.short 0x01c2 @ ARM or Thumb .short IMAGE_FILE_MACHINE_THUMB @ Machine
.short 2 @ nr_sections .short section_count @ NumberOfSections
.long 0 @ TimeDateStamp .long 0 @ TimeDateStamp
.long 0 @ PointerToSymbolTable .long 0 @ PointerToSymbolTable
.long 1 @ NumberOfSymbols .long 0 @ NumberOfSymbols
.short section_table - optional_header .short section_table - optional_header @ SizeOfOptionalHeader
@ SizeOfOptionalHeader .short IMAGE_FILE_32BIT_MACHINE | \
.short 0x306 @ Characteristics. IMAGE_FILE_DEBUG_STRIPPED | \
@ IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE | \
@ IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_LINE_NUMS_STRIPPED @ Characteristics
@ IMAGE_FILE_EXECUTABLE_IMAGE |
@ IMAGE_FILE_LINE_NUMS_STRIPPED #define __pecoff_code_size (__pecoff_data_start - __efi_start)
optional_header: optional_header:
.short 0x10b @ PE32 format .short PE_OPT_MAGIC_PE32 @ PE32 format
.byte 0x02 @ MajorLinkerVersion .byte 0x02 @ MajorLinkerVersion
.byte 0x14 @ MinorLinkerVersion .byte 0x14 @ MinorLinkerVersion
.long _end - __efi_start @ SizeOfCode .long __pecoff_code_size @ SizeOfCode
.long 0 @ SizeOfInitializedData .long __pecoff_data_size @ SizeOfInitializedData
.long 0 @ SizeOfUninitializedData .long 0 @ SizeOfUninitializedData
.long efi_stub_entry - start @ AddressOfEntryPoint .long efi_stub_entry - start @ AddressOfEntryPoint
.long start_offset @ BaseOfCode .long start_offset @ BaseOfCode
.long 0 @ data .long __pecoff_data_start - start @ BaseOfData
extra_header_fields: extra_header_fields:
.long 0 @ ImageBase .long 0 @ ImageBase
.long 0x200 @ SectionAlignment .long SZ_4K @ SectionAlignment
.long 0x200 @ FileAlignment .long SZ_512 @ FileAlignment
.short 0 @ MajorOperatingSystemVersion .short 0 @ MajorOsVersion
.short 0 @ MinorOperatingSystemVersion .short 0 @ MinorOsVersion
.short 0 @ MajorImageVersion .short 0 @ MajorImageVersion
.short 0 @ MinorImageVersion .short 0 @ MinorImageVersion
.short 0 @ MajorSubsystemVersion .short 0 @ MajorSubsystemVersion
.short 0 @ MinorSubsystemVersion .short 0 @ MinorSubsystemVersion
.long 0 @ Win32VersionValue .long 0 @ Win32VersionValue
.long _end - start @ SizeOfImage .long __pecoff_end - start @ SizeOfImage
.long start_offset @ SizeOfHeaders .long start_offset @ SizeOfHeaders
.long 0 @ CheckSum .long 0 @ CheckSum
.short 0xa @ Subsystem (EFI application) .short IMAGE_SUBSYSTEM_EFI_APPLICATION @ Subsystem
.short 0 @ DllCharacteristics .short 0 @ DllCharacteristics
.long 0 @ SizeOfStackReserve .long 0 @ SizeOfStackReserve
.long 0 @ SizeOfStackCommit .long 0 @ SizeOfStackCommit
.long 0 @ SizeOfHeapReserve .long 0 @ SizeOfHeapReserve
.long 0 @ SizeOfHeapCommit .long 0 @ SizeOfHeapCommit
.long 0 @ LoaderFlags .long 0 @ LoaderFlags
.long 0x6 @ NumberOfRvaAndSizes .long (section_table - .) / 8 @ NumberOfRvaAndSizes
.quad 0 @ ExportTable .quad 0 @ ExportTable
.quad 0 @ ImportTable .quad 0 @ ImportTable
...@@ -96,34 +99,35 @@ extra_header_fields: ...@@ -96,34 +99,35 @@ extra_header_fields:
.quad 0 @ BaseRelocationTable .quad 0 @ BaseRelocationTable
section_table: section_table:
@ .ascii ".text\0\0\0"
@ The EFI application loader requires a relocation section .long __pecoff_code_size @ VirtualSize
@ because EFI applications must be relocatable. This is a .long __efi_start @ VirtualAddress
@ dummy section as far as we are concerned. .long __pecoff_code_size @ SizeOfRawData
@ .long __efi_start @ PointerToRawData
.ascii ".reloc\0\0"
.long 0 @ VirtualSize
.long 0 @ VirtualAddress
.long 0 @ SizeOfRawData
.long 0 @ PointerToRawData
.long 0 @ PointerToRelocations .long 0 @ PointerToRelocations
.long 0 @ PointerToLineNumbers .long 0 @ PointerToLineNumbers
.short 0 @ NumberOfRelocations .short 0 @ NumberOfRelocations
.short 0 @ NumberOfLineNumbers .short 0 @ NumberOfLineNumbers
.long 0x42100040 @ Characteristics .long IMAGE_SCN_CNT_CODE | \
IMAGE_SCN_MEM_READ | \
IMAGE_SCN_MEM_EXECUTE @ Characteristics
.ascii ".text\0\0\0" .ascii ".data\0\0\0"
.long _end - __efi_start @ VirtualSize .long __pecoff_data_size @ VirtualSize
.long __efi_start @ VirtualAddress .long __pecoff_data_start - start @ VirtualAddress
.long _edata - __efi_start @ SizeOfRawData .long __pecoff_data_rawsize @ SizeOfRawData
.long __efi_start @ PointerToRawData .long __pecoff_data_start - start @ PointerToRawData
.long 0 @ PointerToRelocations .long 0 @ PointerToRelocations
.long 0 @ PointerToLineNumbers .long 0 @ PointerToLineNumbers
.short 0 @ NumberOfRelocations .short 0 @ NumberOfRelocations
.short 0 @ NumberOfLineNumbers .short 0 @ NumberOfLineNumbers
.long 0xe0500020 @ Characteristics .long IMAGE_SCN_CNT_INITIALIZED_DATA | \
IMAGE_SCN_MEM_READ | \
IMAGE_SCN_MEM_WRITE @ Characteristics
.set section_count, (. - section_table) / 40
.align 9 .align 12
__efi_start: __efi_start:
#endif #endif
.endm .endm
...@@ -48,13 +48,6 @@ SECTIONS ...@@ -48,13 +48,6 @@ SECTIONS
*(.rodata) *(.rodata)
*(.rodata.*) *(.rodata.*)
} }
.data : {
/*
* The EFI stub always executes from RAM, and runs strictly before the
* decompressor, so we can make an exception for its r/w data, and keep it
*/
*(.data.efistub)
}
.piggydata : { .piggydata : {
*(.piggydata) *(.piggydata)
} }
...@@ -70,6 +63,26 @@ SECTIONS ...@@ -70,6 +63,26 @@ SECTIONS
/* ensure the zImage file size is always a multiple of 64 bits */ /* ensure the zImage file size is always a multiple of 64 bits */
/* (without a dummy byte, ld just ignores the empty section) */ /* (without a dummy byte, ld just ignores the empty section) */
.pad : { BYTE(0); . = ALIGN(8); } .pad : { BYTE(0); . = ALIGN(8); }
#ifdef CONFIG_EFI_STUB
.data : ALIGN(4096) {
__pecoff_data_start = .;
/*
* The EFI stub always executes from RAM, and runs strictly before the
* decompressor, so we can make an exception for its r/w data, and keep it
*/
*(.data.efistub)
__pecoff_data_end = .;
/*
* PE/COFF mandates a file size which is a multiple of 512 bytes if the
* section size equals or exceeds 4 KB
*/
. = ALIGN(512);
}
__pecoff_data_rawsize = . - ADDR(.data);
#endif
_edata = .; _edata = .;
_magic_sig = ZIMAGE_MAGIC(0x016f2818); _magic_sig = ZIMAGE_MAGIC(0x016f2818);
...@@ -84,6 +97,9 @@ SECTIONS ...@@ -84,6 +97,9 @@ SECTIONS
. = ALIGN(8); /* the stack must be 64-bit aligned */ . = ALIGN(8); /* the stack must be 64-bit aligned */
.stack : { *(.stack) } .stack : { *(.stack) }
PROVIDE(__pecoff_data_size = ALIGN(512) - ADDR(.data));
PROVIDE(__pecoff_end = ALIGN(512));
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) } .stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) } .stab.excl 0 : { *(.stab.excl) }
......
...@@ -90,6 +90,9 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, ...@@ -90,6 +90,9 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
#define alloc_screen_info(x...) &screen_info #define alloc_screen_info(x...) &screen_info
#define free_screen_info(x...) #define free_screen_info(x...)
/* 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) static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
{ {
} }
......
...@@ -997,6 +997,9 @@ struct boot_params *efi_main(struct efi_config *c, ...@@ -997,6 +997,9 @@ struct boot_params *efi_main(struct efi_config *c,
if (boot_params->secure_boot == efi_secureboot_mode_unset) if (boot_params->secure_boot == efi_secureboot_mode_unset)
boot_params->secure_boot = efi_get_secureboot(sys_table); boot_params->secure_boot = efi_get_secureboot(sys_table);
/* Ask the firmware to clear memory on unclean shutdown */
efi_enable_reset_attack_mitigation(sys_table);
setup_graphics(boot_params); setup_graphics(boot_params);
setup_efi_pci(boot_params); setup_efi_pci(boot_params);
......
...@@ -1032,25 +1032,6 @@ void __init efi_enter_virtual_mode(void) ...@@ -1032,25 +1032,6 @@ void __init efi_enter_virtual_mode(void)
efi_dump_pagetable(); efi_dump_pagetable();
} }
/*
* Convenience functions to obtain memory types and attributes
*/
int efi_mem_type(unsigned long phys_addr)
{
efi_memory_desc_t *md;
if (!efi_enabled(EFI_MEMMAP))
return -ENOTSUPP;
for_each_efi_memory_desc(md) {
if ((md->phys_addr <= phys_addr) &&
(phys_addr < (md->phys_addr +
(md->num_pages << EFI_PAGE_SHIFT))))
return md->type;
}
return -EINVAL;
}
static int __init arch_parse_efi_cmdline(char *str) static int __init arch_parse_efi_cmdline(char *str)
{ {
if (!str) { if (!str) {
......
...@@ -534,7 +534,7 @@ static struct attribute *dcdbas_dev_attrs[] = { ...@@ -534,7 +534,7 @@ static struct attribute *dcdbas_dev_attrs[] = {
NULL NULL
}; };
static struct attribute_group dcdbas_attr_group = { static const struct attribute_group dcdbas_attr_group = {
.attrs = dcdbas_dev_attrs, .attrs = dcdbas_dev_attrs,
.bin_attrs = dcdbas_bin_attrs, .bin_attrs = dcdbas_bin_attrs,
}; };
......
...@@ -151,6 +151,16 @@ config APPLE_PROPERTIES ...@@ -151,6 +151,16 @@ config APPLE_PROPERTIES
If unsure, say Y if you have a Mac. Otherwise N. If unsure, say Y if you have a Mac. Otherwise N.
config RESET_ATTACK_MITIGATION
bool "Reset memory attack mitigation"
depends on EFI_STUB
help
Request that the firmware clear the contents of RAM after a reboot
using the TCG Platform Reset Attack Mitigation specification. This
protects against an attacker forcibly rebooting the system while it
still contains secrets in RAM, booting another OS and extracting the
secrets.
endmenu endmenu
config UEFI_CPER config UEFI_CPER
......
...@@ -145,6 +145,9 @@ static int __init uefi_init(void) ...@@ -145,6 +145,9 @@ static int __init uefi_init(void)
sizeof(efi_config_table_t), sizeof(efi_config_table_t),
arch_tables); arch_tables);
if (!retval)
efi.config_table = (unsigned long)efi.systab->tables;
early_memunmap(config_tables, table_size); early_memunmap(config_tables, table_size);
out: out:
early_memunmap(efi.systab, sizeof(efi_system_table_t)); early_memunmap(efi.systab, sizeof(efi_system_table_t));
...@@ -159,6 +162,7 @@ static __init int is_usable_memory(efi_memory_desc_t *md) ...@@ -159,6 +162,7 @@ static __init int is_usable_memory(efi_memory_desc_t *md)
switch (md->type) { switch (md->type) {
case EFI_LOADER_CODE: case EFI_LOADER_CODE:
case EFI_LOADER_DATA: case EFI_LOADER_DATA:
case EFI_ACPI_RECLAIM_MEMORY:
case EFI_BOOT_SERVICES_CODE: case EFI_BOOT_SERVICES_CODE:
case EFI_BOOT_SERVICES_DATA: case EFI_BOOT_SERVICES_DATA:
case EFI_CONVENTIONAL_MEMORY: case EFI_CONVENTIONAL_MEMORY:
...@@ -211,6 +215,10 @@ static __init void reserve_regions(void) ...@@ -211,6 +215,10 @@ static __init void reserve_regions(void)
if (!is_usable_memory(md)) if (!is_usable_memory(md))
memblock_mark_nomap(paddr, size); memblock_mark_nomap(paddr, size);
/* keep ACPI reclaim memory intact for kexec etc. */
if (md->type == EFI_ACPI_RECLAIM_MEMORY)
memblock_reserve(paddr, size);
} }
} }
} }
......
...@@ -27,26 +27,6 @@ struct bmp_header { ...@@ -27,26 +27,6 @@ struct bmp_header {
u32 size; u32 size;
} __packed; } __packed;
static bool efi_bgrt_addr_valid(u64 addr)
{
efi_memory_desc_t *md;
for_each_efi_memory_desc(md) {
u64 size;
u64 end;
if (md->type != EFI_BOOT_SERVICES_DATA)
continue;
size = md->num_pages << EFI_PAGE_SHIFT;
end = md->phys_addr + size;
if (addr >= md->phys_addr && addr < end)
return true;
}
return false;
}
void __init efi_bgrt_init(struct acpi_table_header *table) void __init efi_bgrt_init(struct acpi_table_header *table)
{ {
void *image; void *image;
...@@ -85,7 +65,7 @@ void __init efi_bgrt_init(struct acpi_table_header *table) ...@@ -85,7 +65,7 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
goto out; goto out;
} }
if (!efi_bgrt_addr_valid(bgrt->image_address)) { if (efi_mem_type(bgrt->image_address) != EFI_BOOT_SERVICES_DATA) {
pr_notice("Ignoring BGRT: invalid image address\n"); pr_notice("Ignoring BGRT: invalid image address\n");
goto out; goto out;
} }
......
...@@ -198,7 +198,7 @@ static umode_t efi_attr_is_visible(struct kobject *kobj, ...@@ -198,7 +198,7 @@ static umode_t efi_attr_is_visible(struct kobject *kobj,
return attr->mode; return attr->mode;
} }
static struct attribute_group efi_subsys_attr_group = { static const struct attribute_group efi_subsys_attr_group = {
.attrs = efi_subsys_attrs, .attrs = efi_subsys_attrs,
.is_visible = efi_attr_is_visible, .is_visible = efi_attr_is_visible,
}; };
...@@ -541,6 +541,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, ...@@ -541,6 +541,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
if (seed != NULL) { if (seed != NULL) {
add_device_randomness(seed->bits, seed->size); add_device_randomness(seed->bits, seed->size);
early_memunmap(seed, sizeof(*seed) + size); early_memunmap(seed, sizeof(*seed) + size);
pr_notice("seeding entropy pool\n");
} else { } else {
pr_err("Could not map UEFI random seed!\n"); pr_err("Could not map UEFI random seed!\n");
} }
...@@ -809,6 +810,11 @@ char * __init efi_md_typeattr_format(char *buf, size_t size, ...@@ -809,6 +810,11 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
return buf; return buf;
} }
/*
* IA64 has a funky EFI memory map that doesn't work the same way as
* other architectures.
*/
#ifndef CONFIG_IA64
/* /*
* efi_mem_attributes - lookup memmap attributes for physical address * efi_mem_attributes - lookup memmap attributes for physical address
* @phys_addr: the physical address to lookup * @phys_addr: the physical address to lookup
...@@ -816,13 +822,8 @@ char * __init efi_md_typeattr_format(char *buf, size_t size, ...@@ -816,13 +822,8 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
* Search in the EFI memory map for the region covering * Search in the EFI memory map for the region covering
* @phys_addr. Returns the EFI memory attributes if the region * @phys_addr. Returns the EFI memory attributes if the region
* was found in the memory map, 0 otherwise. * was found in the memory map, 0 otherwise.
*
* Despite being marked __weak, most architectures should *not*
* override this function. It is __weak solely for the benefit
* of ia64 which has a funky EFI memory map that doesn't work
* the same way as other architectures.
*/ */
u64 __weak efi_mem_attributes(unsigned long phys_addr) u64 efi_mem_attributes(unsigned long phys_addr)
{ {
efi_memory_desc_t *md; efi_memory_desc_t *md;
...@@ -838,6 +839,31 @@ u64 __weak efi_mem_attributes(unsigned long phys_addr) ...@@ -838,6 +839,31 @@ u64 __weak efi_mem_attributes(unsigned long phys_addr)
return 0; return 0;
} }
/*
* efi_mem_type - lookup memmap type for physical address
* @phys_addr: the physical address to lookup
*
* Search in the EFI memory map for the region covering @phys_addr.
* Returns the EFI memory type if the region was found in the memory
* map, EFI_RESERVED_TYPE (zero) otherwise.
*/
int efi_mem_type(unsigned long phys_addr)
{
const efi_memory_desc_t *md;
if (!efi_enabled(EFI_MEMMAP))
return -ENOTSUPP;
for_each_efi_memory_desc(md) {
if ((md->phys_addr <= phys_addr) &&
(phys_addr < (md->phys_addr +
(md->num_pages << EFI_PAGE_SHIFT))))
return md->type;
}
return -EINVAL;
}
#endif
int efi_status_to_err(efi_status_t status) int efi_status_to_err(efi_status_t status)
{ {
int err; int err;
...@@ -900,7 +926,7 @@ static int update_efi_random_seed(struct notifier_block *nb, ...@@ -900,7 +926,7 @@ static int update_efi_random_seed(struct notifier_block *nb,
seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB); seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
if (seed != NULL) { if (seed != NULL) {
size = min(seed->size, 32U); size = min(seed->size, EFI_RANDOM_SEED_SIZE);
memunmap(seed); memunmap(seed);
} else { } else {
pr_err("Could not map UEFI random seed!\n"); pr_err("Could not map UEFI random seed!\n");
......
...@@ -230,7 +230,7 @@ static umode_t esrt_attr_is_visible(struct kobject *kobj, ...@@ -230,7 +230,7 @@ static umode_t esrt_attr_is_visible(struct kobject *kobj,
return attr->mode; return attr->mode;
} }
static struct attribute_group esrt_attr_group = { static const struct attribute_group esrt_attr_group = {
.attrs = esrt_attrs, .attrs = esrt_attrs,
.is_visible = esrt_attr_is_visible, .is_visible = esrt_attr_is_visible,
}; };
......
...@@ -10,7 +10,7 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -O2 \ ...@@ -10,7 +10,7 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -O2 \
-fPIC -fno-strict-aliasing -mno-red-zone \ -fPIC -fno-strict-aliasing -mno-red-zone \
-mno-mmx -mno-sse -mno-mmx -mno-sse
cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) -fpie
cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \ cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \
-fno-builtin -fpic -mno-single-pic-base -fno-builtin -fpic -mno-single-pic-base
...@@ -30,6 +30,7 @@ OBJECT_FILES_NON_STANDARD := y ...@@ -30,6 +30,7 @@ OBJECT_FILES_NON_STANDARD := y
KCOV_INSTRUMENT := n KCOV_INSTRUMENT := n
lib-y := efi-stub-helper.o gop.o secureboot.o lib-y := efi-stub-helper.o gop.o secureboot.o
lib-$(CONFIG_RESET_ATTACK_MITIGATION) += tpm.o
# include the stub's generic dependencies from lib/ when building for ARM/arm64 # include the stub's generic dependencies from lib/ when building for ARM/arm64
arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c
......
...@@ -192,6 +192,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, ...@@ -192,6 +192,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
goto fail_free_cmdline; goto fail_free_cmdline;
} }
/* Ask the firmware to clear memory on unclean shutdown */
efi_enable_reset_attack_mitigation(sys_table);
secure_boot = efi_get_secureboot(sys_table); secure_boot = efi_get_secureboot(sys_table);
/* /*
......
...@@ -9,10 +9,18 @@ ...@@ -9,10 +9,18 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
* *
*/ */
/*
* To prevent the compiler from emitting GOT-indirected (and thus absolute)
* references to the section markers, override their visibility as 'hidden'
*/
#pragma GCC visibility push(hidden)
#include <asm/sections.h>
#pragma GCC visibility pop
#include <linux/efi.h> #include <linux/efi.h>
#include <asm/efi.h> #include <asm/efi.h>
#include <asm/memory.h> #include <asm/memory.h>
#include <asm/sections.h>
#include <asm/sysreg.h> #include <asm/sysreg.h>
#include "efistub.h" #include "efistub.h"
......
...@@ -145,8 +145,6 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg, ...@@ -145,8 +145,6 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
return status; return status;
} }
#define RANDOM_SEED_SIZE 32
efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg) efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
{ {
efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID; efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
...@@ -162,25 +160,25 @@ efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg) ...@@ -162,25 +160,25 @@ efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
return status; return status;
status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA, status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
sizeof(*seed) + RANDOM_SEED_SIZE, sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
(void **)&seed); (void **)&seed);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
return status; return status;
status = rng->get_rng(rng, &rng_algo_raw, RANDOM_SEED_SIZE, status = rng->get_rng(rng, &rng_algo_raw, EFI_RANDOM_SEED_SIZE,
seed->bits); seed->bits);
if (status == EFI_UNSUPPORTED) if (status == EFI_UNSUPPORTED)
/* /*
* Use whatever algorithm we have available if the raw algorithm * Use whatever algorithm we have available if the raw algorithm
* is not implemented. * is not implemented.
*/ */
status = rng->get_rng(rng, NULL, RANDOM_SEED_SIZE, status = rng->get_rng(rng, NULL, EFI_RANDOM_SEED_SIZE,
seed->bits); seed->bits);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
goto err_freepool; goto err_freepool;
seed->size = RANDOM_SEED_SIZE; seed->size = EFI_RANDOM_SEED_SIZE;
status = efi_call_early(install_configuration_table, &rng_table_guid, status = efi_call_early(install_configuration_table, &rng_table_guid,
seed); seed);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
......
/*
* TPM handling.
*
* Copyright (C) 2016 CoreOS, Inc
* Copyright (C) 2017 Google, Inc.
* Matthew Garrett <mjg59@google.com>
*
* This file is part of the Linux kernel, and is made available under the
* terms of the GNU General Public License version 2.
*/
#include <linux/efi.h>
#include <asm/efi.h>
#include "efistub.h"
static const efi_char16_t efi_MemoryOverWriteRequest_name[] = {
'M', 'e', 'm', 'o', 'r', 'y', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't',
'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 'n', 't', 'r', 'o',
'l', 0
};
#define MEMORY_ONLY_RESET_CONTROL_GUID \
EFI_GUID(0xe20939be, 0x32d4, 0x41be, 0xa1, 0x50, 0x89, 0x7f, 0x85, 0xd4, 0x98, 0x29)
#define get_efi_var(name, vendor, ...) \
efi_call_runtime(get_variable, \
(efi_char16_t *)(name), (efi_guid_t *)(vendor), \
__VA_ARGS__)
#define set_efi_var(name, vendor, ...) \
efi_call_runtime(set_variable, \
(efi_char16_t *)(name), (efi_guid_t *)(vendor), \
__VA_ARGS__)
/*
* Enable reboot attack mitigation. This requests that the firmware clear the
* RAM on next reboot before proceeding with boot, ensuring that any secrets
* are cleared. If userland has ensured that all secrets have been removed
* from RAM before reboot it can simply reset this variable.
*/
void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg)
{
u8 val = 1;
efi_guid_t var_guid = MEMORY_ONLY_RESET_CONTROL_GUID;
efi_status_t status;
unsigned long datasize = 0;
status = get_efi_var(efi_MemoryOverWriteRequest_name, &var_guid,
NULL, &datasize, NULL);
if (status == EFI_NOT_FOUND)
return;
set_efi_var(efi_MemoryOverWriteRequest_name, &var_guid,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS, sizeof(val), &val);
}
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/reboot.h> #include <linux/reboot.h>
static void (*orig_pm_power_off)(void);
int efi_reboot_quirk_mode = -1; int efi_reboot_quirk_mode = -1;
void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) void efi_reboot(enum reboot_mode reboot_mode, const char *__unused)
...@@ -51,6 +53,12 @@ bool __weak efi_poweroff_required(void) ...@@ -51,6 +53,12 @@ bool __weak efi_poweroff_required(void)
static void efi_power_off(void) static void efi_power_off(void)
{ {
efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
/*
* The above call should not return, if it does fall back to
* the original power off method (typically ACPI poweroff).
*/
if (orig_pm_power_off)
orig_pm_power_off();
} }
static int __init efi_shutdown_init(void) static int __init efi_shutdown_init(void)
...@@ -58,8 +66,10 @@ static int __init efi_shutdown_init(void) ...@@ -58,8 +66,10 @@ static int __init efi_shutdown_init(void)
if (!efi_enabled(EFI_RUNTIME_SERVICES)) if (!efi_enabled(EFI_RUNTIME_SERVICES))
return -ENODEV; return -ENODEV;
if (efi_poweroff_required()) if (efi_poweroff_required()) {
orig_pm_power_off = pm_power_off;
pm_power_off = efi_power_off; pm_power_off = efi_power_off;
}
return 0; return 0;
} }
......
...@@ -149,6 +149,10 @@ ATTRIBUTE_GROUPS(efifb); ...@@ -149,6 +149,10 @@ ATTRIBUTE_GROUPS(efifb);
static bool pci_dev_disabled; /* FB base matches BAR of a disabled device */ static bool pci_dev_disabled; /* FB base matches BAR of a disabled device */
static struct pci_dev *efifb_pci_dev; /* dev with BAR covering the efifb */
static struct resource *bar_resource;
static u64 bar_offset;
static int efifb_probe(struct platform_device *dev) static int efifb_probe(struct platform_device *dev)
{ {
struct fb_info *info; struct fb_info *info;
...@@ -203,6 +207,13 @@ static int efifb_probe(struct platform_device *dev) ...@@ -203,6 +207,13 @@ static int efifb_probe(struct platform_device *dev)
efifb_fix.smem_start |= ext_lfb_base; efifb_fix.smem_start |= ext_lfb_base;
} }
if (bar_resource &&
bar_resource->start + bar_offset != efifb_fix.smem_start) {
dev_info(&efifb_pci_dev->dev,
"BAR has moved, updating efifb address\n");
efifb_fix.smem_start = bar_resource->start + bar_offset;
}
efifb_defined.bits_per_pixel = screen_info.lfb_depth; efifb_defined.bits_per_pixel = screen_info.lfb_depth;
efifb_defined.xres = screen_info.lfb_width; efifb_defined.xres = screen_info.lfb_width;
efifb_defined.yres = screen_info.lfb_height; efifb_defined.yres = screen_info.lfb_height;
...@@ -370,15 +381,13 @@ static struct platform_driver efifb_driver = { ...@@ -370,15 +381,13 @@ static struct platform_driver efifb_driver = {
builtin_platform_driver(efifb_driver); builtin_platform_driver(efifb_driver);
#if defined(CONFIG_PCI) && !defined(CONFIG_X86) #if defined(CONFIG_PCI)
static bool pci_bar_found; /* did we find a BAR matching the efifb base? */
static void claim_efifb_bar(struct pci_dev *dev, int idx) static void record_efifb_bar_resource(struct pci_dev *dev, int idx, u64 offset)
{ {
u16 word; u16 word;
pci_bar_found = true; efifb_pci_dev = dev;
pci_read_config_word(dev, PCI_COMMAND, &word); pci_read_config_word(dev, PCI_COMMAND, &word);
if (!(word & PCI_COMMAND_MEMORY)) { if (!(word & PCI_COMMAND_MEMORY)) {
...@@ -389,12 +398,8 @@ static void claim_efifb_bar(struct pci_dev *dev, int idx) ...@@ -389,12 +398,8 @@ static void claim_efifb_bar(struct pci_dev *dev, int idx)
return; return;
} }
if (pci_claim_resource(dev, idx)) { bar_resource = &dev->resource[idx];
pci_dev_disabled = true; bar_offset = offset;
dev_err(&dev->dev,
"BAR %d: failed to claim resource for efifb!\n", idx);
return;
}
dev_info(&dev->dev, "BAR %d: assigned to efifb\n", idx); dev_info(&dev->dev, "BAR %d: assigned to efifb\n", idx);
} }
...@@ -405,7 +410,7 @@ static void efifb_fixup_resources(struct pci_dev *dev) ...@@ -405,7 +410,7 @@ static void efifb_fixup_resources(struct pci_dev *dev)
u64 size = screen_info.lfb_size; u64 size = screen_info.lfb_size;
int i; int i;
if (pci_bar_found || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) if (efifb_pci_dev || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
return; return;
if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
...@@ -421,7 +426,7 @@ static void efifb_fixup_resources(struct pci_dev *dev) ...@@ -421,7 +426,7 @@ static void efifb_fixup_resources(struct pci_dev *dev)
continue; continue;
if (res->start <= base && res->end >= base + size - 1) { if (res->start <= base && res->end >= base + size - 1) {
claim_efifb_bar(dev, i); record_efifb_bar_resource(dev, i, base - res->start);
break; break;
} }
} }
......
...@@ -1526,6 +1526,13 @@ enum efi_secureboot_mode { ...@@ -1526,6 +1526,13 @@ enum efi_secureboot_mode {
}; };
enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table); enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table);
#ifdef CONFIG_RESET_ATTACK_MITIGATION
void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg);
#else
static inline void
efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg) { }
#endif
/* /*
* Arch code can implement the following three template macros, avoiding * Arch code can implement the following three template macros, avoiding
* reptition for the void/non-void return cases of {__,}efi_call_virt(): * reptition for the void/non-void return cases of {__,}efi_call_virt():
...@@ -1586,6 +1593,8 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table, ...@@ -1586,6 +1593,8 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table,
void *priv, void *priv,
efi_exit_boot_map_processing priv_func); efi_exit_boot_map_processing priv_func);
#define EFI_RANDOM_SEED_SIZE 64U
struct linux_efi_random_seed { struct linux_efi_random_seed {
u32 size; u32 size;
u8 bits[]; u8 bits[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment