Use Restricted std in UEFI8 min read June 16, 2022 #rust #tianocore #gsoc22 #uefi
Hello Everyone; in my last post, I set up the development environment for working on adding Rust support for UEFI. In this post, I will get a restricted version of std (basically a glorified core + alloc) to work for the x86_64 UEFI target. We will be starting with the
no_std hello_world program from the last post.
Add env module for UEFI in std
Add uefi Module
First, I will add
uefi module under
library/std/src/sys. To do this, we will create a new file
library/std/src/sys/uefi/mod.rs. We will point everything other than the
env module to the unsupported module. The contents of
library/std/src/sys/uefi/mod.rs are given below:
//! Platform-specific extensions to `std` for UEFI platforms. //! //! Provides access to platform-level information on UEFI platforms, and //! exposes Unix-specific functions that would otherwise be inappropriate as //! part of the core `std` library. //! //! It exposes more ways to deal with platform-specific strings ([`OsStr`], //! [`OsString`]), allows to set permissions more granularly, extract low-level //! file descriptors from files and sockets, and has platform-specific helpers //! for spawning processes. //! //! [`OsStr`]: crate::ffi::OsStr //! [`OsString`]: crate::ffi::OsString pub use *;
As you can see,
path point to the
windows module instead of
unsupported. This is because
unsupported does not provide any definition for those. The
cmath unix module API can be provided by
compiler-builtins, so that should work. However,
path are simply placeholders for now.
Implement env module
The env module is very basic and we just need to define a few constants for it. Here are the contents of
Export UEFI module contents
This can be done by adding the following lines to
} else if else if else if
And we now have the
env module implemented. These constants are exposed under
Build the new toolchain
We will now need to build the toolchain again:
stage1 should now be pointing to this new toolchain.
Now, we will try to print these constants to UEFI in a very primitive manner (since io, strings, etc have not been implemented yet).
Compile hello_world with std
Firstly, we will remove the
no_std attribute and
src/main.rs. Then we will update
.cargo/config.toml with the following contents:
 = ["std", "compiler_builtins"] = ["compiler-builtins-mem"]
On trying to compile the project now, we get the following error:
The first error is a bug in build-std. It doesn’t know how to handle panic_abort vs panic_unwind, so it doesn’t use either crate, resulting in the above error. It can be fixed by adding
The second error can be fixed by adding the
restricted_std feature to the
Trying to build now and ………. It fails. We get the following error:
| = = >>> referenced ) ) >>> referenced ) )
This error is, well, a bit weird. We can fix the build for now by providing a blank implementation of
__CxxFrameHandler3, but this needs more research. The following lines need to be added to
pub extern "C"
The application builds and runs fine now.
Print EXE_EXTENSION constant
Now we will print EXE_EXTENSION to the console. Since we do not have io and string implemented yet, we will have to do it in a primitive way using
u16 arrays. The final
src/main.rs is given below:
use efi; use consts; pub extern "C" pub extern "C"
Here is the program running under qemu:
With this, we are using our new
std for UEFI.
__CxxFrameHandler3 blank implementation is no longer required in the
master branch. I was previously basing my changes on the v1.61.0 tag. However, from now, I am going to work on master directly.
Technically, we are now using
std (even though none of it has yet been implemented). Now I will slowly start implementing parts of
std starting with allocation. I also wanted to find a way to use the normal Rust
main function instead of the current
efi_main. However, this still does not seem possible (see #29633). So, let’s get allocation working and replace all the arrays with vectors in this code.
Back to top