mirror of https://gitee.com/openkylin/linux.git
* 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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJTR5QIAAoJEC84WcCNIz1VMn0P/01GF8A2frSK+NuCJCkmZoAa fcOvcHmQajNwG3WAVsVWlS/i2QsYwK1jAgameEusn+FFrnWIwaZ9qb1TjEMbJylu 4odaRc1YYiLOJi9UD2jRB644374jJwgwteKGs0Vt99g4pa8HsgSbXTR6oF8PUDWr 1HZUV9tq8O1eAzpQdMADEgWYieylnldfvHk+ArPTJyR5fTNx8xCYALlCthc6Tv+A cpi0rQj/YzNh+vqZF1YYZ8xqktvV1di2Hvmy3UVt05y1kwkaTquNY9478ZRF5UHm oUk3nAYyA9M/1gxVnvUfyLgUtrWtyF02N+iDTxLoz05KxeK5wVdKaIPZfSAUrglt hOvnL+5EOss6w9gG19zpPD4FVHCd696W+iCIBoqooWJqX8AqOVRr81GTYb3q3YDr EIH0wLipuV4XI4sdN8JMH9fIbfkRdAvaGUR2lPSYFq2Cm7nn2hs820UdKFYeH0wT fdgtGpWAdXhEq/SUW4KRZMCXLDz4XuNF3d/JREcC28CyiRgdjKFD/PMbZEShpisF fYE16+IiAq8UMgfgUDqlrSP2UMqkyZ2kp5itvJBrLbTD6rWzEcpK+CMXqykWTOwV ONzPAfZEbUmFuU3JhKOTFO5uf7dM9EG5BDKduWR6Wjl8VIVTQlD8R1OB5o1lbZPN ecFWo1eIQGZjeoMm36EM =rovT -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
3151b942ba
|
@ -112,7 +112,7 @@ __file_size64(void *__fh, efi_char16_t *filename_16,
|
||||||
efi_file_info_t *info;
|
efi_file_info_t *info;
|
||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
efi_guid_t info_guid = EFI_FILE_INFO_ID;
|
efi_guid_t info_guid = EFI_FILE_INFO_ID;
|
||||||
u32 info_sz;
|
u64 info_sz;
|
||||||
|
|
||||||
status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16,
|
status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16,
|
||||||
EFI_FILE_MODE_READ, (u64)0);
|
EFI_FILE_MODE_READ, (u64)0);
|
||||||
|
@ -167,31 +167,31 @@ efi_file_size(efi_system_table_t *sys_table, void *__fh,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline efi_status_t
|
static inline efi_status_t
|
||||||
efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
|
efi_file_read(void *handle, unsigned long *size, void *addr)
|
||||||
{
|
{
|
||||||
unsigned long func;
|
unsigned long func;
|
||||||
|
|
||||||
if (efi_early->is64) {
|
if (efi_early->is64) {
|
||||||
efi_file_handle_64_t *fh = __fh;
|
efi_file_handle_64_t *fh = handle;
|
||||||
|
|
||||||
func = (unsigned long)fh->read;
|
func = (unsigned long)fh->read;
|
||||||
return efi_early->call(func, handle, size, addr);
|
return efi_early->call(func, handle, size, addr);
|
||||||
} else {
|
} else {
|
||||||
efi_file_handle_32_t *fh = __fh;
|
efi_file_handle_32_t *fh = handle;
|
||||||
|
|
||||||
func = (unsigned long)fh->read;
|
func = (unsigned long)fh->read;
|
||||||
return efi_early->call(func, handle, size, addr);
|
return efi_early->call(func, handle, size, addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline efi_status_t efi_file_close(void *__fh, void *handle)
|
static inline efi_status_t efi_file_close(void *handle)
|
||||||
{
|
{
|
||||||
if (efi_early->is64) {
|
if (efi_early->is64) {
|
||||||
efi_file_handle_64_t *fh = __fh;
|
efi_file_handle_64_t *fh = handle;
|
||||||
|
|
||||||
return efi_early->call((unsigned long)fh->close, handle);
|
return efi_early->call((unsigned long)fh->close, handle);
|
||||||
} else {
|
} else {
|
||||||
efi_file_handle_32_t *fh = __fh;
|
efi_file_handle_32_t *fh = handle;
|
||||||
|
|
||||||
return efi_early->call((unsigned long)fh->close, handle);
|
return efi_early->call((unsigned long)fh->close, handle);
|
||||||
}
|
}
|
||||||
|
@ -1016,6 +1016,9 @@ void setup_graphics(struct boot_params *boot_params)
|
||||||
* Because the x86 boot code expects to be passed a boot_params we
|
* Because the x86 boot code expects to be passed a boot_params we
|
||||||
* need to create one ourselves (usually the bootloader would create
|
* need to create one ourselves (usually the bootloader would create
|
||||||
* one for us).
|
* one for us).
|
||||||
|
*
|
||||||
|
* The caller is responsible for filling out ->code32_start in the
|
||||||
|
* returned boot_params.
|
||||||
*/
|
*/
|
||||||
struct boot_params *make_boot_params(struct efi_config *c)
|
struct boot_params *make_boot_params(struct efi_config *c)
|
||||||
{
|
{
|
||||||
|
@ -1081,8 +1084,6 @@ struct boot_params *make_boot_params(struct efi_config *c)
|
||||||
hdr->vid_mode = 0xffff;
|
hdr->vid_mode = 0xffff;
|
||||||
hdr->boot_flag = 0xAA55;
|
hdr->boot_flag = 0xAA55;
|
||||||
|
|
||||||
hdr->code32_start = (__u64)(unsigned long)image->image_base;
|
|
||||||
|
|
||||||
hdr->type_of_loader = 0x21;
|
hdr->type_of_loader = 0x21;
|
||||||
|
|
||||||
/* Convert unicode cmdline to ascii */
|
/* Convert unicode cmdline to ascii */
|
||||||
|
|
|
@ -59,6 +59,7 @@ ENTRY(efi_pe_entry)
|
||||||
call make_boot_params
|
call make_boot_params
|
||||||
cmpl $0, %eax
|
cmpl $0, %eax
|
||||||
je fail
|
je fail
|
||||||
|
movl %esi, BP_code32_start(%eax)
|
||||||
popl %ecx
|
popl %ecx
|
||||||
pushl %eax
|
pushl %eax
|
||||||
pushl %ecx
|
pushl %ecx
|
||||||
|
@ -90,12 +91,7 @@ fail:
|
||||||
hlt
|
hlt
|
||||||
jmp fail
|
jmp fail
|
||||||
2:
|
2:
|
||||||
call 3f
|
movl BP_code32_start(%esi), %eax
|
||||||
3:
|
|
||||||
popl %eax
|
|
||||||
subl $3b, %eax
|
|
||||||
subl BP_pref_address(%esi), %eax
|
|
||||||
add BP_code32_start(%esi), %eax
|
|
||||||
leal preferred_addr(%eax), %eax
|
leal preferred_addr(%eax), %eax
|
||||||
jmp *%eax
|
jmp *%eax
|
||||||
|
|
||||||
|
|
|
@ -261,6 +261,8 @@ ENTRY(efi_pe_entry)
|
||||||
cmpq $0,%rax
|
cmpq $0,%rax
|
||||||
je fail
|
je fail
|
||||||
mov %rax, %rsi
|
mov %rax, %rsi
|
||||||
|
leaq startup_32(%rip), %rax
|
||||||
|
movl %eax, BP_code32_start(%rsi)
|
||||||
jmp 2f /* Skip the relocation */
|
jmp 2f /* Skip the relocation */
|
||||||
|
|
||||||
handover_entry:
|
handover_entry:
|
||||||
|
@ -284,12 +286,7 @@ fail:
|
||||||
hlt
|
hlt
|
||||||
jmp fail
|
jmp fail
|
||||||
2:
|
2:
|
||||||
call 3f
|
movl BP_code32_start(%esi), %eax
|
||||||
3:
|
|
||||||
popq %rax
|
|
||||||
subq $3b, %rax
|
|
||||||
subq BP_pref_address(%rsi), %rax
|
|
||||||
add BP_code32_start(%esi), %eax
|
|
||||||
leaq preferred_addr(%rax), %rax
|
leaq preferred_addr(%rax), %rax
|
||||||
jmp *%rax
|
jmp *%rax
|
||||||
|
|
||||||
|
|
|
@ -397,7 +397,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
|
||||||
else
|
else
|
||||||
chunksize = size;
|
chunksize = size;
|
||||||
|
|
||||||
status = efi_file_read(fh, files[j].handle,
|
status = efi_file_read(files[j].handle,
|
||||||
&chunksize,
|
&chunksize,
|
||||||
(void *)addr);
|
(void *)addr);
|
||||||
if (status != EFI_SUCCESS) {
|
if (status != EFI_SUCCESS) {
|
||||||
|
@ -408,7 +408,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
|
||||||
size -= chunksize;
|
size -= chunksize;
|
||||||
}
|
}
|
||||||
|
|
||||||
efi_file_close(fh, files[j].handle);
|
efi_file_close(files[j].handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -425,7 +425,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
|
||||||
|
|
||||||
close_handles:
|
close_handles:
|
||||||
for (k = j; k < i; k++)
|
for (k = j; k < i; k++)
|
||||||
efi_file_close(fh, files[k].handle);
|
efi_file_close(files[k].handle);
|
||||||
free_files:
|
free_files:
|
||||||
efi_call_early(free_pool, files);
|
efi_call_early(free_pool, files);
|
||||||
fail:
|
fail:
|
||||||
|
|
Loading…
Reference in New Issue