rustc_target/spec/base/
uefi_msvc.rs

1// This defines a base target-configuration for native UEFI systems. The UEFI specification has
2// quite detailed sections on the ABI of all the supported target architectures. In almost all
3// cases it simply follows what Microsoft Windows does. Hence, whenever in doubt, see the MSDN
4// documentation.
5// UEFI uses COFF/PE32+ format for binaries. All binaries must be statically linked. No dynamic
6// linker is supported. As native to COFF, binaries are position-dependent, but will be relocated
7// by the loader if the pre-chosen memory location is already in use.
8// UEFI forbids running code on anything but the boot-CPU. No interrupts are allowed other than
9// the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all
10// code runs in the same environment, no process separation is supported.
11
12use crate::spec::{LinkerFlavor, Lld, PanicStrategy, StackProbeType, TargetOptions, base};
13
14pub(crate) fn opts() -> TargetOptions {
15    let mut base = base::msvc::opts();
16
17    base.add_pre_link_args(
18        LinkerFlavor::Msvc(Lld::No),
19        &[
20            // Non-standard subsystems have no default entry-point in PE+ files. We have to define
21            // one. "efi_main" seems to be a common choice amongst other implementations and the
22            // spec.
23            "/entry:efi_main",
24            // COFF images have a "Subsystem" field in their header, which defines what kind of
25            // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION,
26            // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION,
27            // which is very likely the most common option. Individual projects can override this
28            // with custom linker flags.
29            // The subsystem-type only has minor effects on the application. It defines the memory
30            // regions the application is loaded into (runtime-drivers need to be put into
31            // reserved areas), as well as whether a return from the entry-point is treated as
32            // exit (default for applications).
33            "/subsystem:efi_application",
34        ],
35    );
36
37    TargetOptions {
38        os: "uefi".into(),
39        linker_flavor: LinkerFlavor::Msvc(Lld::Yes),
40        disable_redzone: true,
41        exe_suffix: ".efi".into(),
42        allows_weak_linkage: false,
43        panic_strategy: PanicStrategy::Abort,
44        // LLVM does not emit inline assembly because the LLVM target does not get considered as…
45        // "Windows".
46        stack_probes: StackProbeType::Call,
47        singlethread: true,
48        linker: Some("rust-lld".into()),
49        entry_name: "efi_main".into(),
50        ..base
51    }
52}