diff options
author | Nigel Croxon <nigel.croxon@hp.com> | 2013-06-12 09:38:10 -0400 |
---|---|---|
committer | Nigel Croxon <nigel.croxon@hp.com> | 2013-06-12 09:38:10 -0400 |
commit | c0b8d974a6cb6ad6e562ebb972ae32d21671e605 (patch) | |
tree | 3c7b7959306962c311bee534852ef19b2e2df3bd /gnu-efi-3.0/inc/x86_64 | |
parent | 0ca0dacb59d71d9078604df290ea285f460b61fc (diff) | |
download | gnu-efi-3.0-c0b8d974a6cb6ad6e562ebb972ae32d21671e605.tar.gz gnu-efi-3.0-c0b8d974a6cb6ad6e562ebb972ae32d21671e605.tar.xz gnu-efi-3.0-c0b8d974a6cb6ad6e562ebb972ae32d21671e605.zip |
fix parameter-passing corruption on x86_64 for >= 5 args
On x86_64 without HAVE_USE_MS_ABI support, uefi_call_wrapper() is a
variadic function. Parameters >=5 are copied to the stack and, when
passed small immediate values (and possibly other parameters), gcc
would emit a movl instruction before calling uefi_call_wrapper(). As a
result, only the lower 32b of these stack values are significant, the
upper 32b potentially contain garbage. Considering that
uefi_call_wrapper() assumes these arguments are clean 64b values
before calling the efi_callX() trampolines, the latter may be passed
garbage. This makes calling functions like
EFI_PCI_IO_PROTOCOL.Mem.Read()/Write() or BS->OpenProtocol() quite
unreliable.
This patch fixes this by turning uefi_call_wrapper() into a macro that
allows to expose the efi_callX() trampoline signatures to the callers,
so that gcc can know upfront that it has to pass all arguments to
efi_callX() as clean 64b values (eg. movq for immediates). The
_cast64_efi_callX macros are just here to avoid a gcc warning, they do
nothing otherwise.
Signed-off-by: David Decotigny <decot@googlers.com>
Diffstat (limited to 'gnu-efi-3.0/inc/x86_64')
-rw-r--r-- | gnu-efi-3.0/inc/x86_64/efibind.h | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/gnu-efi-3.0/inc/x86_64/efibind.h b/gnu-efi-3.0/inc/x86_64/efibind.h index ee620f2..d322b6c 100644 --- a/gnu-efi-3.0/inc/x86_64/efibind.h +++ b/gnu-efi-3.0/inc/x86_64/efibind.h @@ -290,7 +290,64 @@ typedef uint64_t UINTN; #if defined(HAVE_USE_MS_ABI) #define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) #else -UINTN uefi_call_wrapper(void *func, unsigned long va_num, ...); +/* Prototypes of EFI cdecl -> stdcall trampolines */ +UINT64 efi_call0(void *func); +UINT64 efi_call1(void *func, UINT64 arg1); +UINT64 efi_call2(void *func, UINT64 arg1, UINT64 arg2); +UINT64 efi_call3(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3); +UINT64 efi_call4(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4); +UINT64 efi_call5(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5); +UINT64 efi_call6(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6); +UINT64 efi_call7(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7); +UINT64 efi_call8(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8); +UINT64 efi_call9(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8, UINT64 arg9); +UINT64 efi_call10(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8, UINT64 arg9, UINT64 arg10); + +/* Front-ends to efi_callX to avoid compiler warnings */ +#define _cast64_efi_call0(f) \ + efi_call0(f) +#define _cast64_efi_call1(f,a1) \ + efi_call1(f, (UINT64)(a1)) +#define _cast64_efi_call2(f,a1,a2) \ + efi_call2(f, (UINT64)(a1), (UINT64)(a2)) +#define _cast64_efi_call3(f,a1,a2,a3) \ + efi_call3(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3)) +#define _cast64_efi_call4(f,a1,a2,a3,a4) \ + efi_call4(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4)) +#define _cast64_efi_call5(f,a1,a2,a3,a4,a5) \ + efi_call5(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5)) +#define _cast64_efi_call6(f,a1,a2,a3,a4,a5,a6) \ + efi_call6(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6)) +#define _cast64_efi_call7(f,a1,a2,a3,a4,a5,a6,a7) \ + efi_call7(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7)) +#define _cast64_efi_call8(f,a1,a2,a3,a4,a5,a6,a7,a8) \ + efi_call8(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8)) +#define _cast64_efi_call9(f,a1,a2,a3,a4,a5,a6,a7,a8,a9) \ + efi_call9(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \ + (UINT64)(a9)) +#define _cast64_efi_call10(f,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \ + efi_call10(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \ + (UINT64)(a9), (UINT64)(a10)) + +#define uefi_call_wrapper(func,va_num,...) \ + _cast64_efi_call ## va_num (func , ##__VA_ARGS__) + #endif #define EFI_FUNCTION __attribute__((ms_abi)) @@ -299,4 +356,3 @@ UINTN uefi_call_wrapper(void *func, unsigned long va_num, ...); #endif #endif - |