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
//! Rusty wrapper for the [Unified Extensible Firmware Interface][UEFI].
//!
//! 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].
//!
//! Feel free to file bug reports and questions in our [issue tracker], and [PR
//! contributions][contributing] are also welcome!
//!
//! # Interaction with uefi services
//!
//! With this crate you can write code for the pre- and post-exit boot services
//! epochs. However, the `uefi` crate unfolds its true potential when
//! interacting with UEFI boot services.
//!
//! # Crate organisation
//!
//! 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.
//!
//! ## Tables
//!
//! The [`SystemTable`] provides access to almost everything in UEFI. It comes
//! in two flavors:
//! - `SystemTable<Boot>`: for boot-time applications such as bootloaders,
//!   provides access to both boot and runtime services.
//! - `SystemTable<Runtime>`: for operating systems after boot services have
//!   been exited.
//!
//! ## 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 [`BootServices`] 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 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.
//! - `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`.
//! - `panic-on-logger-errors` (enabled by default): Panic if a text
//!   output error occurs in the logger.
//! - `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.
//!
//! [Rust UEFI Book]: https://rust-osdev.github.io/uefi-rs/HEAD/
//! [UEFI]: https://uefi.org/
//! [`BootServices`]: table::boot::BootServices
//! [`GlobalAlloc`]: alloc::alloc::GlobalAlloc
//! [`SystemTable`]: table::SystemTable
//! [`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
//! [spec]: https://uefi.org/specifications
//! [unstable features]: https://doc.rust-lang.org/unstable-book/

#![cfg_attr(feature = "unstable", feature(error_in_core))]
#![cfg_attr(all(feature = "unstable", feature = "alloc"), feature(allocator_api))]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![no_std]
// Enable some additional warnings and lints.
#![warn(clippy::ptr_as_ptr, missing_docs, unused)]
#![deny(clippy::all)]
#![deny(clippy::must_use_candidate)]
#![deny(missing_debug_implementations)]

#[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;
#[cfg(feature = "alloc")]
pub use self::data_types::CString16;
pub use self::data_types::{CStr16, CStr8, Char16, Char8, Event, Guid, Handle, Identify};
pub use uefi_macros::{cstr16, cstr8, entry};
pub use uguid::guid;

mod result;
pub use self::result::{Error, Result, ResultExt, Status, StatusExt};

pub mod table;

pub mod proto;

pub mod prelude;

pub mod allocator;

#[cfg(feature = "alloc")]
pub mod fs;

// As long as this is behind "alloc", we can simplify cfg-feature attributes in this module.
#[cfg(feature = "alloc")]
pub(crate) mod mem;

pub(crate) mod polyfill;

pub mod helpers;

mod util;

#[cfg(test)]
// Crates that create procedural macros can't unit test the macros they export.
// Therefore, we do some tests here.
mod macro_tests {
    use uefi_macros::{cstr16, cstr8};

    #[test]
    fn cstr8_macro_literal() {
        let _empty1 = cstr8!();
        let _empty2 = cstr8!("");
        let _regular = cstr8!("foobar");
    }

    #[test]
    fn cstr16_macro_literal() {
        let _empty1 = cstr16!();
        let _empty2 = cstr16!("");
        let _regular = cstr16!("foobar");
    }
}