-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
All firmware API function pointers in std.os.uefi
should be marked with callconv(.Win64)
#16309
Comments
I also hit this issue. I would like to compile my efi app with a different ABI. There are too many libraries out there that expect LP64. |
Am I understanding correctly that sometimes the Line 108 in 78eb3c5
It might look like this: pub const uefi_cc: std.builtin.CallingConvention = if (@hasDecl(options_override, "uefi_cc"))
options_override.uefi_cc
else
.Win64; In all the UEFI function definitions it would be used like this: raiseTpl: *const fn (new_tpl: usize) callconv(std.options.enable_segfault_handler) usize, |
Not quite I don't think. The UEFI spec requires all functions to adhere to the Win64 calling convention. It just happens to be that when compiling for the |
From looking at the spec, I don't think https://uefi.org/specs/UEFI/2.10/02_Overview.html#calling-conventions |
Ah, it is, of course, more complicated than I initially thought. And I also just saw FWIW, this how Linux declares EFI functions: #if defined(CONFIG_X86_64)
#define __efiapi __attribute__((ms_abi))
#elif defined(CONFIG_X86_32)
#define __efiapi __attribute__((regparm(0)))
#else
#define __efiapi
#endif So it seems that |
Ok so I've read up on the topic a bit and to me it seems that GCC's pub const ueficc = switch (@import("builtin").target.cpu.arch) {
.x86_64 => .Win64,
.x86 => .regparm,
else => .C,
}; Only problem is, zig's In the meantime, I've found a somewhat acceptable workaround for x86-64: fn efiCall(fn_ptr: anytype) *const efiABI(@TypeOf(fn_ptr)) {
return @ptrCast(*const efiABI(@TypeOf(fn_ptr)), fn_ptr);
}
fn efiABI(comptime fn_ptr: type) type {
const fn_info = @typeInfo(fn_ptr);
if (fn_info.Pointer) |_| {} else {
@compileError("type parameter is not a function.");
}
var info = @typeInfo(fn_info.Pointer.child);
if (info.Fn) |_| {} else {
@compileError("type parameter is not a function.");
}
if (info.Fn.calling_convention == .Win64) {
@compileError("function already has correct calling convention");
}
info.Fn.calling_convention = .Win64;
return @Type(info);
} (this allows casting any EDIT: Some further prior art: Rust has pub const ueficc = switch (@import("builtin").target.cpu.arch) {
.x86_64 => .Win64,
else => .C,
}; |
I didn't test this at all (should definitely compile though) but if there's anything wrong it shouldn't be hard to fix. With this change it's going to be very easy to make further adjustments ot the calling conventions of all these external UEFI functions. Closes ziglang#16309
I didn't test this at all (should definitely compile though and these changes were done programmatically) but if there's anything wrong it shouldn't be hard to fix. With this change it's going to be very easy to make further adjustments to the calling conventions of all these external UEFI functions. Closes ziglang#16309
I tested this and this definitely compiles and these changes were done programmatically but if there's still anything wrong it shouldn't be hard to fix. With this change it's going to be very easy to make further adjustments to the calling conventions of all these external UEFI functions. Closes ziglang#16309
I tested this and this definitely compiles and these changes were done programmatically but if there's still anything wrong it shouldn't be hard to fix. With this change it's going to be very easy to make further adjustments to the calling conventions of all these external UEFI functions. Closes ziglang#16309
Example:
zig/lib/std/os/uefi/tables/boot_services.zig
Line 25 in de227ac
should become:
Using
callconv(.C)
works when compiling for anuefi
target, but not in, e.g., in an EFI stub with a different ABI, like the Linux kernel withCONFIG_EFI_STUB
.From my understanding, using
callconv(.Win64)
would still be correct for theuefi
target, but would allow also calling these functions in a strictly greater set of programs, such as EFI-stub OS kernels with no downsides, without having to use ABI conversion wrappers.Am I correct in my assessment? If so, I would be willing to open a corresponding PR, I just wanted to make sure I am not missing something, first.
The text was updated successfully, but these errors were encountered: