| // This defines a base target-configuration for native UEFI systems. The UEFI specification has |
| // quite detailed sections on the ABI of all the supported target architectures. In almost all |
| // cases it simply follows what Microsoft Windows does. Hence, whenever in doubt, see the MSDN |
| // documentation. |
| // UEFI uses COFF/PE32+ format for binaries. All binaries must be statically linked. No dynamic |
| // linker is supported. As native to COFF, binaries are position-dependent, but will be relocated |
| // by the loader if the pre-chosen memory location is already in use. |
| // UEFI forbids running code on anything but the boot-CPU. No interrupts are allowed other than |
| // the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all |
| // code runs in the same environment, no process separation is supported. |
| |
| use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions}; |
| use std::default::Default; |
| |
| pub fn opts() -> TargetOptions { |
| let mut pre_link_args = LinkArgs::new(); |
| |
| pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Link), vec![ |
| // Suppress the verbose logo and authorship debugging output, which would needlessly |
| // clog any log files. |
| "/NOLOGO".to_string(), |
| |
| // UEFI is fully compatible to non-executable data pages. Tell the compiler that |
| // non-code sections can be marked as non-executable, including stack pages. In fact, |
| // firmware might enforce this, so we better let the linker know about this, so it |
| // will fail if the compiler ever tries placing code on the stack (e.g., trampoline |
| // constructs and alike). |
| "/NXCOMPAT".to_string(), |
| |
| // There is no runtime for UEFI targets, prevent them from being linked. UEFI targets |
| // must be freestanding. |
| "/nodefaultlib".to_string(), |
| |
| // Non-standard subsystems have no default entry-point in PE+ files. We have to define |
| // one. "efi_main" seems to be a common choice amongst other implementations and the |
| // spec. |
| "/entry:efi_main".to_string(), |
| |
| // COFF images have a "Subsystem" field in their header, which defines what kind of |
| // program it is. UEFI has 3 fields reserved, which are EFI_APPLICATION, |
| // EFI_BOOT_SERVICE_DRIVER, and EFI_RUNTIME_DRIVER. We default to EFI_APPLICATION, |
| // which is very likely the most common option. Individual projects can override this |
| // with custom linker flags. |
| // The subsystem-type only has minor effects on the application. It defines the memory |
| // regions the application is loaded into (runtime-drivers need to be put into |
| // reserved areas), as well as whether a return from the entry-point is treated as |
| // exit (default for applications). |
| "/subsystem:efi_application".to_string(), |
| ]); |
| |
| TargetOptions { |
| dynamic_linking: false, |
| executables: true, |
| disable_redzone: true, |
| exe_suffix: ".efi".to_string(), |
| allows_weak_linkage: false, |
| panic_strategy: PanicStrategy::Abort, |
| stack_probes: true, |
| singlethread: true, |
| emit_debug_gdb_scripts: false, |
| |
| linker: Some("rust-lld".to_string()), |
| lld_flavor: LldFlavor::Link, |
| pre_link_args, |
| |
| .. Default::default() |
| } |
| } |