aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-09-13 15:02:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-09-13 15:02:00 -0400
commit7c2c1144164c0a6fd91642909042862db907e053 (patch)
treefda8ad6fd5f087d71c1ecedb83ac479665368093 /drivers/firmware
parent106f2e59ee3b89a2f93735f65499eae4e8d55abc (diff)
parentcbf2f8a99a2337894c3592c9ac2170e8c1f8f73f (diff)
Merge branch 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI fixes from Ingo Molnar: "This contains a Xen fix, an arm64 fix and a race condition / robustization set of fixes related to ExitBootServices() usage and boundary conditions" * 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/efi: Use efi_exit_boot_services() efi/libstub: Use efi_exit_boot_services() in FDT efi/libstub: Introduce ExitBootServices helper efi/libstub: Allocate headspace in efi_get_memory_map() efi: Fix handling error value in fdt_find_uefi_params efi: Make for_each_efi_memory_desc_in_map() cope with running on Xen
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/efi/efi.c7
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c169
-rw-r--r--drivers/firmware/efi/libstub/fdt.c54
-rw-r--r--drivers/firmware/efi/libstub/random.c12
4 files changed, 193 insertions, 49 deletions
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 5a2631af7410..7dd2e2d37231 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -657,9 +657,12 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
657 } 657 }
658 658
659 if (subnode) { 659 if (subnode) {
660 node = of_get_flat_dt_subnode_by_name(node, subnode); 660 int err = of_get_flat_dt_subnode_by_name(node, subnode);
661 if (node < 0) 661
662 if (err < 0)
662 return 0; 663 return 0;
664
665 node = err;
663 } 666 }
664 667
665 return __find_uefi_params(node, info, dt_params[i].params); 668 return __find_uefi_params(node, info, dt_params[i].params);
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 3bd127f95315..aded10662020 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -41,6 +41,8 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
41#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE 41#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
42#endif 42#endif
43 43
44#define EFI_MMAP_NR_SLACK_SLOTS 8
45
44struct file_info { 46struct file_info {
45 efi_file_handle_t *handle; 47 efi_file_handle_t *handle;
46 u64 size; 48 u64 size;
@@ -63,49 +65,62 @@ void efi_printk(efi_system_table_t *sys_table_arg, char *str)
63 } 65 }
64} 66}
65 67
68static 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
66efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg, 77efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
67 efi_memory_desc_t **map, 78 struct efi_boot_memmap *map)
68 unsigned long *map_size,
69 unsigned long *desc_size,
70 u32 *desc_ver,
71 unsigned long *key_ptr)
72{ 79{
73 efi_memory_desc_t *m = NULL; 80 efi_memory_desc_t *m = NULL;
74 efi_status_t status; 81 efi_status_t status;
75 unsigned long key; 82 unsigned long key;
76 u32 desc_version; 83 u32 desc_version;
77 84
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;
79again: 88again:
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);
85 status = efi_call_early(allocate_pool, EFI_LOADER_DATA, 89 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
86 *map_size, (void **)&m); 90 *map->map_size, (void **)&m);
87 if (status != EFI_SUCCESS) 91 if (status != EFI_SUCCESS)
88 goto fail; 92 goto fail;
89 93
90 *desc_size = 0; 94 *map->desc_size = 0;
91 key = 0; 95 key = 0;
92 status = efi_call_early(get_memory_map, map_size, m, 96 status = efi_call_early(get_memory_map, map->map_size, m,
93 &key, desc_size, &desc_version); 97 &key, map->desc_size, &desc_version);
94 if (status == EFI_BUFFER_TOO_SMALL) { 98 if (status == EFI_BUFFER_TOO_SMALL ||
99 !mmap_has_headroom(*map->buff_size, *map->map_size,
100 *map->desc_size)) {
95 efi_call_early(free_pool, m); 101 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;
96 goto again; 111 goto again;
97 } 112 }
98 113
99 if (status != EFI_SUCCESS) 114 if (status != EFI_SUCCESS)
100 efi_call_early(free_pool, m); 115 efi_call_early(free_pool, m);
101 116
102 if (key_ptr && status == EFI_SUCCESS) 117 if (map->key_ptr && status == EFI_SUCCESS)
103 *key_ptr = key; 118 *map->key_ptr = key;
104 if (desc_ver && status == EFI_SUCCESS) 119 if (map->desc_ver && status == EFI_SUCCESS)
105 *desc_ver = desc_version; 120 *map->desc_ver = desc_version;
106 121
107fail: 122fail:
108 *map = m; 123 *map->map = m;
109 return status; 124 return status;
110} 125}
111 126
@@ -113,13 +128,20 @@ fail:
113unsigned long get_dram_base(efi_system_table_t *sys_table_arg) 128unsigned long get_dram_base(efi_system_table_t *sys_table_arg)
114{ 129{
115 efi_status_t status; 130 efi_status_t status;
116 unsigned long map_size; 131 unsigned long map_size, buff_size;
117 unsigned long membase = EFI_ERROR; 132 unsigned long membase = EFI_ERROR;
118 struct efi_memory_map map; 133 struct efi_memory_map map;
119 efi_memory_desc_t *md; 134 efi_memory_desc_t *md;
135 struct efi_boot_memmap boot_map;
120 136
121 status = efi_get_memory_map(sys_table_arg, (efi_memory_desc_t **)&map.map, 137 boot_map.map = (efi_memory_desc_t **)&map.map;
122 &map_size, &map.desc_size, NULL, NULL); 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);
123 if (status != EFI_SUCCESS) 145 if (status != EFI_SUCCESS)
124 return membase; 146 return membase;
125 147
@@ -144,15 +166,22 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
144 unsigned long size, unsigned long align, 166 unsigned long size, unsigned long align,
145 unsigned long *addr, unsigned long max) 167 unsigned long *addr, unsigned long max)
146{ 168{
147 unsigned long map_size, desc_size; 169 unsigned long map_size, desc_size, buff_size;
148 efi_memory_desc_t *map; 170 efi_memory_desc_t *map;
149 efi_status_t status; 171 efi_status_t status;
150 unsigned long nr_pages; 172 unsigned long nr_pages;
151 u64 max_addr = 0; 173 u64 max_addr = 0;
152 int i; 174 int i;
175 struct efi_boot_memmap boot_map;
176
177 boot_map.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;
153 183
154 status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size, 184 status = efi_get_memory_map(sys_table_arg, &boot_map);
155 NULL, NULL);
156 if (status != EFI_SUCCESS) 185 if (status != EFI_SUCCESS)
157 goto fail; 186 goto fail;
158 187
@@ -230,14 +259,21 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
230 unsigned long size, unsigned long align, 259 unsigned long size, unsigned long align,
231 unsigned long *addr) 260 unsigned long *addr)
232{ 261{
233 unsigned long map_size, desc_size; 262 unsigned long map_size, desc_size, buff_size;
234 efi_memory_desc_t *map; 263 efi_memory_desc_t *map;
235 efi_status_t status; 264 efi_status_t status;
236 unsigned long nr_pages; 265 unsigned long nr_pages;
237 int i; 266 int i;
267 struct efi_boot_memmap boot_map;
238 268
239 status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size, 269 boot_map.map = &map;
240 NULL, NULL); 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;
275
276 status = efi_get_memory_map(sys_table_arg, &boot_map);
241 if (status != EFI_SUCCESS) 277 if (status != EFI_SUCCESS)
242 goto fail; 278 goto fail;
243 279
@@ -704,3 +740,76 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
704 *cmd_line_len = options_bytes; 740 *cmd_line_len = options_bytes;
705 return (char *)cmdline_addr; 741 return (char *)cmdline_addr;
706} 742}
743
744/*
745 * Handle calling ExitBootServices according to the requirements set out by the
746 * spec. Obtains the current memory map, and returns that info after calling
747 * ExitBootServices. The client must specify a function to perform any
748 * processing of the memory map data prior to ExitBootServices. A client
749 * specific structure may be passed to the function via priv. The client
750 * function may be called multiple times.
751 */
752efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table_arg,
753 void *handle,
754 struct efi_boot_memmap *map,
755 void *priv,
756 efi_exit_boot_map_processing priv_func)
757{
758 efi_status_t status;
759
760 status = efi_get_memory_map(sys_table_arg, map);
761
762 if (status != EFI_SUCCESS)
763 goto fail;
764
765 status = priv_func(sys_table_arg, map, priv);
766 if (status != EFI_SUCCESS)
767 goto free_map;
768
769 status = efi_call_early(exit_boot_services, handle, *map->key_ptr);
770
771 if (status == EFI_INVALID_PARAMETER) {
772 /*
773 * The memory map changed between efi_get_memory_map() and
774 * exit_boot_services(). Per the UEFI Spec v2.6, Section 6.4:
775 * EFI_BOOT_SERVICES.ExitBootServices we need to get the
776 * updated map, and try again. The spec implies one retry
777 * should be sufficent, which is confirmed against the EDK2
778 * implementation. Per the spec, we can only invoke
779 * get_memory_map() and exit_boot_services() - we cannot alloc
780 * so efi_get_memory_map() cannot be used, and we must reuse
781 * the buffer. For all practical purposes, the headroom in the
782 * buffer should account for any changes in the map so the call
783 * to get_memory_map() is expected to succeed here.
784 */
785 *map->map_size = *map->buff_size;
786 status = efi_call_early(get_memory_map,
787 map->map_size,
788 *map->map,
789 map->key_ptr,
790 map->desc_size,
791 map->desc_ver);
792
793 /* exit_boot_services() was called, thus cannot free */
794 if (status != EFI_SUCCESS)
795 goto fail;
796
797 status = priv_func(sys_table_arg, map, priv);
798 /* exit_boot_services() was called, thus cannot free */
799 if (status != EFI_SUCCESS)
800 goto fail;
801
802 status = efi_call_early(exit_boot_services, handle, *map->key_ptr);
803 }
804
805 /* exit_boot_services() was called, thus cannot free */
806 if (status != EFI_SUCCESS)
807 goto fail;
808
809 return EFI_SUCCESS;
810
811free_map:
812 efi_call_early(free_pool, *map->map);
813fail:
814 return status;
815}
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index e58abfa953cc..a6a93116a8f0 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -152,6 +152,27 @@ fdt_set_fail:
152#define EFI_FDT_ALIGN EFI_PAGE_SIZE 152#define EFI_FDT_ALIGN EFI_PAGE_SIZE
153#endif 153#endif
154 154
155struct exit_boot_struct {
156 efi_memory_desc_t *runtime_map;
157 int *runtime_entry_count;
158};
159
160static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
161 struct efi_boot_memmap *map,
162 void *priv)
163{
164 struct exit_boot_struct *p = priv;
165 /*
166 * Update the memory map with virtual addresses. The function will also
167 * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
168 * entries so that we can pass it straight to SetVirtualAddressMap()
169 */
170 efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
171 p->runtime_map, p->runtime_entry_count);
172
173 return EFI_SUCCESS;
174}
175
155/* 176/*
156 * Allocate memory for a new FDT, then add EFI, commandline, and 177 * Allocate memory for a new FDT, then add EFI, commandline, and
157 * initrd related fields to the FDT. This routine increases the 178 * initrd related fields to the FDT. This routine increases the
@@ -175,13 +196,22 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
175 unsigned long fdt_addr, 196 unsigned long fdt_addr,
176 unsigned long fdt_size) 197 unsigned long fdt_size)
177{ 198{
178 unsigned long map_size, desc_size; 199 unsigned long map_size, desc_size, buff_size;
179 u32 desc_ver; 200 u32 desc_ver;
180 unsigned long mmap_key; 201 unsigned long mmap_key;
181 efi_memory_desc_t *memory_map, *runtime_map; 202 efi_memory_desc_t *memory_map, *runtime_map;
182 unsigned long new_fdt_size; 203 unsigned long new_fdt_size;
183 efi_status_t status; 204 efi_status_t status;
184 int runtime_entry_count = 0; 205 int runtime_entry_count = 0;
206 struct efi_boot_memmap map;
207 struct exit_boot_struct priv;
208
209 map.map = &runtime_map;
210 map.map_size = &map_size;
211 map.desc_size = &desc_size;
212 map.desc_ver = &desc_ver;
213 map.key_ptr = &mmap_key;
214 map.buff_size = &buff_size;
185 215
186 /* 216 /*
187 * Get a copy of the current memory map that we will use to prepare 217 * Get a copy of the current memory map that we will use to prepare
@@ -189,8 +219,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
189 * subsequent allocations adding entries, since they could not affect 219 * subsequent allocations adding entries, since they could not affect
190 * the number of EFI_MEMORY_RUNTIME regions. 220 * the number of EFI_MEMORY_RUNTIME regions.
191 */ 221 */
192 status = efi_get_memory_map(sys_table, &runtime_map, &map_size, 222 status = efi_get_memory_map(sys_table, &map);
193 &desc_size, &desc_ver, &mmap_key);
194 if (status != EFI_SUCCESS) { 223 if (status != EFI_SUCCESS) {
195 pr_efi_err(sys_table, "Unable to retrieve UEFI memory map.\n"); 224 pr_efi_err(sys_table, "Unable to retrieve UEFI memory map.\n");
196 return status; 225 return status;
@@ -199,6 +228,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
199 pr_efi(sys_table, 228 pr_efi(sys_table,
200 "Exiting boot services and installing virtual address map...\n"); 229 "Exiting boot services and installing virtual address map...\n");
201 230
231 map.map = &memory_map;
202 /* 232 /*
203 * Estimate size of new FDT, and allocate memory for it. We 233 * Estimate size of new FDT, and allocate memory for it. We
204 * will allocate a bigger buffer if this ends up being too 234 * will allocate a bigger buffer if this ends up being too
@@ -218,8 +248,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
218 * we can get the memory map key needed for 248 * we can get the memory map key needed for
219 * exit_boot_services(). 249 * exit_boot_services().
220 */ 250 */
221 status = efi_get_memory_map(sys_table, &memory_map, &map_size, 251 status = efi_get_memory_map(sys_table, &map);
222 &desc_size, &desc_ver, &mmap_key);
223 if (status != EFI_SUCCESS) 252 if (status != EFI_SUCCESS)
224 goto fail_free_new_fdt; 253 goto fail_free_new_fdt;
225 254
@@ -250,16 +279,11 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
250 } 279 }
251 } 280 }
252 281
253 /* 282 sys_table->boottime->free_pool(memory_map);
254 * Update the memory map with virtual addresses. The function will also 283 priv.runtime_map = runtime_map;
255 * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME 284 priv.runtime_entry_count = &runtime_entry_count;
256 * entries so that we can pass it straight into SetVirtualAddressMap() 285 status = efi_exit_boot_services(sys_table, handle, &map, &priv,
257 */ 286 exit_boot_func);
258 efi_get_virtmap(memory_map, map_size, desc_size, runtime_map,
259 &runtime_entry_count);
260
261 /* Now we are ready to exit_boot_services.*/
262 status = sys_table->boottime->exit_boot_services(handle, mmap_key);
263 287
264 if (status == EFI_SUCCESS) { 288 if (status == EFI_SUCCESS) {
265 efi_set_virtual_address_map_t *svam; 289 efi_set_virtual_address_map_t *svam;
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 53f6d3fe6d86..0c9f58c5ba50 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -73,12 +73,20 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
73 unsigned long random_seed) 73 unsigned long random_seed)
74{ 74{
75 unsigned long map_size, desc_size, total_slots = 0, target_slot; 75 unsigned long map_size, desc_size, total_slots = 0, target_slot;
76 unsigned long buff_size;
76 efi_status_t status; 77 efi_status_t status;
77 efi_memory_desc_t *memory_map; 78 efi_memory_desc_t *memory_map;
78 int map_offset; 79 int map_offset;
80 struct efi_boot_memmap map;
79 81
80 status = efi_get_memory_map(sys_table_arg, &memory_map, &map_size, 82 map.map = &memory_map;
81 &desc_size, NULL, NULL); 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);
82 if (status != EFI_SUCCESS) 90 if (status != EFI_SUCCESS)
83 return status; 91 return status;
84 92