Commit bc16d405 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 EFI changes in this cycle were:

   - Fix the apple-properties code (Andy Shevchenko)

   - Add WARN() on arm64 if UEFI Runtime Services corrupt the reserved
     x18 register (Ard Biesheuvel)

   - Use efi_switch_mm() on x86 instead of manipulating %cr3 directly
     (Sai Praneeth)

   - Fix early memremap leak in ESRT code (Ard Biesheuvel)

   - Switch to L"xxx" notation for wide string literals (Ard Biesheuvel)

   - ... plus misc other cleanups and bugfixes"

* 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/efi: Use efi_switch_mm() rather than manually twiddling with %cr3
  x86/efi: Replace efi_pgd with efi_mm.pgd
  efi: Use string literals for efi_char16_t variable initializers
  efi/esrt: Fix handling of early ESRT table mapping
  efi: Use efi_mm in x86 as well as ARM
  efi: Make const array 'apple' static
  efi/apple-properties: Use memremap() instead of ioremap()
  efi: Reorder pr_notice() with add_device_randomness() call
  x86/efi: Replace GFP_ATOMIC with GFP_KERNEL in efi_query_variable_store()
  efi/arm64: Check whether x18 is preserved by runtime services calls
  efi/arm*: Stop printing addresses of virtual mappings
  efi/apple-properties: Remove redundant attribute initialization from unmarshal_key_value_pairs()
  efi/arm*: Only register page tables when they exist
