diff options
Diffstat (limited to 'arch/x86/kernel/efi.c')
-rw-r--r-- | arch/x86/kernel/efi.c | 67 |
1 files changed, 58 insertions, 9 deletions
diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index 77d424cf68b3..06cc8d4254b1 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c | |||
@@ -64,6 +64,17 @@ static int __init setup_noefi(char *arg) | |||
64 | } | 64 | } |
65 | early_param("noefi", setup_noefi); | 65 | early_param("noefi", setup_noefi); |
66 | 66 | ||
67 | int add_efi_memmap; | ||
68 | EXPORT_SYMBOL(add_efi_memmap); | ||
69 | |||
70 | static int __init setup_add_efi_memmap(char *arg) | ||
71 | { | ||
72 | add_efi_memmap = 1; | ||
73 | return 0; | ||
74 | } | ||
75 | early_param("add_efi_memmap", setup_add_efi_memmap); | ||
76 | |||
77 | |||
67 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | 78 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) |
68 | { | 79 | { |
69 | return efi_call_virt2(get_time, tm, tc); | 80 | return efi_call_virt2(get_time, tm, tc); |
@@ -213,6 +224,50 @@ unsigned long efi_get_time(void) | |||
213 | eft.minute, eft.second); | 224 | eft.minute, eft.second); |
214 | } | 225 | } |
215 | 226 | ||
227 | /* | ||
228 | * Tell the kernel about the EFI memory map. This might include | ||
229 | * more than the max 128 entries that can fit in the e820 legacy | ||
230 | * (zeropage) memory map. | ||
231 | */ | ||
232 | |||
233 | static void __init do_add_efi_memmap(void) | ||
234 | { | ||
235 | void *p; | ||
236 | |||
237 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
238 | efi_memory_desc_t *md = p; | ||
239 | unsigned long long start = md->phys_addr; | ||
240 | unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; | ||
241 | int e820_type; | ||
242 | |||
243 | if (md->attribute & EFI_MEMORY_WB) | ||
244 | e820_type = E820_RAM; | ||
245 | else | ||
246 | e820_type = E820_RESERVED; | ||
247 | e820_add_region(start, size, e820_type); | ||
248 | } | ||
249 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | ||
250 | } | ||
251 | |||
252 | void __init efi_reserve_early(void) | ||
253 | { | ||
254 | unsigned long pmap; | ||
255 | |||
256 | #ifdef CONFIG_X86_32 | ||
257 | pmap = boot_params.efi_info.efi_memmap; | ||
258 | #else | ||
259 | pmap = (boot_params.efi_info.efi_memmap | | ||
260 | ((__u64)boot_params.efi_info.efi_memmap_hi<<32)); | ||
261 | #endif | ||
262 | memmap.phys_map = (void *)pmap; | ||
263 | memmap.nr_map = boot_params.efi_info.efi_memmap_size / | ||
264 | boot_params.efi_info.efi_memdesc_size; | ||
265 | memmap.desc_version = boot_params.efi_info.efi_memdesc_version; | ||
266 | memmap.desc_size = boot_params.efi_info.efi_memdesc_size; | ||
267 | reserve_early(pmap, pmap + memmap.nr_map * memmap.desc_size, | ||
268 | "EFI memmap"); | ||
269 | } | ||
270 | |||
216 | #if EFI_DEBUG | 271 | #if EFI_DEBUG |
217 | static void __init print_efi_memmap(void) | 272 | static void __init print_efi_memmap(void) |
218 | { | 273 | { |
@@ -244,19 +299,11 @@ void __init efi_init(void) | |||
244 | 299 | ||
245 | #ifdef CONFIG_X86_32 | 300 | #ifdef CONFIG_X86_32 |
246 | efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; | 301 | efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; |
247 | memmap.phys_map = (void *)boot_params.efi_info.efi_memmap; | ||
248 | #else | 302 | #else |
249 | efi_phys.systab = (efi_system_table_t *) | 303 | efi_phys.systab = (efi_system_table_t *) |
250 | (boot_params.efi_info.efi_systab | | 304 | (boot_params.efi_info.efi_systab | |
251 | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); | 305 | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); |
252 | memmap.phys_map = (void *) | ||
253 | (boot_params.efi_info.efi_memmap | | ||
254 | ((__u64)boot_params.efi_info.efi_memmap_hi<<32)); | ||
255 | #endif | 306 | #endif |
256 | memmap.nr_map = boot_params.efi_info.efi_memmap_size / | ||
257 | boot_params.efi_info.efi_memdesc_size; | ||
258 | memmap.desc_version = boot_params.efi_info.efi_memdesc_version; | ||
259 | memmap.desc_size = boot_params.efi_info.efi_memdesc_size; | ||
260 | 307 | ||
261 | efi.systab = early_ioremap((unsigned long)efi_phys.systab, | 308 | efi.systab = early_ioremap((unsigned long)efi_phys.systab, |
262 | sizeof(efi_system_table_t)); | 309 | sizeof(efi_system_table_t)); |
@@ -370,6 +417,8 @@ void __init efi_init(void) | |||
370 | if (memmap.desc_size != sizeof(efi_memory_desc_t)) | 417 | if (memmap.desc_size != sizeof(efi_memory_desc_t)) |
371 | printk(KERN_WARNING "Kernel-defined memdesc" | 418 | printk(KERN_WARNING "Kernel-defined memdesc" |
372 | "doesn't match the one from EFI!\n"); | 419 | "doesn't match the one from EFI!\n"); |
420 | if (add_efi_memmap) | ||
421 | do_add_efi_memmap(); | ||
373 | 422 | ||
374 | /* Setup for EFI runtime service */ | 423 | /* Setup for EFI runtime service */ |
375 | reboot_type = BOOT_EFI; | 424 | reboot_type = BOOT_EFI; |
@@ -424,7 +473,7 @@ void __init efi_enter_virtual_mode(void) | |||
424 | size = md->num_pages << EFI_PAGE_SHIFT; | 473 | size = md->num_pages << EFI_PAGE_SHIFT; |
425 | end = md->phys_addr + size; | 474 | end = md->phys_addr + size; |
426 | 475 | ||
427 | if (PFN_UP(end) <= max_pfn_mapped) | 476 | if (PFN_UP(end) <= max_low_pfn_mapped) |
428 | va = __va(md->phys_addr); | 477 | va = __va(md->phys_addr); |
429 | else | 478 | else |
430 | va = efi_ioremap(md->phys_addr, size); | 479 | va = efi_ioremap(md->phys_addr, size); |