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