Skip to content
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

Investigate efiapi!{} macro #41

Closed
HadrienG2 opened this issue Sep 24, 2018 · 3 comments
Closed

Investigate efiapi!{} macro #41

HadrienG2 opened this issue Sep 24, 2018 · 3 comments

Comments

@HadrienG2
Copy link
Contributor

HadrienG2 commented Sep 24, 2018

In Rust, I think resolving #38 entails generating different extern "<something>" statements depending on the target architecture. The pointer wrapping discussed in #40, if it ends up being implemented, could also use a bit of code generation to automatically turn *const T into EfiPtr<T> and *mut T into EfiPtrMut<T>.

A general solution to handle this kind of EFI API boilerplate would be to borrow the EFIAPI design from the UEFI spec and turn it into a Rust macro. For example, this code...

efiapi! { fn(u64, usize) -> Status }

...would generate this code on x86_64:

extern "win64" fn(u64, usize) -> Status

...and this code on i386:

extern "cdecl" fn(u64, usize) -> Status

There are limitations to what a declarative macro can generate in Rust (IIRC they can't generate types), and we probably don't want to go for procedural macros on a task this simple, so the final design may be modified to accomodate these limitations. But I think the general idea could portably address the issue of EFI calling conventions without bringing too much boilerplate in the declaration of each individual API entry point.

@GabrielMajeri
Copy link
Collaborator

GabrielMajeri commented Sep 24, 2018

extern "stdcall" fn(u64, usize) -> Status

But that's the thing, this is supposed to be extern "C" on i386, and everywhere else actually. UEFI spec wanted to have all functions just use extern "C" on every platform, but x86_64 is the only place where we have this weird separation of Windows vs UNIX ABI, even though they both, in theory, use extern "C".

borrow the EFIAPI design

Using a macro seems to sort of go around the real problem. I would rather raise an issue upstream about this.

In this old-ish comment it is mentioned that the only reason Rust even exposes the win64 ABI is because UEFI requires it.

I'm sure the Rust devs would be open to a proposal to add an extern "uefi" or something ABI, if we can justify that it is useful.

@HadrienG2
Copy link
Contributor Author

I'm sure the Rust devs would be open to a proposal to add an extern "uefi" or something ABI, if we can justify that it is useful.

Sounds like a good idea! I opened an issue on rust-lang to test waters, let's see how this goes...

@HadrienG2
Copy link
Contributor Author

After further investigation, this is too much for declarative macros (as they cannot expand into types, but only into items, the whole struct definition would need to be parsed, which is too much work) and too little to justify a procedural macro, so I'll live with the code duplication for now 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants