aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-04-11 04:25:28 -0400
committerIngo Molnar <mingo@kernel.org>2014-04-11 04:25:28 -0400
commit3151b942badd059431eff93833cc1e957195b53b (patch)
tree36aeeed4fecefcd60343dc05e5de512c497bdc68
parentf704a7d7f1d815621cb4c47f7a94787e1bd7c27c (diff)
parent47514c996fac5e6f13ef3a4c5e23f1c5cffabb7b (diff)
Merge tag 'efi-urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi into x86/urgent
Pull EFI fixes from Matt Fleming: "* Fix EFI boot regression introduced during the merge window where the firmware was reading random values from the stack because we were passing a pointer to the wrong object type. * Kernel corruption has been reported when booting with the EFI boot stub which was tracked down to setting a bogus value for bp->hdr.code32_start, resulting in corruption during relocation. * Olivier Martin reported that the wrong file handles were being passed to efi_file_(read|close), which works for x86 by luck due to the way that the FAT driver is implemented, but doesn't work on ARM." Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/boot/compressed/eboot.c19
-rw-r--r--arch/x86/boot/compressed/head_32.S8
-rw-r--r--arch/x86/boot/compressed/head_64.S9
-rw-r--r--drivers/firmware/efi/efi-stub-helper.c6
4 files changed, 18 insertions, 24 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 1e6146137f8e..4703a6c4b8e3 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -112,7 +112,7 @@ __file_size64(void *__fh, efi_char16_t *filename_16,
112 efi_file_info_t *info; 112 efi_file_info_t *info;
113 efi_status_t status; 113 efi_status_t status;
114 efi_guid_t info_guid = EFI_FILE_INFO_ID; 114 efi_guid_t info_guid = EFI_FILE_INFO_ID;
115 u32 info_sz; 115 u64 info_sz;
116 116
117 status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16, 117 status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16,
118 EFI_FILE_MODE_READ, (u64)0); 118 EFI_FILE_MODE_READ, (u64)0);
@@ -167,31 +167,31 @@ efi_file_size(efi_system_table_t *sys_table, void *__fh,
167} 167}
168 168
169static inline efi_status_t 169static inline efi_status_t
170efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr) 170efi_file_read(void *handle, unsigned long *size, void *addr)
171{ 171{
172 unsigned long func; 172 unsigned long func;
173 173
174 if (efi_early->is64) { 174 if (efi_early->is64) {
175 efi_file_handle_64_t *fh = __fh; 175 efi_file_handle_64_t *fh = handle;
176 176
177 func = (unsigned long)fh->read; 177 func = (unsigned long)fh->read;
178 return efi_early->call(func, handle, size, addr); 178 return efi_early->call(func, handle, size, addr);
179 } else { 179 } else {
180 efi_file_handle_32_t *fh = __fh; 180 efi_file_handle_32_t *fh = handle;
181 181
182 func = (unsigned long)fh->read; 182 func = (unsigned long)fh->read;
183 return efi_early->call(func, handle, size, addr); 183 return efi_early->call(func, handle, size, addr);
184 } 184 }
185} 185}
186 186
187static inline efi_status_t efi_file_close(void *__fh, void *handle) 187static inline efi_status_t efi_file_close(void *handle)
188{ 188{
189 if (efi_early->is64) { 189 if (efi_early->is64) {
190 efi_file_handle_64_t *fh = __fh; 190 efi_file_handle_64_t *fh = handle;
191 191
192 return efi_early->call((unsigned long)fh->close, handle); 192 return efi_early->call((unsigned long)fh->close, handle);
193 } else { 193 } else {
194 efi_file_handle_32_t *fh = __fh; 194 efi_file_handle_32_t *fh = handle;
195 195
196 return efi_early->call((unsigned long)fh->close, handle); 196 return efi_early->call((unsigned long)fh->close, handle);
197 } 197 }
@@ -1016,6 +1016,9 @@ void setup_graphics(struct boot_params *boot_params)
1016 * Because the x86 boot code expects to be passed a boot_params we 1016 * Because the x86 boot code expects to be passed a boot_params we
1017 * need to create one ourselves (usually the bootloader would create 1017 * need to create one ourselves (usually the bootloader would create
1018 * one for us). 1018 * one for us).
1019 *
1020 * The caller is responsible for filling out ->code32_start in the
1021 * returned boot_params.
1019 */ 1022 */
1020struct boot_params *make_boot_params(struct efi_config *c) 1023struct boot_params *make_boot_params(struct efi_config *c)
1021{ 1024{
@@ -1081,8 +1084,6 @@ struct boot_params *make_boot_params(struct efi_config *c)
1081 hdr->vid_mode = 0xffff; 1084 hdr->vid_mode = 0xffff;
1082 hdr->boot_flag = 0xAA55; 1085 hdr->boot_flag = 0xAA55;
1083 1086
1084 hdr->code32_start = (__u64)(unsigned long)image->image_base;
1085
1086 hdr->type_of_loader = 0x21; 1087 hdr->type_of_loader = 0x21;
1087 1088
1088 /* Convert unicode cmdline to ascii */ 1089 /* Convert unicode cmdline to ascii */
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index de9d4200d305..cbed1407a5cd 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -59,6 +59,7 @@ ENTRY(efi_pe_entry)
59 call make_boot_params 59 call make_boot_params
60 cmpl $0, %eax 60 cmpl $0, %eax
61 je fail 61 je fail
62 movl %esi, BP_code32_start(%eax)
62 popl %ecx 63 popl %ecx
63 pushl %eax 64 pushl %eax
64 pushl %ecx 65 pushl %ecx
@@ -90,12 +91,7 @@ fail:
90 hlt 91 hlt
91 jmp fail 92 jmp fail
922: 932:
93 call 3f 94 movl BP_code32_start(%esi), %eax
943:
95 popl %eax
96 subl $3b, %eax
97 subl BP_pref_address(%esi), %eax
98 add BP_code32_start(%esi), %eax
99 leal preferred_addr(%eax), %eax 95 leal preferred_addr(%eax), %eax
100 jmp *%eax 96 jmp *%eax
101 97
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 57e58a5fa210..0d558ee899ae 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -261,6 +261,8 @@ ENTRY(efi_pe_entry)
261 cmpq $0,%rax 261 cmpq $0,%rax
262 je fail 262 je fail
263 mov %rax, %rsi 263 mov %rax, %rsi
264 leaq startup_32(%rip), %rax
265 movl %eax, BP_code32_start(%rsi)
264 jmp 2f /* Skip the relocation */ 266 jmp 2f /* Skip the relocation */
265 267
266handover_entry: 268handover_entry:
@@ -284,12 +286,7 @@ fail:
284 hlt 286 hlt
285 jmp fail 287 jmp fail
2862: 2882:
287 call 3f 289 movl BP_code32_start(%esi), %eax
2883:
289 popq %rax
290 subq $3b, %rax
291 subq BP_pref_address(%rsi), %rax
292 add BP_code32_start(%esi), %eax
293 leaq preferred_addr(%rax), %rax 290 leaq preferred_addr(%rax), %rax
294 jmp *%rax 291 jmp *%rax
295 292
diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c
index ff50aeebf0d9..2c41eaece2c1 100644
--- a/drivers/firmware/efi/efi-stub-helper.c
+++ b/drivers/firmware/efi/efi-stub-helper.c
@@ -397,7 +397,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
397 else 397 else
398 chunksize = size; 398 chunksize = size;
399 399
400 status = efi_file_read(fh, files[j].handle, 400 status = efi_file_read(files[j].handle,
401 &chunksize, 401 &chunksize,
402 (void *)addr); 402 (void *)addr);
403 if (status != EFI_SUCCESS) { 403 if (status != EFI_SUCCESS) {
@@ -408,7 +408,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
408 size -= chunksize; 408 size -= chunksize;
409 } 409 }
410 410
411 efi_file_close(fh, files[j].handle); 411 efi_file_close(files[j].handle);
412 } 412 }
413 413
414 } 414 }
@@ -425,7 +425,7 @@ free_file_total:
425 425
426close_handles: 426close_handles:
427 for (k = j; k < i; k++) 427 for (k = j; k < i; k++)
428 efi_file_close(fh, files[k].handle); 428 efi_file_close(files[k].handle);
429free_files: 429free_files:
430 efi_call_early(free_pool, files); 430 efi_call_early(free_pool, files);
431fail: 431fail: