-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Add x86_64-unknown-uefi target #56769
Conversation
This adds a new rustc target-configuration called 'x86_64-unknown_uefi'. Furthermore, it adds a UEFI base-configuration to be used with other targets supported by UEFI (e.g., i386, armv7hl, aarch64, itanium, ...). UEFI systems provide a very basic operating-system environment, meant to unify how systems are booted. It is tailored for simplicity and fast setup, as it is only meant to bootstrap other systems. For instance, it copies most of the ABI from Microsoft Windows, rather than inventing anything on its own. Furthermore, any complex CPU features are disabled. Only one CPU is allowed to be up, no interrupts other than the timer-interrupt are allowed, no process-separation is performed, page-tables are identity-mapped, ... Nevertheless, UEFI has an application model. Its main purpose is to allow operating-system vendors to write small UEFI applications that load their kernel and terminate the UEFI system. However, many other UEFI applications have emerged in the past, including network-boot, debug-consoles, and more. This UEFI target allows to compile rust code natively as UEFI applications. No standard library support is added, but libcore can be used out-of-the-box if a panic-handler is provided. Furthermore, liballoc works as well, if a `GlobalAlloc` handler is provided. Both have been tested with this target-configuration. Note that full libstd support is unlikely to happen. While UEFI does have standardized interfaces for networking and alike, none of these are mandatory and they are unlikely to be shipped in common consumer firmwares. Furthermore, several features like process-separation are not available (or only in very limited fashion). Those parts of libstd would have to be masked.
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @cramertj (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
Thanks for this! My only hesitation would be that this defaults to |
@alexcrichton I believe this uses |
Ah, no, it doesn't default to Thing is, you need a COFF/PE32+ linker for UEFI targets. So if you run this on linux, it is as if you cross-compile for Windows (UEFI and windows targets are almost the same). Since lld-link is a built-in of Long story short: The lld-link link-flavor just selects the COFF backend of lld as default linker. |
@bors: r+ Oh wow sorry about that, I completely missed that aspect! Glad LLD can save the day again for us here :) |
📌 Commit 88cf2a2 has been approved by |
@bors: rollup |
Add x86_64-unknown-uefi target This adds a new rustc target-configuration called 'x86_64-unknown_uefi'. Furthermore, it adds a UEFI base-configuration to be used with other targets supported by UEFI (e.g., i386, armv7hl, aarch64, itanium, ...). UEFI systems provide a very basic operating-system environment, meant to unify how systems are booted. It is tailored for simplicity and fast setup, as it is only meant to bootstrap other systems. For instance, it copies most of the ABI from Microsoft Windows, rather than inventing anything on its own. Furthermore, any complex CPU features are disabled. Only one CPU is allowed to be up, no interrupts other than the timer-interrupt are allowed, no process-separation is performed, page-tables are identity-mapped, ... Nevertheless, UEFI has an application model. Its main purpose is to allow operating-system vendors to write small UEFI applications that load their kernel and terminate the UEFI system. However, many other UEFI applications have emerged in the past, including network-boot, debug-consoles, and more. This UEFI target allows to compile rust code natively as UEFI applications. No standard library support is added, but libcore can be used out-of-the-box if a panic-handler is provided. Furthermore, liballoc works as well, if a `GlobalAlloc` handler is provided. Both have been tested with this target-configuration. Note that full libstd support is unlikely to happen. While UEFI does have standardized interfaces for networking and alike, none of these are mandatory and they are unlikely to be shipped in common consumer firmwares. Furthermore, several features like process-separation are not available (or only in very limited fashion). Those parts of libstd would have to be masked.
Add x86_64-unknown-uefi target This adds a new rustc target-configuration called 'x86_64-unknown_uefi'. Furthermore, it adds a UEFI base-configuration to be used with other targets supported by UEFI (e.g., i386, armv7hl, aarch64, itanium, ...). UEFI systems provide a very basic operating-system environment, meant to unify how systems are booted. It is tailored for simplicity and fast setup, as it is only meant to bootstrap other systems. For instance, it copies most of the ABI from Microsoft Windows, rather than inventing anything on its own. Furthermore, any complex CPU features are disabled. Only one CPU is allowed to be up, no interrupts other than the timer-interrupt are allowed, no process-separation is performed, page-tables are identity-mapped, ... Nevertheless, UEFI has an application model. Its main purpose is to allow operating-system vendors to write small UEFI applications that load their kernel and terminate the UEFI system. However, many other UEFI applications have emerged in the past, including network-boot, debug-consoles, and more. This UEFI target allows to compile rust code natively as UEFI applications. No standard library support is added, but libcore can be used out-of-the-box if a panic-handler is provided. Furthermore, liballoc works as well, if a `GlobalAlloc` handler is provided. Both have been tested with this target-configuration. Note that full libstd support is unlikely to happen. While UEFI does have standardized interfaces for networking and alike, none of these are mandatory and they are unlikely to be shipped in common consumer firmwares. Furthermore, several features like process-separation are not available (or only in very limited fashion). Those parts of libstd would have to be masked.
Add x86_64-unknown-uefi target This adds a new rustc target-configuration called 'x86_64-unknown_uefi'. Furthermore, it adds a UEFI base-configuration to be used with other targets supported by UEFI (e.g., i386, armv7hl, aarch64, itanium, ...). UEFI systems provide a very basic operating-system environment, meant to unify how systems are booted. It is tailored for simplicity and fast setup, as it is only meant to bootstrap other systems. For instance, it copies most of the ABI from Microsoft Windows, rather than inventing anything on its own. Furthermore, any complex CPU features are disabled. Only one CPU is allowed to be up, no interrupts other than the timer-interrupt are allowed, no process-separation is performed, page-tables are identity-mapped, ... Nevertheless, UEFI has an application model. Its main purpose is to allow operating-system vendors to write small UEFI applications that load their kernel and terminate the UEFI system. However, many other UEFI applications have emerged in the past, including network-boot, debug-consoles, and more. This UEFI target allows to compile rust code natively as UEFI applications. No standard library support is added, but libcore can be used out-of-the-box if a panic-handler is provided. Furthermore, liballoc works as well, if a `GlobalAlloc` handler is provided. Both have been tested with this target-configuration. Note that full libstd support is unlikely to happen. While UEFI does have standardized interfaces for networking and alike, none of these are mandatory and they are unlikely to be shipped in common consumer firmwares. Furthermore, several features like process-separation are not available (or only in very limited fashion). Those parts of libstd would have to be masked.
// 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(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this work for application writers?
Are they responsible for defining an efi_main
symbol? Perhaps not the best approach then, as we already have #[start]
and expect function annotated with that attribute to get invoked at start-up even in #[no_std]
contexts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some crate in your application must provide the efi_main
symbol. If we port std
, we could make the #[start]
logic do this. However, I don't think core
should provide wrappers around the entry-point. We explicitly want a way to link applications with full control over the entry-point. With this target, you need:
pub extern fn efi_main(_h: efi::Handle, st: *mut efi::SystemTable) -> efi::Status
..to exist somewhere in your application.
I expect applications to pull in helper crates that wrap the UEFI API with a safe rust interface. Those crates can then provide the entry-point and retain the system-table somehow. However, note that due to ExitBootServices()
, it is non-trivial to safely wrap all of the UEFI API (at least it requires some thought). By blocking ExitBootServices()
and the VM-remapping, it is at least easier to imagine a safe wrapper.
We already have a public crate that simply provides the symbols from the UEFI spec as rust symbols (really just copying the definitions, not wrapper code in there) at https://github.com/r-util/r-efi
Our safe wrappers are still being worked on.
base.abi_return_struct_as_int = true; | ||
|
||
Ok(Target { | ||
llvm_target: "x86_64-unknown-windows".to_string(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems debatable to me. Are you sure this is correct (as opposed to just "x86_64"?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have to trick llvm into creating COFF objects, rather than ELF objects. In theory this shouldn't matter. You should be able to use any available target compiler to get your object files, and then in the end tell your linker about the target format. However, this sadly does not work. The different object files have different capabilities, or specific annotations are only supported in one, not the other, etc. So I never succeeded in linking coff-objects into ELF-executables, or vice versa.
Preferably, I would use x86_64-unknown-coff
, but that does not exit. If anyone has better suggestions, I would gladly switch over.
Selecting the windows target might cause LLVM to optimize for something that will not apply to LLVM. However, I don't think anyone can apply any assumptions on a generic target like the one I picked, because it has to be backwards-compatible to all the existing windows versions. So I believe this will be safe.
I contacted colleagues of mine here at Red Hat, maybe they have a suggestion. Sadly, it is all gcc, not LLVM ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense then. It appears that llc
has no way to specify format of the produced object file either, which most likely makes the target
specification like this the best approach.
// places no locality-restrictions, so it fits well here. | ||
base.code_model = Some("large".to_string()); | ||
|
||
// UEFI mostly mirrors the calling-conventions used on windows. In case of x86-64 this means |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: x64 UEFI uses the exact same msabi (aka. x64) calling convention that windows uses. There is not a single difference (and therefore “mostly” is not applicable).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure about that? UEFI explicitly disallows passing values bigger than 64bit by value (both as argument or return value; see UEFI-2.7 2.3.4.2
). Isn't this allowed in msabi?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UEFI explicitly disallows passing values bigger than 64bit by value (both as argument or return value; see UEFI-2.7 2.3.4.2). Isn't this allowed in msabi?
Other than XMM/floating point registers, nothing larger than 64-bit is passed by-register in x64 msabi.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than XMM/floating point registers, nothing larger than 64-bit is passed by-register in x64 msabi.
Well, in registers, yes, but is that true for the stack as well? Does msabi require you to put objects bigger than 64bit in caller allocated memory and pass it by reference? Because that is how I read the UEFI spec, even for arguments passed on the stack.
The caller passes arrays and strings via a pointer to memory allocated by the
caller. The caller passes structures and unions of size 8, 16, 32, or 64 bits as if
they were integers of the same size. The caller is not allowed to pass structures
and unions of other than these sizes and must pass these unions and structures
via a pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Either way, this is proved by the fact that it wasn’t necessary for you to do anything special to implement UEFI’s ABI: it was already implemented!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, the MSDN docs are almost identical. Thanks a lot for the link!
I certainly expecteded the ABIs to be compatible. I just wasn't sure whether the UEFI ABI is a subset (e.g., their coding-convention forbids returning anything but ints, which I expected to be rooted in a restricted ABI). I am confident using the msabi will just work, given that's what tianocore does as well.
Cool trick with lld though! |
Add x86_64-unknown-uefi target This adds a new rustc target-configuration called 'x86_64-unknown_uefi'. Furthermore, it adds a UEFI base-configuration to be used with other targets supported by UEFI (e.g., i386, armv7hl, aarch64, itanium, ...). UEFI systems provide a very basic operating-system environment, meant to unify how systems are booted. It is tailored for simplicity and fast setup, as it is only meant to bootstrap other systems. For instance, it copies most of the ABI from Microsoft Windows, rather than inventing anything on its own. Furthermore, any complex CPU features are disabled. Only one CPU is allowed to be up, no interrupts other than the timer-interrupt are allowed, no process-separation is performed, page-tables are identity-mapped, ... Nevertheless, UEFI has an application model. Its main purpose is to allow operating-system vendors to write small UEFI applications that load their kernel and terminate the UEFI system. However, many other UEFI applications have emerged in the past, including network-boot, debug-consoles, and more. This UEFI target allows to compile rust code natively as UEFI applications. No standard library support is added, but libcore can be used out-of-the-box if a panic-handler is provided. Furthermore, liballoc works as well, if a `GlobalAlloc` handler is provided. Both have been tested with this target-configuration. Note that full libstd support is unlikely to happen. While UEFI does have standardized interfaces for networking and alike, none of these are mandatory and they are unlikely to be shipped in common consumer firmwares. Furthermore, several features like process-separation are not available (or only in very limited fashion). Those parts of libstd would have to be masked.
Rollup of 14 pull requests Successful merges: - #56718 (Use libbacktrace pretty-printing) - #56725 (fix rust-lang/rust issue #50583) - #56731 (Add missing urls in ffi module docs) - #56738 (Fix private_no_mangle_fns message grammar) - #56746 (Add test of current behavior (infer free region within closure body)) - #56747 (target: remove Box returned by get_targets) - #56751 (Allow ptr::hash to accept fat pointers) - #56755 (Account for `impl Trait` when suggesting lifetime) - #56758 (Add short emoji status to toolstate updates) - #56760 (Deduplicate unsatisfied trait bounds) - #56769 (Add x86_64-unknown-uefi target) - #56792 (Bootstrap: Add testsuite for compiletest tool) - #56808 (Fixes broken links) - #56809 (Fix docs path to PermissionsExt) Failed merges: r? @ghost
Rust now supports uefi as a build target: rust-lang/rust#56769 This change mainly eliminates references to the custom JSON target file. It also requires that the entry point's name be changed to `efi_main`. Note that the "C" abi is now correct for EFI applications, but will still be incorrect when uefi-rs is brought in as an external dependancy for a different target. This means the entry point should always be `extern "C"` while the table of function pointers should be `extern "win64"`.
Rust now supports uefi as a build target: rust-lang/rust#56769 This change mainly eliminates references to the custom JSON target file. It also requires that the entry point's name be changed to `efi_main`. Note that the "C" abi is now correct for EFI applications, but will still be incorrect when uefi-rs is brought in as an external dependancy for a different target. This means the entry point should always be `extern "C"` while the table of function pointers should be `extern "win64"`.
Why isn’t this using |
|
When trying to compile a project with this target, |
I've used those interfaces quite a bit, and they're available on many common firmware images. The filesystem interfaces are always available. And in general, almost all of what std needs should be regularly available, other than things that depend on |
I know implementations exist, and I know that people use them. Can you clarify what "many common firmware images" means? Does that include low-budget devices? Does it mean 50% of devices? 10%? Or 99.9%? I know that we had issues with the most simple of UEFI protocols being implemented wrongly in consumer hardware (speaking of efi_simple_input_protocol and efi_graphics_output_protocol), and we had to work around peculiarities in very simple projects like gummiboot, sd-boot, efifb, etc. (see their implementations for details). So I am a bit skeptical if you claim that the more elaborate protocols like the network stack exists on many devices. I hope you are right ;)
Just because a protocol is available does not mean that you can use it. For instance, to safely use any of the UEFI protocols that support device hotplugging, you must register a EFI_DRIVER_BINDING_PROTOCOL instance yourself. Otherwise, there is no way that you are notified of devices being removed. For instance, UEFI Applications (unlike UEFI Drivers) usually only make use of singleton protocols (the ones that multiplex input/output of multiple devices on a single interface). While technically nobody stops you from using other protocols, they can be dropped at any point in time without you being notified, thus getting lots of stale pointers. I still think porting |
I've certainly encountered devices that don't have the EFI network protocols, I'm just saying I've run into many devices that do (various random PC hardware, both laptops and desktops). There'd be value in being able to write DXE applications using Rust, and also in writing PEI or similar code in Rust without std. The stock Tiano core includes the network protocols, so it's more a matter of whether the device vendor shipped a working driver for network hardware. |
Pkgsrc changes: * Bump required rust version to build to 1.32.0. * Adapt patches to changed file locations. * Since we now patch some more vendor/ modules, doctor the corresponding .cargo-checksum.json files accordingly Upstream changes: Version 1.33.0 (2019-02-28) ========================== Language -------- - [You can now use the `cfg(target_vendor)` attribute.][57465] E.g. `#[cfg(target_vendor="apple")] fn main() { println!("Hello Apple!"); }` - [Integer patterns such as in a match expression can now be exhaustive.][56362] E.g. You can have match statement on a `u8` that covers `0..=255` and you would no longer be required to have a `_ => unreachable!()` case. - [You can now have multiple patterns in `if let` and `while let` expressions.][57532] You can do this with the same syntax as a `match` expression. E.g. ```rust enum Creature { Crab(String), Lobster(String), Person(String), } fn main() { let state = Creature::Crab("Ferris"); if let Creature::Crab(name) | Creature::Person(name) = state { println!("This creature's name is: {}", name); } } ``` - [You can now have irrefutable `if let` and `while let` patterns.][57535] Using this feature will by default produce a warning as this behaviour can be unintuitive. E.g. `if let _ = 5 {}` - [You can now use `let` bindings, assignments, expression statements, and irrefutable pattern destructuring in const functions.][57175] - [You can now call unsafe const functions.][57067] E.g. ```rust const unsafe fn foo() -> i32 { 5 } const fn bar() -> i32 { unsafe { foo() } } ``` - [You can now specify multiple attributes in a `cfg_attr` attribute.][57332] E.g. `#[cfg_attr(all(), must_use, optimize)]` - [You can now specify a specific alignment with the `#[repr(packed)]` attribute.][57049] E.g. `#[repr(packed(2))] struct Foo(i16, i32);` is a struct with an alignment of 2 bytes and a size of 6 bytes. - [You can now import an item from a module as an `_`.][56303] This allows you to import a trait's impls, and not have the name in the namespace. E.g. ```rust use std::io::Read as _; // Allowed as there is only one `Read` in the module. pub trait Read {} ``` - [You may now use `Rc`, `Arc`, and `Pin` as method receivers][56805]. Compiler -------- - [You can now set a linker flavor for `rustc` with the `-Clinker-flavor` command line argument.][56351] - [The mininum required LLVM version has been bumped to 6.0.][56642] - [Added support for the PowerPC64 architecture on FreeBSD.][57615] - [The `x86_64-fortanix-unknown-sgx` target support has been upgraded to tier 2 support.][57130] Visit the [platform support][platform-support] page for information on Rust's platform support. - [Added support for the `thumbv7neon-linux-androideabi` and `thumbv7neon-unknown-linux-gnueabihf` targets.][56947] - [Added support for the `x86_64-unknown-uefi` target.][56769] Libraries --------- - [The methods `overflowing_{add, sub, mul, shl, shr}` are now `const` functions for all numeric types.][57566] - [The methods `rotate_left`, `rotate_right`, and `wrapping_{add, sub, mul, shl, shr}` are now `const` functions for all numeric types.][57105] - [The methods `is_positive` and `is_negative` are now `const` functions for all signed numeric types.][57105] - [The `get` method for all `NonZero` types is now `const`.][57167] - [The methods `count_ones`, `count_zeros`, `leading_zeros`, `trailing_zeros`, `swap_bytes`, `from_be`, `from_le`, `to_be`, `to_le` are now `const` for all numeric types.][57234] - [`Ipv4Addr::new` is now a `const` function][57234] Stabilized APIs --------------- - [`unix::FileExt::read_exact_at`] - [`unix::FileExt::write_all_at`] - [`Option::transpose`] - [`Result::transpose`] - [`convert::identity`] - [`pin::Pin`] - [`marker::Unpin`] - [`marker::PhantomPinned`] - [`Vec::resize_with`] - [`VecDeque::resize_with`] - [`Duration::as_millis`] - [`Duration::as_micros`] - [`Duration::as_nanos`] Cargo ----- - [Cargo should now rebuild a crate if a file was modified during the initial build.][cargo/6484] Compatibility Notes ------------------- - The methods `str::{trim_left, trim_right, trim_left_matches, trim_right_matches}` are now deprecated in the standard library, and their usage will now produce a warning. Please use the `str::{trim_start, trim_end, trim_start_matches, trim_end_matches}` methods instead. - The `Error::cause` method has been deprecated in favor of `Error::source` which supports downcasting. [55982]: rust-lang/rust#55982 [56303]: rust-lang/rust#56303 [56351]: rust-lang/rust#56351 [56362]: rust-lang/rust#56362 [56642]: rust-lang/rust#56642 [56769]: rust-lang/rust#56769 [56805]: rust-lang/rust#56805 [56947]: rust-lang/rust#56947 [57049]: rust-lang/rust#57049 [57067]: rust-lang/rust#57067 [57105]: rust-lang/rust#57105 [57130]: rust-lang/rust#57130 [57167]: rust-lang/rust#57167 [57175]: rust-lang/rust#57175 [57234]: rust-lang/rust#57234 [57332]: rust-lang/rust#57332 [57465]: rust-lang/rust#57465 [57532]: rust-lang/rust#57532 [57535]: rust-lang/rust#57535 [57566]: rust-lang/rust#57566 [57615]: rust-lang/rust#57615 [cargo/6484]: rust-lang/cargo#6484 [`unix::FileExt::read_exact_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.read_exact_at [`unix::FileExt::write_all_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.write_all_at [`Option::transpose`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.transpose [`Result::transpose`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose [`convert::identity`]: https://doc.rust-lang.org/std/convert/fn.identity.html [`pin::Pin`]: https://doc.rust-lang.org/std/pin/struct.Pin.html [`marker::Unpin`]: https://doc.rust-lang.org/stable/std/marker/trait.Unpin.html [`marker::PhantomPinned`]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomPinned.html [`Vec::resize_with`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.resize_with [`VecDeque::resize_with`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.resize_with [`Duration::as_millis`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_millis [`Duration::as_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_micros [`Duration::as_nanos`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_nanos [platform-support]: https://forge.rust-lang.org/platform-support.html
Default to integrated `rust-lld` linker for UEFI targets The `x86_64-unknown-uefi` target was added in rust-lang#56769 with the linker defaulting to `lld-link`. This means that a system linker with that name is required for linking. I think defaulting to `rust-lld`, which is shipped with Rust, is a better default for the following reasons: - Most systems don't have `lld-link` installed, so it forces users to install it first. - The naming of LLD executables is not standarized, so users often need to create an additional symlink before things work. For example, on Ubuntu `apt install lld` leads to an executable named `lld-link-6.0`. - We already default to `rust-lld` for [many targets](https://github.com/rust-lang/rust/search?utf8=%E2%9C%93&q=rust-lld&type=), including embedded and WASM targets, so doing the same for UEFI crates seems consistent to me. (It even seems like `x86_64-unknown-uefi` is the [only target](https://github.com/rust-lang/rust/search?q=lld-link&unscoped_q=lld-link) that uses `lld-link`.) cc @dvdhrm who added the target and @KKK669 who [proposed to use `rust-lld`](rust-lang#56769 (comment)).
Default to integrated `rust-lld` linker for UEFI targets The `x86_64-unknown-uefi` target was added in rust-lang#56769 with the linker defaulting to `lld-link`. This means that a system linker with that name is required for linking. I think defaulting to `rust-lld`, which is shipped with Rust, is a better default for the following reasons: - Most systems don't have `lld-link` installed, so it forces users to install it first. - The naming of LLD executables is not standarized, so users often need to create an additional symlink before things work. For example, on Ubuntu `apt install lld` leads to an executable named `lld-link-6.0`. - We already default to `rust-lld` for [many targets](https://github.com/rust-lang/rust/search?utf8=%E2%9C%93&q=rust-lld&type=), including embedded and WASM targets, so doing the same for UEFI crates seems consistent to me. (It even seems like `x86_64-unknown-uefi` is the [only target](https://github.com/rust-lang/rust/search?q=lld-link&unscoped_q=lld-link) that uses `lld-link`.) cc @dvdhrm who added the target and @KKK669 who [proposed to use `rust-lld`](rust-lang#56769 (comment)).
Default to integrated `rust-lld` linker for UEFI targets The `x86_64-unknown-uefi` target was added in rust-lang#56769 with the linker defaulting to `lld-link`. This means that a system linker with that name is required for linking. I think defaulting to `rust-lld`, which is shipped with Rust, is a better default for the following reasons: - Most systems don't have `lld-link` installed, so it forces users to install it first. - The naming of LLD executables is not standarized, so users often need to create an additional symlink before things work. For example, on Ubuntu `apt install lld` leads to an executable named `lld-link-6.0`. - We already default to `rust-lld` for [many targets](https://github.com/rust-lang/rust/search?utf8=%E2%9C%93&q=rust-lld&type=), including embedded and WASM targets, so doing the same for UEFI crates seems consistent to me. (It even seems like `x86_64-unknown-uefi` is the [only target](https://github.com/rust-lang/rust/search?q=lld-link&unscoped_q=lld-link) that uses `lld-link`.) cc @dvdhrm who added the target and @KKK669 who [proposed to use `rust-lld`](rust-lang#56769 (comment)).
Default to integrated `rust-lld` linker for UEFI targets The `x86_64-unknown-uefi` target was added in rust-lang#56769 with the linker defaulting to `lld-link`. This means that a system linker with that name is required for linking. I think defaulting to `rust-lld`, which is shipped with Rust, is a better default for the following reasons: - Most systems don't have `lld-link` installed, so it forces users to install it first. - The naming of LLD executables is not standarized, so users often need to create an additional symlink before things work. For example, on Ubuntu `apt install lld` leads to an executable named `lld-link-6.0`. - We already default to `rust-lld` for [many targets](https://github.com/rust-lang/rust/search?utf8=%E2%9C%93&q=rust-lld&type=), including embedded and WASM targets, so doing the same for UEFI crates seems consistent to me. (It even seems like `x86_64-unknown-uefi` is the [only target](https://github.com/rust-lang/rust/search?q=lld-link&unscoped_q=lld-link) that uses `lld-link`.) cc @dvdhrm who added the target and @KKK669 who [proposed to use `rust-lld`](rust-lang#56769 (comment)).
Pkgsrc changes: * Bump required rust version to build to 1.32.0. * Adapt patches to changed file locations. * Since we now patch some more vendor/ modules, doctor the corresponding .cargo-checksum.json files accordingly Upstream changes: Version 1.33.0 (2019-02-28) ========================== Language -------- - [You can now use the `cfg(target_vendor)` attribute.][57465] E.g. `#[cfg(target_vendor="apple")] fn main() { println!("Hello Apple!"); }` - [Integer patterns such as in a match expression can now be exhaustive.][56362] E.g. You can have match statement on a `u8` that covers `0..=255` and you would no longer be required to have a `_ => unreachable!()` case. - [You can now have multiple patterns in `if let` and `while let` expressions.][57532] You can do this with the same syntax as a `match` expression. E.g. ```rust enum Creature { Crab(String), Lobster(String), Person(String), } fn main() { let state = Creature::Crab("Ferris"); if let Creature::Crab(name) | Creature::Person(name) = state { println!("This creature's name is: {}", name); } } ``` - [You can now have irrefutable `if let` and `while let` patterns.][57535] Using this feature will by default produce a warning as this behaviour can be unintuitive. E.g. `if let _ = 5 {}` - [You can now use `let` bindings, assignments, expression statements, and irrefutable pattern destructuring in const functions.][57175] - [You can now call unsafe const functions.][57067] E.g. ```rust const unsafe fn foo() -> i32 { 5 } const fn bar() -> i32 { unsafe { foo() } } ``` - [You can now specify multiple attributes in a `cfg_attr` attribute.][57332] E.g. `#[cfg_attr(all(), must_use, optimize)]` - [You can now specify a specific alignment with the `#[repr(packed)]` attribute.][57049] E.g. `#[repr(packed(2))] struct Foo(i16, i32);` is a struct with an alignment of 2 bytes and a size of 6 bytes. - [You can now import an item from a module as an `_`.][56303] This allows you to import a trait's impls, and not have the name in the namespace. E.g. ```rust use std::io::Read as _; // Allowed as there is only one `Read` in the module. pub trait Read {} ``` - [You may now use `Rc`, `Arc`, and `Pin` as method receivers][56805]. Compiler -------- - [You can now set a linker flavor for `rustc` with the `-Clinker-flavor` command line argument.][56351] - [The mininum required LLVM version has been bumped to 6.0.][56642] - [Added support for the PowerPC64 architecture on FreeBSD.][57615] - [The `x86_64-fortanix-unknown-sgx` target support has been upgraded to tier 2 support.][57130] Visit the [platform support][platform-support] page for information on Rust's platform support. - [Added support for the `thumbv7neon-linux-androideabi` and `thumbv7neon-unknown-linux-gnueabihf` targets.][56947] - [Added support for the `x86_64-unknown-uefi` target.][56769] Libraries --------- - [The methods `overflowing_{add, sub, mul, shl, shr}` are now `const` functions for all numeric types.][57566] - [The methods `rotate_left`, `rotate_right`, and `wrapping_{add, sub, mul, shl, shr}` are now `const` functions for all numeric types.][57105] - [The methods `is_positive` and `is_negative` are now `const` functions for all signed numeric types.][57105] - [The `get` method for all `NonZero` types is now `const`.][57167] - [The methods `count_ones`, `count_zeros`, `leading_zeros`, `trailing_zeros`, `swap_bytes`, `from_be`, `from_le`, `to_be`, `to_le` are now `const` for all numeric types.][57234] - [`Ipv4Addr::new` is now a `const` function][57234] Stabilized APIs --------------- - [`unix::FileExt::read_exact_at`] - [`unix::FileExt::write_all_at`] - [`Option::transpose`] - [`Result::transpose`] - [`convert::identity`] - [`pin::Pin`] - [`marker::Unpin`] - [`marker::PhantomPinned`] - [`Vec::resize_with`] - [`VecDeque::resize_with`] - [`Duration::as_millis`] - [`Duration::as_micros`] - [`Duration::as_nanos`] Cargo ----- - [Cargo should now rebuild a crate if a file was modified during the initial build.][cargo/6484] Compatibility Notes ------------------- - The methods `str::{trim_left, trim_right, trim_left_matches, trim_right_matches}` are now deprecated in the standard library, and their usage will now produce a warning. Please use the `str::{trim_start, trim_end, trim_start_matches, trim_end_matches}` methods instead. - The `Error::cause` method has been deprecated in favor of `Error::source` which supports downcasting. [55982]: rust-lang/rust#55982 [56303]: rust-lang/rust#56303 [56351]: rust-lang/rust#56351 [56362]: rust-lang/rust#56362 [56642]: rust-lang/rust#56642 [56769]: rust-lang/rust#56769 [56805]: rust-lang/rust#56805 [56947]: rust-lang/rust#56947 [57049]: rust-lang/rust#57049 [57067]: rust-lang/rust#57067 [57105]: rust-lang/rust#57105 [57130]: rust-lang/rust#57130 [57167]: rust-lang/rust#57167 [57175]: rust-lang/rust#57175 [57234]: rust-lang/rust#57234 [57332]: rust-lang/rust#57332 [57465]: rust-lang/rust#57465 [57532]: rust-lang/rust#57532 [57535]: rust-lang/rust#57535 [57566]: rust-lang/rust#57566 [57615]: rust-lang/rust#57615 [cargo/6484]: rust-lang/cargo#6484 [`unix::FileExt::read_exact_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.read_exact_at [`unix::FileExt::write_all_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.write_all_at [`Option::transpose`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.transpose [`Result::transpose`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose [`convert::identity`]: https://doc.rust-lang.org/std/convert/fn.identity.html [`pin::Pin`]: https://doc.rust-lang.org/std/pin/struct.Pin.html [`marker::Unpin`]: https://doc.rust-lang.org/stable/std/marker/trait.Unpin.html [`marker::PhantomPinned`]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomPinned.html [`Vec::resize_with`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.resize_with [`VecDeque::resize_with`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.resize_with [`Duration::as_millis`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_millis [`Duration::as_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_micros [`Duration::as_nanos`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_nanos [platform-support]: https://forge.rust-lang.org/platform-support.html
This adds a new rustc target-configuration called 'x86_64-unknown_uefi'.
Furthermore, it adds a UEFI base-configuration to be used with other
targets supported by UEFI (e.g., i386, armv7hl, aarch64, itanium, ...).
UEFI systems provide a very basic operating-system environment, meant
to unify how systems are booted. It is tailored for simplicity and fast
setup, as it is only meant to bootstrap other systems. For instance, it
copies most of the ABI from Microsoft Windows, rather than inventing
anything on its own. Furthermore, any complex CPU features are
disabled. Only one CPU is allowed to be up, no interrupts other than
the timer-interrupt are allowed, no process-separation is performed,
page-tables are identity-mapped, ...
Nevertheless, UEFI has an application model. Its main purpose is to
allow operating-system vendors to write small UEFI applications that
load their kernel and terminate the UEFI system. However, many other
UEFI applications have emerged in the past, including network-boot,
debug-consoles, and more.
This UEFI target allows to compile rust code natively as UEFI
applications. No standard library support is added, but libcore can be
used out-of-the-box if a panic-handler is provided. Furthermore,
liballoc works as well, if a
GlobalAlloc
handler is provided. Bothhave been tested with this target-configuration.
Note that full libstd support is unlikely to happen. While UEFI does
have standardized interfaces for networking and alike, none of these
are mandatory and they are unlikely to be shipped in common consumer
firmwares. Furthermore, several features like process-separation are
not available (or only in very limited fashion). Those parts of libstd
would have to be masked.