diff options
-rw-r--r-- | arch/x86/platform/efi/quirks.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 4480c06cade7..89d1146f5a6f 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c | |||
@@ -254,6 +254,7 @@ void __init efi_free_boot_services(void) | |||
254 | for_each_efi_memory_desc(md) { | 254 | for_each_efi_memory_desc(md) { |
255 | unsigned long long start = md->phys_addr; | 255 | unsigned long long start = md->phys_addr; |
256 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | 256 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; |
257 | size_t rm_size; | ||
257 | 258 | ||
258 | if (md->type != EFI_BOOT_SERVICES_CODE && | 259 | if (md->type != EFI_BOOT_SERVICES_CODE && |
259 | md->type != EFI_BOOT_SERVICES_DATA) | 260 | md->type != EFI_BOOT_SERVICES_DATA) |
@@ -263,6 +264,26 @@ void __init efi_free_boot_services(void) | |||
263 | if (md->attribute & EFI_MEMORY_RUNTIME) | 264 | if (md->attribute & EFI_MEMORY_RUNTIME) |
264 | continue; | 265 | continue; |
265 | 266 | ||
267 | /* | ||
268 | * Nasty quirk: if all sub-1MB memory is used for boot | ||
269 | * services, we can get here without having allocated the | ||
270 | * real mode trampoline. It's too late to hand boot services | ||
271 | * memory back to the memblock allocator, so instead | ||
272 | * try to manually allocate the trampoline if needed. | ||
273 | * | ||
274 | * I've seen this on a Dell XPS 13 9350 with firmware | ||
275 | * 1.4.4 with SGX enabled booting Linux via Fedora 24's | ||
276 | * grub2-efi on a hard disk. (And no, I don't know why | ||
277 | * this happened, but Linux should still try to boot rather | ||
278 | * panicing early.) | ||
279 | */ | ||
280 | rm_size = real_mode_size_needed(); | ||
281 | if (rm_size && (start + rm_size) < (1<<20) && size >= rm_size) { | ||
282 | set_real_mode_mem(start, rm_size); | ||
283 | start += rm_size; | ||
284 | size -= rm_size; | ||
285 | } | ||
286 | |||
266 | free_bootmem_late(start, size); | 287 | free_bootmem_late(start, size); |
267 | } | 288 | } |
268 | 289 | ||