| 1 | |
| 2 | |
| 3 | * Common EFI memory map functions.
|
| 4 |
|
| 5 |
|
| 6 | #define pr_fmt(fmt) "efi: " fmt
|
| 7 |
|
| 8 | #include <linux/init.h>
|
| 9 | #include <linux/kernel.h>
|
| 10 | #include <linux/efi.h>
|
| 11 | #include <linux/io.h>
|
| 12 | #include <linux/memblock.h>
|
| 13 | #include <linux/slab.h>
|
| 14 |
|
| 15 | #include <asm/early_ioremap.h>
|
| 16 | #include <asm/efi.h>
|
| 17 |
|
| 18 | |
| 19 | * __efi_memmap_init - Common code for mapping the EFI memory map
|
| 20 | * @data: EFI memory map data
|
| 21 | *
|
| 22 | * This function takes care of figuring out which function to use to
|
| 23 | * map the EFI memory map in efi.memmap based on how far into the boot
|
| 24 | * we are.
|
| 25 | *
|
| 26 | * During bootup EFI_MEMMAP_LATE in data->flags should be clear since we
|
| 27 | * only have access to the early_memremap*() functions as the vmalloc
|
| 28 | * space isn't setup. Once the kernel is fully booted we can fallback
|
| 29 | * to the more robust memremap*() API.
|
| 30 | *
|
| 31 | * Returns: zero on success, a negative error code on failure.
|
| 32 |
|
| 33 | int __init __efi_memmap_init(struct efi_memory_map_data *data)
|
| 34 | {
|
| 35 | struct efi_memory_map map;
|
| 36 | phys_addr_t phys_map;
|
| 37 |
|
| 38 | phys_map = data->phys_map;
|
| 39 |
|
| 40 | if (data->flags & EFI_MEMMAP_LATE)
|
| 41 | map.map = memremap(phys_map, data->size, MEMREMAP_WB);
|
| 42 | else
|
| 43 | map.map = early_memremap(phys_map, data->size);
|
| 44 |
|
| 45 | if (!map.map) {
|
| 46 | pr_err("Could not map the memory map! phys_map=%pa, size=0x%lx\n",
|
| 47 | &phys_map, data->size);
|
| 48 | return -ENOMEM;
|
| 49 | }
|
| 50 |
|
| 51 | map.phys_map = data->phys_map;
|
| 52 | map.nr_map = data->size / data->desc_size;
|
| 53 | map.map_end = map.map + data->size;
|
| 54 |
|
| 55 | map.desc_version = data->desc_version;
|
| 56 | map.desc_size = data->desc_size;
|
| 57 | map.flags = data->flags;
|
| 58 |
|
| 59 | set_bit(EFI_MEMMAP, &efi.flags);
|
| 60 |
|
| 61 | efi.memmap = map;
|
| 62 |
|
| 63 | return 0;
|
| 64 | }
|
| 65 |
|
| 66 | |
| 67 | * efi_memmap_init_early - Map the EFI memory map data structure
|
| 68 | * @data: EFI memory map data
|
| 69 | *
|
| 70 | * Use early_memremap() to map the passed in EFI memory map and assign
|
| 71 | * it to efi.memmap.
|
| 72 | *
|
| 73 | * Returns: zero on success, a negative error code on failure.
|
| 74 |
|
| 75 | int __init efi_memmap_init_early(struct efi_memory_map_data *data)
|
| 76 | {
|
| 77 |
|
| 78 | WARN_ON(efi.memmap.flags & EFI_MEMMAP_LATE);
|
| 79 |
|
| 80 | data->flags = 0;
|
| 81 | return __efi_memmap_init(data);
|
| 82 | }
|
| 83 |
|
| 84 | void __init efi_memmap_unmap(void)
|
| 85 | {
|
| 86 | if (!efi_enabled(EFI_MEMMAP))
|
| 87 | return;
|
| 88 |
|
| 89 | if (!(efi.memmap.flags & EFI_MEMMAP_LATE)) {
|
| 90 | unsigned long size;
|
| 91 |
|
| 92 | size = efi.memmap.desc_size * efi.memmap.nr_map;
|
| 93 | early_memunmap(efi.memmap.map, size);
|
| 94 | } else {
|
| 95 | memunmap(efi.memmap.map);
|
| 96 | }
|
| 97 |
|
| 98 | efi.memmap.map = NULL;
|
| 99 | clear_bit(EFI_MEMMAP, &efi.flags);
|
| 100 | }
|
| 101 |
|
| 102 | |
| 103 | * efi_memmap_init_late - Map efi.memmap with memremap()
|
| 104 | * @addr: Physical address of the new EFI memory map
|
| 105 | * @size: Size in bytes of the new EFI memory map
|
| 106 | *
|
| 107 | * Setup a mapping of the EFI memory map using ioremap_cache(). This
|
| 108 | * function should only be called once the vmalloc space has been
|
| 109 | * setup and is therefore not suitable for calling during early EFI
|
| 110 | * initialise, e.g. in efi_init(). Additionally, it expects
|
| 111 | * efi_memmap_init_early() to have already been called.
|
| 112 | *
|
| 113 | * The reason there are two EFI memmap initialisation
|
| 114 | * (efi_memmap_init_early() and this late version) is because the
|
| 115 | * early EFI memmap should be explicitly unmapped once EFI
|
| 116 | * initialisation is complete as the fixmap space used to map the EFI
|
| 117 | * memmap (via early_memremap()) is a scarce resource.
|
| 118 | *
|
| 119 | * This late mapping is intended to persist for the duration of
|
| 120 | * runtime so that things like efi_mem_desc_lookup() and
|
| 121 | * efi_mem_attributes() always work.
|
| 122 | *
|
| 123 | * Returns: zero on success, a negative error code on failure.
|
| 124 |
|
| 125 | int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size)
|
| 126 | {
|
| 127 | struct efi_memory_map_data data = {
|
| 128 | .phys_map = addr,
|
| 129 | .size = size,
|
| 130 | .flags = EFI_MEMMAP_LATE,
|
| 131 | };
|
| 132 |
|
| 133 |
|
| 134 | WARN_ON(efi.memmap.map);
|
| 135 |
|
| 136 |
|
| 137 | WARN_ON(efi.memmap.flags & EFI_MEMMAP_LATE);
|
| 138 |
|
| 139 | |
| 140 | * It makes no sense to allow callers to register different
|
| 141 | * values for the following fields. Copy them out of the
|
| 142 | * existing early EFI memmap.
|
| 143 |
|
| 144 | data.desc_version = efi.memmap.desc_version;
|
| 145 | data.desc_size = efi.memmap.desc_size;
|
| 146 |
|
| 147 | return __efi_memmap_init(&data);
|
| 148 | }
|