2 * Extensible Firmware Interface
4 * Based on Extensible Firmware Interface Specification version 2.4
6 * Copyright (C) 2013, 2014 Linaro Ltd.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 #include <linux/efi.h>
15 #include <linux/export.h>
16 #include <linux/memblock.h>
17 #include <linux/bootmem.h>
19 #include <linux/of_fdt.h>
20 #include <linux/sched.h>
21 #include <linux/slab.h>
23 #include <asm/cacheflush.h>
25 #include <asm/tlbflush.h>
26 #include <asm/mmu_context.h>
28 struct efi_memory_map memmap
;
30 static efi_runtime_services_t
*runtime
;
32 static u64 efi_system_table
;
34 static int uefi_debug __initdata
;
35 static int __init
uefi_debug_setup(char *str
)
41 early_param("uefi_debug", uefi_debug_setup
);
43 static int __init
is_normal_ram(efi_memory_desc_t
*md
)
45 if (md
->attribute
& EFI_MEMORY_WB
)
50 static void __init
efi_setup_idmap(void)
52 struct memblock_region
*r
;
53 efi_memory_desc_t
*md
;
54 u64 paddr
, npages
, size
;
56 for_each_memblock(memory
, r
)
57 create_id_mapping(r
->base
, r
->size
, 0);
59 /* map runtime io spaces */
60 for_each_efi_memory_desc(&memmap
, md
) {
61 if (!(md
->attribute
& EFI_MEMORY_RUNTIME
) || is_normal_ram(md
))
63 paddr
= md
->phys_addr
;
64 npages
= md
->num_pages
;
65 memrange_efi_to_native(&paddr
, &npages
);
66 size
= npages
<< PAGE_SHIFT
;
67 create_id_mapping(paddr
, size
, 1);
71 static int __init
uefi_init(void)
74 char vendor
[100] = "unknown";
77 efi
.systab
= early_memremap(efi_system_table
,
78 sizeof(efi_system_table_t
));
79 if (efi
.systab
== NULL
) {
80 pr_warn("Unable to map EFI system table.\n");
84 set_bit(EFI_BOOT
, &efi
.flags
);
85 set_bit(EFI_64BIT
, &efi
.flags
);
88 * Verify the EFI Table
90 if (efi
.systab
->hdr
.signature
!= EFI_SYSTEM_TABLE_SIGNATURE
) {
91 pr_err("System table signature incorrect\n");
95 if ((efi
.systab
->hdr
.revision
>> 16) < 2)
96 pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
97 efi
.systab
->hdr
.revision
>> 16,
98 efi
.systab
->hdr
.revision
& 0xffff);
100 /* Show what we know for posterity */
101 c16
= early_memremap(efi
.systab
->fw_vendor
,
104 for (i
= 0; i
< (int) sizeof(vendor
) - 1 && *c16
; ++i
)
107 early_memunmap(c16
, sizeof(vendor
));
110 pr_info("EFI v%u.%.02u by %s\n",
111 efi
.systab
->hdr
.revision
>> 16,
112 efi
.systab
->hdr
.revision
& 0xffff, vendor
);
114 retval
= efi_config_init(NULL
);
116 set_bit(EFI_CONFIG_TABLES
, &efi
.flags
);
119 early_memunmap(efi
.systab
, sizeof(efi_system_table_t
));
124 * Return true for RAM regions we want to permanently reserve.
126 static __init
int is_reserve_region(efi_memory_desc_t
*md
)
128 if (!is_normal_ram(md
))
131 if (md
->attribute
& EFI_MEMORY_RUNTIME
)
134 if (md
->type
== EFI_ACPI_RECLAIM_MEMORY
||
135 md
->type
== EFI_RESERVED_TYPE
)
141 static __init
void reserve_regions(void)
143 efi_memory_desc_t
*md
;
144 u64 paddr
, npages
, size
;
147 pr_info("Processing EFI memory map:\n");
149 for_each_efi_memory_desc(&memmap
, md
) {
150 paddr
= md
->phys_addr
;
151 npages
= md
->num_pages
;
156 pr_info(" 0x%012llx-0x%012llx %s",
157 paddr
, paddr
+ (npages
<< EFI_PAGE_SHIFT
) - 1,
158 efi_md_typeattr_format(buf
, sizeof(buf
), md
));
161 memrange_efi_to_native(&paddr
, &npages
);
162 size
= npages
<< PAGE_SHIFT
;
164 if (is_normal_ram(md
))
165 early_init_dt_add_memory_arch(paddr
, size
);
167 if (is_reserve_region(md
) ||
168 md
->type
== EFI_BOOT_SERVICES_CODE
||
169 md
->type
== EFI_BOOT_SERVICES_DATA
) {
170 memblock_reserve(paddr
, size
);
179 set_bit(EFI_MEMMAP
, &efi
.flags
);
183 static u64 __init
free_one_region(u64 start
, u64 end
)
185 u64 size
= end
- start
;
188 pr_info(" EFI freeing: 0x%012llx-0x%012llx\n", start
, end
- 1);
190 free_bootmem_late(start
, size
);
194 static u64 __init
free_region(u64 start
, u64 end
)
196 u64 map_start
, map_end
, total
= 0;
201 map_start
= (u64
)memmap
.phys_map
;
202 map_end
= PAGE_ALIGN(map_start
+ (memmap
.map_end
- memmap
.map
));
203 map_start
&= PAGE_MASK
;
205 if (start
< map_end
&& end
> map_start
) {
206 /* region overlaps UEFI memmap */
207 if (start
< map_start
)
208 total
+= free_one_region(start
, map_start
);
211 total
+= free_one_region(map_end
, end
);
213 total
+= free_one_region(start
, end
);
218 static void __init
free_boot_services(void)
221 u64 keep_end
, free_start
, free_end
;
222 efi_memory_desc_t
*md
;
225 * If kernel uses larger pages than UEFI, we have to be careful
226 * not to inadvertantly free memory we want to keep if there is
227 * overlap at the kernel page size alignment. We do not want to
228 * free is_reserve_region() memory nor the UEFI memmap itself.
230 * The memory map is sorted, so we keep track of the end of
231 * any previous region we want to keep, remember any region
232 * we want to free and defer freeing it until we encounter
233 * the next region we want to keep. This way, before freeing
234 * it, we can clip it as needed to avoid freeing memory we
235 * want to keep for UEFI.
241 for_each_efi_memory_desc(&memmap
, md
) {
242 u64 paddr
, npages
, size
;
244 if (is_reserve_region(md
)) {
246 * We don't want to free any memory from this region.
249 /* adjust free_end then free region */
250 if (free_end
> md
->phys_addr
)
251 free_end
-= PAGE_SIZE
;
252 total_freed
+= free_region(free_start
, free_end
);
255 keep_end
= md
->phys_addr
+ (md
->num_pages
<< EFI_PAGE_SHIFT
);
259 if (md
->type
!= EFI_BOOT_SERVICES_CODE
&&
260 md
->type
!= EFI_BOOT_SERVICES_DATA
) {
261 /* no need to free this region */
266 * We want to free memory from this region.
268 paddr
= md
->phys_addr
;
269 npages
= md
->num_pages
;
270 memrange_efi_to_native(&paddr
, &npages
);
271 size
= npages
<< PAGE_SHIFT
;
274 if (paddr
<= free_end
)
275 free_end
= paddr
+ size
;
277 total_freed
+= free_region(free_start
, free_end
);
279 free_end
= paddr
+ size
;
283 free_end
= paddr
+ size
;
285 if (free_start
< keep_end
) {
286 free_start
+= PAGE_SIZE
;
287 if (free_start
>= free_end
)
292 total_freed
+= free_region(free_start
, free_end
);
295 pr_info("Freed 0x%llx bytes of EFI boot services memory",
299 void __init
efi_init(void)
301 struct efi_fdt_params params
;
303 /* Grab UEFI information placed in FDT by stub */
304 if (!efi_get_fdt_params(¶ms
, uefi_debug
))
307 efi_system_table
= params
.system_table
;
309 memblock_reserve(params
.mmap
& PAGE_MASK
,
310 PAGE_ALIGN(params
.mmap_size
+ (params
.mmap
& ~PAGE_MASK
)));
311 memmap
.phys_map
= (void *)params
.mmap
;
312 memmap
.map
= early_memremap(params
.mmap
, params
.mmap_size
);
313 memmap
.map_end
= memmap
.map
+ params
.mmap_size
;
314 memmap
.desc_size
= params
.desc_size
;
315 memmap
.desc_version
= params
.desc_ver
;
323 void __init
efi_idmap_init(void)
325 if (!efi_enabled(EFI_BOOT
))
328 /* boot time idmap_pg_dir is incomplete, so fill in missing parts */
332 static int __init
remap_region(efi_memory_desc_t
*md
, void **new)
334 u64 paddr
, vaddr
, npages
, size
;
336 paddr
= md
->phys_addr
;
337 npages
= md
->num_pages
;
338 memrange_efi_to_native(&paddr
, &npages
);
339 size
= npages
<< PAGE_SHIFT
;
341 if (is_normal_ram(md
))
342 vaddr
= (__force u64
)ioremap_cache(paddr
, size
);
344 vaddr
= (__force u64
)ioremap(paddr
, size
);
347 pr_err("Unable to remap 0x%llx pages @ %p\n",
348 npages
, (void *)paddr
);
352 /* adjust for any rounding when EFI and system pagesize differs */
353 md
->virt_addr
= vaddr
+ (md
->phys_addr
- paddr
);
356 pr_info(" EFI remap 0x%012llx => %p\n",
357 md
->phys_addr
, (void *)md
->virt_addr
);
359 memcpy(*new, md
, memmap
.desc_size
);
360 *new += memmap
.desc_size
;
366 * Switch UEFI from an identity map to a kernel virtual map
368 static int __init
arm64_enter_virtual_mode(void)
370 efi_memory_desc_t
*md
;
371 phys_addr_t virtmap_phys
;
372 void *virtmap
, *virt_md
;
378 if (!efi_enabled(EFI_BOOT
)) {
379 pr_info("EFI services will not be available.\n");
383 mapsize
= memmap
.map_end
- memmap
.map
;
384 early_memunmap(memmap
.map
, mapsize
);
386 if (efi_runtime_disabled()) {
387 pr_info("EFI runtime services will be disabled.\n");
391 pr_info("Remapping and enabling EFI services.\n");
392 /* replace early memmap mapping with permanent mapping */
393 memmap
.map
= (__force
void *)ioremap_cache((phys_addr_t
)memmap
.phys_map
,
395 memmap
.map_end
= memmap
.map
+ mapsize
;
397 efi
.memmap
= &memmap
;
399 /* Map the runtime regions */
400 virtmap
= kmalloc(mapsize
, GFP_KERNEL
);
402 pr_err("Failed to allocate EFI virtual memmap\n");
405 virtmap_phys
= virt_to_phys(virtmap
);
408 for_each_efi_memory_desc(&memmap
, md
) {
409 if (!(md
->attribute
& EFI_MEMORY_RUNTIME
))
411 if (!remap_region(md
, &virt_md
))
416 efi
.systab
= (__force
void *)efi_lookup_mapped_addr(efi_system_table
);
419 * If we have no virtual mapping for the System Table at this
420 * point, the memory map doesn't cover the physical offset where
421 * it resides. This means the System Table will be inaccessible
422 * to Runtime Services themselves once the virtual mapping is
425 pr_err("Failed to remap EFI System Table -- buggy firmware?\n");
428 set_bit(EFI_SYSTEM_TABLES
, &efi
.flags
);
430 local_irq_save(flags
);
431 cpu_switch_mm(idmap_pg_dir
, &init_mm
);
433 /* Call SetVirtualAddressMap with the physical address of the map */
434 runtime
= efi
.systab
->runtime
;
435 efi
.set_virtual_address_map
= runtime
->set_virtual_address_map
;
437 status
= efi
.set_virtual_address_map(count
* memmap
.desc_size
,
440 (efi_memory_desc_t
*)virtmap_phys
);
441 cpu_set_reserved_ttbr0();
443 local_irq_restore(flags
);
447 free_boot_services();
449 if (status
!= EFI_SUCCESS
) {
450 pr_err("Failed to set EFI virtual address map! [%lx]\n",
455 /* Set up runtime services function pointers */
456 runtime
= efi
.systab
->runtime
;
457 efi_native_runtime_setup();
458 set_bit(EFI_RUNTIME_SERVICES
, &efi
.flags
);
460 efi
.runtime_version
= efi
.systab
->hdr
.revision
;
465 /* unmap all mappings that succeeded: there are 'count' of those */
466 for (virt_md
= virtmap
; count
--; virt_md
+= memmap
.desc_size
) {
468 iounmap((__force
void __iomem
*)md
->virt_addr
);
473 early_initcall(arm64_enter_virtual_mode
);