parents 2fcd2b30 03781e40
...@@ -31,7 +31,7 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); ...@@ -31,7 +31,7 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
({ \ ({ \
efi_##f##_t *__f; \ efi_##f##_t *__f; \
__f = p->f; \ __f = p->f; \
__f(args); \ __efi_rt_asm_wrapper(__f, #f, args); \
}) })
#define arch_efi_call_virt_teardown() \ #define arch_efi_call_virt_teardown() \
...@@ -40,6 +40,8 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); ...@@ -40,6 +40,8 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
efi_virtmap_unload(); \ efi_virtmap_unload(); \
}) })
efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
#define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT) #define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
/* arch specific definitions used by the stub code */ /* arch specific definitions used by the stub code */
......
...@@ -38,7 +38,8 @@ arm64-obj-$(CONFIG_CPU_PM) += sleep.o suspend.o ...@@ -38,7 +38,8 @@ arm64-obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
arm64-obj-$(CONFIG_KGDB) += kgdb.o arm64-obj-$(CONFIG_KGDB) += kgdb.o
arm64-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o arm64-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o \
efi-rt-wrapper.o
arm64-obj-$(CONFIG_PCI) += pci.o arm64-obj-$(CONFIG_PCI) += pci.o
arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
arm64-obj-$(CONFIG_ACPI) += acpi.o arm64-obj-$(CONFIG_ACPI) += acpi.o
......
/*
* Copyright (C) 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
ENTRY(__efi_rt_asm_wrapper)
stp x29, x30, [sp, #-32]!
mov x29, sp
/*
* Register x18 is designated as the 'platform' register by the AAPCS,
* which means firmware running at the same exception level as the OS
* (such as UEFI) should never touch it.
*/
stp x1, x18, [sp, #16]
/*
* We are lucky enough that no EFI runtime services take more than
* 5 arguments, so all are passed in registers rather than via the
* stack.
*/
mov x8, x0
mov x0, x2
mov x1, x3
mov x2, x4
mov x3, x5
mov x4, x6
blr x8
ldp x1, x2, [sp, #16]
cmp x2, x18
ldp x29, x30, [sp], #32
b.ne 0f
ret
0: b efi_handle_corrupted_x18 // tail call
ENDPROC(__efi_rt_asm_wrapper)
...@@ -126,3 +126,9 @@ bool efi_poweroff_required(void) ...@@ -126,3 +126,9 @@ bool efi_poweroff_required(void)
{ {
return efi_enabled(EFI_RUNTIME_SERVICES); return efi_enabled(EFI_RUNTIME_SERVICES);
} }
asmlinkage efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f)
{
pr_err_ratelimited(FW_BUG "register x18 corrupted by EFI %s\n", f);
return s;
}
...@@ -421,9 +421,10 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params) ...@@ -421,9 +421,10 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
} }
} }
static const efi_char16_t apple[] = L"Apple";
static void setup_quirks(struct boot_params *boot_params) static void setup_quirks(struct boot_params *boot_params)
{ {
efi_char16_t const apple[] = { 'A', 'p', 'p', 'l', 'e', 0 };
efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long) efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
efi_table_attr(efi_system_table, fw_vendor, sys_table); efi_table_attr(efi_system_table, fw_vendor, sys_table);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <asm/processor-flags.h> #include <asm/processor-flags.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/nospec-branch.h> #include <asm/nospec-branch.h>
#include <asm/mmu_context.h>
/* /*
* We map the EFI regions needed for runtime services non-contiguously, * We map the EFI regions needed for runtime services non-contiguously,
...@@ -69,14 +70,13 @@ extern asmlinkage u64 efi_call(void *fp, ...); ...@@ -69,14 +70,13 @@ extern asmlinkage u64 efi_call(void *fp, ...);
#define efi_call_phys(f, args...) efi_call((f), args) #define efi_call_phys(f, args...) efi_call((f), args)
/* /*
* Scratch space used for switching the pagetable in the EFI stub * struct efi_scratch - Scratch space used while switching to/from efi_mm
* @phys_stack: stack used during EFI Mixed Mode
* @prev_mm: store/restore stolen mm_struct while switching to/from efi_mm
*/ */
struct efi_scratch { struct efi_scratch {
u64 r15; u64 phys_stack;
u64 prev_cr3; struct mm_struct *prev_mm;
pgd_t *efi_pgt;
bool use_pgd;
u64 phys_stack;
} __packed; } __packed;
#define arch_efi_call_virt_setup() \ #define arch_efi_call_virt_setup() \
...@@ -86,11 +86,8 @@ struct efi_scratch { ...@@ -86,11 +86,8 @@ struct efi_scratch {
__kernel_fpu_begin(); \ __kernel_fpu_begin(); \
firmware_restrict_branch_speculation_start(); \ firmware_restrict_branch_speculation_start(); \
\ \
if (efi_scratch.use_pgd) { \ if (!efi_enabled(EFI_OLD_MEMMAP)) \
efi_scratch.prev_cr3 = __read_cr3(); \ efi_switch_mm(&efi_mm); \
write_cr3((unsigned long)efi_scratch.efi_pgt); \
__flush_tlb_all(); \
} \
}) })
#define arch_efi_call_virt(p, f, args...) \ #define arch_efi_call_virt(p, f, args...) \
...@@ -98,10 +95,8 @@ struct efi_scratch { ...@@ -98,10 +95,8 @@ struct efi_scratch {
#define arch_efi_call_virt_teardown() \ #define arch_efi_call_virt_teardown() \
({ \ ({ \
if (efi_scratch.use_pgd) { \ if (!efi_enabled(EFI_OLD_MEMMAP)) \
write_cr3(efi_scratch.prev_cr3); \ efi_switch_mm(efi_scratch.prev_mm); \
__flush_tlb_all(); \
} \
\ \
firmware_restrict_branch_speculation_end(); \ firmware_restrict_branch_speculation_end(); \
__kernel_fpu_end(); \ __kernel_fpu_end(); \
...@@ -144,6 +139,7 @@ extern void __init efi_dump_pagetable(void); ...@@ -144,6 +139,7 @@ extern void __init efi_dump_pagetable(void);
extern void __init efi_apply_memmap_quirks(void); extern void __init efi_apply_memmap_quirks(void);
extern int __init efi_reuse_config(u64 tables, int nr_tables); extern int __init efi_reuse_config(u64 tables, int nr_tables);
extern void efi_delete_dummy_variable(void); extern void efi_delete_dummy_variable(void);
extern void efi_switch_mm(struct mm_struct *mm);
struct efi_setup_data { struct efi_setup_data {
u64 fw_vendor; u64 fw_vendor;
......
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/efi.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
...@@ -73,13 +74,12 @@ static const struct file_operations ptdump_curusr_fops = { ...@@ -73,13 +74,12 @@ static const struct file_operations ptdump_curusr_fops = {
#endif #endif
#if defined(CONFIG_EFI) && defined(CONFIG_X86_64) #if defined(CONFIG_EFI) && defined(CONFIG_X86_64)
extern pgd_t *efi_pgd;
static struct dentry *pe_efi; static struct dentry *pe_efi;
static int ptdump_show_efi(struct seq_file *m, void *v) static int ptdump_show_efi(struct seq_file *m, void *v)
{ {
if (efi_pgd) if (efi_mm.pgd)
ptdump_walk_pgd_level_debugfs(m, efi_pgd, false); ptdump_walk_pgd_level_debugfs(m, efi_mm.pgd, false);
return 0; return 0;
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ucs2_string.h> #include <linux/ucs2_string.h>
#include <linux/mem_encrypt.h> #include <linux/mem_encrypt.h>
#include <linux/sched/task.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -82,9 +83,8 @@ pgd_t * __init efi_call_phys_prolog(void) ...@@ -82,9 +83,8 @@ pgd_t * __init efi_call_phys_prolog(void)
int n_pgds, i, j; int n_pgds, i, j;
if (!efi_enabled(EFI_OLD_MEMMAP)) { if (!efi_enabled(EFI_OLD_MEMMAP)) {
save_pgd = (pgd_t *)__read_cr3(); efi_switch_mm(&efi_mm);
write_cr3((unsigned long)efi_scratch.efi_pgt); return NULL;
goto out;
} }
early_code_mapping_set_exec(1); early_code_mapping_set_exec(1);
...@@ -156,8 +156,7 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) ...@@ -156,8 +156,7 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
pud_t *pud; pud_t *pud;
if (!efi_enabled(EFI_OLD_MEMMAP)) { if (!efi_enabled(EFI_OLD_MEMMAP)) {
write_cr3((unsigned long)save_pgd); efi_switch_mm(efi_scratch.prev_mm);
__flush_tlb_all();
return; return;
} }
...@@ -191,8 +190,7 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) ...@@ -191,8 +190,7 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
early_code_mapping_set_exec(0); early_code_mapping_set_exec(0);
} }
pgd_t *efi_pgd; EXPORT_SYMBOL_GPL(efi_mm);
EXPORT_SYMBOL_GPL(efi_pgd);
/* /*
* We need our own copy of the higher levels of the page tables * We need our own copy of the higher levels of the page tables
...@@ -205,7 +203,7 @@ EXPORT_SYMBOL_GPL(efi_pgd); ...@@ -205,7 +203,7 @@ EXPORT_SYMBOL_GPL(efi_pgd);
*/ */
int __init efi_alloc_page_tables(void) int __init efi_alloc_page_tables(void)
{ {
pgd_t *pgd; pgd_t *pgd, *efi_pgd;
p4d_t *p4d; p4d_t *p4d;
pud_t *pud; pud_t *pud;
gfp_t gfp_mask; gfp_t gfp_mask;
...@@ -233,6 +231,10 @@ int __init efi_alloc_page_tables(void) ...@@ -233,6 +231,10 @@ int __init efi_alloc_page_tables(void)
return -ENOMEM; return -ENOMEM;
} }
efi_mm.pgd = efi_pgd;
mm_init_cpumask(&efi_mm);
init_new_context(NULL, &efi_mm);
return 0; return 0;
} }
...@@ -245,6 +247,7 @@ void efi_sync_low_kernel_mappings(void) ...@@ -245,6 +247,7 @@ void efi_sync_low_kernel_mappings(void)
pgd_t *pgd_k, *pgd_efi; pgd_t *pgd_k, *pgd_efi;
p4d_t *p4d_k, *p4d_efi; p4d_t *p4d_k, *p4d_efi;
pud_t *pud_k, *pud_efi; pud_t *pud_k, *pud_efi;
pgd_t *efi_pgd = efi_mm.pgd;
if (efi_enabled(EFI_OLD_MEMMAP)) if (efi_enabled(EFI_OLD_MEMMAP))
return; return;
...@@ -338,19 +341,11 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) ...@@ -338,19 +341,11 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
unsigned long pfn, text, pf; unsigned long pfn, text, pf;
struct page *page; struct page *page;
unsigned npages; unsigned npages;
pgd_t *pgd; pgd_t *pgd = efi_mm.pgd;
if (efi_enabled(EFI_OLD_MEMMAP)) if (efi_enabled(EFI_OLD_MEMMAP))
return 0; return 0;
/*
* Since the PGD is encrypted, set the encryption mask so that when
* this value is loaded into cr3 the PGD will be decrypted during
* the pagetable walk.
*/
efi_scratch.efi_pgt = (pgd_t *)__sme_pa(efi_pgd);
pgd = efi_pgd;
/* /*
* It can happen that the physical address of new_memmap lands in memory * It can happen that the physical address of new_memmap lands in memory
* which is not mapped in the EFI page table. Therefore we need to go * which is not mapped in the EFI page table. Therefore we need to go
...@@ -364,8 +359,6 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) ...@@ -364,8 +359,6 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
return 1; return 1;
} }
efi_scratch.use_pgd = true;
/* /*
* Certain firmware versions are way too sentimential and still believe * Certain firmware versions are way too sentimential and still believe
* they are exclusive and unquestionable owners of the first physical page, * they are exclusive and unquestionable owners of the first physical page,
...@@ -419,7 +412,7 @@ static void __init __map_region(efi_memory_desc_t *md, u64 va) ...@@ -419,7 +412,7 @@ static void __init __map_region(efi_memory_desc_t *md, u64 va)
{ {
unsigned long flags = _PAGE_RW; unsigned long flags = _PAGE_RW;
unsigned long pfn; unsigned long pfn;
pgd_t *pgd = efi_pgd; pgd_t *pgd = efi_mm.pgd;
if (!(md->attribute & EFI_MEMORY_WB)) if (!(md->attribute & EFI_MEMORY_WB))
flags |= _PAGE_PCD; flags |= _PAGE_PCD;
...@@ -523,7 +516,7 @@ void __init parse_efi_setup(u64 phys_addr, u32 data_len) ...@@ -523,7 +516,7 @@ void __init parse_efi_setup(u64 phys_addr, u32 data_len)
static int __init efi_update_mappings(efi_memory_desc_t *md, unsigned long pf) static int __init efi_update_mappings(efi_memory_desc_t *md, unsigned long pf)
{ {
unsigned long pfn; unsigned long pfn;
pgd_t *pgd = efi_pgd; pgd_t *pgd = efi_mm.pgd;
int err1, err2; int err1, err2;
/* Update the 1:1 mapping */ /* Update the 1:1 mapping */
...@@ -620,10 +613,26 @@ void __init efi_dump_pagetable(void) ...@@ -620,10 +613,26 @@ void __init efi_dump_pagetable(void)
if (efi_enabled(EFI_OLD_MEMMAP)) if (efi_enabled(EFI_OLD_MEMMAP))
ptdump_walk_pgd_level(NULL, swapper_pg_dir); ptdump_walk_pgd_level(NULL, swapper_pg_dir);
else else
ptdump_walk_pgd_level(NULL, efi_pgd); ptdump_walk_pgd_level(NULL, efi_mm.pgd);
#endif #endif
} }
/*
* Makes the calling thread switch to/from efi_mm context. Can be used
* for SetVirtualAddressMap() i.e. current->active_mm == init_mm as well
* as during efi runtime calls i.e current->active_mm == current_mm.
* We are not mm_dropping()/mm_grabbing() any mm, because we are not
* losing/creating any references.
*/
void efi_switch_mm(struct mm_struct *mm)
{
task_lock(current);
efi_scratch.prev_mm = current->active_mm;
current->active_mm = mm;
switch_mm(efi_scratch.prev_mm, mm, NULL);
task_unlock(current);
}
#ifdef CONFIG_EFI_MIXED #ifdef CONFIG_EFI_MIXED
extern efi_status_t efi64_thunk(u32, ...); extern efi_status_t efi64_thunk(u32, ...);
...@@ -677,16 +686,13 @@ efi_status_t efi_thunk_set_virtual_address_map( ...@@ -677,16 +686,13 @@ efi_status_t efi_thunk_set_virtual_address_map(
efi_sync_low_kernel_mappings(); efi_sync_low_kernel_mappings();
local_irq_save(flags); local_irq_save(flags);
efi_scratch.prev_cr3 = __read_cr3(); efi_switch_mm(&efi_mm);
write_cr3((unsigned long)efi_scratch.efi_pgt);
__flush_tlb_all();
func = (u32)(unsigned long)phys_set_virtual_address_map; func = (u32)(unsigned long)phys_set_virtual_address_map;
status = efi64_thunk(func, memory_map_size, descriptor_size, status = efi64_thunk(func, memory_map_size, descriptor_size,
descriptor_version, virtual_map); descriptor_version, virtual_map);
write_cr3(efi_scratch.prev_cr3); efi_switch_mm(efi_scratch.prev_mm);
__flush_tlb_all();
local_irq_restore(flags); local_irq_restore(flags);
return status; return status;
......
...@@ -33,7 +33,7 @@ ENTRY(efi64_thunk) ...@@ -33,7 +33,7 @@ ENTRY(efi64_thunk)
* Switch to 1:1 mapped 32-bit stack pointer. * Switch to 1:1 mapped 32-bit stack pointer.
*/ */
movq %rsp, efi_saved_sp(%rip) movq %rsp, efi_saved_sp(%rip)
movq efi_scratch+25(%rip), %rsp movq efi_scratch(%rip), %rsp
/* /*
* Calculate the physical address of the kernel text. * Calculate the physical address of the kernel text.
......
...@@ -75,7 +75,7 @@ struct quark_security_header { ...@@ -75,7 +75,7 @@ struct quark_security_header {
u32 rsvd[2]; u32 rsvd[2];
}; };
static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; static const efi_char16_t efi_dummy_name[] = L"DUMMY";
static bool efi_no_storage_paranoia; static bool efi_no_storage_paranoia;
...@@ -105,7 +105,8 @@ early_param("efi_no_storage_paranoia", setup_storage_paranoia); ...@@ -105,7 +105,8 @@ early_param("efi_no_storage_paranoia", setup_storage_paranoia);
*/ */
void efi_delete_dummy_variable(void) void efi_delete_dummy_variable(void)
{ {
efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, efi.set_variable((efi_char16_t *)efi_dummy_name,
&EFI_DUMMY_GUID,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS, EFI_VARIABLE_RUNTIME_ACCESS,
...@@ -177,12 +178,13 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size, ...@@ -177,12 +178,13 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size,
* that by attempting to use more space than is available. * that by attempting to use more space than is available.
*/ */
unsigned long dummy_size = remaining_size + 1024; unsigned long dummy_size = remaining_size + 1024;
void *dummy = kzalloc(dummy_size, GFP_ATOMIC); void *dummy = kzalloc(dummy_size, GFP_KERNEL);
if (!dummy) if (!dummy)
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID, status = efi.set_variable((efi_char16_t *)efi_dummy_name,
&EFI_DUMMY_GUID,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS, EFI_VARIABLE_RUNTIME_ACCESS,
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/io.h>
#include <linux/platform_data/x86/apple.h> #include <linux/platform_data/x86/apple.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -52,8 +53,6 @@ struct properties_header { ...@@ -52,8 +53,6 @@ struct properties_header {
struct dev_header dev_header[0]; struct dev_header dev_header[0];
}; };
static u8 one __initdata = 1;
static void __init unmarshal_key_value_pairs(struct dev_header *dev_header, static void __init unmarshal_key_value_pairs(struct dev_header *dev_header,
struct device *dev, void *ptr, struct device *dev, void *ptr,
struct property_entry entry[]) struct property_entry entry[])
...@@ -95,14 +94,9 @@ static void __init unmarshal_key_value_pairs(struct dev_header *dev_header, ...@@ -95,14 +94,9 @@ static void __init unmarshal_key_value_pairs(struct dev_header *dev_header,
key_len - sizeof(key_len)); key_len - sizeof(key_len));
entry[i].name = key; entry[i].name = key;
entry[i].is_array = true;
entry[i].length = val_len - sizeof(val_len); entry[i].length = val_len - sizeof(val_len);
entry[i].is_array = !!entry[i].length;
entry[i].pointer.raw_data = ptr + key_len + sizeof(val_len); entry[i].pointer.raw_data = ptr + key_len + sizeof(val_len);
if (!entry[i].length) {
/* driver core doesn't accept empty properties */
entry[i].length = 1;
entry[i].pointer.raw_data = &one;
}
if (dump_properties) { if (dump_properties) {
dev_info(dev, "property: %s\n", entry[i].name); dev_info(dev, "property: %s\n", entry[i].name);
...@@ -196,7 +190,7 @@ static int __init map_properties(void) ...@@ -196,7 +190,7 @@ static int __init map_properties(void)
pa_data = boot_params.hdr.setup_data; pa_data = boot_params.hdr.setup_data;
while (pa_data) { while (pa_data) {
data = ioremap(pa_data, sizeof(*data)); data = memremap(pa_data, sizeof(*data), MEMREMAP_WB);
if (!data) { if (!data) {
pr_err("cannot map setup_data header\n"); pr_err("cannot map setup_data header\n");
return -ENOMEM; return -ENOMEM;
...@@ -204,14 +198,14 @@ static int __init map_properties(void) ...@@ -204,14 +198,14 @@ static int __init map_properties(void)
if (data->type != SETUP_APPLE_PROPERTIES) { if (data->type != SETUP_APPLE_PROPERTIES) {
pa_data = data->next; pa_data = data->next;
iounmap(data); memunmap(data);
continue; continue;
} }
data_len = data->len; data_len = data->len;
iounmap(data); memunmap(data);
data = ioremap(pa_data, sizeof(*data) + data_len); data = memremap(pa_data, sizeof(*data) + data_len, MEMREMAP_WB);
if (!data) { if (!data) {
pr_err("cannot map setup_data payload\n"); pr_err("cannot map setup_data payload\n");
return -ENOMEM; return -ENOMEM;
...@@ -236,7 +230,7 @@ static int __init map_properties(void) ...@@ -236,7 +230,7 @@ static int __init map_properties(void)
* to avoid breaking the chain of ->next pointers. * to avoid breaking the chain of ->next pointers.
*/ */
data->len = 0; data->len = 0;
iounmap(data); memunmap(data);
free_bootmem_late(pa_data + sizeof(*data), data_len); free_bootmem_late(pa_data + sizeof(*data), data_len);
return ret; return ret;
......
...@@ -31,15 +31,6 @@ ...@@ -31,15 +31,6 @@
extern u64 efi_system_table; extern u64 efi_system_table;
static struct mm_struct efi_mm = {
.mm_rb = RB_ROOT,
.mm_users = ATOMIC_INIT(2),
.mm_count = ATOMIC_INIT(1),
.mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
.page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
.mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
};
#ifdef CONFIG_ARM64_PTDUMP_DEBUGFS #ifdef CONFIG_ARM64_PTDUMP_DEBUGFS
#include <asm/ptdump.h> #include <asm/ptdump.h>
...@@ -54,6 +45,9 @@ static struct ptdump_info efi_ptdump_info = { ...@@ -54,6 +45,9 @@ static struct ptdump_info efi_ptdump_info = {
static int __init ptdump_init(void) static int __init ptdump_init(void)
{ {
if (!efi_enabled(EFI_RUNTIME_SERVICES))
return 0;
return ptdump_debugfs_register(&efi_ptdump_info, "efi_page_tables"); return ptdump_debugfs_register(&efi_ptdump_info, "efi_page_tables");
} }
device_initcall(ptdump_init); device_initcall(ptdump_init);
...@@ -80,10 +74,7 @@ static bool __init efi_virtmap_init(void) ...@@ -80,10 +74,7 @@ static bool __init efi_virtmap_init(void)
return false; return false;
ret = efi_create_mapping(&efi_mm, md); ret = efi_create_mapping(&efi_mm, md);
if (!ret) { if (ret) {
pr_info(" EFI remap %pa => %p\n",
&phys, (void *)(unsigned long)md->virt_addr);
} else {
pr_warn(" EFI remap %pa: failed to create mapping (%d)\n", pr_warn(" EFI remap %pa: failed to create mapping (%d)\n",
&phys, ret); &phys, ret);
return false; return false;
......
...@@ -75,6 +75,15 @@ static unsigned long *efi_tables[] = { ...@@ -75,6 +75,15 @@ static unsigned long *efi_tables[] = {
&efi.mem_attr_table, &efi.mem_attr_table,
}; };
struct mm_struct efi_mm = {
.mm_rb = RB_ROOT,
.mm_users = ATOMIC_INIT(2),
.mm_count = ATOMIC_INIT(1),
.mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
.page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
.mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
};
static bool disable_runtime; static bool disable_runtime;
static int __init setup_noefi(char *arg) static int __init setup_noefi(char *arg)
{ {
...@@ -542,9 +551,9 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, ...@@ -542,9 +551,9 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
seed = early_memremap(efi.rng_seed, seed = early_memremap(efi.rng_seed,
sizeof(*seed) + size); sizeof(*seed) + size);
if (seed != NULL) { if (seed != NULL) {
pr_notice("seeding entropy pool\n");
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");
} }
......
...@@ -279,6 +279,7 @@ void __init efi_esrt_init(void) ...@@ -279,6 +279,7 @@ void __init efi_esrt_init(void)
} }
memcpy(&tmpesrt, va, sizeof(tmpesrt)); memcpy(&tmpesrt, va, sizeof(tmpesrt));
early_memunmap(va, size);
if (tmpesrt.fw_resource_version == 1) { if (tmpesrt.fw_resource_version == 1) {
entry_size = sizeof (*v1_entries); entry_size = sizeof (*v1_entries);
...@@ -291,7 +292,7 @@ void __init efi_esrt_init(void) ...@@ -291,7 +292,7 @@ void __init efi_esrt_init(void)
if (tmpesrt.fw_resource_count > 0 && max - size < entry_size) { if (tmpesrt.fw_resource_count > 0 && max - size < entry_size) {
pr_err("ESRT memory map entry can only hold the header. (max: %zu size: %zu)\n", pr_err("ESRT memory map entry can only hold the header. (max: %zu size: %zu)\n",
max - size, entry_size); max - size, entry_size);
goto err_memunmap; return;
} }
/* /*
...@@ -304,7 +305,7 @@ void __init efi_esrt_init(void) ...@@ -304,7 +305,7 @@ void __init efi_esrt_init(void)
if (tmpesrt.fw_resource_count > 128) { if (tmpesrt.fw_resource_count > 128) {
pr_err("ESRT says fw_resource_count has very large value %d.\n", pr_err("ESRT says fw_resource_count has very large value %d.\n",
tmpesrt.fw_resource_count); tmpesrt.fw_resource_count);
goto err_memunmap; return;
} }
/* /*
...@@ -315,18 +316,10 @@ void __init efi_esrt_init(void) ...@@ -315,18 +316,10 @@ void __init efi_esrt_init(void)
if (max < size + entries_size) { if (max < size + entries_size) {
pr_err("ESRT does not fit on single memory map entry (size: %zu max: %zu)\n", pr_err("ESRT does not fit on single memory map entry (size: %zu max: %zu)\n",
size, max); size, max);
goto err_memunmap; return;
} }
/* remap it with our (plausible) new pages */
early_memunmap(va, size);
size += entries_size; size += entries_size;
va = early_memremap(efi.esrt, size);
if (!va) {
pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
size);
return;
}
esrt_data = (phys_addr_t)efi.esrt; esrt_data = (phys_addr_t)efi.esrt;
esrt_data_size = size; esrt_data_size = size;
...@@ -336,8 +329,6 @@ void __init efi_esrt_init(void) ...@@ -336,8 +329,6 @@ void __init efi_esrt_init(void)
efi_mem_reserve(esrt_data, esrt_data_size); efi_mem_reserve(esrt_data, esrt_data_size);
pr_debug("esrt-init: loaded.\n"); pr_debug("esrt-init: loaded.\n");
err_memunmap:
early_memunmap(va, size);
} }
static int __init register_entries(void) static int __init register_entries(void)
......
...@@ -9,7 +9,7 @@ cflags-$(CONFIG_X86_32) := -march=i386 ...@@ -9,7 +9,7 @@ cflags-$(CONFIG_X86_32) := -march=i386
cflags-$(CONFIG_X86_64) := -mcmodel=small cflags-$(CONFIG_X86_64) := -mcmodel=small
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -O2 \ 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 -fshort-wchar
cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) -fpie cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) -fpie
cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \ cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \
......
...@@ -16,18 +16,12 @@ ...@@ -16,18 +16,12 @@
/* BIOS variables */ /* BIOS variables */
static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID; static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
static const efi_char16_t efi_SecureBoot_name[] = { static const efi_char16_t efi_SecureBoot_name[] = L"SecureBoot";
'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 static const efi_char16_t efi_SetupMode_name[] = L"SetupMode";
};
static const efi_char16_t efi_SetupMode_name[] = {
'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0
};
/* SHIM variables */ /* SHIM variables */
static const efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID; static const efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
static efi_char16_t const shim_MokSBState_name[] = { static const efi_char16_t shim_MokSBState_name[] = L"MokSBState";
'M', 'o', 'k', 'S', 'B', 'S', 't', 'a', 't', 'e', 0
};
#define get_efi_var(name, vendor, ...) \ #define get_efi_var(name, vendor, ...) \
efi_call_runtime(get_variable, \ efi_call_runtime(get_variable, \
......
...@@ -16,11 +16,8 @@ ...@@ -16,11 +16,8 @@
#include "efistub.h" #include "efistub.h"
#ifdef CONFIG_RESET_ATTACK_MITIGATION #ifdef CONFIG_RESET_ATTACK_MITIGATION
static const efi_char16_t efi_MemoryOverWriteRequest_name[] = { static const efi_char16_t efi_MemoryOverWriteRequest_name[] =
'M', 'e', 'm', 'o', 'r', 'y', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't', L"MemoryOverwriteRequestControl";
'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 'n', 't', 'r', 'o',
'l', 0
};
#define MEMORY_ONLY_RESET_CONTROL_GUID \ #define MEMORY_ONLY_RESET_CONTROL_GUID \
EFI_GUID(0xe20939be, 0x32d4, 0x41be, 0xa1, 0x50, 0x89, 0x7f, 0x85, 0xd4, 0x98, 0x29) EFI_GUID(0xe20939be, 0x32d4, 0x41be, 0xa1, 0x50, 0x89, 0x7f, 0x85, 0xd4, 0x98, 0x29)
......
...@@ -966,6 +966,8 @@ extern struct efi { ...@@ -966,6 +966,8 @@ extern struct efi {
unsigned long flags; unsigned long flags;
} efi; } efi;
extern struct mm_struct efi_mm;
static inline int static inline int
efi_guidcmp (efi_guid_t left, efi_guid_t right) efi_guidcmp (efi_guid_t left, efi_guid_t right)
{ {
......
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