diff options
-rw-r--r-- | arch/x86/kernel/setup.c | 7 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi.c | 45 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi_64.c | 5 | ||||
-rw-r--r-- | include/linux/efi.h | 1 |
4 files changed, 55 insertions, 3 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 605e5ae19c7f..b9ca498f5602 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -910,6 +910,13 @@ void __init setup_arch(char **cmdline_p) | |||
910 | memblock.current_limit = get_max_mapped(); | 910 | memblock.current_limit = get_max_mapped(); |
911 | memblock_x86_fill(); | 911 | memblock_x86_fill(); |
912 | 912 | ||
913 | /* | ||
914 | * The EFI specification says that boot service code won't be called | ||
915 | * after ExitBootServices(). This is, in fact, a lie. | ||
916 | */ | ||
917 | if (efi_enabled) | ||
918 | efi_reserve_boot_services(); | ||
919 | |||
913 | /* preallocate 4k for mptable mpc */ | 920 | /* preallocate 4k for mptable mpc */ |
914 | early_reserve_e820_mpc_new(); | 921 | early_reserve_e820_mpc_new(); |
915 | 922 | ||
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index b30aa26a8df2..0d3a4fa34560 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -304,6 +304,40 @@ static void __init print_efi_memmap(void) | |||
304 | } | 304 | } |
305 | #endif /* EFI_DEBUG */ | 305 | #endif /* EFI_DEBUG */ |
306 | 306 | ||
307 | void __init efi_reserve_boot_services(void) | ||
308 | { | ||
309 | void *p; | ||
310 | |||
311 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
312 | efi_memory_desc_t *md = p; | ||
313 | unsigned long long start = md->phys_addr; | ||
314 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | ||
315 | |||
316 | if (md->type != EFI_BOOT_SERVICES_CODE && | ||
317 | md->type != EFI_BOOT_SERVICES_DATA) | ||
318 | continue; | ||
319 | |||
320 | memblock_x86_reserve_range(start, start + size, "EFI Boot"); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | static void __init efi_free_boot_services(void) | ||
325 | { | ||
326 | void *p; | ||
327 | |||
328 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
329 | efi_memory_desc_t *md = p; | ||
330 | unsigned long long start = md->phys_addr; | ||
331 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | ||
332 | |||
333 | if (md->type != EFI_BOOT_SERVICES_CODE && | ||
334 | md->type != EFI_BOOT_SERVICES_DATA) | ||
335 | continue; | ||
336 | |||
337 | free_bootmem_late(start, size); | ||
338 | } | ||
339 | } | ||
340 | |||
307 | void __init efi_init(void) | 341 | void __init efi_init(void) |
308 | { | 342 | { |
309 | efi_config_table_t *config_tables; | 343 | efi_config_table_t *config_tables; |
@@ -536,7 +570,9 @@ void __init efi_enter_virtual_mode(void) | |||
536 | 570 | ||
537 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 571 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
538 | md = p; | 572 | md = p; |
539 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) | 573 | if (!(md->attribute & EFI_MEMORY_RUNTIME) && |
574 | md->type != EFI_BOOT_SERVICES_CODE && | ||
575 | md->type != EFI_BOOT_SERVICES_DATA) | ||
540 | continue; | 576 | continue; |
541 | 577 | ||
542 | size = md->num_pages << EFI_PAGE_SHIFT; | 578 | size = md->num_pages << EFI_PAGE_SHIFT; |
@@ -593,6 +629,13 @@ void __init efi_enter_virtual_mode(void) | |||
593 | } | 629 | } |
594 | 630 | ||
595 | /* | 631 | /* |
632 | * Thankfully, it does seem that no runtime services other than | ||
633 | * SetVirtualAddressMap() will touch boot services code, so we can | ||
634 | * get rid of it all at this point | ||
635 | */ | ||
636 | efi_free_boot_services(); | ||
637 | |||
638 | /* | ||
596 | * Now that EFI is in virtual mode, update the function | 639 | * Now that EFI is in virtual mode, update the function |
597 | * pointers in the runtime service table to the new virtual addresses. | 640 | * pointers in the runtime service table to the new virtual addresses. |
598 | * | 641 | * |
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 2649426a7905..ac3aa54e2654 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
@@ -49,10 +49,11 @@ static void __init early_code_mapping_set_exec(int executable) | |||
49 | if (!(__supported_pte_mask & _PAGE_NX)) | 49 | if (!(__supported_pte_mask & _PAGE_NX)) |
50 | return; | 50 | return; |
51 | 51 | ||
52 | /* Make EFI runtime service code area executable */ | 52 | /* Make EFI service code area executable */ |
53 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 53 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
54 | md = p; | 54 | md = p; |
55 | if (md->type == EFI_RUNTIME_SERVICES_CODE) | 55 | if (md->type == EFI_RUNTIME_SERVICES_CODE || |
56 | md->type == EFI_BOOT_SERVICES_CODE) | ||
56 | efi_set_executable(md, executable); | 57 | efi_set_executable(md, executable); |
57 | } | 58 | } |
58 | } | 59 | } |
diff --git a/include/linux/efi.h b/include/linux/efi.h index 33fa1203024e..e376270cd26e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -299,6 +299,7 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource, | |||
299 | struct resource *data_resource, struct resource *bss_resource); | 299 | struct resource *data_resource, struct resource *bss_resource); |
300 | extern unsigned long efi_get_time(void); | 300 | extern unsigned long efi_get_time(void); |
301 | extern int efi_set_rtc_mmss(unsigned long nowtime); | 301 | extern int efi_set_rtc_mmss(unsigned long nowtime); |
302 | extern void efi_reserve_boot_services(void); | ||
302 | extern struct efi_memory_map memmap; | 303 | extern struct efi_memory_map memmap; |
303 | 304 | ||
304 | /** | 305 | /** |