diff options
Diffstat (limited to '0001-efi-prune-invalid-memory-map-entries.patch')
-rw-r--r-- | 0001-efi-prune-invalid-memory-map-entries.patch | 141 |
1 files changed, 0 insertions, 141 deletions
diff --git a/0001-efi-prune-invalid-memory-map-entries.patch b/0001-efi-prune-invalid-memory-map-entries.patch deleted file mode 100644 index 4b65ef504..000000000 --- a/0001-efi-prune-invalid-memory-map-entries.patch +++ /dev/null @@ -1,141 +0,0 @@ -From c7c7030a020405d5826c03839e38986e0f78f2ea Mon Sep 17 00:00:00 2001 -From: Peter Jones <pjones@redhat.com> -Date: Tue, 13 Dec 2016 10:25:10 +0000 -Subject: [PATCH] efi: prune invalid memory map entries - -Some machines, such as the Lenovo ThinkPad W541 with firmware GNET80WW -(2.28), include memory map entries with phys_addr=0x0 and num_pages=0. - -Currently the log output for this case (with efi=debug) looks like: - -[ 0.000000] efi: mem45: [Reserved | | | | | | | | | | | | ] range=[0x0000000000000000-0xffffffffffffffff] (0MB) - -This is clearly wrong, and also not as informative as it could be. This -patch changes it so that if we find obviously invalid memory map -entries, we print an error and those entries. It also detects the -display of the address range calculation overflow, so the new output is: - -[ 0.000000] efi: [Firmware Bug]: Invalid EFI memory map entries: -[ 0.000000] efi: mem45: [Reserved | | | | | | | | | | | | ] range=[0x0000000000000000-0x0000000000000000] (invalid) - -It also detects memory map sizes that would overflow the physical -address, for example phys_addr=0xfffffffffffff000 and -num_pages=0x0200000000000001, and prints: - -[ 0.000000] efi: [Firmware Bug]: Invalid EFI memory map entries: -[ 0.000000] efi: mem45: [Reserved | | | | | | | | | | | | ] range=[phys_addr=0xfffffffffffff000-0x20ffffffffffffffff] (invalid) - -It then removes these entries from the memory map. - -Cc: Matt Fleming <matt@codeblueprint.co.uk> -Signed-off-by: Peter Jones <pjones@redhat.com> -[ardb: refactor for clarity with no functional changes, avoid PAGE_SHIFT] -Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> ---- - arch/x86/platform/efi/efi.c | 70 +++++++++++++++++++++++++++++++++++++++++++++ - include/linux/efi.h | 1 + - 2 files changed, 71 insertions(+) - -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index bf99aa7..0a1550b 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -210,6 +210,74 @@ int __init efi_memblock_x86_reserve_range(void) - return 0; - } - -+#define OVERFLOW_ADDR_SHIFT (64 - EFI_PAGE_SHIFT) -+#define OVERFLOW_ADDR_MASK (U64_MAX << OVERFLOW_ADDR_SHIFT) -+#define U64_HIGH_BIT (~(U64_MAX >> 1)) -+ -+static bool __init efi_memmap_entry_valid(const efi_memory_desc_t *md, int i) -+{ -+ static __initdata bool once = true; -+ u64 end = (md->num_pages << EFI_PAGE_SHIFT) + md->phys_addr - 1; -+ u64 end_hi = 0; -+ char buf[64]; -+ -+ if (md->num_pages == 0) { -+ end = 0; -+ } else if (md->num_pages > EFI_PAGES_MAX || -+ EFI_PAGES_MAX - md->num_pages < -+ (md->phys_addr >> EFI_PAGE_SHIFT)) { -+ end_hi = (md->num_pages & OVERFLOW_ADDR_MASK) -+ >> OVERFLOW_ADDR_SHIFT; -+ -+ if ((md->phys_addr & U64_HIGH_BIT) && !(end & U64_HIGH_BIT)) -+ end_hi += 1; -+ } else { -+ return true; -+ } -+ -+ if (once) { -+ pr_warn(FW_BUG "Invalid EFI memory map entries:\n"); -+ once = false; -+ } -+ -+ if (end_hi) { -+ pr_warn("mem%02u: %s range=[0x%016llx-0x%llx%016llx] (invalid)\n", -+ i, efi_md_typeattr_format(buf, sizeof(buf), md), -+ md->phys_addr, end_hi, end); -+ } else { -+ pr_warn("mem%02u: %s range=[0x%016llx-0x%016llx] (invalid)\n", -+ i, efi_md_typeattr_format(buf, sizeof(buf), md), -+ md->phys_addr, end); -+ } -+ return false; -+} -+ -+static void __init efi_clean_memmap(void) -+{ -+ efi_memory_desc_t *out = efi.memmap.map; -+ const efi_memory_desc_t *in = out; -+ const efi_memory_desc_t *end = efi.memmap.map_end; -+ int i, n_removal; -+ -+ for (i = n_removal = 0; in < end; i++) { -+ if (efi_memmap_entry_valid(in, i)) { -+ if (out != in) -+ memcpy(out, in, efi.memmap.desc_size); -+ out = (void *)out + efi.memmap.desc_size; -+ } else { -+ n_removal++; -+ } -+ in = (void *)in + efi.memmap.desc_size; -+ } -+ -+ if (n_removal > 0) { -+ u64 size = efi.memmap.nr_map - n_removal; -+ -+ pr_warn("Removing %d invalid memory map entries.\n", n_removal); -+ efi_memmap_install(efi.memmap.phys_map, size); -+ } -+} -+ - void __init efi_print_memmap(void) - { - efi_memory_desc_t *md; -@@ -472,6 +540,8 @@ void __init efi_init(void) - } - } - -+ efi_clean_memmap(); -+ - if (efi_enabled(EFI_DBG)) - efi_print_memmap(); - } -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 4c1b3ea..712a3aa 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -103,6 +103,7 @@ typedef struct { - - #define EFI_PAGE_SHIFT 12 - #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) -+#define EFI_PAGES_MAX (U64_MAX >> EFI_PAGE_SHIFT) - - typedef struct { - u32 type; --- -2.9.3 - |