Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/firmware/efi/memmap.c
26444 views
1
// SPDX-License-Identifier: GPL-2.0
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
/* Cannot go backwards */
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
/* Did we forget to unmap the early EFI memmap? */
134
WARN_ON(efi.memmap.map);
135
136
/* Were we already called? */
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
}
149
150