History

efi/libstub: Allocate headspace in efi_get_memory_map()

efi_get_memory_map() allocates a buffer to store the memory map that it retrieves. This buffer may need to be reused by the client after ExitBootServices() is called, at which point allocations are not longer permitted. To support this usecase, provide the allocated buffer size back to the client, and allocate some additional headroom to account for any reasonable growth in the map that is likely to happen between the call to efi_get_memory_map() and the client reusing the buffer.

Jeffrey Hugo committed 10 years ago

Commit dadb57a1 parent 4af9ed55 files · +111 −49Browse files

Unified · Split

5 files
  1. arch/x86/boot/compressed/eboot.c +13 −7
  2. drivers/firmware/efi/libstub/efi-stub-helper.c +66 −30
  3. drivers/firmware/efi/libstub/fdt.c +12 −5
  4. drivers/firmware/efi/libstub/random.c +10 −2
  5. include/linux/efi.h +10 −5
arch/x86/boot/compressed/eboot.c+13−7
@@ -1008,7 +1008,7 @@ static efi_status_t exit_boot(struct boot_params *boot_params, · 1007 unmodified lines
10081008 void *handle, bool is64)
10091009 {
10101010 struct efi_info *efi = &boot_params->efi_info;
1011− unsigned long map_sz, key, desc_size;
1011+ unsigned long map_sz, key, desc_size, buff_size;
10121012 efi_memory_desc_t *mem_map;
10131013 struct setup_data *e820ext;
10141014 const char *signature;
@@ -1019,14 +1019,20 @@ static efi_status_t exit_boot(struct boot_params *boot_params, · 4 unmodified lines
10191019 bool called_exit = false;
10201020 u8 nr_entries;
10211021 int i;
1022−
1023− nr_desc = 0;
1024− e820ext = NULL;
1025− e820ext_size = 0;
1022+ struct efi_boot_memmap map;
1023+
1024+ nr_desc = 0;
1025+ e820ext = NULL;
1026+ e820ext_size = 0;
1027+ map.map = &mem_map;
1028+ map.map_size = &map_sz;
1029+ map.desc_size = &desc_size;
1030+ map.desc_ver = &desc_version;
1031+ map.key_ptr = &key;
1032+ map.buff_size = &buff_size;
10261033
10271034 get_map:
1028− status = efi_get_memory_map(sys_table, &mem_map, &map_sz, &desc_size,
1029− &desc_version, &key);
1035+ status = efi_get_memory_map(sys_table, &map);
10301036
10311037 if (status != EFI_SUCCESS)
10321038 return status;
drivers/firmware/efi/libstub/efi-stub-helper.c+66−30
@@ -41,6 +41,8 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE; · 40 unmodified lines
4141 #define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
4242 #endif
4343
44+#define EFI_MMAP_NR_SLACK_SLOTS 8
45+
4446 struct file_info {
4547 efi_file_handle_t *handle;
4648 u64 size;
@@ -63,49 +65,62 @@ void efi_printk(efi_system_table_t *sys_table_arg, char *str) · 16 unmodified lines
6365 }
6466 }
6567
68+static inline bool mmap_has_headroom(unsigned long buff_size,
69+ unsigned long map_size,
70+ unsigned long desc_size)
71+{
72+ unsigned long slack = buff_size - map_size;
73+
74+ return slack / desc_size >= EFI_MMAP_NR_SLACK_SLOTS;
75+}
76+
6677 efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
67− efi_memory_desc_t **map,
68− unsigned long *map_size,
69− unsigned long *desc_size,
70− u32 *desc_ver,
71− unsigned long *key_ptr)
78+ struct efi_boot_memmap *map)
7279 {
7380 efi_memory_desc_t *m = NULL;
7481 efi_status_t status;
7582 unsigned long key;
7683 u32 desc_version;
7784
78− *map_size = sizeof(*m) * 32;
85+ *map->desc_size = sizeof(*m);
86+ *map->map_size = *map->desc_size * 32;
87+ *map->buff_size = *map->map_size;
7988 again:
80− /*
81− * Add an additional efi_memory_desc_t because we're doing an
82− * allocation which may be in a new descriptor region.
83− */
84− *map_size += sizeof(*m);
8589 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
86− *map_size, (void **)&m);
90+ *map->map_size, (void **)&m);
8791 if (status != EFI_SUCCESS)
8892 goto fail;
8993
90− *desc_size = 0;
94+ *map->desc_size = 0;
9195 key = 0;
92− status = efi_call_early(get_memory_map, map_size, m,
93− &key, desc_size, &desc_version);
94− if (status == EFI_BUFFER_TOO_SMALL) {
96+ status = efi_call_early(get_memory_map, map->map_size, m,
97+ &key, map->desc_size, &desc_version);
98+ if (status == EFI_BUFFER_TOO_SMALL ||
99+ !mmap_has_headroom(*map->buff_size, *map->map_size,
100+ *map->desc_size)) {
95101 efi_call_early(free_pool, m);
102+ /*
103+ * Make sure there is some entries of headroom so that the
104+ * buffer can be reused for a new map after allocations are
105+ * no longer permitted. Its unlikely that the map will grow to
106+ * exceed this headroom once we are ready to trigger
107+ * ExitBootServices()
108+ */
109+ *map->map_size += *map->desc_size * EFI_MMAP_NR_SLACK_SLOTS;
110+ *map->buff_size = *map->map_size;
96111 goto again;
97112 }
98113
99114 if (status != EFI_SUCCESS)
100115 efi_call_early(free_pool, m);
101116
102− if (key_ptr && status == EFI_SUCCESS)
103− *key_ptr = key;
104− if (desc_ver && status == EFI_SUCCESS)
105− *desc_ver = desc_version;
117+ if (map->key_ptr && status == EFI_SUCCESS)
118+ *map->key_ptr = key;
119+ if (map->desc_ver && status == EFI_SUCCESS)
120+ *map->desc_ver = desc_version;
106121
107122 fail:
108− *map = m;
123+ *map->map = m;
109124 return status;
110125 }
111126
@@ -113,13 +128,20 @@ fail: · 1 unmodified line
113128 unsigned long get_dram_base(efi_system_table_t *sys_table_arg)
114129 {
115130 efi_status_t status;
116− unsigned long map_size;
131+ unsigned long map_size, buff_size;
117132 unsigned long membase = EFI_ERROR;
118133 struct efi_memory_map map;
119134 efi_memory_desc_t *md;
135+ struct efi_boot_memmap boot_map;
120136
121− status = efi_get_memory_map(sys_table_arg, (efi_memory_desc_t **)&map.map,
122− &map_size, &map.desc_size, NULL, NULL);
137+ boot_map.map = (efi_memory_desc_t **)&map.map;
138+ boot_map.map_size = &map_size;
139+ boot_map.desc_size = &map.desc_size;
140+ boot_map.desc_ver = NULL;
141+ boot_map.key_ptr = NULL;
142+ boot_map.buff_size = &buff_size;
143+
144+ status = efi_get_memory_map(sys_table_arg, &boot_map);
123145 if (status != EFI_SUCCESS)
124146 return membase;
125147
@@ -144,15 +166,22 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, · 18 unmodified lines
144166 unsigned long size, unsigned long align,
145167 unsigned long *addr, unsigned long max)
146168 {
147− unsigned long map_size, desc_size;
169+ unsigned long map_size, desc_size, buff_size;
148170 efi_memory_desc_t *map;
149171 efi_status_t status;
150172 unsigned long nr_pages;
151173 u64 max_addr = 0;
152174 int i;
175+ struct efi_boot_memmap boot_map;
176+
177+ boot_map.map = ↦
178+ boot_map.map_size = &map_size;
179+ boot_map.desc_size = &desc_size;
180+ boot_map.desc_ver = NULL;
181+ boot_map.key_ptr = NULL;
182+ boot_map.buff_size = &buff_size;
153183
154− status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size,
155− NULL, NULL);
184+ status = efi_get_memory_map(sys_table_arg, &boot_map);
156185 if (status != EFI_SUCCESS)
157186 goto fail;
158187
@@ -230,14 +259,21 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, · 71 unmodified lines
230259 unsigned long size, unsigned long align,
231260 unsigned long *addr)
232261 {
233− unsigned long map_size, desc_size;
262+ unsigned long map_size, desc_size, buff_size;
234263 efi_memory_desc_t *map;
235264 efi_status_t status;
236265 unsigned long nr_pages;
237266 int i;
267+ struct efi_boot_memmap boot_map;
268+
269+ boot_map.map = ↦
270+ boot_map.map_size = &map_size;
271+ boot_map.desc_size = &desc_size;
272+ boot_map.desc_ver = NULL;
273+ boot_map.key_ptr = NULL;
274+ boot_map.buff_size = &buff_size;
238275
239− status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size,
240− NULL, NULL);
276+ status = efi_get_memory_map(sys_table_arg, &boot_map);
241277 if (status != EFI_SUCCESS)
242278 goto fail;
243279
drivers/firmware/efi/libstub/fdt.c+12−5
@@ -175,13 +175,21 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, · 174 unmodified lines
175175 unsigned long fdt_addr,
176176 unsigned long fdt_size)
177177 {
178− unsigned long map_size, desc_size;
178+ unsigned long map_size, desc_size, buff_size;
179179 u32 desc_ver;
180180 unsigned long mmap_key;
181181 efi_memory_desc_t *memory_map, *runtime_map;
182182 unsigned long new_fdt_size;
183183 efi_status_t status;
184184 int runtime_entry_count = 0;
185+ struct efi_boot_memmap map;
186+
187+ map.map = &runtime_map;
188+ map.map_size = &map_size;
189+ map.desc_size = &desc_size;
190+ map.desc_ver = &desc_ver;
191+ map.key_ptr = &mmap_key;
192+ map.buff_size = &buff_size;
185193
186194 /*
187195 * Get a copy of the current memory map that we will use to prepare
@@ -189,8 +197,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, · 1 unmodified line
189197 * subsequent allocations adding entries, since they could not affect
190198 * the number of EFI_MEMORY_RUNTIME regions.
191199 */
192− status = efi_get_memory_map(sys_table, &runtime_map, &map_size,
193− &desc_size, &desc_ver, &mmap_key);
200+ status = efi_get_memory_map(sys_table, &map);
194201 if (status != EFI_SUCCESS) {
195202 pr_efi_err(sys_table, "Unable to retrieve UEFI memory map.\n");
196203 return status;
@@ -199,6 +206,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, · 2 unmodified lines
199206 pr_efi(sys_table,
200207 "Exiting boot services and installing virtual address map...\n");
201208
209+ map.map = &memory_map;
202210 /*
203211 * Estimate size of new FDT, and allocate memory for it. We
204212 * will allocate a bigger buffer if this ends up being too
@@ -218,8 +226,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, · 13 unmodified lines
218226 * we can get the memory map key needed for
219227 * exit_boot_services().
220228 */
221− status = efi_get_memory_map(sys_table, &memory_map, &map_size,
222− &desc_size, &desc_ver, &mmap_key);
229+ status = efi_get_memory_map(sys_table, &map);
223230 if (status != EFI_SUCCESS)
224231 goto fail_free_new_fdt;
225232
drivers/firmware/efi/libstub/random.c+10−2
@@ -73,12 +73,20 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg, · 72 unmodified lines
7373 unsigned long random_seed)
7474 {
7575 unsigned long map_size, desc_size, total_slots = 0, target_slot;
76+ unsigned long buff_size;
7677 efi_status_t status;
7778 efi_memory_desc_t *memory_map;
7879 int map_offset;
80+ struct efi_boot_memmap map;
7981
80− status = efi_get_memory_map(sys_table_arg, &memory_map, &map_size,
81− &desc_size, NULL, NULL);
82+ map.map = &memory_map;
83+ map.map_size = &map_size;
84+ map.desc_size = &desc_size;
85+ map.desc_ver = NULL;
86+ map.key_ptr = NULL;
87+ map.buff_size = &buff_size;
88+
89+ status = efi_get_memory_map(sys_table_arg, &map);
8290 if (status != EFI_SUCCESS)
8391 return status;
8492
include/linux/efi.h+10−5
@@ -118,6 +118,15 @@ typedef struct { · 117 unmodified lines
118118 u32 imagesize;
119119 } efi_capsule_header_t;
120120
121+struct efi_boot_memmap {
122+ efi_memory_desc_t **map;
123+ unsigned long *map_size;
124+ unsigned long *desc_size;
125+ u32 *desc_ver;
126+ unsigned long *key_ptr;
127+ unsigned long *buff_size;
128+};
129+
121130 /*
122131 * EFI capsule flags
123132 */
@@ -1371,11 +1380,7 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, · 1247 unmodified lines
13711380 efi_loaded_image_t *image, int *cmd_line_len);
13721381
13731382 efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
1374− efi_memory_desc_t **map,
1375− unsigned long *map_size,
1376− unsigned long *desc_size,
1377− u32 *desc_ver,
1378− unsigned long *key_ptr);
1383+ struct efi_boot_memmap *map);
13791384
13801385 efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
13811386 unsigned long size, unsigned long align,