1 //! Rusty wrapper for the [Unified Extensible Firmware Interface][UEFI].
2 //!
3 //! This crate makes it easy to develop Rust software that leverages **safe**,
4 //! **convenient**, and **performant** abstractions for [UEFI] functionality.
5 //!
6 //! See the [Rust UEFI Book] for a tutorial, how-tos, and overviews of some
7 //! important UEFI concepts. For more details of UEFI, see the latest [UEFI
8 //! Specification][spec].
9 //!
10 //! # Minimal Example
11 //!
12 //! Minimal example for an UEFI application using functionality of the
13 //! `uefi` crate:
14 //!
15 //! ```no_run
16 //! #![no_main]
17 //! #![no_std]
18 //!
19 //! use uefi::prelude::*;
20 //!
21 //! #[entry]
22 //! fn main() -> Status {
23 //!     uefi::helpers::init().unwrap();
24 //!
25 //!     Status::SUCCESS
26 //! }
27 //! # extern crate std;
28 //! ```
29 //!
30 //! Please find more info in our [Rust UEFI Book].
31 //!
32 //! # Value-add and Use Cases
33 //!
34 //! `uefi` supports writing code for both pre- and post-exit boot services
35 //! epochs, but its true strength shines when you create UEFI images that heavily
36 //! interact with UEFI boot services. Still, you have the flexibility to just
37 //! integrate selected types and abstractions into your project, for example to
38 //! parse the UEFI memory map.
39 //!
40 //! _Note that for producing UEFI images, you also need to use a corresponding
41 //! `uefi` compiler target of Rust, such as `x86_64-unknown-uefi`._
42 //!
43 //! ## Example Use Cases
44 //!
45 //! This library significantly simplifies the process of creating **UEFI images**
46 //! by abstracting away much of the UEFI API complexity and by providing
47 //! convenient wrappers. When we mention UEFI images, we are talking about UEFI
48 //! applications, UEFI boot service drivers, and EFI runtime service drivers,
49 //! which typically have the `.efi` file extension. For instance, an UEFI
50 //! application could be an OS-specific loader, similar to _GRUB_ or _Limine_.
51 //!
52 //! Additionally, you can use this crate in non-UEFI images (such as a kernel
53 //! in ELF format) to perform tasks like parsing the UEFI memory map embedded in
54 //! the boot information provided by a bootloader. It also enables access to
55 //! UEFI runtime services from a non-UEFI image kernel.
56 //!
57 //! # Supported Compiler Versions and Architectures
58 //!
59 //! `uefi` works with stable Rust, but additional nightly-only features are
60 //! gated behind the `unstable` Cargo feature. Please find more information
61 //! about additional crate features below.
62 //!
63 //! `uefi` is compatible with all platforms that both the Rust compiler and
64 //! UEFI support, such as `i686`, `x86_64`, and `aarch64`. Please note that we
65 //! can't test all possible hardware/firmware/platform combinations in CI.
66 //!
67 //! ## MSRV
68 //! <!-- Keep in Sync with README! -->
69 //!
70 //! The minimum supported Rust version is currently 1.70.
71 //! Our policy is to support at least the past two stable releases.
72 //!
73 //! # API/User Documentation, Documentation Structure, and other Resources
74 //!
75 //! Down below, you find typical technical documentation of all types, modules,
76 //! and functions exported by `uefi`.
77 //!
78 //! For a TL;DR quick start with an example on how to create your own EFI
79 //! application, please check out [the UEFI application template][template]. The
80 //! [Rust UEFI Book] is a more beginner-friendly tutorial with How-Tos, and
81 //! overviews of some important UEFI concepts and the abstractions provided by
82 //! this library.
83 //!
84 //! For more details of UEFI itself, see the latest [UEFI Specification][spec].
85 //!
86 //! # Library Structure & Tips
87 //!
88 //! The top-level module contains some of the most used types and macros,
89 //! including the [`Handle`] and [`Result`] types, the [`CStr16`] and
90 //! [`CString16`] types for working with UCS-2 strings, and the [`entry`] and
91 //! [`guid`] macros.
92 //!
93 //! ## UEFI Strings
94 //!
95 //! Rust string literals are UTF-8 encoded and thus, not compatible with most
96 //! UEFI interfaces. We provide [`CStr16`] and [`CString16`] for proper working
97 //! with UCS-2 strings, including various transformation functions from standard
98 //! Rust strings. You can use [`ctr16!`] to create UCS-2 string literals at
99 //! compile time.
100 //!
101 //! ## Tables
102 //!
103 //! Most UEFI functionality comes from the system, boot, and runtime
104 //! tables. These can be accessed via the [`system`], [`boot`], and [`runtime`]
105 //! modules.
106 //!
107 //! ## Protocols
108 //!
109 //! When boot services are active, most functionality is provided via UEFI
110 //! protocols. Protocols provide operations such as reading and writing files,
111 //! drawing to the screen, sending and receiving network requests, and much
112 //! more. The list of protocols that are actually available when running an
113 //! application depends on the device. For example, a PC with no network card
114 //! may not provide network protocols.
115 //!
116 //! See the [`boot`] documentation for details of how to open a
117 //! protocol, and see the [`proto`] module for protocol implementations. New
118 //! protocols can be defined with the [`unsafe_protocol`] macro.
119 //!
120 //! ## Optional Cargo crate features
121 //!
122 //! - `alloc`: Enable functionality requiring the [`alloc`] crate from
123 //!   the Rust standard library. For example, methods that return a
124 //!   `Vec` rather than filling a statically-sized array. This requires
125 //!   a global allocator; you can use the `global_allocator` feature or
126 //!   provide your own. This is independent of internal direct usages of the
127 //!   UEFI boot service allocator which may happen anyway, where necessary.
128 //! - `global_allocator`: Set [`allocator::Allocator`] as the global Rust
129 //!   allocator. This is a simple allocator that relies on the UEFI pool
130 //!   allocator. You can choose to provide your own allocator instead of
131 //!   using this feature, or no allocator at all if you don't need to
132 //!   dynamically allocate any memory.
133 //! - `logger`: Logging implementation for the standard [`log`] crate
134 //!   that prints output to the UEFI console. No buffering is done; this
135 //!   is not a high-performance logger.
136 //! - `panic_handler`: Add a default panic handler that logs to `stdout`.
137 //! - `unstable`: Enable functionality that depends on [unstable
138 //!   features] in the nightly compiler.
139 //!   As example, in conjunction with the `alloc`-feature, this gate allows
140 //!   the `allocator_api` on certain functions.
141 //! - `qemu`: Enable some code paths to adapt their execution when executed
142 //!   in QEMU, such as using the special `qemu-exit` device when the panic
143 //!   handler is called.
144 //!
145 //! Some of these features, such as the `logger` or `panic_handler` features,
146 //! only unfold their potential when you invoke `uefi::helpers::init` as soon
147 //! as possible in your application.
148 //!
149 //! # Discuss and Contribute
150 //!
151 //! For general discussions, feel free to join us in our [Zulip] and ask
152 //! your questions there.
153 //!
154 //! Further, you can submit bugs and also ask questions in our [issue tracker].
155 //! Contributions in the form of a PR are also highly welcome. Check our
156 //! [contributing guide][contributing] for details.
157 //!
158 //! # Comparison to other Projects in the Ecosystem
159 //!
160 //! ## Rust `std` implementation
161 //!
162 //! There is an ongoing effort for a [`std` implementation][rustc-uefi-std] of
163 //! the Rust standard library, which allows you to write UEFI programs that look
164 //! very similar to normal Rust programs running on top of an OS.
165 //!
166 //! It is still under development. You can track the progress in the
167 //! corresponding [tracking issue][uefi-std-tr-issue].
168 //!
169 //! Using the `std` implementation simplifies the overall process of producing
170 //! the binary. For example, our [`#[entry]`][entry-macro] macro won't be
171 //! required any longer. As the `std` implementation evolves over time, you'll
172 //! need fewer and fewer abstractions of this crate. For everything not covered
173 //! by the `std` implementation, you can obtain relevant structures to work with
174 //! our crate via:
175 //! - `std::os::uefi::env::boot_services()`
176 //! - `std::os::uefi::env::get_system_handle()`
177 //! - `std::os::uefi::env::get_system_table()`
178 //!
179 //! ## `r-efi`
180 //!
181 //! [`r-efi`] provides Raw UEFI bindings without high-level convenience similar
182 //! to our `uefi-raw` crate, which is part of this  project, but more
183 //! feature-complete. It targets a lower-level than our `uefi` crate does.
184 //!
185 //! # License
186 //! <!-- Keep in Sync with README! -->
187 //!
188 //! The code in this repository is licensed under the Mozilla Public License 2.
189 //! This license allows you to use the crate in proprietary programs, but any
190 //! modifications to the files must be open-sourced.
191 //!
192 //! The full text of the license is available in the [license file][LICENSE].
193 //!
194 //! # Terminology
195 //!
196 //! Both "EFI" and "UEFI" can be used interchangeably, such as "UEFI image" or
197 //! "EFI image". We prefer "UEFI" in our crate and its documentation.
198 //!
199 //! [LICENSE]: https://github.com/rust-osdev/uefi-rs/blob/main/uefi/LICENSE
200 //! [Rust UEFI Book]: https://rust-osdev.github.io/uefi-rs/HEAD/
201 //! [UEFI]: https://uefi.org/
202 //! [Zulip]: https://rust-osdev.zulipchat.com
203 //! [`GlobalAlloc`]: alloc::alloc::GlobalAlloc
204 //! [`ctr16!`]: crate::cstr16
205 //! [`entry-macro`]: uefi_macros::entry
206 //! [`r-efi`]: https://crates.io/crates/r-efi
207 //! [`unsafe_protocol`]: proto::unsafe_protocol
208 //! [contributing]: https://github.com/rust-osdev/uefi-rs/blob/main/CONTRIBUTING.md
209 //! [issue tracker]: https://github.com/rust-osdev/uefi-rs/issues
210 //! [rustc-uefi-std]: https://doc.rust-lang.org/nightly/rustc/platform-support/unknown-uefi.html
211 //! [spec]: https://uefi.org/specifications
212 //! [template]: https://github.com/rust-osdev/uefi-rs/tree/main/template
213 //! [uefi-std-tr-issue]: https://github.com/rust-lang/rust/issues/100499
214 //! [unstable features]: https://doc.rust-lang.org/unstable-book/
215 
216 #![cfg_attr(all(feature = "unstable", feature = "alloc"), feature(allocator_api))]
217 #![cfg_attr(docsrs, feature(doc_auto_cfg))]
218 #![no_std]
219 #![deny(
220     clippy::all,
221     clippy::missing_const_for_fn,
222     clippy::must_use_candidate,
223     clippy::ptr_as_ptr,
224     clippy::use_self,
225     missing_debug_implementations,
226     missing_docs,
227     unused
228 )]
229 
230 #[cfg(feature = "alloc")]
231 extern crate alloc;
232 // allow referring to self as ::uefi for macros to work universally (from this crate and from others)
233 // see https://github.com/rust-lang/rust/issues/54647
234 extern crate self as uefi;
235 #[macro_use]
236 extern crate uefi_raw;
237 
238 #[macro_use]
239 pub mod data_types;
240 pub mod allocator;
241 pub mod boot;
242 #[cfg(feature = "alloc")]
243 pub mod fs;
244 pub mod helpers;
245 pub mod mem;
246 pub mod prelude;
247 pub mod proto;
248 pub mod runtime;
249 pub mod system;
250 pub mod table;
251 
252 pub(crate) mod polyfill;
253 
254 mod macros;
255 mod result;
256 mod util;
257 
258 #[cfg(feature = "alloc")]
259 pub use data_types::CString16;
260 pub use data_types::{CStr16, CStr8, Char16, Char8, Event, Guid, Handle, Identify};
261 pub use result::{Error, Result, ResultExt, Status, StatusExt};
262 /// Re-export ucs2_cstr so that it can be used in the implementation of the
263 /// cstr16 macro. It is hidden since it's not intended to be used directly.
264 #[doc(hidden)]
265 pub use ucs2::ucs2_cstr;
266 pub use uefi_macros::entry;
267 pub use uguid::guid;
268