summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2014-09-24 11:56:10 +0100
committerMatt Fleming <matt.fleming@intel.com>2014-09-24 21:56:46 +0100
commit115c6628a59044958c205f8468a1b3ba3d539e61 (patch)
treef4b86b57a3a3de242ab58b8ddd20166fcb5e8a9b
parent56394ab8c26893bbaef02da04a06cc5ae71ccc5c (diff)
x86/efi: Truncate 64-bit values when calling 32-bit OutputString()
If we're executing the 32-bit efi_char16_printk() code path (i.e. running on top of 32-bit firmware) we know that efi_early->text_output will be a 32-bit value, even though ->text_output has type u64. Unfortunately, we currently pass ->text_output directly to efi_early->call() so for CONFIG_X86_32 the compiler will push a 64-bit value onto the stack, causing the other parameters to be misaligned. The way we handle this in the rest of the EFI boot stub is to pass pointers as arguments to efi_early->call(), which automatically do the right thing (pointers are 32-bit on CONFIG_X86_32, and we simply ignore the upper 32-bits of the argument register if running in 64-bit mode with 32-bit firmware). This fixes a corruption bug when printing strings from the 32-bit EFI boot stub. Link: https://bugzilla.kernel.org/show_bug.cgi?id=84241 Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r--arch/x86/boot/compressed/eboot.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index dc30c1732057..de8eebd6f67c 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -268,18 +268,20 @@ void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
offset = offsetof(typeof(*out), output_string);
output_string = efi_early->text_output + offset;
+ out = (typeof(out))(unsigned long)efi_early->text_output;
func = (u64 *)output_string;
- efi_early->call(*func, efi_early->text_output, str);
+ efi_early->call(*func, out, str);
} else {
struct efi_simple_text_output_protocol_32 *out;
u32 *func;
offset = offsetof(typeof(*out), output_string);
output_string = efi_early->text_output + offset;
+ out = (typeof(out))(unsigned long)efi_early->text_output;
func = (u32 *)output_string;
- efi_early->call(*func, efi_early->text_output, str);
+ efi_early->call(*func, out, str);
}
}