Skip to content

[un]install_multiple_protocol_interfaces() requires but is currently incompatible with feature c_variadic #302

Description

@timrobertsdev

Tracking issue

While implementing the missing protocol handler functions in BootServices, I found that extern "efiapi" is incompatible with Rust's current (unstable) implementation of c variadics. Rustc indicates that C variadics must be extern "C" or extern "cdecl", thus install_multiple_protocol_interfaces() and uninstall_multiple_protocol_interfaces() cannot be implemented at this time.

I'll bring this up on the C variadic tracking issue in the next couple days if it hasn't been already.

Rust tracking issue: rust-lang/rust#44930

EDIT: technically I guess this could be possible with some clever and wildly unsafe asm but I'd much rather wait for Rust to support it.

Activity

  1. timrobertsdev commented on Oct 20, 2021

    @timrobertsdev
    ContributorAuthor

    Update: Per Josh Triplett on the rustlang zulip, extern "C" on the "x86_64-unknown-uefi" target should be the proper UEFI ABI, so we can actually implement this, using extern "C" instead of extern "efiapi".

  2. GabrielMajeri commented on Dec 11, 2021

    @GabrielMajeri
    Collaborator

    @timrobertsdev does this mean we should replace all extern "efiapi" declarations in the crate with extern "C", and everything will just work correctly? Or is this workaround just for the protocol handler functions?

  3. timrobertsdev commented on Dec 14, 2021

    @timrobertsdev
    ContributorAuthor

    The way I understood it, since we're targeting EFI, extern "C" will always be the correct calling convention. I've replaced all extern "efiapi" with extern "C" locally and everything still builds and runs/tests correctly.

  4. GabrielMajeri commented on Dec 22, 2021

    @GabrielMajeri
    Collaborator

    @timrobertsdev Ah, I've realized there's a little problem which stops us from switching everything over to extern "C".

    The reason we've introduced the efiabi calling convention was to avoid issues like #38 -- if uefi-rs is used as a library in an OS kernel/driver which interacts with UEFI structures but which is built as an ELF binary, then it won't be able to call the methods correctly, unless they're declared with efiabi.

    I'm not sure what the correct solution would be here.

  5. nicholasbishop commented on Dec 22, 2021

    @nicholasbishop
    Member

    Perhaps the [un]install_multiple_protocol_interfaces function pointers could be declared with extern "C", and then the wrapper methods that call them could be guarded behind a #[cfg(...)] that only allows them to be called from uefi arches, until such time as efiabi supports variadics.

  6. timrobertsdev commented on Dec 22, 2021

    @timrobertsdev
    ContributorAuthor

    @nicholasbishop That sounds like a good solution to me.

    Would an ELF binary be capable of calling these functions (or any boot service functions, I guess)? I had assumed that boot services would be exited by the time a kernel is running.

  7. nicholasbishop commented on Dec 23, 2021

    @nicholasbishop
    Member

    Fair point, I think Linux at least exits boot services quite early in the EFI stub.

  8. GabrielMajeri commented on Dec 23, 2021

    @GabrielMajeri
    Collaborator

    Would an ELF binary be capable of calling these functions (or any boot service functions, I guess)? I had assumed that boot services would be exited by the time a kernel is running.

    That's the issue... we can't really guarantee this. It's what a logical, sane UEFI-based application/kernel would do: first load an ELF binary, then exist boot services and jump into it. But if we want to be pedantic and respect Rust's safety guarantees in all cases, something with a cfg guard like @nicholasbishop suggested would be more appropriate.

  9. nicholasbishop commented on Nov 4, 2022

    @nicholasbishop
    Member

    Quick update here, on current nightly it looks like this is now possible to use efiabi with variadics. However, it's currently gated by the extended_varargs_abi_support feature so I would recommend we not add it for now to avoid requiring more unstable features.

    (Also, as far as I can tell, InstallMultipleProtocolInterfaces is just a thin wrapper around calling InstallProtocolServices. We don't yet have the latter implemented, but we could add that easily I think.)

  10. medhefgo commented on Apr 10, 2023

    @medhefgo
    Contributor

    Just chiming in here to say that getting the calling convention right isn't your only concern if you want to (correctly) support cross ABI calls. If any structs are involved you have to make sure that they are laid out correctly according to the EFI ABI.
    In particular, x86 sysv ABI has long long 4-byte aligned if it appears within a struct. The MS/EFI ABI expects it to be 8-byte aligned.

    This will cause loaded image protocol (in particular) to have a bad memory layout if the uefi-rs definition were used in ELF ABI context. Whether that is a use-case you want to support or not is a different matter.

  11. nicholasbishop commented on Apr 11, 2023

    @nicholasbishop
    Member

    At least with the install_multiple_protocol_interfaces API, that shouldn't be a problem. It's only callable while boot services are active, which means you are running a UEFI executable that uses the efiabi calling convention. I think we only need to worry about cross-ABI calls when in runtime-services mode after an OS loads.

  12. Soveu commented on Dec 13, 2024

    @Soveu

    Quick update here, on current nightly it looks like this is now possible to use efiabi with variadics. However, it's currently gated by the extended_varargs_abi_support feature so I would recommend we not add it for now to avoid requiring more unstable features.

    (Also, as far as I can tell, InstallMultipleProtocolInterfaces is just a thin wrapper around calling InstallProtocolServices. We don't yet have the latter implemented, but we could add that easily I think.)

    On nightly, it is no longer gated and should be available on 1.85 stable release next year :)

  13. self-assigned this
    on Apr 9, 2025
  14. removed their assignment
    on Jun 1, 2025
  15. crawfxrd commented on Nov 13, 2025

    @crawfxrd
    Contributor
  16. phip1611 commented on Jan 1, 2026

    @phip1611
    Member

    It was a pain to get varargs to work nicely in Rust or I had a knot in my head. Instead, I came up with a different pragmatic solution #1856

  17. crawfxrd commented on Sep 9, 2026

    @crawfxrd
    Contributor
  18. phip1611 commented on Sep 10, 2026

    @phip1611
    Member

    cool, feel free to raise a PR

  19. phip1611 commented on Sep 22, 2026

    @phip1611
    Member

    this is now unblocked #2098

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions