diff options
Diffstat (limited to 'arch/x86/platform/efi/efi.c')
-rw-r--r-- | arch/x86/platform/efi/efi.c | 133 |
1 files changed, 62 insertions, 71 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 994a7df84a7b..f93545e7dc54 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -54,10 +54,6 @@ | |||
54 | #include <asm/rtc.h> | 54 | #include <asm/rtc.h> |
55 | #include <asm/uv/uv.h> | 55 | #include <asm/uv/uv.h> |
56 | 56 | ||
57 | #define EFI_DEBUG | ||
58 | |||
59 | struct efi_memory_map memmap; | ||
60 | |||
61 | static struct efi efi_phys __initdata; | 57 | static struct efi efi_phys __initdata; |
62 | static efi_system_table_t efi_systab __initdata; | 58 | static efi_system_table_t efi_systab __initdata; |
63 | 59 | ||
@@ -119,11 +115,10 @@ void efi_get_time(struct timespec *now) | |||
119 | 115 | ||
120 | void __init efi_find_mirror(void) | 116 | void __init efi_find_mirror(void) |
121 | { | 117 | { |
122 | void *p; | 118 | efi_memory_desc_t *md; |
123 | u64 mirror_size = 0, total_size = 0; | 119 | u64 mirror_size = 0, total_size = 0; |
124 | 120 | ||
125 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 121 | for_each_efi_memory_desc(md) { |
126 | efi_memory_desc_t *md = p; | ||
127 | unsigned long long start = md->phys_addr; | 122 | unsigned long long start = md->phys_addr; |
128 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | 123 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; |
129 | 124 | ||
@@ -146,10 +141,9 @@ void __init efi_find_mirror(void) | |||
146 | 141 | ||
147 | static void __init do_add_efi_memmap(void) | 142 | static void __init do_add_efi_memmap(void) |
148 | { | 143 | { |
149 | void *p; | 144 | efi_memory_desc_t *md; |
150 | 145 | ||
151 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 146 | for_each_efi_memory_desc(md) { |
152 | efi_memory_desc_t *md = p; | ||
153 | unsigned long long start = md->phys_addr; | 147 | unsigned long long start = md->phys_addr; |
154 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | 148 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; |
155 | int e820_type; | 149 | int e820_type; |
@@ -209,47 +203,47 @@ int __init efi_memblock_x86_reserve_range(void) | |||
209 | #else | 203 | #else |
210 | pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32)); | 204 | pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32)); |
211 | #endif | 205 | #endif |
212 | memmap.phys_map = pmap; | 206 | efi.memmap.phys_map = pmap; |
213 | memmap.nr_map = e->efi_memmap_size / | 207 | efi.memmap.nr_map = e->efi_memmap_size / |
214 | e->efi_memdesc_size; | 208 | e->efi_memdesc_size; |
215 | memmap.desc_size = e->efi_memdesc_size; | 209 | efi.memmap.desc_size = e->efi_memdesc_size; |
216 | memmap.desc_version = e->efi_memdesc_version; | 210 | efi.memmap.desc_version = e->efi_memdesc_version; |
217 | 211 | ||
218 | memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); | 212 | WARN(efi.memmap.desc_version != 1, |
213 | "Unexpected EFI_MEMORY_DESCRIPTOR version %ld", | ||
214 | efi.memmap.desc_version); | ||
219 | 215 | ||
220 | efi.memmap = &memmap; | 216 | memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size); |
221 | 217 | ||
222 | return 0; | 218 | return 0; |
223 | } | 219 | } |
224 | 220 | ||
225 | void __init efi_print_memmap(void) | 221 | void __init efi_print_memmap(void) |
226 | { | 222 | { |
227 | #ifdef EFI_DEBUG | ||
228 | efi_memory_desc_t *md; | 223 | efi_memory_desc_t *md; |
229 | void *p; | 224 | int i = 0; |
230 | int i; | ||
231 | 225 | ||
232 | for (p = memmap.map, i = 0; | 226 | for_each_efi_memory_desc(md) { |
233 | p < memmap.map_end; | ||
234 | p += memmap.desc_size, i++) { | ||
235 | char buf[64]; | 227 | char buf[64]; |
236 | 228 | ||
237 | md = p; | ||
238 | pr_info("mem%02u: %s range=[0x%016llx-0x%016llx] (%lluMB)\n", | 229 | pr_info("mem%02u: %s range=[0x%016llx-0x%016llx] (%lluMB)\n", |
239 | i, efi_md_typeattr_format(buf, sizeof(buf), md), | 230 | i++, efi_md_typeattr_format(buf, sizeof(buf), md), |
240 | md->phys_addr, | 231 | md->phys_addr, |
241 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1, | 232 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1, |
242 | (md->num_pages >> (20 - EFI_PAGE_SHIFT))); | 233 | (md->num_pages >> (20 - EFI_PAGE_SHIFT))); |
243 | } | 234 | } |
244 | #endif /* EFI_DEBUG */ | ||
245 | } | 235 | } |
246 | 236 | ||
247 | void __init efi_unmap_memmap(void) | 237 | void __init efi_unmap_memmap(void) |
248 | { | 238 | { |
239 | unsigned long size; | ||
240 | |||
249 | clear_bit(EFI_MEMMAP, &efi.flags); | 241 | clear_bit(EFI_MEMMAP, &efi.flags); |
250 | if (memmap.map) { | 242 | |
251 | early_memunmap(memmap.map, memmap.nr_map * memmap.desc_size); | 243 | size = efi.memmap.nr_map * efi.memmap.desc_size; |
252 | memmap.map = NULL; | 244 | if (efi.memmap.map) { |
245 | early_memunmap(efi.memmap.map, size); | ||
246 | efi.memmap.map = NULL; | ||
253 | } | 247 | } |
254 | } | 248 | } |
255 | 249 | ||
@@ -352,8 +346,6 @@ static int __init efi_systab_init(void *phys) | |||
352 | efi.systab->hdr.revision >> 16, | 346 | efi.systab->hdr.revision >> 16, |
353 | efi.systab->hdr.revision & 0xffff); | 347 | efi.systab->hdr.revision & 0xffff); |
354 | 348 | ||
355 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); | ||
356 | |||
357 | return 0; | 349 | return 0; |
358 | } | 350 | } |
359 | 351 | ||
@@ -440,17 +432,22 @@ static int __init efi_runtime_init(void) | |||
440 | 432 | ||
441 | static int __init efi_memmap_init(void) | 433 | static int __init efi_memmap_init(void) |
442 | { | 434 | { |
435 | unsigned long addr, size; | ||
436 | |||
443 | if (efi_enabled(EFI_PARAVIRT)) | 437 | if (efi_enabled(EFI_PARAVIRT)) |
444 | return 0; | 438 | return 0; |
445 | 439 | ||
446 | /* Map the EFI memory map */ | 440 | /* Map the EFI memory map */ |
447 | memmap.map = early_memremap((unsigned long)memmap.phys_map, | 441 | size = efi.memmap.nr_map * efi.memmap.desc_size; |
448 | memmap.nr_map * memmap.desc_size); | 442 | addr = (unsigned long)efi.memmap.phys_map; |
449 | if (memmap.map == NULL) { | 443 | |
444 | efi.memmap.map = early_memremap(addr, size); | ||
445 | if (efi.memmap.map == NULL) { | ||
450 | pr_err("Could not map the memory map!\n"); | 446 | pr_err("Could not map the memory map!\n"); |
451 | return -ENOMEM; | 447 | return -ENOMEM; |
452 | } | 448 | } |
453 | memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); | 449 | |
450 | efi.memmap.map_end = efi.memmap.map + size; | ||
454 | 451 | ||
455 | if (add_efi_memmap) | 452 | if (add_efi_memmap) |
456 | do_add_efi_memmap(); | 453 | do_add_efi_memmap(); |
@@ -552,12 +549,9 @@ void __init efi_set_executable(efi_memory_desc_t *md, bool executable) | |||
552 | void __init runtime_code_page_mkexec(void) | 549 | void __init runtime_code_page_mkexec(void) |
553 | { | 550 | { |
554 | efi_memory_desc_t *md; | 551 | efi_memory_desc_t *md; |
555 | void *p; | ||
556 | 552 | ||
557 | /* Make EFI runtime service code area executable */ | 553 | /* Make EFI runtime service code area executable */ |
558 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 554 | for_each_efi_memory_desc(md) { |
559 | md = p; | ||
560 | |||
561 | if (md->type != EFI_RUNTIME_SERVICES_CODE) | 555 | if (md->type != EFI_RUNTIME_SERVICES_CODE) |
562 | continue; | 556 | continue; |
563 | 557 | ||
@@ -604,12 +598,10 @@ void __init old_map_region(efi_memory_desc_t *md) | |||
604 | /* Merge contiguous regions of the same type and attribute */ | 598 | /* Merge contiguous regions of the same type and attribute */ |
605 | static void __init efi_merge_regions(void) | 599 | static void __init efi_merge_regions(void) |
606 | { | 600 | { |
607 | void *p; | ||
608 | efi_memory_desc_t *md, *prev_md = NULL; | 601 | efi_memory_desc_t *md, *prev_md = NULL; |
609 | 602 | ||
610 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 603 | for_each_efi_memory_desc(md) { |
611 | u64 prev_size; | 604 | u64 prev_size; |
612 | md = p; | ||
613 | 605 | ||
614 | if (!prev_md) { | 606 | if (!prev_md) { |
615 | prev_md = md; | 607 | prev_md = md; |
@@ -651,30 +643,31 @@ static void __init get_systab_virt_addr(efi_memory_desc_t *md) | |||
651 | static void __init save_runtime_map(void) | 643 | static void __init save_runtime_map(void) |
652 | { | 644 | { |
653 | #ifdef CONFIG_KEXEC_CORE | 645 | #ifdef CONFIG_KEXEC_CORE |
646 | unsigned long desc_size; | ||
654 | efi_memory_desc_t *md; | 647 | efi_memory_desc_t *md; |
655 | void *tmp, *p, *q = NULL; | 648 | void *tmp, *q = NULL; |
656 | int count = 0; | 649 | int count = 0; |
657 | 650 | ||
658 | if (efi_enabled(EFI_OLD_MEMMAP)) | 651 | if (efi_enabled(EFI_OLD_MEMMAP)) |
659 | return; | 652 | return; |
660 | 653 | ||
661 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 654 | desc_size = efi.memmap.desc_size; |
662 | md = p; | ||
663 | 655 | ||
656 | for_each_efi_memory_desc(md) { | ||
664 | if (!(md->attribute & EFI_MEMORY_RUNTIME) || | 657 | if (!(md->attribute & EFI_MEMORY_RUNTIME) || |
665 | (md->type == EFI_BOOT_SERVICES_CODE) || | 658 | (md->type == EFI_BOOT_SERVICES_CODE) || |
666 | (md->type == EFI_BOOT_SERVICES_DATA)) | 659 | (md->type == EFI_BOOT_SERVICES_DATA)) |
667 | continue; | 660 | continue; |
668 | tmp = krealloc(q, (count + 1) * memmap.desc_size, GFP_KERNEL); | 661 | tmp = krealloc(q, (count + 1) * desc_size, GFP_KERNEL); |
669 | if (!tmp) | 662 | if (!tmp) |
670 | goto out; | 663 | goto out; |
671 | q = tmp; | 664 | q = tmp; |
672 | 665 | ||
673 | memcpy(q + count * memmap.desc_size, md, memmap.desc_size); | 666 | memcpy(q + count * desc_size, md, desc_size); |
674 | count++; | 667 | count++; |
675 | } | 668 | } |
676 | 669 | ||
677 | efi_runtime_map_setup(q, count, memmap.desc_size); | 670 | efi_runtime_map_setup(q, count, desc_size); |
678 | return; | 671 | return; |
679 | 672 | ||
680 | out: | 673 | out: |
@@ -714,10 +707,10 @@ static inline void *efi_map_next_entry_reverse(void *entry) | |||
714 | { | 707 | { |
715 | /* Initial call */ | 708 | /* Initial call */ |
716 | if (!entry) | 709 | if (!entry) |
717 | return memmap.map_end - memmap.desc_size; | 710 | return efi.memmap.map_end - efi.memmap.desc_size; |
718 | 711 | ||
719 | entry -= memmap.desc_size; | 712 | entry -= efi.memmap.desc_size; |
720 | if (entry < memmap.map) | 713 | if (entry < efi.memmap.map) |
721 | return NULL; | 714 | return NULL; |
722 | 715 | ||
723 | return entry; | 716 | return entry; |
@@ -759,10 +752,10 @@ static void *efi_map_next_entry(void *entry) | |||
759 | 752 | ||
760 | /* Initial call */ | 753 | /* Initial call */ |
761 | if (!entry) | 754 | if (!entry) |
762 | return memmap.map; | 755 | return efi.memmap.map; |
763 | 756 | ||
764 | entry += memmap.desc_size; | 757 | entry += efi.memmap.desc_size; |
765 | if (entry >= memmap.map_end) | 758 | if (entry >= efi.memmap.map_end) |
766 | return NULL; | 759 | return NULL; |
767 | 760 | ||
768 | return entry; | 761 | return entry; |
@@ -776,8 +769,11 @@ static void * __init efi_map_regions(int *count, int *pg_shift) | |||
776 | { | 769 | { |
777 | void *p, *new_memmap = NULL; | 770 | void *p, *new_memmap = NULL; |
778 | unsigned long left = 0; | 771 | unsigned long left = 0; |
772 | unsigned long desc_size; | ||
779 | efi_memory_desc_t *md; | 773 | efi_memory_desc_t *md; |
780 | 774 | ||
775 | desc_size = efi.memmap.desc_size; | ||
776 | |||
781 | p = NULL; | 777 | p = NULL; |
782 | while ((p = efi_map_next_entry(p))) { | 778 | while ((p = efi_map_next_entry(p))) { |
783 | md = p; | 779 | md = p; |
@@ -792,7 +788,7 @@ static void * __init efi_map_regions(int *count, int *pg_shift) | |||
792 | efi_map_region(md); | 788 | efi_map_region(md); |
793 | get_systab_virt_addr(md); | 789 | get_systab_virt_addr(md); |
794 | 790 | ||
795 | if (left < memmap.desc_size) { | 791 | if (left < desc_size) { |
796 | new_memmap = realloc_pages(new_memmap, *pg_shift); | 792 | new_memmap = realloc_pages(new_memmap, *pg_shift); |
797 | if (!new_memmap) | 793 | if (!new_memmap) |
798 | return NULL; | 794 | return NULL; |
@@ -801,10 +797,9 @@ static void * __init efi_map_regions(int *count, int *pg_shift) | |||
801 | (*pg_shift)++; | 797 | (*pg_shift)++; |
802 | } | 798 | } |
803 | 799 | ||
804 | memcpy(new_memmap + (*count * memmap.desc_size), md, | 800 | memcpy(new_memmap + (*count * desc_size), md, desc_size); |
805 | memmap.desc_size); | ||
806 | 801 | ||
807 | left -= memmap.desc_size; | 802 | left -= desc_size; |
808 | (*count)++; | 803 | (*count)++; |
809 | } | 804 | } |
810 | 805 | ||
@@ -816,7 +811,6 @@ static void __init kexec_enter_virtual_mode(void) | |||
816 | #ifdef CONFIG_KEXEC_CORE | 811 | #ifdef CONFIG_KEXEC_CORE |
817 | efi_memory_desc_t *md; | 812 | efi_memory_desc_t *md; |
818 | unsigned int num_pages; | 813 | unsigned int num_pages; |
819 | void *p; | ||
820 | 814 | ||
821 | efi.systab = NULL; | 815 | efi.systab = NULL; |
822 | 816 | ||
@@ -840,8 +834,7 @@ static void __init kexec_enter_virtual_mode(void) | |||
840 | * Map efi regions which were passed via setup_data. The virt_addr is a | 834 | * Map efi regions which were passed via setup_data. The virt_addr is a |
841 | * fixed addr which was used in first kernel of a kexec boot. | 835 | * fixed addr which was used in first kernel of a kexec boot. |
842 | */ | 836 | */ |
843 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 837 | for_each_efi_memory_desc(md) { |
844 | md = p; | ||
845 | efi_map_region_fixed(md); /* FIXME: add error handling */ | 838 | efi_map_region_fixed(md); /* FIXME: add error handling */ |
846 | get_systab_virt_addr(md); | 839 | get_systab_virt_addr(md); |
847 | } | 840 | } |
@@ -850,10 +843,10 @@ static void __init kexec_enter_virtual_mode(void) | |||
850 | 843 | ||
851 | BUG_ON(!efi.systab); | 844 | BUG_ON(!efi.systab); |
852 | 845 | ||
853 | num_pages = ALIGN(memmap.nr_map * memmap.desc_size, PAGE_SIZE); | 846 | num_pages = ALIGN(efi.memmap.nr_map * efi.memmap.desc_size, PAGE_SIZE); |
854 | num_pages >>= PAGE_SHIFT; | 847 | num_pages >>= PAGE_SHIFT; |
855 | 848 | ||
856 | if (efi_setup_page_tables(memmap.phys_map, num_pages)) { | 849 | if (efi_setup_page_tables(efi.memmap.phys_map, num_pages)) { |
857 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); | 850 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); |
858 | return; | 851 | return; |
859 | } | 852 | } |
@@ -937,16 +930,16 @@ static void __init __efi_enter_virtual_mode(void) | |||
937 | 930 | ||
938 | if (efi_is_native()) { | 931 | if (efi_is_native()) { |
939 | status = phys_efi_set_virtual_address_map( | 932 | status = phys_efi_set_virtual_address_map( |
940 | memmap.desc_size * count, | 933 | efi.memmap.desc_size * count, |
941 | memmap.desc_size, | 934 | efi.memmap.desc_size, |
942 | memmap.desc_version, | 935 | efi.memmap.desc_version, |
943 | (efi_memory_desc_t *)__pa(new_memmap)); | 936 | (efi_memory_desc_t *)__pa(new_memmap)); |
944 | } else { | 937 | } else { |
945 | status = efi_thunk_set_virtual_address_map( | 938 | status = efi_thunk_set_virtual_address_map( |
946 | efi_phys.set_virtual_address_map, | 939 | efi_phys.set_virtual_address_map, |
947 | memmap.desc_size * count, | 940 | efi.memmap.desc_size * count, |
948 | memmap.desc_size, | 941 | efi.memmap.desc_size, |
949 | memmap.desc_version, | 942 | efi.memmap.desc_version, |
950 | (efi_memory_desc_t *)__pa(new_memmap)); | 943 | (efi_memory_desc_t *)__pa(new_memmap)); |
951 | } | 944 | } |
952 | 945 | ||
@@ -1011,13 +1004,11 @@ void __init efi_enter_virtual_mode(void) | |||
1011 | u32 efi_mem_type(unsigned long phys_addr) | 1004 | u32 efi_mem_type(unsigned long phys_addr) |
1012 | { | 1005 | { |
1013 | efi_memory_desc_t *md; | 1006 | efi_memory_desc_t *md; |
1014 | void *p; | ||
1015 | 1007 | ||
1016 | if (!efi_enabled(EFI_MEMMAP)) | 1008 | if (!efi_enabled(EFI_MEMMAP)) |
1017 | return 0; | 1009 | return 0; |
1018 | 1010 | ||
1019 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 1011 | for_each_efi_memory_desc(md) { |
1020 | md = p; | ||
1021 | if ((md->phys_addr <= phys_addr) && | 1012 | if ((md->phys_addr <= phys_addr) && |
1022 | (phys_addr < (md->phys_addr + | 1013 | (phys_addr < (md->phys_addr + |
1023 | (md->num_pages << EFI_PAGE_SHIFT)))) | 1014 | (md->num_pages << EFI_PAGE_SHIFT)))) |