From ff34fcbe86182f4acafd034e955243ecd4d286a5 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Wed, 14 Aug 2024 20:27:01 +0200 Subject: [PATCH 001/512] uefi: handle: add constructor This is a prerequisite for the next step. --- uefi/CHANGELOG.md | 2 ++ uefi/src/data_types/mod.rs | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 32429126e..f7b2db0c2 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,5 +1,7 @@ # uefi - [Unreleased] +## Added +- Added `Handle::new` # uefi - 0.31.0 (2024-08-21) diff --git a/uefi/src/data_types/mod.rs b/uefi/src/data_types/mod.rs index 33cd201ff..463fa7ff7 100644 --- a/uefi/src/data_types/mod.rs +++ b/uefi/src/data_types/mod.rs @@ -13,6 +13,17 @@ use core::ptr::{self, NonNull}; pub struct Handle(NonNull); impl Handle { + /// Creates a new [`Handle`]. + /// + /// # Safety + /// This function is unsafe because the caller must be sure that the pointer + /// is valid. Otherwise, further operations on the object might result in + /// undefined behaviour, even if the methods aren't marked as unsafe. + #[must_use] + pub const unsafe fn new(ptr: NonNull) -> Self { + Self(ptr) + } + /// Creates a new [`Handle`] from a raw address. The address might /// come from the Multiboot2 information structure or something similar. /// From 47aaec7b822c848ce77e8e21babf164248af29ba Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Thu, 15 Aug 2024 12:23:19 +0200 Subject: [PATCH 002/512] workspace: add uefi-std-example member --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + README.md | 2 ++ uefi-std-example/Cargo.toml | 11 +++++++++++ uefi-std-example/README.md | 18 ++++++++++++++++++ uefi-std-example/src/main.rs | 31 +++++++++++++++++++++++++++++++ 6 files changed, 70 insertions(+) create mode 100644 uefi-std-example/Cargo.toml create mode 100644 uefi-std-example/README.md create mode 100644 uefi-std-example/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index c40e334fb..de598e93b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -903,6 +903,13 @@ dependencies = [ "uguid", ] +[[package]] +name = "uefi-std-example" +version = "0.1.0" +dependencies = [ + "uefi", +] + [[package]] name = "uefi-test-runner" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 89e9533f5..57263c679 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "uefi", "uefi-macros", "uefi-raw", + "uefi-std-example", "uefi-test-runner", "xtask", ] diff --git a/README.md b/README.md index f352b7632..01c656cf2 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,8 @@ This project contains multiple sub-crates: Specification. Safe wrappers for these types are provided by the `uefi` crate. The raw types are suitable for implementing UEFI firmware. +- `uefi-std-example`: Example UEFI app but as Rust standard binary. + - `uefi-test-runner`: a UEFI application that runs unit / integration tests. [log]: https://github.com/rust-lang-nursery/log diff --git a/uefi-std-example/Cargo.toml b/uefi-std-example/Cargo.toml new file mode 100644 index 000000000..5a2e3e293 --- /dev/null +++ b/uefi-std-example/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "uefi-std-example" +version = "0.1.0" +authors = ["The Rust OSDev team"] +publish = false +edition = "2021" + +[dependencies] +# Attention: Don't activate the panic_handler feature, as it will clash with +# the one coming from `std`. +uefi = { path = "../uefi", features = ["alloc"], default-features = false } diff --git a/uefi-std-example/README.md b/uefi-std-example/README.md new file mode 100644 index 000000000..dc57c41bd --- /dev/null +++ b/uefi-std-example/README.md @@ -0,0 +1,18 @@ +# Minimal Rust App using `std` and `uefi` + +Minimal example of a "standard Rust application" that showcases how `uefi` can +be utilized and enhance the developers experience, when `std` is available. + +For simplicity, this example is minimal and the documentation is focused on +`x86_64-unknown-uefi`. However, it works similar for other supported UEFI +platforms. + +## Build + +Build the app using +`$ cargo +nightly build --target x86_64-unknown-uefi`. To build it from the root +directory (the Cargo workspace), append `-p uefi-std-example`. + +## Run + +The resulting `.efi` file can be found in `target/x86_64-unknown-uefi//uefi-std-example.efi`. diff --git a/uefi-std-example/src/main.rs b/uefi-std-example/src/main.rs new file mode 100644 index 000000000..6bb17c61c --- /dev/null +++ b/uefi-std-example/src/main.rs @@ -0,0 +1,31 @@ +// Note: In Rust 1.82.0-nightly and before, the `uefi_std` feature is +// required for accessing `std::os::uefi::env::*`. The other default +// functionality doesn't need a nightly toolchain (with Rust 1.80 and later), +// but with that limited functionality you - currently - also can't integrate +// the `uefi` crate. +#![feature(uefi_std)] + +use std::os::uefi as uefi_std; +use uefi::runtime::ResetType; +use uefi::{Handle, Status}; + +/// Performs the necessary setup code for the `uefi` crate. +fn setup_uefi_crate() { + let st = uefi_std::env::system_table(); + let ih = uefi_std::env::image_handle(); + + // Mandatory setup code for `uefi` crate. + unsafe { + uefi::table::set_system_table(st.as_ptr().cast()); + + let ih = Handle::from_ptr(ih.as_ptr().cast()).unwrap(); + uefi::boot::set_image_handle(ih); + } +} + +fn main() { + println!("Hello World from uefi_std"); + setup_uefi_crate(); + println!("UEFI-Version is {}", uefi::system::uefi_revision()); + uefi::runtime::reset(ResetType::SHUTDOWN, Status::SUCCESS, None); +} From 547e53b05dd6cbe33e3c2b58be64513382b8a7b6 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Wed, 14 Aug 2024 20:27:24 +0200 Subject: [PATCH 003/512] ci: build uefi-std-example workspace member --- .github/workflows/rust.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0f09f2701..dfb4abe74 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -170,3 +170,16 @@ jobs: run: | rustup component add miri cargo xtask miri + # Builds a Rust standard binary using the `std` impl for UEFI, rather than + # creating a `no_std` + `no_main` binary. + build_standard_uefi_binary: + name: Build Standard Binary (nightly) + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Set toolchain + run: cp .github/workflows/nightly_toolchain.toml rust-toolchain.toml + - uses: Swatinem/rust-cache@v2 + - name: Build + run: cargo +nightly build --target x86_64-unknown-uefi --verbose -p uefi-std-example From 7212462a9985eb39614eb110db9412a8b07f654f Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Thu, 15 Aug 2024 12:24:16 +0200 Subject: [PATCH 004/512] doc: add rust-std chapter to book --- book/src/SUMMARY.md | 1 + book/src/how_to/rust-std.md | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 book/src/how_to/rust-std.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index bf8972087..bcdd27a65 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -10,6 +10,7 @@ - [Using Protocols](how_to/protocols.md) - [Drawing to the Screen](how_to/drawing.md) - [Building drivers](how_to/building_drivers.md) + - [Combining Rust `std` with `uefi`](how_to/rust-std.md) - [Concepts](concepts/introduction.md) - [Boot Stages](concepts/boot_stages.md) - [Tables](concepts/tables.md) diff --git a/book/src/how_to/rust-std.md b/book/src/how_to/rust-std.md new file mode 100644 index 000000000..5d3284298 --- /dev/null +++ b/book/src/how_to/rust-std.md @@ -0,0 +1,29 @@ +# Combining Rust `std` with `uefi` + +## TL;DR + +In Mid-2024, we recommend to stick to our normal guide. Use this document as +guide and outlook for the future of UEFI and Rust. + +## About + +Programs created with the `uefi` crate are typically created with `#![no_std]` +and `#![no_main]`. A `#![no_std]` crate can use the `core` and `alloc` parts of +Rust's standard library, but not `std`. A `#![no_main]` executable does not use +the standard main entry point, and must define its own entry point; `uefi` +provides the `#[entry]` macro for this purpose. + +Rust has added partial support for building UEFI executables without +`#![no_std]` and `#![no_main]`, thus, the standard way. Some functionality +requires a nightly toolchain, they are gated by the `uefi_std` feature (Rust +language feature, not `uefi` crate feature). Follow the +[tracking issue](https://github.com/rust-lang/rust/issues/100499) for details. + +## Code Example + +Please refer to [`/uefi-std-example`](/uefi-std-example/README.md) to +see a specific example. The relevant `main.rs` looks as follows: + +```rust +{{#include ../../../uefi-std-example/src/main.rs}} +``` From 2e661655866580f15d7fb3082920634954fd02b8 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Thu, 15 Aug 2024 12:24:25 +0200 Subject: [PATCH 005/512] nix: add mdbook tool to locally build and serve the book --- shell.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/shell.nix b/shell.nix index f16ba337c..72d5f9328 100644 --- a/shell.nix +++ b/shell.nix @@ -21,6 +21,7 @@ pkgs.mkShell { rustToolchain # Other + mdbook yamlfmt which # used by "cargo xtask fmt" ]; From 8b09be32f968b7bd7882fc002388138a2069d29b Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Thu, 15 Aug 2024 12:21:56 +0200 Subject: [PATCH 006/512] uefi: update CHANGELOG --- uefi/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index f7b2db0c2..a451e1fdc 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,5 +1,9 @@ # uefi - [Unreleased] +We added documentation to `lib.rs` and the [uefi-rs book] about how +`uefi` compares to "standard Rust binaries" for UEFI (those using `std`), and +how to integrate the `uefi` crate into them. + ## Added - Added `Handle::new` @@ -605,3 +609,6 @@ Rust 1.68 or higher. truncated and could result in out-of-bounds reads. - Fixed size check for file info types so that alignment padding is taken into account. This fixes potential out-of-bounds writes. + + +[uefi-rs book]: https://rust-osdev.github.io/uefi-rs/HEAD From cdca03e91f7ab2bde082518d08548d4aca3b4a2e Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Tue, 30 Jul 2024 10:23:54 +0200 Subject: [PATCH 007/512] doc: add "API/User Documentation, Documentation Structure, and other Resources" This is logically following the About section. --- uefi/README.md | 17 ----------------- uefi/src/lib.rs | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/uefi/README.md b/uefi/README.md index 962fad270..69e168975 100644 --- a/uefi/README.md +++ b/uefi/README.md @@ -33,23 +33,6 @@ This crate's features are described in [`src/lib.rs`]. [`src/lib.rs`]: src/lib.rs -## User Documentation - - - -For a quick start, please check out [the UEFI application template](template). - -The [uefi-rs book] contains a tutorial, how-tos, and overviews of some important -UEFI concepts. Reference documentation for the various crates can be found on -[docs.rs]: - -- [docs.rs/uefi](https://docs.rs/uefi) -- [docs.rs/uefi-macros](https://docs.rs/uefi-macros) -- [docs.rs/uefi-raw](https://docs.rs/uefi-raw) - -[spec]: http://www.uefi.org/specifications -[uefi-rs book]: https://rust-osdev.github.io/uefi-rs/HEAD - ## MSRV The minimum supported Rust version is currently 1.70. diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 851dd74a7..66537afb8 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -69,6 +69,19 @@ //! The minimum supported Rust version is currently 1.70. //! 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]. +//! //! # Crate organisation //! //! The top-level module contains some of the most used types and macros, @@ -190,6 +203,7 @@ //! [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 +//! [template]: https://github.com/rust-osdev/uefi-rs/tree/main/template //! [unstable features]: https://doc.rust-lang.org/unstable-book/ //! [rustc-uefi-std]: https://doc.rust-lang.org/nightly/rustc/platform-support/unknown-uefi.html //! [uefi-std-tr-issue]: https://github.com/rust-lang/rust/issues/100499 From 63e37c4d4a2fd99b0ced55b793fd9175cd45803d Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Tue, 30 Jul 2024 10:25:07 +0200 Subject: [PATCH 008/512] doc: lib.rs: Crate organization -> Library Structure & Tips Also added "UEFI Strings" subsection --- uefi/src/lib.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 66537afb8..e9a4e037b 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -82,13 +82,21 @@ //! //! For more details of UEFI itself, see the latest [UEFI Specification][spec]. //! -//! # Crate organisation +//! # 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 //! //! The [`SystemTable`] provides access to almost everything in UEFI. It comes @@ -199,6 +207,7 @@ //! [`SystemTable`]: table::SystemTable //! [`r-efi`]: https://crates.io/crates/r-efi //! [`entry-macro`]: uefi_macros::entry +//! [`ctr16!`]: crate::cstr16 //! [`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 From edb859dcb276811744b7339b427fd3cd056252fd Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 12 Aug 2024 18:59:34 -0400 Subject: [PATCH 009/512] uefi: Drop BootServices arg from device path <-> text conversions Since BootServices will be deprecated, we don't want the public API to require using it. --- uefi-test-runner/examples/loaded_image.rs | 1 - uefi-test-runner/src/proto/device_path.rs | 6 +-- uefi/CHANGELOG.md | 5 +++ uefi/src/proto/device_path/mod.rs | 25 +++++------- uefi/src/proto/device_path/text.rs | 47 +++++++++-------------- 5 files changed, 35 insertions(+), 49 deletions(-) diff --git a/uefi-test-runner/examples/loaded_image.rs b/uefi-test-runner/examples/loaded_image.rs index 216af7a89..1f72bcbdb 100644 --- a/uefi-test-runner/examples/loaded_image.rs +++ b/uefi-test-runner/examples/loaded_image.rs @@ -49,7 +49,6 @@ fn print_image_path(boot_services: &BootServices) -> Result { loaded_image.file_path().expect("File path is not set"); let image_device_path_text = device_path_to_text .convert_device_path_to_text( - boot_services, image_device_path, DisplayOnly(true), AllowShortcuts(false), diff --git a/uefi-test-runner/src/proto/device_path.rs b/uefi-test-runner/src/proto/device_path.rs index 311b51847..b9f1ee0c0 100644 --- a/uefi-test-runner/src/proto/device_path.rs +++ b/uefi-test-runner/src/proto/device_path.rs @@ -43,7 +43,7 @@ pub fn test(bt: &BootServices) { ); let text = device_path_to_text - .convert_device_node_to_text(bt, path, DisplayOnly(true), AllowShortcuts(false)) + .convert_device_node_to_text(path, DisplayOnly(true), AllowShortcuts(false)) .expect("Failed to convert device path to text"); let text = &*text; info!("path name: {text}"); @@ -81,7 +81,7 @@ pub fn test(bt: &BootServices) { let path_components = device_path .node_iter() - .map(|node| node.to_string(bt, DisplayOnly(false), AllowShortcuts(false))) + .map(|node| node.to_string(DisplayOnly(false), AllowShortcuts(false))) .map(|str| str.unwrap().to_string()) .collect::>(); @@ -107,7 +107,7 @@ pub fn test(bt: &BootServices) { // Test that to_string works for device_paths let path = device_path - .to_string(bt, DisplayOnly(false), AllowShortcuts(false)) + .to_string(DisplayOnly(false), AllowShortcuts(false)) .unwrap() .to_string(); diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index a451e1fdc..ea000fc05 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -7,6 +7,11 @@ how to integrate the `uefi` crate into them. ## Added - Added `Handle::new` +## Changed +- **Breaking:** The conversion functions between device paths and text no longer + take a `BootServices` argument. The global system table is used instead. + + # uefi - 0.31.0 (2024-08-21) See [Deprecating SystemTable/BootServices/RuntimeServices][funcmigrate] for diff --git a/uefi/src/proto/device_path/mod.rs b/uefi/src/proto/device_path/mod.rs index feae09d97..49462c0f5 100644 --- a/uefi/src/proto/device_path/mod.rs +++ b/uefi/src/proto/device_path/mod.rs @@ -90,10 +90,8 @@ use ptr_meta::Pointee; #[cfg(feature = "alloc")] use { + crate::boot::{self, OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol, SearchType}, crate::proto::device_path::text::{AllowShortcuts, DevicePathToText, DisplayOnly}, - crate::table::boot::{ - BootServices, OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol, SearchType, - }, crate::{CString16, Identify}, alloc::borrow::ToOwned, alloc::boxed::Box, @@ -232,14 +230,13 @@ impl DevicePathNode { #[cfg(feature = "alloc")] pub fn to_string( &self, - bs: &BootServices, display_only: DisplayOnly, allow_shortcuts: AllowShortcuts, ) -> Result { - let to_text_protocol = open_text_protocol(bs)?; + let to_text_protocol = open_text_protocol()?; to_text_protocol - .convert_device_node_to_text(bs, self, display_only, allow_shortcuts) + .convert_device_node_to_text(self, display_only, allow_shortcuts) .map(|pool_string| { let cstr16 = &*pool_string; // Another allocation; pool string is dropped. This overhead @@ -484,14 +481,13 @@ impl DevicePath { #[cfg(feature = "alloc")] pub fn to_string( &self, - bs: &BootServices, display_only: DisplayOnly, allow_shortcuts: AllowShortcuts, ) -> Result { - let to_text_protocol = open_text_protocol(bs)?; + let to_text_protocol = open_text_protocol()?; to_text_protocol - .convert_device_path_to_text(bs, self, display_only, allow_shortcuts) + .convert_device_path_to_text(self, display_only, allow_shortcuts) .map(|pool_string| { let cstr16 = &*pool_string; // Another allocation; pool string is dropped. This overhead @@ -878,20 +874,17 @@ impl core::error::Error for DevicePathToTextError { /// Helper function to open the [`DevicePathToText`] protocol using the boot /// services. #[cfg(feature = "alloc")] -fn open_text_protocol( - bs: &BootServices, -) -> Result, DevicePathToTextError> { - let &handle = bs - .locate_handle_buffer(SearchType::ByProtocol(&DevicePathToText::GUID)) +fn open_text_protocol() -> Result, DevicePathToTextError> { + let &handle = boot::locate_handle_buffer(SearchType::ByProtocol(&DevicePathToText::GUID)) .map_err(DevicePathToTextError::CantLocateHandleBuffer)? .first() .ok_or(DevicePathToTextError::NoHandle)?; unsafe { - bs.open_protocol::( + boot::open_protocol::( OpenProtocolParams { handle, - agent: bs.image_handle(), + agent: boot::image_handle(), controller: None, }, OpenProtocolAttributes::GetProtocol, diff --git a/uefi/src/proto/device_path/text.rs b/uefi/src/proto/device_path/text.rs index 5bff5c9c2..ebd725b3e 100644 --- a/uefi/src/proto/device_path/text.rs +++ b/uefi/src/proto/device_path/text.rs @@ -10,9 +10,9 @@ use crate::proto::device_path::{DevicePath, DevicePathNode}; use crate::proto::unsafe_protocol; -use crate::table::boot::BootServices; -use crate::{CStr16, Char16, Result, Status}; +use crate::{boot, CStr16, Char16, Result, Status}; use core::ops::Deref; +use core::ptr::NonNull; use uefi_raw::protocol::device_path::{DevicePathFromTextProtocol, DevicePathToTextProtocol}; /// This struct is a wrapper of `display_only` parameter @@ -42,36 +42,27 @@ pub struct AllowShortcuts(pub bool); /// Wrapper for a string internally allocated from /// UEFI boot services memory. #[derive(Debug)] -pub struct PoolString<'a> { - boot_services: &'a BootServices, - text: *const Char16, -} +pub struct PoolString(NonNull); -impl<'a> PoolString<'a> { - fn new(boot_services: &'a BootServices, text: *const Char16) -> Result { - if text.is_null() { - Err(Status::OUT_OF_RESOURCES.into()) - } else { - Ok(Self { - boot_services, - text, - }) - } +impl PoolString { + fn new(text: *const Char16) -> Result { + NonNull::new(text.cast_mut()) + .map(Self) + .ok_or(Status::OUT_OF_RESOURCES.into()) } } -impl<'a> Deref for PoolString<'a> { +impl Deref for PoolString { type Target = CStr16; fn deref(&self) -> &Self::Target { - unsafe { CStr16::from_ptr(self.text) } + unsafe { CStr16::from_ptr(self.0.as_ptr()) } } } -impl Drop for PoolString<'_> { +impl Drop for PoolString { fn drop(&mut self) { - let addr = self.text as *mut u8; - unsafe { self.boot_services.free_pool(addr) }.expect("Failed to free pool [{addr:#?}]"); + unsafe { boot::free_pool(self.0.cast()) }.expect("Failed to free pool [{addr:#?}]"); } } @@ -91,13 +82,12 @@ impl DevicePathToText { /// memory for the conversion. /// /// [`OUT_OF_RESOURCES`]: Status::OUT_OF_RESOURCES - pub fn convert_device_node_to_text<'boot>( + pub fn convert_device_node_to_text( &self, - boot_services: &'boot BootServices, device_node: &DevicePathNode, display_only: DisplayOnly, allow_shortcuts: AllowShortcuts, - ) -> Result> { + ) -> Result { let text_device_node = unsafe { (self.0.convert_device_node_to_text)( device_node.as_ffi_ptr().cast(), @@ -105,7 +95,7 @@ impl DevicePathToText { allow_shortcuts.0, ) }; - PoolString::new(boot_services, text_device_node.cast()) + PoolString::new(text_device_node.cast()) } /// Convert a device path to its text representation. @@ -114,13 +104,12 @@ impl DevicePathToText { /// memory for the conversion. /// /// [`OUT_OF_RESOURCES`]: Status::OUT_OF_RESOURCES - pub fn convert_device_path_to_text<'boot>( + pub fn convert_device_path_to_text( &self, - boot_services: &'boot BootServices, device_path: &DevicePath, display_only: DisplayOnly, allow_shortcuts: AllowShortcuts, - ) -> Result> { + ) -> Result { let text_device_path = unsafe { (self.0.convert_device_path_to_text)( device_path.as_ffi_ptr().cast(), @@ -128,7 +117,7 @@ impl DevicePathToText { allow_shortcuts.0, ) }; - PoolString::new(boot_services, text_device_path.cast()) + PoolString::new(text_device_path.cast()) } } From 70ad9411e2ee7bb5f31baeb5227ed3865b531642 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 12 Aug 2024 18:48:08 -0400 Subject: [PATCH 010/512] test-runner: Convert all examples to new style Drop all uses of SystemTable, BootServices, and RuntimeServices. --- uefi-test-runner/examples/hello_world.rs | 2 +- uefi-test-runner/examples/loaded_image.rs | 33 +++++++++++------------ uefi-test-runner/examples/shell_params.rs | 2 +- uefi-test-runner/examples/sierpinski.rs | 17 ++++++------ uefi-test-runner/examples/timestamp.rs | 18 ++++++------- 5 files changed, 35 insertions(+), 37 deletions(-) diff --git a/uefi-test-runner/examples/hello_world.rs b/uefi-test-runner/examples/hello_world.rs index 91081cb9e..ba858b1c8 100644 --- a/uefi-test-runner/examples/hello_world.rs +++ b/uefi-test-runner/examples/hello_world.rs @@ -11,7 +11,7 @@ use uefi::prelude::*; // ANCHOR: entry #[entry] -fn main(_image_handle: Handle, system_table: SystemTable) -> Status { +fn main() -> Status { // ANCHOR_END: entry // ANCHOR: services uefi::helpers::init().unwrap(); diff --git a/uefi-test-runner/examples/loaded_image.rs b/uefi-test-runner/examples/loaded_image.rs index 1f72bcbdb..bb9e5f0c7 100644 --- a/uefi-test-runner/examples/loaded_image.rs +++ b/uefi-test-runner/examples/loaded_image.rs @@ -3,45 +3,44 @@ #![no_std] use log::info; +use uefi::boot::{self, SearchType}; use uefi::prelude::*; use uefi::proto::device_path::text::{ AllowShortcuts, DevicePathToText, DisplayOnly, }; use uefi::proto::loaded_image::LoadedImage; -use uefi::table::boot::SearchType; use uefi::{Identify, Result}; // ANCHOR: main #[entry] -fn main(image_handle: Handle, system_table: SystemTable) -> Status { +fn main() -> Status { uefi::helpers::init().unwrap(); - let boot_services = system_table.boot_services(); - print_image_path(boot_services).unwrap(); + print_image_path().unwrap(); - boot_services.stall(10_000_000); + boot::stall(10_000_000); Status::SUCCESS } // ANCHOR_END: main // ANCHOR: print_image_path -fn print_image_path(boot_services: &BootServices) -> Result { +fn print_image_path() -> Result { // ANCHOR_END: print_image_path // ANCHOR: loaded_image - let loaded_image = boot_services - .open_protocol_exclusive::(boot_services.image_handle())?; + let loaded_image = + boot::open_protocol_exclusive::(boot::image_handle())?; // ANCHOR_END: loaded_image // ANCHOR: device_path - let device_path_to_text_handle = *boot_services - .locate_handle_buffer(SearchType::ByProtocol(&DevicePathToText::GUID))? - .first() - .expect("DevicePathToText is missing"); - - let device_path_to_text = boot_services - .open_protocol_exclusive::( - device_path_to_text_handle, - )?; + let device_path_to_text_handle = *boot::locate_handle_buffer( + SearchType::ByProtocol(&DevicePathToText::GUID), + )? + .first() + .expect("DevicePathToText is missing"); + + let device_path_to_text = boot::open_protocol_exclusive::( + device_path_to_text_handle, + )?; // ANCHOR_END: device_path // ANCHOR: text diff --git a/uefi-test-runner/examples/shell_params.rs b/uefi-test-runner/examples/shell_params.rs index 90d72bcb8..9aef92dae 100644 --- a/uefi-test-runner/examples/shell_params.rs +++ b/uefi-test-runner/examples/shell_params.rs @@ -17,7 +17,7 @@ use alloc::vec::Vec; // ANCHOR: entry #[entry] -fn main(image_handle: Handle, system_table: SystemTable) -> Status { +fn main() -> Status { // ANCHOR_END: entry // ANCHOR: services uefi::helpers::init().unwrap(); diff --git a/uefi-test-runner/examples/sierpinski.rs b/uefi-test-runner/examples/sierpinski.rs index f0b0912c3..28906e3c9 100644 --- a/uefi-test-runner/examples/sierpinski.rs +++ b/uefi-test-runner/examples/sierpinski.rs @@ -10,7 +10,7 @@ use core::mem; use uefi::prelude::*; use uefi::proto::console::gop::{BltOp, BltPixel, BltRegion, GraphicsOutput}; use uefi::proto::rng::Rng; -use uefi::Result; +use uefi::{boot, Result}; #[derive(Clone, Copy)] struct Point { @@ -82,14 +82,14 @@ fn get_random_usize(rng: &mut Rng) -> usize { usize::from_le_bytes(buf) } -fn draw_sierpinski(bt: &BootServices) -> Result { +fn draw_sierpinski() -> Result { // Open graphics output protocol. - let gop_handle = bt.get_handle_for_protocol::()?; - let mut gop = bt.open_protocol_exclusive::(gop_handle)?; + let gop_handle = boot::get_handle_for_protocol::()?; + let mut gop = boot::open_protocol_exclusive::(gop_handle)?; // Open random number generator protocol. - let rng_handle = bt.get_handle_for_protocol::()?; - let mut rng = bt.open_protocol_exclusive::(rng_handle)?; + let rng_handle = boot::get_handle_for_protocol::()?; + let mut rng = boot::open_protocol_exclusive::(rng_handle)?; // Create a buffer to draw into. let (width, height) = gop.current_mode_info().resolution(); @@ -144,10 +144,9 @@ fn draw_sierpinski(bt: &BootServices) -> Result { } #[entry] -fn main(_handle: Handle, system_table: SystemTable) -> Status { +fn main() -> Status { uefi::helpers::init().unwrap(); - let bt = system_table.boot_services(); - draw_sierpinski(bt).unwrap(); + draw_sierpinski().unwrap(); Status::SUCCESS } // ANCHOR_END: all diff --git a/uefi-test-runner/examples/timestamp.rs b/uefi-test-runner/examples/timestamp.rs index 1ce578614..88cb53add 100644 --- a/uefi-test-runner/examples/timestamp.rs +++ b/uefi-test-runner/examples/timestamp.rs @@ -9,6 +9,7 @@ extern crate alloc; use log::{info, warn}; // ANCHOR: use +use uefi::boot; use uefi::prelude::*; use uefi::proto::misc::Timestamp; @@ -16,19 +17,18 @@ use uefi::proto::misc::Timestamp; // ANCHOR: entry #[entry] -fn main(image_handle: Handle, system_table: SystemTable) -> Status { +fn main() -> Status { // ANCHOR_END: entry // ANCHOR: services uefi::helpers::init().unwrap(); - let boot_services = system_table.boot_services(); // ANCHOR_END: services // ANCHOR: params - test_timestamp(boot_services); + test_timestamp(); // ANCHOR_END: params // ANCHOR: stall - boot_services.stall(10_000_000); + boot::stall(10_000_000); // ANCHOR_END: stall // ANCHOR: return @@ -37,17 +37,17 @@ fn main(image_handle: Handle, system_table: SystemTable) -> Status { // ANCHOR_END: return // ANCHOR: test_timestamp -pub fn test_timestamp(bt: &BootServices) { +pub fn test_timestamp() { // ANCHOR_END: test_timestamp info!("Running loaded Timestamp Protocol test"); - let handle = bt.get_handle_for_protocol::(); + let handle = boot::get_handle_for_protocol::(); match handle { Ok(handle) => { - let timestamp_proto = bt - .open_protocol_exclusive::(handle) - .expect("Founded Timestamp Protocol but open failed"); + let timestamp_proto = + boot::open_protocol_exclusive::(handle) + .expect("Founded Timestamp Protocol but open failed"); // ANCHOR: text let timestamp = timestamp_proto.get_timestamp(); info!("Timestamp Protocol's timestamp: {:?}", timestamp); From 09e2809734140720c13cefda11880430ff42d9e3 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 23 Aug 2024 22:46:49 -0400 Subject: [PATCH 011/512] uefi: Drop BootServices arg from GraphicsOutput::modes --- uefi-test-runner/src/proto/console/gop.rs | 6 +++--- uefi/CHANGELOG.md | 2 ++ uefi/src/proto/console/gop.rs | 17 ++++++++--------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/uefi-test-runner/src/proto/console/gop.rs b/uefi-test-runner/src/proto/console/gop.rs index 7afb163fd..26a71b6d0 100644 --- a/uefi-test-runner/src/proto/console/gop.rs +++ b/uefi-test-runner/src/proto/console/gop.rs @@ -22,7 +22,7 @@ pub unsafe fn test(bt: &BootServices) { ) .expect("failed to open Graphics Output Protocol"); - set_graphics_mode(gop, bt); + set_graphics_mode(gop); fill_color(gop); draw_fb(gop); @@ -33,10 +33,10 @@ pub unsafe fn test(bt: &BootServices) { } // Set a larger graphics mode. -fn set_graphics_mode(gop: &mut GraphicsOutput, bs: &BootServices) { +fn set_graphics_mode(gop: &mut GraphicsOutput) { // We know for sure QEMU has a 1024x768 mode. let mode = gop - .modes(bs) + .modes() .find(|mode| { let info = mode.info(); info.resolution() == (1024, 768) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index ea000fc05..ecfc8ce69 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -10,6 +10,8 @@ how to integrate the `uefi` crate into them. ## Changed - **Breaking:** The conversion functions between device paths and text no longer take a `BootServices` argument. The global system table is used instead. +- **Breaking:** `GraphicsOutput::modes` no longer takes a `BootServices` + argument. The global system table is used instead. # uefi - 0.31.0 (2024-08-21) diff --git a/uefi/src/proto/console/gop.rs b/uefi/src/proto/console/gop.rs index 0676df547..81e60b708 100644 --- a/uefi/src/proto/console/gop.rs +++ b/uefi/src/proto/console/gop.rs @@ -50,13 +50,13 @@ //! You will have to implement your own double buffering if you want to //! avoid tearing with animations. -use crate::prelude::BootServices; use crate::proto::unsafe_protocol; use crate::util::usize_from_u32; -use crate::{Result, StatusExt}; +use crate::{boot, Result, StatusExt}; use core::fmt::{Debug, Formatter}; use core::marker::PhantomData; -use core::{mem, ptr}; +use core::mem; +use core::ptr::{self, NonNull}; use uefi_raw::protocol::console::{ GraphicsOutputBltOperation, GraphicsOutputModeInformation, GraphicsOutputProtocol, GraphicsOutputProtocolMode, @@ -76,7 +76,7 @@ pub struct GraphicsOutput(GraphicsOutputProtocol); impl GraphicsOutput { /// Returns information for an available graphics mode that the graphics /// device and the set of active video output devices supports. - fn query_mode(&self, index: u32, bs: &BootServices) -> Result { + fn query_mode(&self, index: u32) -> Result { let mut info_sz = 0; let mut info_heap_ptr = ptr::null(); // query_mode allocates a buffer and stores the heap ptr in the provided @@ -90,7 +90,8 @@ impl GraphicsOutput { // User has no benefit from propagating this error. If this // fails, it is an error of the UEFI implementation. - unsafe { bs.free_pool(info_heap_ptr) }.expect("buffer should be deallocatable"); + unsafe { boot::free_pool(NonNull::new(info_heap_ptr).unwrap()) } + .expect("buffer should be deallocatable"); Mode { index, @@ -102,10 +103,9 @@ impl GraphicsOutput { /// Returns a [`ModeIter`]. #[must_use] - pub const fn modes<'a>(&'a self, bs: &'a BootServices) -> ModeIter { + pub const fn modes(&self) -> ModeIter { ModeIter { gop: self, - bs, current: 0, max: self.mode().max_mode, } @@ -410,7 +410,6 @@ impl ModeInfo { /// Iterator for [`Mode`]s of the [`GraphicsOutput`] protocol. pub struct ModeIter<'gop> { gop: &'gop GraphicsOutput, - bs: &'gop BootServices, current: u32, max: u32, } @@ -421,7 +420,7 @@ impl<'gop> Iterator for ModeIter<'gop> { fn next(&mut self) -> Option { let index = self.current; if index < self.max { - let m = self.gop.query_mode(index, self.bs); + let m = self.gop.query_mode(index); self.current += 1; m.ok().or_else(|| self.next()) From 0fbe5b1ad96b503692becf26c7a68f588d2a67be Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 24 Aug 2024 07:24:02 +0000 Subject: [PATCH 012/512] fix(deps): update rust crate syn to v2.0.76 --- Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de598e93b..89f95123a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,7 +145,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -656,7 +656,7 @@ checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -722,9 +722,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.75" +version = "2.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" dependencies = [ "proc-macro2", "quote", @@ -787,7 +787,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", ] [[package]] @@ -889,7 +889,7 @@ version = "0.15.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.76", "trybuild", "uefi", ] @@ -1157,7 +1157,7 @@ dependencies = [ "regex", "serde_json", "sha2", - "syn 2.0.75", + "syn 2.0.76", "tar", "tempfile", "ureq", From 34d5de06147b6f82b7b8ae9fe3eb1ce8fd153f35 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 23 Aug 2024 21:46:49 -0400 Subject: [PATCH 013/512] uefi: Use standalone boot functions in the allocator --- uefi/src/allocator.rs | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/uefi/src/allocator.rs b/uefi/src/allocator.rs index 9518420cb..535da23fd 100644 --- a/uefi/src/allocator.rs +++ b/uefi/src/allocator.rs @@ -13,12 +13,12 @@ use core::alloc::{GlobalAlloc, Layout}; use core::ffi::c_void; -use core::ptr; +use core::ptr::{self, NonNull}; use core::sync::atomic::{AtomicPtr, AtomicU32, Ordering}; +use crate::boot; use crate::mem::memory_map::MemoryType; use crate::proto::loaded_image::LoadedImage; -use crate::table::boot::BootServices; use crate::table::{Boot, SystemTable}; /// Reference to the system table, used to call the boot services pool memory @@ -42,20 +42,12 @@ pub unsafe fn init(system_table: &mut SystemTable) { let boot_services = system_table.boot_services(); if let Ok(loaded_image) = - boot_services.open_protocol_exclusive::(boot_services.image_handle()) + boot::open_protocol_exclusive::(boot_services.image_handle()) { MEMORY_TYPE.store(loaded_image.data_type().0, Ordering::Release); } } -/// Access the boot services -fn boot_services() -> *const BootServices { - let ptr = SYSTEM_TABLE.load(Ordering::Acquire); - let system_table = - unsafe { SystemTable::from_ptr(ptr) }.expect("The system table handle is not available"); - system_table.boot_services() -} - /// Notify the allocator library that boot services are not safe to call anymore /// /// You must arrange for this function to be called on exit from UEFI boot services @@ -70,7 +62,7 @@ pub fn exit_boot_services() { pub struct Allocator; unsafe impl GlobalAlloc for Allocator { - /// Allocate memory using [`BootServices::allocate_pool`]. The allocation is + /// Allocate memory using [`boot::allocate_pool`]. The allocation is /// of type [`MemoryType::LOADER_DATA`] for UEFI applications, [`MemoryType::BOOT_SERVICES_DATA`] /// for UEFI boot drivers and [`MemoryType::RUNTIME_SERVICES_DATA`] for UEFI runtime drivers. unsafe fn alloc(&self, layout: Layout) -> *mut u8 { @@ -78,19 +70,16 @@ unsafe impl GlobalAlloc for Allocator { let align = layout.align(); let memory_type = MemoryType(MEMORY_TYPE.load(Ordering::Acquire)); - let boot_services = &*boot_services(); - if align > 8 { // The requested alignment is greater than 8, but `allocate_pool` is // only guaranteed to provide eight-byte alignment. Allocate extra // space so that we can return an appropriately-aligned pointer // within the allocation. - let full_alloc_ptr = - if let Ok(ptr) = boot_services.allocate_pool(memory_type, size + align) { - ptr.as_ptr() - } else { - return ptr::null_mut(); - }; + let full_alloc_ptr = if let Ok(ptr) = boot::allocate_pool(memory_type, size + align) { + ptr.as_ptr() + } else { + return ptr::null_mut(); + }; // Calculate the offset needed to get an aligned pointer within the // full allocation. If that offset is zero, increase it to `align` @@ -115,20 +104,24 @@ unsafe impl GlobalAlloc for Allocator { // The requested alignment is less than or equal to eight, and // `allocate_pool` always provides eight-byte alignment, so we can // use `allocate_pool` directly. - boot_services - .allocate_pool(memory_type, size) + boot::allocate_pool(memory_type, size) .map(|ptr| ptr.as_ptr()) .unwrap_or(ptr::null_mut()) } } - /// Deallocate memory using [`BootServices::free_pool`]. + /// Deallocate memory using [`boot::free_pool`]. unsafe fn dealloc(&self, mut ptr: *mut u8, layout: Layout) { if layout.align() > 8 { // Retrieve the pointer to the full allocation that was packed right // before the aligned allocation in `alloc`. ptr = (ptr as *const *mut u8).sub(1).read(); } - (*boot_services()).free_pool(ptr).unwrap(); + + // OK to unwrap: `ptr` is required to be a valid allocation by the trait API. + let ptr = NonNull::new(ptr).unwrap(); + + // Warning: this will panic after exiting boot services. + boot::free_pool(ptr).unwrap(); } } From 351d8a05cceb43fc936d78134cbd6465cb71e9f1 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 23 Aug 2024 21:43:09 -0400 Subject: [PATCH 014/512] uefi: Return null from allocator if boot services are not active --- uefi/src/allocator.rs | 4 ++++ uefi/src/boot.rs | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/uefi/src/allocator.rs b/uefi/src/allocator.rs index 535da23fd..760d576a8 100644 --- a/uefi/src/allocator.rs +++ b/uefi/src/allocator.rs @@ -66,6 +66,10 @@ unsafe impl GlobalAlloc for Allocator { /// of type [`MemoryType::LOADER_DATA`] for UEFI applications, [`MemoryType::BOOT_SERVICES_DATA`] /// for UEFI boot drivers and [`MemoryType::RUNTIME_SERVICES_DATA`] for UEFI runtime drivers. unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if !boot::are_boot_services_active() { + return ptr::null_mut(); + } + let size = layout.size(); let align = layout.align(); let memory_type = MemoryType(MEMORY_TYPE.load(Ordering::Acquire)); diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index 5337e5ff8..0f6170044 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -60,6 +60,18 @@ pub unsafe fn set_image_handle(image_handle: Handle) { IMAGE_HANDLE.store(image_handle.as_ptr(), Ordering::Release); } +/// Return true if boot services are active, false otherwise. +pub(crate) fn are_boot_services_active() -> bool { + let Some(st) = table::system_table_raw() else { + return false; + }; + + // SAFETY: valid per requirements of `set_system_table`. + let st = unsafe { st.as_ref() }; + + !st.boot_services.is_null() +} + fn boot_services_raw_panicking() -> NonNull { let st = table::system_table_raw_panicking(); // SAFETY: valid per requirements of `set_system_table`. From a001b5d03cad289cdd466d88bc2f62222126979a Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 23 Aug 2024 21:55:59 -0400 Subject: [PATCH 015/512] uefi: Rework how the allocator gets the memory type The static memory type is now initialized at the time of the first allocation rather than requiring a call to `init`. --- uefi/src/allocator.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/uefi/src/allocator.rs b/uefi/src/allocator.rs index 760d576a8..19addf1ce 100644 --- a/uefi/src/allocator.rs +++ b/uefi/src/allocator.rs @@ -55,6 +55,32 @@ pub fn exit_boot_services() { SYSTEM_TABLE.store(ptr::null_mut(), Ordering::Release); } +/// Get the memory type to use for allocation. +/// +/// The first time this is called, the data type of the loaded image will be +/// retrieved. That value is cached in a static and reused on subsequent +/// calls. If the memory type of the loaded image cannot be retrieved for some +/// reason, a default of `LOADER_DATA` is used. +fn get_memory_type() -> MemoryType { + // Initialize to a `RESERVED` to indicate the actual value hasn't been set yet. + static MEMORY_TYPE: AtomicU32 = AtomicU32::new(MemoryType::RESERVED.0); + + let memory_type = MEMORY_TYPE.load(Ordering::Acquire); + if memory_type == MemoryType::RESERVED.0 { + let memory_type = if let Ok(loaded_image) = + boot::open_protocol_exclusive::(boot::image_handle()) + { + loaded_image.data_type() + } else { + MemoryType::LOADER_DATA + }; + MEMORY_TYPE.store(memory_type.0, Ordering::Release); + memory_type + } else { + MemoryType(memory_type) + } +} + /// Allocator which uses the UEFI pool allocation functions. /// /// Only valid for as long as the UEFI boot services are available. @@ -72,7 +98,7 @@ unsafe impl GlobalAlloc for Allocator { let size = layout.size(); let align = layout.align(); - let memory_type = MemoryType(MEMORY_TYPE.load(Ordering::Acquire)); + let memory_type = get_memory_type(); if align > 8 { // The requested alignment is greater than 8, but `allocate_pool` is From 578931805a6b4d8b40726b65e2694e695bffbb8e Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 23 Aug 2024 22:00:20 -0400 Subject: [PATCH 016/512] uefi: Remove the implementations of allocator::{init,exit_boot_services} These are no longer needed and will be deprecated in the following commit. --- uefi/src/allocator.rs | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/uefi/src/allocator.rs b/uefi/src/allocator.rs index 19addf1ce..593e4ed79 100644 --- a/uefi/src/allocator.rs +++ b/uefi/src/allocator.rs @@ -12,48 +12,28 @@ //! Failure to do so will turn subsequent allocation into undefined behaviour. use core::alloc::{GlobalAlloc, Layout}; -use core::ffi::c_void; use core::ptr::{self, NonNull}; -use core::sync::atomic::{AtomicPtr, AtomicU32, Ordering}; +use core::sync::atomic::{AtomicU32, Ordering}; use crate::boot; use crate::mem::memory_map::MemoryType; use crate::proto::loaded_image::LoadedImage; use crate::table::{Boot, SystemTable}; -/// Reference to the system table, used to call the boot services pool memory -/// allocation functions. -/// -/// The pointer is only safe to dereference if UEFI boot services have not been -/// exited by the host application yet. -static SYSTEM_TABLE: AtomicPtr = AtomicPtr::new(ptr::null_mut()); - -/// The memory type used for pool memory allocations. -static MEMORY_TYPE: AtomicU32 = AtomicU32::new(MemoryType::LOADER_DATA.0); - /// Initializes the allocator. /// /// # Safety /// /// This function is unsafe because you _must_ make sure that exit_boot_services /// will be called when UEFI boot services will be exited. -pub unsafe fn init(system_table: &mut SystemTable) { - SYSTEM_TABLE.store(system_table.as_ptr().cast_mut(), Ordering::Release); - - let boot_services = system_table.boot_services(); - if let Ok(loaded_image) = - boot::open_protocol_exclusive::(boot_services.image_handle()) - { - MEMORY_TYPE.store(loaded_image.data_type().0, Ordering::Release); - } -} +#[allow(unused_unsafe)] +pub unsafe fn init(_: &mut SystemTable) {} /// Notify the allocator library that boot services are not safe to call anymore /// /// You must arrange for this function to be called on exit from UEFI boot services -pub fn exit_boot_services() { - SYSTEM_TABLE.store(ptr::null_mut(), Ordering::Release); -} +#[allow(clippy::missing_const_for_fn)] +pub fn exit_boot_services() {} /// Get the memory type to use for allocation. /// From 85667fb7bd8b577166b96633c744ac00bdee6af7 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 23 Aug 2024 21:58:41 -0400 Subject: [PATCH 017/512] uefi: Deprecate allocator::{init,exit_boot_services} These no longer do anything. --- uefi/CHANGELOG.md | 3 +++ uefi/src/allocator.rs | 25 ++++++++----------------- uefi/src/helpers/mod.rs | 15 ++------------- 3 files changed, 13 insertions(+), 30 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index ecfc8ce69..22837ec96 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -12,6 +12,9 @@ how to integrate the `uefi` crate into them. take a `BootServices` argument. The global system table is used instead. - **Breaking:** `GraphicsOutput::modes` no longer takes a `BootServices` argument. The global system table is used instead. +- `allocator::init` and `allocator::exit_boot_services` have been + deprecated. These functions are now no-ops. The allocator now internally uses + the global system table. # uefi - 0.31.0 (2024-08-21) diff --git a/uefi/src/allocator.rs b/uefi/src/allocator.rs index 593e4ed79..bd00d468a 100644 --- a/uefi/src/allocator.rs +++ b/uefi/src/allocator.rs @@ -3,13 +3,9 @@ //! If the `global_allocator` feature is enabled, the [`Allocator`] will be used //! as the global Rust allocator. //! -//! # Usage -//! -//! Call the `init` function with a reference to the boot services table. -//! Failure to do so before calling a memory allocating function will panic. -//! -//! Call the `exit_boot_services` function before exiting UEFI boot services. -//! Failure to do so will turn subsequent allocation into undefined behaviour. +//! This allocator can only be used while boot services are active. If boot +//! services are not active, `alloc` will return a null pointer, and `dealloc` +//! will panic. use core::alloc::{GlobalAlloc, Layout}; use core::ptr::{self, NonNull}; @@ -20,18 +16,13 @@ use crate::mem::memory_map::MemoryType; use crate::proto::loaded_image::LoadedImage; use crate::table::{Boot, SystemTable}; -/// Initializes the allocator. -/// -/// # Safety -/// -/// This function is unsafe because you _must_ make sure that exit_boot_services -/// will be called when UEFI boot services will be exited. -#[allow(unused_unsafe)] +/// Deprecated; this function is now a no-op. +#[deprecated = "this function is now a no-op"] +#[allow(unused_unsafe, clippy::missing_safety_doc)] pub unsafe fn init(_: &mut SystemTable) {} -/// Notify the allocator library that boot services are not safe to call anymore -/// -/// You must arrange for this function to be called on exit from UEFI boot services +/// Deprecated; this function is now a no-op. +#[deprecated = "this function is now a no-op"] #[allow(clippy::missing_const_for_fn)] pub fn exit_boot_services() {} diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index 650720966..3b1ac1db2 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -48,28 +48,20 @@ pub fn system_table() -> SystemTable { /// Initialize all helpers defined in [`uefi::helpers`] whose Cargo features /// are activated. /// -/// This must be called as early as possible, before trying to use logging or -/// memory allocation capabilities. +/// This must be called as early as possible, before trying to use logging. /// /// **PLEASE NOTE** that these helpers are meant for the pre exit boot service /// epoch. Limited functionality might work after exiting them, such as logging /// to the debugcon device. #[allow(clippy::missing_const_for_fn)] pub fn init() -> Result<()> { - // Setup logging and memory allocation - + // Set up logging. #[cfg(feature = "logger")] unsafe { let mut st = table::system_table_boot().expect("boot services are not active"); logger::init(&mut st); } - #[cfg(feature = "global_allocator")] - unsafe { - let mut st = table::system_table_boot().expect("boot services are not active"); - crate::allocator::init(&mut st); - } - Ok(()) } @@ -77,7 +69,4 @@ pub fn init() -> Result<()> { pub(crate) fn exit() { #[cfg(feature = "logger")] logger::disable(); - - #[cfg(feature = "global_allocator")] - crate::allocator::exit_boot_services(); } From cd4e81477688a1b94ad75ed81a959807f6ccd7d6 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 23 Aug 2024 22:57:37 -0400 Subject: [PATCH 018/512] uefi: Drop BootServices arg from ComponentName::open --- uefi-test-runner/src/proto/driver.rs | 43 +++++++++++-------------- uefi-test-runner/src/proto/mod.rs | 2 +- uefi/CHANGELOG.md | 2 ++ uefi/src/proto/driver/component_name.rs | 26 +++++++-------- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/uefi-test-runner/src/proto/driver.rs b/uefi-test-runner/src/proto/driver.rs index 267d1f1df..8ee3858fb 100644 --- a/uefi-test-runner/src/proto/driver.rs +++ b/uefi-test-runner/src/proto/driver.rs @@ -1,6 +1,6 @@ +use uefi::boot::{self, ScopedProtocol, SearchType}; use uefi::prelude::*; use uefi::proto::driver::{ComponentName, ComponentName2, LanguageError, LanguageIter}; -use uefi::table::boot::{ScopedProtocol, SearchType}; use uefi::{CStr16, Result}; #[allow(deprecated)] @@ -8,8 +8,8 @@ use uefi::proto::driver::ComponentName1; /// Generic interface for testing `ComponentName1`, `ComponentName2`, and /// `ComponentName`. -trait ComponentNameInterface<'a>: Sized { - fn open(boot_services: &'a BootServices, handle: Handle) -> Result; +trait ComponentNameInterface: Sized { + fn open(handle: Handle) -> Result; fn supported_languages(&self) -> core::result::Result; fn driver_name(&self, language: &str) -> Result<&CStr16>; fn controller_name( @@ -21,9 +21,9 @@ trait ComponentNameInterface<'a>: Sized { } #[allow(deprecated)] -impl<'a> ComponentNameInterface<'a> for ScopedProtocol<'a, ComponentName1> { - fn open(boot_services: &'a BootServices, handle: Handle) -> Result { - boot_services.open_protocol_exclusive::(handle) +impl ComponentNameInterface for ScopedProtocol { + fn open(handle: Handle) -> Result { + boot::open_protocol_exclusive::(handle) } fn supported_languages(&self) -> core::result::Result { @@ -44,9 +44,9 @@ impl<'a> ComponentNameInterface<'a> for ScopedProtocol<'a, ComponentName1> { } } -impl<'a> ComponentNameInterface<'a> for ScopedProtocol<'a, ComponentName2> { - fn open(boot_services: &'a BootServices, handle: Handle) -> Result { - boot_services.open_protocol_exclusive::(handle) +impl ComponentNameInterface for ScopedProtocol { + fn open(handle: Handle) -> Result { + boot::open_protocol_exclusive::(handle) } fn supported_languages(&self) -> core::result::Result { @@ -67,9 +67,9 @@ impl<'a> ComponentNameInterface<'a> for ScopedProtocol<'a, ComponentName2> { } } -impl<'a> ComponentNameInterface<'a> for ComponentName<'a> { - fn open(boot_services: &'a BootServices, handle: Handle) -> Result { - Self::open(boot_services, handle) +impl ComponentNameInterface for ComponentName { + fn open(handle: Handle) -> Result { + Self::open(handle) } fn supported_languages(&self) -> core::result::Result { @@ -90,13 +90,8 @@ impl<'a> ComponentNameInterface<'a> for ComponentName<'a> { } } -fn test_component_name<'a, C: ComponentNameInterface<'a>>( - boot_services: &'a BootServices, - english: &str, -) { - let all_handles = boot_services - .locate_handle_buffer(SearchType::AllHandles) - .unwrap(); +fn test_component_name(english: &str) { + let all_handles = boot::locate_handle_buffer(SearchType::AllHandles).unwrap(); let fat_driver_name = cstr16!("FAT File System Driver"); let fat_controller_name = cstr16!("FAT File System"); @@ -105,7 +100,7 @@ fn test_component_name<'a, C: ComponentNameInterface<'a>>( let component_name: C = all_handles .iter() .find_map(|handle| { - let component_name = C::open(boot_services, *handle).ok()?; + let component_name = C::open(*handle).ok()?; assert!(component_name .supported_languages() @@ -138,11 +133,11 @@ fn test_component_name<'a, C: ComponentNameInterface<'a>>( .expect("failed to find FAT controller"); } -pub fn test(boot_services: &BootServices) { +pub fn test() { info!("Running component name test"); #[allow(deprecated)] - test_component_name::>(boot_services, "eng"); - test_component_name::>(boot_services, "en"); - test_component_name::(boot_services, "en"); + test_component_name::>("eng"); + test_component_name::>("en"); + test_component_name::("en"); } diff --git a/uefi-test-runner/src/proto/mod.rs b/uefi-test-runner/src/proto/mod.rs index 09a9fd5ef..a1335b3af 100644 --- a/uefi-test-runner/src/proto/mod.rs +++ b/uefi-test-runner/src/proto/mod.rs @@ -16,7 +16,7 @@ pub fn test(st: &mut SystemTable) { debug::test(bt); device_path::test(bt); - driver::test(bt); + driver::test(); load::test(bt); loaded_image::test(bt); media::test(bt); diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 22837ec96..2c794c4c5 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -12,6 +12,8 @@ how to integrate the `uefi` crate into them. take a `BootServices` argument. The global system table is used instead. - **Breaking:** `GraphicsOutput::modes` no longer takes a `BootServices` argument. The global system table is used instead. +- **Breaking:** `ComponentName::open` no longer takes a `BootServices` + argument. The global system table is used instead. - `allocator::init` and `allocator::exit_boot_services` have been deprecated. These functions are now no-ops. The allocator now internally uses the global system table. diff --git a/uefi/src/proto/driver/component_name.rs b/uefi/src/proto/driver/component_name.rs index f3b647ebb..395e6730f 100644 --- a/uefi/src/proto/driver/component_name.rs +++ b/uefi/src/proto/driver/component_name.rs @@ -4,8 +4,8 @@ // allow more fine-grained, see https://github.com/rust-lang/rust/issues/62398. #![allow(deprecated)] +use crate::boot::{self, ScopedProtocol}; use crate::proto::unsafe_protocol; -use crate::table::boot::{BootServices, ScopedProtocol}; use crate::{CStr16, Error, Handle, Result, Status, StatusExt}; use core::fmt::{self, Debug, Display, Formatter}; use core::{ptr, slice}; @@ -153,24 +153,24 @@ impl ComponentName2 { /// Wrapper around [`ComponentName1`] and [`ComponentName2`]. This will use /// [`ComponentName2`] if available, otherwise it will back to /// [`ComponentName1`]. -pub enum ComponentName<'a> { +pub enum ComponentName { /// Opened [`ComponentName1`] protocol. - V1(ScopedProtocol<'a, ComponentName1>), + V1(ScopedProtocol), /// Opened [`ComponentName2`] protocol. - V2(ScopedProtocol<'a, ComponentName2>), + V2(ScopedProtocol), } -impl<'a> ComponentName<'a> { +impl ComponentName { /// Open the [`ComponentName2`] protocol if available, otherwise fall back to /// [`ComponentName1`]. - pub fn open(boot_services: &'a BootServices, handle: Handle) -> Result { - if let Ok(cn2) = boot_services.open_protocol_exclusive::(handle) { + pub fn open(handle: Handle) -> Result { + if let Ok(cn2) = boot::open_protocol_exclusive::(handle) { Ok(Self::V2(cn2)) } else { - Ok(Self::V1( - boot_services.open_protocol_exclusive::(handle)?, - )) + Ok(Self::V1(boot::open_protocol_exclusive::( + handle, + )?)) } } @@ -219,11 +219,11 @@ impl<'a> ComponentName<'a> { } } -impl<'a> Debug for ComponentName<'a> { +impl Debug for ComponentName { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { match self { - ComponentName::V1(_) => f.debug_tuple("V1").finish(), - ComponentName::V2(_) => f.debug_tuple("V2").finish(), + Self::V1(_) => f.debug_tuple("V1").finish(), + Self::V2(_) => f.debug_tuple("V2").finish(), } } } From f7f2bf989d677bbbedfda2db8b185078d6796192 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sat, 24 Aug 2024 17:04:29 +0200 Subject: [PATCH 019/512] uefi: doc: sort links alphabetically --- uefi/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index e9a4e037b..3368cd27c 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -205,17 +205,17 @@ //! [`BootServices`]: table::boot::BootServices //! [`GlobalAlloc`]: alloc::alloc::GlobalAlloc //! [`SystemTable`]: table::SystemTable -//! [`r-efi`]: https://crates.io/crates/r-efi -//! [`entry-macro`]: uefi_macros::entry //! [`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 -//! [unstable features]: https://doc.rust-lang.org/unstable-book/ -//! [rustc-uefi-std]: https://doc.rust-lang.org/nightly/rustc/platform-support/unknown-uefi.html //! [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))] From b9b30afd81a6624da2ae1820578ceca4f3f43ad0 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Tue, 30 Jul 2024 10:38:42 +0200 Subject: [PATCH 020/512] doc: final streamlining of README files Now, the README are the entry into the repository and guide the user to the actual documentation in lib.rs respectively on docs.rs. --- README.md | 82 +++++++++++++------------------------------------- uefi/README.md | 35 ++++++++------------- 2 files changed, 33 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index 01c656cf2..e08448eca 100644 --- a/README.md +++ b/README.md @@ -11,77 +11,37 @@ This crate makes it easy to develop Rust software that leverages **safe**, ![Build status](https://github.com/rust-osdev/uefi-rs/workflows/Rust/badge.svg) ![Stars](https://img.shields.io/github/stars/rust-osdev/uefi-rs) -## Description - -Our mission is to provide **safe** and **performant** wrappers for UEFI -interfaces, and allow developers to write idiomatic Rust code. - -This repository provides various crates: - -- `uefi-raw`: Raw Rust UEFI bindings for basic structures and functions. -- `uefi`: High-level wrapper around various low-level UEFI APIs. \ - Offers various optional features for typical Rust convenience, such as a - Logger and an Allocator. (_This is what you are usually looking for!_) -- `uefi-macros`: Helper macros. Used by `uefi`. - - -You can use the abstractions for example to: - -- create OS-specific loaders and leverage UEFI boot service -- access UEFI runtime services from an OS - -[UEFI]: https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface - ![UEFI App running in QEMU](https://imgur.com/SFPSVuO.png) Screenshot of an application running in QEMU on an UEFI firmware that leverages our Rust library. -## User Documentation - - - -For a quick start, please check out [the UEFI application template](template). +## API and User Documentation + -The [uefi-rs book] contains a tutorial, how-tos, and overviews of some important -UEFI concepts. Reference documentation for the various crates can be found on -[docs.rs]: - -- [docs.rs/uefi](https://docs.rs/uefi) -- [docs.rs/uefi-macros](https://docs.rs/uefi-macros) -- [docs.rs/uefi-raw](https://docs.rs/uefi-raw) - -For additional information, refer to the [UEFI specification][spec]. - -[spec]: https://uefi.org/specs/UEFI/2.10 -[uefi-rs book]: https://rust-osdev.github.io/uefi-rs/HEAD -[docs.rs]: https://docs.rs - -### MSRV - -See the [uefi package's README](uefi/README.md#MSRV). +The main contribution of this project is the [`uefi` crate](./uefi/README.md). +Please refer to [docs.rs](https://docs.rs/uefi) for comprehensive documentation +of the **latest stable release**. The latest not necessarily yet published +documentation can be found in [`src/lib.rs`](./uefi/src/lib.rs), which can also +be locally viewed by running `$ cargo xtask doc --open`. ## Developer Guide -### Project structure - -This project contains multiple sub-crates: +### Repository Structure -- `uefi`: defines the standard UEFI tables / interfaces. - The objective is to stay unopinionated and safely wrap most interfaces. - Additional opinionated features (such as a Logger) are feature-gated. - -- `uefi-macros`: procedural macros that are used to derive some traits - in `uefi`. - -- `uefi-raw`: raw types that closely match the definitions in the UEFI - Specification. Safe wrappers for these types are provided by the `uefi` - crate. The raw types are suitable for implementing UEFI firmware. - -- `uefi-std-example`: Example UEFI app but as Rust standard binary. - -- `uefi-test-runner`: a UEFI application that runs unit / integration tests. +This repository provides various crates: -[log]: https://github.com/rust-lang-nursery/log +- [`uefi`](/uefi/README.md): High-level wrapper around various low-level UEFI + APIs. This crate makes it easy to develop Rust software that leverages safe, + convenient, and performant abstractions for UEFI functionality. + This is the **main contribution** of this project. +- [`uefi-raw`](/uefi-raw/README.md): Raw ABI-compatible types that closely + match the definitions in the UEFI Specification. They are suitable for + implementing UEFI firmware or creating interfaces to it. +- [`uefi-macros`](/uefi-macros/README.md): Helper macros used by `uefi`. +- [`uefi-test-runner`](/uefi-test-runner/README.md): A UEFI application that + runs our integration tests. +- [`uefi-std-example`](/uefi-std-example/README.md): Example UEFI app but as + Rust standard binary. ### Building and testing uefi-rs diff --git a/uefi/README.md b/uefi/README.md index 69e168975..63cf83180 100644 --- a/uefi/README.md +++ b/uefi/README.md @@ -22,29 +22,18 @@ 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`._ -For an introduction to the `uefi-rs` project and documentation, please refer to -our main [README]. - -[README]: https://github.com/rust-osdev/uefi-rs/blob/main/README.md - -## Optional features - -This crate's features are described in [`src/lib.rs`]. - -[`src/lib.rs`]: src/lib.rs - -## MSRV - -The minimum supported Rust version is currently 1.70. - -Our policy is to support at least the past two stable releases. - -## License - -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). +## API and User Documentation + + +Please refer to [docs.rs](https://docs.rs/uefi) for comprehensive documentation +of the **latest stable release**. The latest not necessarily yet published +documentation can be found in [`src/lib.rs`](./src/lib.rs), which can also be +locally viewed by running `$ cargo xtask doc --open`. + +For an introduction to the `uefi-rs` project and this repository, please refer +to our main [README](https://github.com/rust-osdev/uefi-rs/blob/main/README.md). + [UEFI]: https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface From fc5c0a98c7f19acb9ccada14cd6a63d4c85e9b62 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sat, 24 Aug 2024 17:10:35 +0200 Subject: [PATCH 021/512] ci: check if crate can be packaged This way, we can early spot issues before they occur in unfortunate situations, as happened with [0]. [0] https://github.com/rust-osdev/uefi-rs/pull/1338 --- .github/workflows/rust.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index dfb4abe74..7ef8da0cc 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -121,6 +121,17 @@ jobs: # library packages. Note that xtask isn't used or built here; since it's # just a dev tool we don't care about the MSRV for that package. run: cargo build --target x86_64-unknown-uefi -p uefi-test-runner + # Tests that the published crates keep being package-able (thus, releasable). + package: + name: Package Crates + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - uses: Swatinem/rust-cache@v2 + - name: Build + run: cargo package -p uefi -p uefi-raw -p uefi-macros + # This job requires the nightly channel, but keep it as a separate job from # `nightly_channel` because it takes a while to run. build_feature_permutations: From 88ce33610703409f374f823b28ad14a1b50d2b62 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 24 Aug 2024 11:22:38 -0400 Subject: [PATCH 022/512] book: Update protocols how-to to use the `boot` module --- book/src/how_to/protocols.md | 41 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/book/src/how_to/protocols.md b/book/src/how_to/protocols.md index 85d6dea28..157ef76ba 100644 --- a/book/src/how_to/protocols.md +++ b/book/src/how_to/protocols.md @@ -5,21 +5,21 @@ on that handle. See [Handles and Protocols] for an overview of what these terms mean. To get a handle you can use: -* [`BootServices::locate_handle_buffer`]: this can be used to get _all_ +* [`boot::locate_handle_buffer`]: this can be used to get _all_ available handles, or just the handles that support a particular protocol. -* [`BootServices::locate_handle`]: the same as `locate_handle_buffer`, +* [`boot::locate_handle`]: the same as `locate_handle_buffer`, but you provide the slice that stores the handles. -* [`BootServices::locate_device_path`]: find a handle by [Device Path]. +* [`boot::locate_device_path`]: find a handle by [Device Path]. Once you have obtained a handle, use -[`BootServices::open_protocol_exclusive`] to open a protocol on that +[`boot::open_protocol_exclusive`] to open a protocol on that handle. This returns a [`ScopedProtocol`], which automatically closes the protocol when dropped. -Using [`BootServices::open_protocol_exclusive`] is the safest way to +Using [`boot::open_protocol_exclusive`] is the safest way to open a protocol, but in some cases a protocol cannot be opened in -exclusive mode. The `unsafe` [`BootServices::open_protocol`] can be used +exclusive mode. The `unsafe` [`boot::open_protocol`] can be used in that case. ## Example @@ -63,12 +63,11 @@ The function starts by opening the [`LoadedImage`] protocol: {{#include ../../../uefi-test-runner/examples/loaded_image.rs:loaded_image}} ``` -The [`open_protocol_exclusive`] method takes a type parameter, which is +The [`boot::open_protocol_exclusive`] method takes a type parameter, which is the type of [`Protocol`] you want to open ([`LoadedImage`] in this case). It also takes one regular argument of type [`Handle`]. For this -example we want the handle of the currently-running image, which was -passed in as the first argument to `main`. The handle is conveniently -accessible through [`BootServices::image_handle`], so we use that here. +example we want the handle of the currently-running image, conveniently +accessible through [`boot::image_handle`]. Next the program opens the [`DevicePathToText`] protocol: @@ -77,9 +76,9 @@ Next the program opens the [`DevicePathToText`] protocol: ``` This protocol isn't available for the `image_handle`, so we start by -using [`locate_handle_buffer`] to find all handles that support +using [`boot::locate_handle_buffer`] to find all handles that support `DevicePathToText`. We only need one handle though, so we call `first()` -and discard the rest. Then we call [`open_protocol_exclusive`] again. It +and discard the rest. Then we call [`boot::open_protocol_exclusive`] again. It looks more or less like the previous time, but with [`DevicePathToText`] as the type parameter and `device_path_to_text_handle` as the handle. @@ -98,13 +97,12 @@ reference documentation] and the [UEFI Specification]. [Device Path]: ../concepts/device_paths.md [Handles and Protocols]: ../concepts/handles_and_protocols.md [UEFI Specification]: https://uefi.org/specifications -[`BootServices::image_handle`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html#method.image_handle -[`BootServices::locate_device_path`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html#method.locate_device_path -[`BootServices::locate_handle_buffer`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html#method.locate_handle_buffer -[`BootServices::locate_handle`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html#method.locate_handle -[`BootServices::open_protocol`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html#method.open_protocol -[`BootServices::open_protocol_exclusive`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html#method.open_protocol_exclusive -[`BootServices`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html +[`boot::image_handle`]: https://docs.rs/uefi/latest/uefi/boot/fn.image_handle.html +[`boot::locate_device_path`]: https://docs.rs/uefi/latest/uefi/boot/fn.locate_device_path.html +[`boot::locate_handle_buffer`]: https://docs.rs/uefi/latest/uefi/boot/fn.locate_handle_buffer.html +[`boot::locate_handle`]: https://docs.rs/uefi/latest/uefi/boot/fn.locate_handle.html +[`boot::open_protocol`]: https://docs.rs/uefi/latest/uefi/boot/fn.open_protocol.html +[`boot::open_protocol_exclusive`]: https://docs.rs/uefi/latest/uefi/boot/fn.open_protocol_exclusive.html [`DevicePathToText`]: https://docs.rs/uefi/latest/uefi/proto/device_path/text/struct.DevicePathToText.html ["Hello world!" example]: ../tutorial/app.html [`Handle`]: https://docs.rs/uefi/latest/uefi/data_types/struct.Handle.html @@ -113,10 +111,7 @@ reference documentation] and the [UEFI Specification]. [`OpenProtocolAttributes`]: https://docs.rs/uefi/latest/uefi/table/boot/enum.OpenProtocolAttributes.html [`OpenProtocolParams`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.OpenProtocolParams.html [`Protocol`]: https://docs.rs/uefi/latest/uefi/proto/trait.Protocol.html -[`ScopedProtocol`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.ScopedProtocol.html -[`locate_handle_buffer`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html#method.locate_handle_buffer -[`open_protocol`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html#method.open_protocol -[`open_protocol_exclusive`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html#method.open_protocol_exclusive +[`ScopedProtocol`]: https://docs.rs/uefi/latest/uefi/boot/struct.ScopedProtocol.html [uefi-rs reference documentation]: https://docs.rs/uefi/latest/uefi/proto/index.html [`uefi::Result`]: https://docs.rs/uefi/latest/uefi/type.Result.html [`uefi::Status`]: https://docs.rs/uefi/latest/uefi/struct.Status.html From 3d3a5f375954f3eb7db1a74e2429f776ffc0c72b Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 24 Aug 2024 11:55:01 -0400 Subject: [PATCH 023/512] uefi: Move various types to the `uefi::boot` module The types are publicly re-exported from `uefi::table::boot`, so there should be no breaking change to the public API. --- uefi/src/boot.rs | 211 +++++++++++++++++++++++++++++++++++++++-- uefi/src/table/boot.rs | 211 +---------------------------------------- 2 files changed, 210 insertions(+), 212 deletions(-) diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index 0f6170044..c1764c83f 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -2,21 +2,17 @@ //! //! These functions will panic if called after exiting boot services. -pub use crate::table::boot::{ - AllocateType, EventNotifyFn, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams, - ProtocolSearchKey, SearchType, TimerTrigger, -}; pub use uefi_raw::table::boot::{EventType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl}; use crate::data_types::PhysicalAddress; use crate::mem::memory_map::{MemoryMapBackingMemory, MemoryMapKey, MemoryMapMeta, MemoryMapOwned}; use crate::polyfill::maybe_uninit_slice_assume_init_ref; -use crate::proto::device_path::DevicePath; #[cfg(doc)] use crate::proto::device_path::LoadedImageDevicePath; +use crate::proto::device_path::{DevicePath, FfiDevicePath}; use crate::proto::loaded_image::LoadedImage; use crate::proto::media::fs::SimpleFileSystem; -use crate::proto::{Protocol, ProtocolPointer}; +use crate::proto::{BootPolicy, Protocol, ProtocolPointer}; use crate::runtime::{self, ResetType}; use crate::table::Revision; use crate::util::opt_nonnull_to_ptr; @@ -1438,3 +1434,206 @@ impl Drop for TplGuard { } } } + +// OpenProtocolAttributes is safe to model as a regular enum because it +// is only used as an input. The attributes are bitflags, but all valid +// combinations are listed in the spec and only ByDriver and Exclusive +// can actually be combined. +// +// Some values intentionally excluded: +// +// ByHandleProtocol (0x01) excluded because it is only intended to be +// used in an implementation of `HandleProtocol`. +// +// TestProtocol (0x04) excluded because it doesn't actually open the +// protocol, just tests if it's present on the handle. Since that +// changes the interface significantly, that's exposed as a separate +// method: `BootServices::test_protocol`. + +/// Attributes for [`open_protocol`]. +#[repr(u32)] +#[derive(Debug)] +pub enum OpenProtocolAttributes { + /// Used by drivers to get a protocol interface for a handle. The + /// driver will not be informed if the interface is uninstalled or + /// reinstalled. + GetProtocol = 0x02, + + /// Used by bus drivers to show that a protocol is being used by one + /// of the child controllers of the bus. + ByChildController = 0x08, + + /// Used by a driver to gain access to a protocol interface. When + /// this mode is used, the driver's `Stop` function will be called + /// if the protocol interface is reinstalled or uninstalled. Once a + /// protocol interface is opened with this attribute, no other + /// drivers will be allowed to open the same protocol interface with + /// the `ByDriver` attribute. + ByDriver = 0x10, + + /// Used by a driver to gain exclusive access to a protocol + /// interface. If any other drivers have the protocol interface + /// opened with an attribute of `ByDriver`, then an attempt will be + /// made to remove them with `DisconnectController`. + ByDriverExclusive = 0x30, + + /// Used by applications to gain exclusive access to a protocol + /// interface. If any drivers have the protocol opened with an + /// attribute of `ByDriver`, then an attempt will be made to remove + /// them by calling the driver's `Stop` function. + Exclusive = 0x20, +} + +/// Parameters passed to [`open_protocol`]. +#[derive(Debug)] +pub struct OpenProtocolParams { + /// The handle for the protocol to open. + pub handle: Handle, + + /// The handle of the calling agent. For drivers, this is the handle + /// containing the `EFI_DRIVER_BINDING_PROTOCOL` instance. For + /// applications, this is the image handle. + pub agent: Handle, + + /// For drivers, this is the controller handle that requires the + /// protocol interface. For applications this should be set to + /// `None`. + pub controller: Option, +} + +/// Used as a parameter of [`load_image`] to provide the image source. +#[derive(Debug)] +pub enum LoadImageSource<'a> { + /// Load an image from a buffer. The data will be copied from the + /// buffer, so the input reference doesn't need to remain valid + /// after the image is loaded. + FromBuffer { + /// Raw image data. + buffer: &'a [u8], + + /// If set, this path will be added as the file path of the + /// loaded image. This is not required to load the image, but + /// may be used by the image itself to load other resources + /// relative to the image's path. + file_path: Option<&'a DevicePath>, + }, + + /// Load an image via the [`SimpleFileSystem`] protocol. If there is + /// no instance of that protocol associated with the path then the + /// behavior depends on [`BootPolicy`]. If [`BootPolicy::BootSelection`], + /// attempt to load via the [`LoadFile`] protocol. If + /// [`BootPolicy::ExactMatch`], attempt to load via the [`LoadFile2`] + /// protocol, then fall back to [`LoadFile`]. + /// + /// [`LoadFile`]: crate::proto::media::load_file::LoadFile + /// [`LoadFile2`]: crate::proto::media::load_file::LoadFile2 + FromDevicePath { + /// The full device path from which to load the image. + /// + /// The provided path should be a full device path and not just the + /// file path portion of it. So for example, it must be (the binary + /// representation) + /// `PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0xFFFF,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/\\EFI\\BOOT\\BOOTX64.EFI` + /// and not just `\\EFI\\BOOT\\BOOTX64.EFI`. + device_path: &'a DevicePath, + + /// The [`BootPolicy`] to use. + boot_policy: BootPolicy, + }, +} + +impl<'a> LoadImageSource<'a> { + /// Returns the raw FFI parameters for `load_image`. + #[must_use] + pub(crate) fn to_ffi_params( + &self, + ) -> ( + BootPolicy, + *const FfiDevicePath, + *const u8, /* buffer */ + usize, /* buffer length */ + ) { + let boot_policy; + let device_path; + let source_buffer; + let source_size; + match self { + LoadImageSource::FromBuffer { buffer, file_path } => { + // Boot policy is ignored when loading from source buffer. + boot_policy = BootPolicy::default(); + + device_path = file_path.map(|p| p.as_ffi_ptr()).unwrap_or(ptr::null()); + source_buffer = buffer.as_ptr(); + source_size = buffer.len(); + } + LoadImageSource::FromDevicePath { + device_path: d_path, + boot_policy: b_policy, + } => { + boot_policy = *b_policy; + device_path = d_path.as_ffi_ptr(); + source_buffer = ptr::null(); + source_size = 0; + } + }; + (boot_policy, device_path, source_buffer, source_size) + } +} + +/// Type of allocation to perform. +#[derive(Debug, Copy, Clone)] +pub enum AllocateType { + /// Allocate any possible pages. + AnyPages, + /// Allocate pages at any address below the given address. + MaxAddress(PhysicalAddress), + /// Allocate pages at the specified address. + Address(PhysicalAddress), +} + +/// The type of handle search to perform. +#[derive(Debug, Copy, Clone)] +pub enum SearchType<'guid> { + /// Return all handles present on the system. + AllHandles, + /// Returns all handles supporting a certain protocol, specified by its GUID. + /// + /// If the protocol implements the `Protocol` interface, + /// you can use the `from_proto` function to construct a new `SearchType`. + ByProtocol(&'guid Guid), + /// Return all handles that implement a protocol when an interface for that protocol + /// is (re)installed. + ByRegisterNotify(ProtocolSearchKey), +} + +impl<'guid> SearchType<'guid> { + /// Constructs a new search type for a specified protocol. + #[must_use] + pub const fn from_proto() -> Self { + SearchType::ByProtocol(&P::GUID) + } +} + +/// Event notification callback type. +pub type EventNotifyFn = unsafe extern "efiapi" fn(event: Event, context: Option>); + +/// Timer events manipulation. +#[derive(Debug)] +pub enum TimerTrigger { + /// Cancel event's timer + Cancel, + /// The event is to be signaled periodically. + /// Parameter is the period in 100ns units. + /// Delay of 0 will be signalled on every timer tick. + Periodic(u64), + /// The event is to be signaled once in 100ns units. + /// Parameter is the delay in 100ns units. + /// Delay of 0 will be signalled on next timer tick. + Relative(u64), +} + +/// Opaque pointer returned by [`register_protocol_notify`] to be used +/// with [`locate_handle`] via [`SearchType::ByRegisterNotify`]. +#[derive(Debug, Clone, Copy)] +#[repr(transparent)] +pub struct ProtocolSearchKey(pub(crate) NonNull); diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 666685d18..43379c31e 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -1,5 +1,9 @@ //! UEFI services available during boot. +pub use crate::boot::{ + AllocateType, EventNotifyFn, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams, + ProtocolSearchKey, SearchType, TimerTrigger, +}; pub use uefi_raw::table::boot::{ EventType, InterfaceType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl, }; @@ -8,10 +12,9 @@ use super::Revision; use crate::data_types::PhysicalAddress; use crate::mem::memory_map::*; use crate::proto::device_path::DevicePath; -use crate::proto::device_path::FfiDevicePath; use crate::proto::loaded_image::LoadedImage; use crate::proto::media::fs::SimpleFileSystem; -use crate::proto::{BootPolicy, Protocol, ProtocolPointer}; +use crate::proto::{Protocol, ProtocolPointer}; use crate::util::opt_nonnull_to_ptr; use crate::{Char16, Error, Event, Guid, Handle, Result, Status, StatusExt}; #[cfg(feature = "alloc")] @@ -1362,86 +1365,6 @@ impl super::Table for BootServices { const SIGNATURE: u64 = 0x5652_4553_544f_4f42; } -/// Used as a parameter of [`BootServices::load_image`] to provide the -/// image source. -#[derive(Debug)] -pub enum LoadImageSource<'a> { - /// Load an image from a buffer. The data will be copied from the - /// buffer, so the input reference doesn't need to remain valid - /// after the image is loaded. - FromBuffer { - /// Raw image data. - buffer: &'a [u8], - - /// If set, this path will be added as the file path of the - /// loaded image. This is not required to load the image, but - /// may be used by the image itself to load other resources - /// relative to the image's path. - file_path: Option<&'a DevicePath>, - }, - - /// Load an image via the [`SimpleFileSystem`] protocol. If there is - /// no instance of that protocol associated with the path then the - /// behavior depends on [`BootPolicy`]. If [`BootPolicy::BootSelection`], - /// attempt to load via the [`LoadFile`] protocol. If - /// [`BootPolicy::ExactMatch`], attempt to load via the [`LoadFile2`] - /// protocol, then fall back to [`LoadFile`]. - /// - /// [`LoadFile`]: crate::proto::media::load_file::LoadFile - /// [`LoadFile2`]: crate::proto::media::load_file::LoadFile2 - FromDevicePath { - /// The full device path from which to load the image. - /// - /// The provided path should be a full device path and not just the - /// file path portion of it. So for example, it must be (the binary - /// representation) - /// `PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0xFFFF,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/\\EFI\\BOOT\\BOOTX64.EFI` - /// and not just `\\EFI\\BOOT\\BOOTX64.EFI`. - device_path: &'a DevicePath, - - /// The [`BootPolicy`] to use. - boot_policy: BootPolicy, - }, -} - -impl<'a> LoadImageSource<'a> { - /// Returns the raw FFI parameters for `load_image`. - #[must_use] - pub(crate) fn to_ffi_params( - &self, - ) -> ( - BootPolicy, - *const FfiDevicePath, - *const u8, /* buffer */ - usize, /* buffer length */ - ) { - let boot_policy; - let device_path; - let source_buffer; - let source_size; - match self { - LoadImageSource::FromBuffer { buffer, file_path } => { - // Boot policy is ignored when loading from source buffer. - boot_policy = BootPolicy::default(); - - device_path = file_path.map(|p| p.as_ffi_ptr()).unwrap_or(ptr::null()); - source_buffer = buffer.as_ptr(); - source_size = buffer.len(); - } - LoadImageSource::FromDevicePath { - device_path: d_path, - boot_policy: b_policy, - } => { - boot_policy = *b_policy; - device_path = d_path.as_ffi_ptr(); - source_buffer = ptr::null(); - source_size = 0; - } - }; - (boot_policy, device_path, source_buffer, source_size) - } -} - /// RAII guard for task priority level changes /// /// Will automatically restore the former task priority level when dropped. @@ -1459,72 +1382,6 @@ impl Drop for TplGuard<'_> { } } -// OpenProtocolAttributes is safe to model as a regular enum because it -// is only used as an input. The attributes are bitflags, but all valid -// combinations are listed in the spec and only ByDriver and Exclusive -// can actually be combined. -// -// Some values intentionally excluded: -// -// ByHandleProtocol (0x01) excluded because it is only intended to be -// used in an implementation of `HandleProtocol`. -// -// TestProtocol (0x04) excluded because it doesn't actually open the -// protocol, just tests if it's present on the handle. Since that -// changes the interface significantly, that's exposed as a separate -// method: `BootServices::test_protocol`. - -/// Attributes for [`BootServices::open_protocol`]. -#[repr(u32)] -#[derive(Debug)] -pub enum OpenProtocolAttributes { - /// Used by drivers to get a protocol interface for a handle. The - /// driver will not be informed if the interface is uninstalled or - /// reinstalled. - GetProtocol = 0x02, - - /// Used by bus drivers to show that a protocol is being used by one - /// of the child controllers of the bus. - ByChildController = 0x08, - - /// Used by a driver to gain access to a protocol interface. When - /// this mode is used, the driver's `Stop` function will be called - /// if the protocol interface is reinstalled or uninstalled. Once a - /// protocol interface is opened with this attribute, no other - /// drivers will be allowed to open the same protocol interface with - /// the `ByDriver` attribute. - ByDriver = 0x10, - - /// Used by a driver to gain exclusive access to a protocol - /// interface. If any other drivers have the protocol interface - /// opened with an attribute of `ByDriver`, then an attempt will be - /// made to remove them with `DisconnectController`. - ByDriverExclusive = 0x30, - - /// Used by applications to gain exclusive access to a protocol - /// interface. If any drivers have the protocol opened with an - /// attribute of `ByDriver`, then an attempt will be made to remove - /// them by calling the driver's `Stop` function. - Exclusive = 0x20, -} - -/// Parameters passed to [`BootServices::open_protocol`]. -#[derive(Debug)] -pub struct OpenProtocolParams { - /// The handle for the protocol to open. - pub handle: Handle, - - /// The handle of the calling agent. For drivers, this is the handle - /// containing the `EFI_DRIVER_BINDING_PROTOCOL` instance. For - /// applications, this is the image handle. - pub agent: Handle, - - /// For drivers, this is the controller handle that requires the - /// protocol interface. For applications this should be set to - /// `None`. - pub controller: Option, -} - /// An open protocol interface. Automatically closes the protocol /// interface on drop. /// @@ -1601,58 +1458,6 @@ impl<'a, P: Protocol + ?Sized> ScopedProtocol<'a, P> { } } -/// Type of allocation to perform. -#[derive(Debug, Copy, Clone)] -pub enum AllocateType { - /// Allocate any possible pages. - AnyPages, - /// Allocate pages at any address below the given address. - MaxAddress(PhysicalAddress), - /// Allocate pages at the specified address. - Address(PhysicalAddress), -} - -/// The type of handle search to perform. -#[derive(Debug, Copy, Clone)] -pub enum SearchType<'guid> { - /// Return all handles present on the system. - AllHandles, - /// Returns all handles supporting a certain protocol, specified by its GUID. - /// - /// If the protocol implements the `Protocol` interface, - /// you can use the `from_proto` function to construct a new `SearchType`. - ByProtocol(&'guid Guid), - /// Return all handles that implement a protocol when an interface for that protocol - /// is (re)installed. - ByRegisterNotify(ProtocolSearchKey), -} - -impl<'guid> SearchType<'guid> { - /// Constructs a new search type for a specified protocol. - #[must_use] - pub const fn from_proto() -> Self { - SearchType::ByProtocol(&P::GUID) - } -} - -/// Event notification callback type. -pub type EventNotifyFn = unsafe extern "efiapi" fn(event: Event, context: Option>); - -/// Timer events manipulation. -#[derive(Debug)] -pub enum TimerTrigger { - /// Cancel event's timer - Cancel, - /// The event is to be signaled periodically. - /// Parameter is the period in 100ns units. - /// Delay of 0 will be signalled on every timer tick. - Periodic(u64), - /// The event is to be signaled once in 100ns units. - /// Parameter is the delay in 100ns units. - /// Delay of 0 will be signalled on next timer tick. - Relative(u64), -} - /// Protocol interface [`Guids`][Guid] that are installed on a [`Handle`] as /// returned by [`BootServices::protocols_per_handle`]. #[derive(Debug)] @@ -1730,9 +1535,3 @@ impl<'a> HandleBuffer<'a> { unsafe { slice::from_raw_parts(self.buffer, self.count) } } } - -/// Opaque pointer returned by [`BootServices::register_protocol_notify`] to be used -/// with [`BootServices::locate_handle`] via [`SearchType::ByRegisterNotify`]. -#[derive(Debug, Clone, Copy)] -#[repr(transparent)] -pub struct ProtocolSearchKey(pub(crate) NonNull); From a2e5b9c779f01e308fefd3a438fc4ed27527af31 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 24 Aug 2024 12:56:21 -0400 Subject: [PATCH 024/512] Apply yamlfmt --- .github/workflows/rust.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7ef8da0cc..f4047c4cf 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -131,7 +131,6 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Build run: cargo package -p uefi -p uefi-raw -p uefi-macros - # This job requires the nightly channel, but keep it as a separate job from # `nightly_channel` because it takes a while to run. build_feature_permutations: From da55df613496b68899996d44e2dc2fb0ffb45bf9 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 24 Aug 2024 13:10:07 -0400 Subject: [PATCH 025/512] ci: Use cargo xtask fmt --check --- .github/workflows/rust.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index f4047c4cf..9e9fa646a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -88,10 +88,8 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 - - name: Run cargo fmt - run: | - rustup component add rustfmt - cargo fmt --all -- --check + - name: Check formatting + run: cargo xtask fmt --check - name: Run clippy run: | rustup component add clippy From e5d5d50e6048e7304ec466a8ab1e4d13810bd47b Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 24 Aug 2024 13:10:20 -0400 Subject: [PATCH 026/512] ci: Install yamlfmt so that yaml formatting can be checked --- .github/workflows/rust.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9e9fa646a..5eda89577 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -88,6 +88,14 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 + - name: Install yamlfmt + env: + YFV: "0.13.0" + HASH: "043e96d754a8afa4f4c5c13ffb2f3e50c6be5a70bf53292d3025abc0b42fe4ae" + run: | + curl -L --fail --output /tmp/yamlfmt.tar.xz https://github.com/google/yamlfmt/releases/download/v${YFV}/yamlfmt_${YFV}_Linux_x86_64.tar.gz + echo "${HASH} /tmp/yamlfmt.tar.xz" | sha256sum --check + tar xf /tmp/yamlfmt.tar.xz -C /usr/local/bin yamlfmt - name: Check formatting run: cargo xtask fmt --check - name: Run clippy From 81e350bfcc72f15dd74f3f22f7a93adf2480ab7e Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 24 Aug 2024 14:14:52 -0400 Subject: [PATCH 027/512] uefi: Move various types to the `uefi::runtime` module The types are publicly re-exported from `uefi::table::runtime`, so there should be no breaking change to the public API. --- uefi/src/runtime.rs | 394 +++++++++++++++++++++++++++++++++++++- uefi/src/table/runtime.rs | 392 +------------------------------------ 2 files changed, 394 insertions(+), 392 deletions(-) diff --git a/uefi/src/runtime.rs b/uefi/src/runtime.rs index db92de505..48c51380c 100644 --- a/uefi/src/runtime.rs +++ b/uefi/src/runtime.rs @@ -8,6 +8,7 @@ use crate::data_types::PhysicalAddress; use crate::table::{self, Revision}; use crate::{CStr16, Error, Result, Status, StatusExt}; +use core::fmt::{self, Debug, Display, Formatter}; use core::mem; use core::ptr::{self, NonNull}; use uefi_raw::table::boot::MemoryDescriptor; @@ -20,14 +21,11 @@ use { #[cfg(all(feature = "unstable", feature = "alloc"))] use alloc::alloc::Global; -pub use crate::table::runtime::{ - CapsuleInfo, Daylight, Time, TimeCapabilities, TimeError, TimeParams, VariableStorageInfo, -}; pub use uefi_raw::capsule::{CapsuleBlockDescriptor, CapsuleFlags, CapsuleHeader}; -pub use uefi_raw::table::runtime::{ResetType, VariableAttributes, VariableVendor}; - -#[cfg(feature = "alloc")] -pub use crate::table::runtime::VariableKey; +pub use uefi_raw::table::runtime::{ + ResetType, TimeCapabilities, VariableAttributes, VariableVendor, +}; +pub use uefi_raw::time::Daylight; fn runtime_services_raw_panicking() -> NonNull { let st = table::system_table_raw_panicking(); @@ -512,3 +510,385 @@ pub unsafe fn set_virtual_address_map( Ok(()) } + +/// Date and time representation. +#[derive(Copy, Clone, Eq, PartialEq)] +#[repr(transparent)] +pub struct Time(uefi_raw::time::Time); + +/// Input parameters for [`Time::new`]. +#[derive(Copy, Clone, Debug)] +pub struct TimeParams { + /// Year in the range `1900..=9999`. + pub year: u16, + + /// Month in the range `1..=12`. + pub month: u8, + + /// Day in the range `1..=31`. + pub day: u8, + + /// Hour in the range `0.=23`. + pub hour: u8, + + /// Minute in the range `0..=59`. + pub minute: u8, + + /// Second in the range `0..=59`. + pub second: u8, + + /// Fraction of a second represented as nanoseconds in the range + /// `0..=999_999_999`. + pub nanosecond: u32, + + /// Offset in minutes from UTC in the range `-1440..=1440`, or + /// local time if `None`. + pub time_zone: Option, + + /// Daylight savings time information. + pub daylight: Daylight, +} + +/// Error returned by [`Time`] methods. A bool value of `true` means +/// the specified field is outside its valid range. +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct TimeError { + pub year: bool, + pub month: bool, + pub day: bool, + pub hour: bool, + pub minute: bool, + pub second: bool, + pub nanosecond: bool, + pub timezone: bool, + pub daylight: bool, +} + +#[cfg(feature = "unstable")] +impl core::error::Error for TimeError {} + +impl Display for TimeError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if self.year { + writeln!(f, "year not within `1900..=9999`")?; + } + if self.month { + writeln!(f, "month not within `1..=12")?; + } + if self.day { + writeln!(f, "day not within `1..=31`")?; + } + if self.hour { + writeln!(f, "hour not within `0..=23`")?; + } + if self.minute { + writeln!(f, "minute not within `0..=59`")?; + } + if self.second { + writeln!(f, "second not within `0..=59`")?; + } + if self.nanosecond { + writeln!(f, "nanosecond not within `0..=999_999_999`")?; + } + if self.timezone { + writeln!( + f, + "time_zone not `Time::UNSPECIFIED_TIMEZONE` nor within `-1440..=1440`" + )?; + } + if self.daylight { + writeln!(f, "unknown bits set for daylight")?; + } + Ok(()) + } +} + +impl Time { + /// Unspecified Timezone/local time. + const UNSPECIFIED_TIMEZONE: i16 = uefi_raw::time::Time::UNSPECIFIED_TIMEZONE; + + /// Create a `Time` value. If a field is not in the valid range, + /// [`TimeError`] is returned. + pub fn new(params: TimeParams) -> core::result::Result { + let time = Self(uefi_raw::time::Time { + year: params.year, + month: params.month, + day: params.day, + hour: params.hour, + minute: params.minute, + second: params.second, + pad1: 0, + nanosecond: params.nanosecond, + time_zone: params.time_zone.unwrap_or(Self::UNSPECIFIED_TIMEZONE), + daylight: params.daylight, + pad2: 0, + }); + + time.is_valid().map(|_| time) + } + + /// Create an invalid `Time` with all fields set to zero. This can + /// be used with [`FileInfo`] to indicate a field should not be + /// updated when calling [`File::set_info`]. + /// + /// [`FileInfo`]: uefi::proto::media::file::FileInfo + /// [`File::set_info`]: uefi::proto::media::file::File::set_info + #[must_use] + pub const fn invalid() -> Self { + Self(uefi_raw::time::Time::invalid()) + } + + /// `Ok()` if all fields are within valid ranges, `Err(TimeError)` otherwise. + pub fn is_valid(&self) -> core::result::Result<(), TimeError> { + let mut err = TimeError::default(); + if !(1900..=9999).contains(&self.year()) { + err.year = true; + } + if !(1..=12).contains(&self.month()) { + err.month = true; + } + if !(1..=31).contains(&self.day()) { + err.day = true; + } + if self.hour() > 23 { + err.hour = true; + } + if self.minute() > 59 { + err.minute = true; + } + if self.second() > 59 { + err.second = true; + } + if self.nanosecond() > 999_999_999 { + err.nanosecond = true; + } + if self.time_zone().is_some() && !((-1440..=1440).contains(&self.time_zone().unwrap())) { + err.timezone = true; + } + // All fields are false, i.e., within their valid range. + if err == TimeError::default() { + Ok(()) + } else { + Err(err) + } + } + + /// Query the year. + #[must_use] + pub const fn year(&self) -> u16 { + self.0.year + } + + /// Query the month. + #[must_use] + pub const fn month(&self) -> u8 { + self.0.month + } + + /// Query the day. + #[must_use] + pub const fn day(&self) -> u8 { + self.0.day + } + + /// Query the hour. + #[must_use] + pub const fn hour(&self) -> u8 { + self.0.hour + } + + /// Query the minute. + #[must_use] + pub const fn minute(&self) -> u8 { + self.0.minute + } + + /// Query the second. + #[must_use] + pub const fn second(&self) -> u8 { + self.0.second + } + + /// Query the nanosecond. + #[must_use] + pub const fn nanosecond(&self) -> u32 { + self.0.nanosecond + } + + /// Query the time offset in minutes from UTC, or None if using local time. + #[must_use] + pub const fn time_zone(&self) -> Option { + if self.0.time_zone == Self::UNSPECIFIED_TIMEZONE { + None + } else { + Some(self.0.time_zone) + } + } + + /// Query the daylight savings time information. + #[must_use] + pub const fn daylight(&self) -> Daylight { + self.0.daylight + } +} + +impl Debug for Time { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!( + f, + "{:04}-{:02}-{:02} ", + self.0.year, self.0.month, self.0.day + )?; + write!( + f, + "{:02}:{:02}:{:02}.{:09}", + self.0.hour, self.0.minute, self.0.second, self.0.nanosecond + )?; + if self.0.time_zone == Self::UNSPECIFIED_TIMEZONE { + write!(f, ", Timezone=local")?; + } else { + write!(f, ", Timezone={}", self.0.time_zone)?; + } + write!(f, ", Daylight={:?}", self.0.daylight) + } +} + +impl Display for Time { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +/// Error returned from failing to convert a byte slice into a [`Time`]. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum TimeByteConversionError { + /// One or more fields of the converted [`Time`] is invalid. + InvalidFields(TimeError), + /// The byte slice is not large enough to hold a [`Time`]. + InvalidSize, +} + +impl Display for TimeByteConversionError { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Self::InvalidFields(error) => write!(f, "{error}"), + Self::InvalidSize => write!( + f, + "the byte slice is not large enough to hold a Time struct" + ), + } + } +} + +impl TryFrom<&[u8]> for Time { + type Error = TimeByteConversionError; + + fn try_from(bytes: &[u8]) -> core::result::Result { + if mem::size_of::() <= bytes.len() { + let year = u16::from_le_bytes(bytes[0..2].try_into().unwrap()); + let month = bytes[2]; + let day = bytes[3]; + let hour = bytes[4]; + let minute = bytes[5]; + let second = bytes[6]; + let nanosecond = u32::from_le_bytes(bytes[8..12].try_into().unwrap()); + let time_zone = match i16::from_le_bytes(bytes[12..14].try_into().unwrap()) { + Self::UNSPECIFIED_TIMEZONE => None, + num => Some(num), + }; + let daylight = Daylight::from_bits(bytes[14]).ok_or( + TimeByteConversionError::InvalidFields(TimeError { + daylight: true, + ..Default::default() + }), + )?; + + let time_params = TimeParams { + year, + month, + day, + hour, + minute, + second, + nanosecond, + time_zone, + daylight, + }; + + Self::new(time_params).map_err(TimeByteConversionError::InvalidFields) + } else { + Err(TimeByteConversionError::InvalidSize) + } + } +} + +/// Unique key for a variable. +#[cfg(feature = "alloc")] +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct VariableKey { + pub(crate) name: Vec, + /// Unique identifier for the vendor. + pub vendor: VariableVendor, +} + +#[cfg(feature = "alloc")] +impl VariableKey { + /// Name of the variable. + pub fn name(&self) -> core::result::Result<&CStr16, crate::data_types::FromSliceWithNulError> { + CStr16::from_u16_with_nul(&self.name) + } +} + +#[cfg(feature = "alloc")] +impl Display for VariableKey { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "VariableKey {{ name: ")?; + + match self.name() { + Ok(name) => write!(f, "\"{name}\"")?, + Err(err) => write!(f, "Err({err:?})")?, + } + + write!(f, ", vendor: ")?; + + if self.vendor == VariableVendor::GLOBAL_VARIABLE { + write!(f, "GLOBAL_VARIABLE")?; + } else { + write!(f, "{}", self.vendor.0)?; + } + + write!(f, " }}") + } +} + +/// Information about UEFI variable storage space returned by +/// [`query_variable_info`]. Note that the data here is +/// limited to a specific type of variable (as specified by the +/// `attributes` argument to `query_variable_info`). +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub struct VariableStorageInfo { + /// Maximum size in bytes of the storage space available for + /// variables of the specified type. + pub maximum_variable_storage_size: u64, + + /// Remaining size in bytes of the storage space available for + /// variables of the specified type. + pub remaining_variable_storage_size: u64, + + /// Maximum size of an individual variable of the specified type. + pub maximum_variable_size: u64, +} + +/// Information about UEFI variable storage space returned by +/// [`query_capsule_capabilities`]. +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub struct CapsuleInfo { + /// The maximum size in bytes that [`update_capsule`] + /// can support as input. Note that the size of an update capsule is composed of + /// all [`CapsuleHeader`]s and [CapsuleBlockDescriptor]s. + pub maximum_capsule_size: u64, + + /// The type of reset required for the capsule update. + pub reset_type: ResetType, +} diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index 0012206ee..5b14808a3 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -1,5 +1,8 @@ //! UEFI services available at runtime, even after the OS boots. +pub use crate::runtime::{ + CapsuleInfo, Time, TimeByteConversionError, TimeError, TimeParams, VariableStorageInfo, +}; pub use uefi_raw::capsule::{CapsuleBlockDescriptor, CapsuleFlags, CapsuleHeader}; pub use uefi_raw::table::runtime::{ ResetType, TimeCapabilities, VariableAttributes, VariableVendor, @@ -7,14 +10,15 @@ pub use uefi_raw::table::runtime::{ pub use uefi_raw::time::Daylight; pub use uefi_raw::PhysicalAddress; +#[cfg(feature = "alloc")] +pub use crate::runtime::VariableKey; + use super::Revision; use crate::{CStr16, Error, Result, Status, StatusExt}; -use core::fmt::{self, Debug, Display, Formatter}; -use core::mem::{size_of, MaybeUninit}; +use core::mem::MaybeUninit; use core::ptr; #[cfg(feature = "alloc")] use { - crate::data_types::FromSliceWithNulError, crate::Guid, alloc::boxed::Box, alloc::{vec, vec::Vec}, @@ -331,388 +335,6 @@ impl super::Table for RuntimeServices { const SIGNATURE: u64 = 0x5652_4553_544e_5552; } -/// Date and time representation. -#[derive(Copy, Clone, Eq, PartialEq)] -#[repr(transparent)] -pub struct Time(uefi_raw::time::Time); - -/// Input parameters for [`Time::new`]. -#[derive(Copy, Clone, Debug)] -pub struct TimeParams { - /// Year in the range `1900..=9999`. - pub year: u16, - - /// Month in the range `1..=12`. - pub month: u8, - - /// Day in the range `1..=31`. - pub day: u8, - - /// Hour in the range `0.=23`. - pub hour: u8, - - /// Minute in the range `0..=59`. - pub minute: u8, - - /// Second in the range `0..=59`. - pub second: u8, - - /// Fraction of a second represented as nanoseconds in the range - /// `0..=999_999_999`. - pub nanosecond: u32, - - /// Offset in minutes from UTC in the range `-1440..=1440`, or - /// local time if `None`. - pub time_zone: Option, - - /// Daylight savings time information. - pub daylight: Daylight, -} - -/// Error returned by [`Time`] methods. A bool value of `true` means -/// the specified field is outside its valid range. -#[allow(missing_docs)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub struct TimeError { - pub year: bool, - pub month: bool, - pub day: bool, - pub hour: bool, - pub minute: bool, - pub second: bool, - pub nanosecond: bool, - pub timezone: bool, - pub daylight: bool, -} - -#[cfg(feature = "unstable")] -impl core::error::Error for TimeError {} - -impl Display for TimeError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - if self.year { - writeln!(f, "year not within `1900..=9999`")?; - } - if self.month { - writeln!(f, "month not within `1..=12")?; - } - if self.day { - writeln!(f, "day not within `1..=31`")?; - } - if self.hour { - writeln!(f, "hour not within `0..=23`")?; - } - if self.minute { - writeln!(f, "minute not within `0..=59`")?; - } - if self.second { - writeln!(f, "second not within `0..=59`")?; - } - if self.nanosecond { - writeln!(f, "nanosecond not within `0..=999_999_999`")?; - } - if self.timezone { - writeln!( - f, - "time_zone not `Time::UNSPECIFIED_TIMEZONE` nor within `-1440..=1440`" - )?; - } - if self.daylight { - writeln!(f, "unknown bits set for daylight")?; - } - Ok(()) - } -} - -impl Time { - /// Unspecified Timezone/local time. - const UNSPECIFIED_TIMEZONE: i16 = uefi_raw::time::Time::UNSPECIFIED_TIMEZONE; - - /// Create a `Time` value. If a field is not in the valid range, - /// [`TimeError`] is returned. - pub fn new(params: TimeParams) -> core::result::Result { - let time = Self(uefi_raw::time::Time { - year: params.year, - month: params.month, - day: params.day, - hour: params.hour, - minute: params.minute, - second: params.second, - pad1: 0, - nanosecond: params.nanosecond, - time_zone: params.time_zone.unwrap_or(Self::UNSPECIFIED_TIMEZONE), - daylight: params.daylight, - pad2: 0, - }); - - time.is_valid().map(|_| time) - } - - /// Create an invalid `Time` with all fields set to zero. This can - /// be used with [`FileInfo`] to indicate a field should not be - /// updated when calling [`File::set_info`]. - /// - /// [`FileInfo`]: uefi::proto::media::file::FileInfo - /// [`File::set_info`]: uefi::proto::media::file::File::set_info - #[must_use] - pub const fn invalid() -> Self { - Self(uefi_raw::time::Time::invalid()) - } - - /// `Ok()` if all fields are within valid ranges, `Err(TimeError)` otherwise. - pub fn is_valid(&self) -> core::result::Result<(), TimeError> { - let mut err = TimeError::default(); - if !(1900..=9999).contains(&self.year()) { - err.year = true; - } - if !(1..=12).contains(&self.month()) { - err.month = true; - } - if !(1..=31).contains(&self.day()) { - err.day = true; - } - if self.hour() > 23 { - err.hour = true; - } - if self.minute() > 59 { - err.minute = true; - } - if self.second() > 59 { - err.second = true; - } - if self.nanosecond() > 999_999_999 { - err.nanosecond = true; - } - if self.time_zone().is_some() && !((-1440..=1440).contains(&self.time_zone().unwrap())) { - err.timezone = true; - } - // All fields are false, i.e., within their valid range. - if err == TimeError::default() { - Ok(()) - } else { - Err(err) - } - } - - /// Query the year. - #[must_use] - pub const fn year(&self) -> u16 { - self.0.year - } - - /// Query the month. - #[must_use] - pub const fn month(&self) -> u8 { - self.0.month - } - - /// Query the day. - #[must_use] - pub const fn day(&self) -> u8 { - self.0.day - } - - /// Query the hour. - #[must_use] - pub const fn hour(&self) -> u8 { - self.0.hour - } - - /// Query the minute. - #[must_use] - pub const fn minute(&self) -> u8 { - self.0.minute - } - - /// Query the second. - #[must_use] - pub const fn second(&self) -> u8 { - self.0.second - } - - /// Query the nanosecond. - #[must_use] - pub const fn nanosecond(&self) -> u32 { - self.0.nanosecond - } - - /// Query the time offset in minutes from UTC, or None if using local time. - #[must_use] - pub const fn time_zone(&self) -> Option { - if self.0.time_zone == Self::UNSPECIFIED_TIMEZONE { - None - } else { - Some(self.0.time_zone) - } - } - - /// Query the daylight savings time information. - #[must_use] - pub const fn daylight(&self) -> Daylight { - self.0.daylight - } -} - -impl Debug for Time { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!( - f, - "{:04}-{:02}-{:02} ", - self.0.year, self.0.month, self.0.day - )?; - write!( - f, - "{:02}:{:02}:{:02}.{:09}", - self.0.hour, self.0.minute, self.0.second, self.0.nanosecond - )?; - if self.0.time_zone == Self::UNSPECIFIED_TIMEZONE { - write!(f, ", Timezone=local")?; - } else { - write!(f, ", Timezone={}", self.0.time_zone)?; - } - write!(f, ", Daylight={:?}", self.0.daylight) - } -} - -impl Display for Time { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Error returned from failing to convert a byte slice into a [`Time`]. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum TimeByteConversionError { - /// One or more fields of the converted [`Time`] is invalid. - InvalidFields(TimeError), - /// The byte slice is not large enough to hold a [`Time`]. - InvalidSize, -} - -impl Display for TimeByteConversionError { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - Self::InvalidFields(error) => write!(f, "{error}"), - Self::InvalidSize => write!( - f, - "the byte slice is not large enough to hold a Time struct" - ), - } - } -} - -impl TryFrom<&[u8]> for Time { - type Error = TimeByteConversionError; - - fn try_from(bytes: &[u8]) -> core::result::Result { - if size_of::() <= bytes.len() { - let year = u16::from_le_bytes(bytes[0..2].try_into().unwrap()); - let month = bytes[2]; - let day = bytes[3]; - let hour = bytes[4]; - let minute = bytes[5]; - let second = bytes[6]; - let nanosecond = u32::from_le_bytes(bytes[8..12].try_into().unwrap()); - let time_zone = match i16::from_le_bytes(bytes[12..14].try_into().unwrap()) { - Self::UNSPECIFIED_TIMEZONE => None, - num => Some(num), - }; - let daylight = Daylight::from_bits(bytes[14]).ok_or( - TimeByteConversionError::InvalidFields(TimeError { - daylight: true, - ..Default::default() - }), - )?; - - let time_params = TimeParams { - year, - month, - day, - hour, - minute, - second, - nanosecond, - time_zone, - daylight, - }; - - Self::new(time_params).map_err(TimeByteConversionError::InvalidFields) - } else { - Err(TimeByteConversionError::InvalidSize) - } - } -} - -/// Unique key for a variable. -#[cfg(feature = "alloc")] -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct VariableKey { - pub(crate) name: Vec, - /// Unique identifier for the vendor. - pub vendor: VariableVendor, -} - -#[cfg(feature = "alloc")] -impl VariableKey { - /// Name of the variable. - pub fn name(&self) -> core::result::Result<&CStr16, FromSliceWithNulError> { - CStr16::from_u16_with_nul(&self.name) - } -} - -#[cfg(feature = "alloc")] -impl Display for VariableKey { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "VariableKey {{ name: ")?; - - match self.name() { - Ok(name) => write!(f, "\"{name}\"")?, - Err(err) => write!(f, "Err({err:?})")?, - } - - write!(f, ", vendor: ")?; - - if self.vendor == VariableVendor::GLOBAL_VARIABLE { - write!(f, "GLOBAL_VARIABLE")?; - } else { - write!(f, "{}", self.vendor.0)?; - } - - write!(f, " }}") - } -} - -/// Information about UEFI variable storage space returned by -/// [`RuntimeServices::query_variable_info`]. Note that the data here is -/// limited to a specific type of variable (as specified by the -/// `attributes` argument to `query_variable_info`). -#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] -pub struct VariableStorageInfo { - /// Maximum size in bytes of the storage space available for - /// variables of the specified type. - pub maximum_variable_storage_size: u64, - - /// Remaining size in bytes of the storage space available for - /// variables of the specified type. - pub remaining_variable_storage_size: u64, - - /// Maximum size of an individual variable of the specified type. - pub maximum_variable_size: u64, -} - -/// Information about UEFI variable storage space returned by -/// [`RuntimeServices::query_capsule_capabilities`]. -#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] -pub struct CapsuleInfo { - /// The maximum size in bytes that [`RuntimeServices::update_capsule`] - /// can support as input. Note that the size of an update capsule is composed of - /// all [`CapsuleHeader`]s and [CapsuleBlockDescriptor]s. - pub maximum_capsule_size: u64, - - /// The type of reset required for the capsule update. - pub reset_type: ResetType, -} - #[cfg(test)] mod tests { use super::*; From da0597ef1a24b29525c2daef232df36f4ffc43db Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 01:16:42 -0400 Subject: [PATCH 028/512] test-runner: Fix accidental use of generated entry args --- uefi-test-runner/examples/hello_world.rs | 3 ++- uefi-test-runner/examples/shell_params.rs | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/uefi-test-runner/examples/hello_world.rs b/uefi-test-runner/examples/hello_world.rs index ba858b1c8..98a346e54 100644 --- a/uefi-test-runner/examples/hello_world.rs +++ b/uefi-test-runner/examples/hello_world.rs @@ -6,6 +6,7 @@ // ANCHOR: use use log::info; +use uefi::boot; use uefi::prelude::*; // ANCHOR_END: use @@ -18,7 +19,7 @@ fn main() -> Status { // ANCHOR_END: services // ANCHOR: log info!("Hello world!"); - system_table.boot_services().stall(10_000_000); + boot::stall(10_000_000); // ANCHOR_END: log // ANCHOR: return Status::SUCCESS diff --git a/uefi-test-runner/examples/shell_params.rs b/uefi-test-runner/examples/shell_params.rs index 9aef92dae..14aad1035 100644 --- a/uefi-test-runner/examples/shell_params.rs +++ b/uefi-test-runner/examples/shell_params.rs @@ -7,8 +7,8 @@ use log::error; // ANCHOR: use use uefi::prelude::*; -use uefi::println; use uefi::proto::shell_params::ShellParameters; +use uefi::{boot, println}; extern crate alloc; use alloc::string::{String, ToString}; @@ -21,12 +21,11 @@ fn main() -> Status { // ANCHOR_END: entry // ANCHOR: services uefi::helpers::init().unwrap(); - let boot_services = system_table.boot_services(); // ANCHOR_END: services // ANCHOR: params let shell_params = - boot_services.open_protocol_exclusive::(image_handle); + boot::open_protocol_exclusive::(boot::image_handle()); let shell_params = match shell_params { Ok(s) => s, Err(e) => { From c135e6c055fa5e5333b4145d98c40f1c22381bfb Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 09:59:35 -0400 Subject: [PATCH 029/512] uefi-macros: Rename generated entry arguments When the `entry` macro is used on a no-argument function, system table and handle arguments are generated so that the table/handle globals can be initialized. These arguments are not meant for other use. (There's no technical issue with the body of the user-supplied function using these arguments, but it makes the code confusing since the arguments appear out of nowhere, and it's a compatibility hazard since the name and type of the arguments may change in the future.) To make this less likely to occur, prepend `internal_` to the arg names. --- uefi-macros/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uefi-macros/src/lib.rs b/uefi-macros/src/lib.rs index 08be64f54..8e4f48c7e 100644 --- a/uefi-macros/src/lib.rs +++ b/uefi-macros/src/lib.rs @@ -203,8 +203,8 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { if f.sig.inputs.is_empty() { f.sig.inputs = parse_quote_spanned!( signature_span=> - image_handle: ::uefi::Handle, - system_table: ::uefi::table::SystemTable<::uefi::table::Boot> + internal_image_handle: ::uefi::Handle, + internal_system_table: ::uefi::table::SystemTable<::uefi::table::Boot> ); } From 02e5f0ec8cf27c4494ed5c2652f61dcf23326591 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 11:54:32 -0400 Subject: [PATCH 030/512] uefi: Make FileSystem work with both variants of ScopedProtocol To help ease the API transition, make `FileSystem::new` accept either variant of ScopedProtocol. --- uefi/CHANGELOG.md | 2 ++ uefi/src/fs/file_system/fs.rs | 42 ++++++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 2c794c4c5..86d118ddc 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -17,6 +17,8 @@ how to integrate the `uefi` crate into them. - `allocator::init` and `allocator::exit_boot_services` have been deprecated. These functions are now no-ops. The allocator now internally uses the global system table. +- `FileSystem::new` now accepts `boot::ScopedProtocol` in addition to + `table::boot::ScopedProtocol`. # uefi - 0.31.0 (2024-08-21) diff --git a/uefi/src/fs/file_system/fs.rs b/uefi/src/fs/file_system/fs.rs index 8925131b9..be0b3abfc 100644 --- a/uefi/src/fs/file_system/fs.rs +++ b/uefi/src/fs/file_system/fs.rs @@ -1,7 +1,6 @@ //! Module for [`FileSystem`]. use crate::fs::*; -use crate::table::boot::ScopedProtocol; use crate::Status; use alloc::boxed::Box; use alloc::string::String; @@ -14,6 +13,15 @@ use core::ops::Deref; /// Return type for public [`FileSystem`] operations. pub type FileSystemResult = Result; +/// Contents of the `FileSystem` struct, allowing either variant of +/// `ScopedProtocol` to be used. This is temporary; once `BootServices` and the +/// associated `ScopedProtocol<'a>` structs are removed this inner type can be +/// removed as well. +enum FileSystemInner<'a> { + WithLifetime(uefi::table::boot::ScopedProtocol<'a, SimpleFileSystemProtocol>), + WithoutLifetime(uefi::boot::ScopedProtocol), +} + /// High-level file-system abstraction for UEFI volumes with an API that is /// close to `std::fs`. It acts as convenient accessor around the /// [`SimpleFileSystemProtocol`]. @@ -21,13 +29,13 @@ pub type FileSystemResult = Result; /// Please refer to the [module documentation] for more information. /// /// [module documentation]: uefi::fs -pub struct FileSystem<'a>(ScopedProtocol<'a, SimpleFileSystemProtocol>); +pub struct FileSystem<'a>(FileSystemInner<'a>); impl<'a> FileSystem<'a> { /// Constructor. #[must_use] - pub const fn new(proto: ScopedProtocol<'a, SimpleFileSystemProtocol>) -> Self { - Self(proto) + pub fn new(proto: impl Into) -> Self { + proto.into() } /// Returns `Ok(true)` if the path points at an existing file. @@ -387,7 +395,11 @@ impl<'a> FileSystem<'a> { /// Opens a fresh handle to the root directory of the volume. fn open_root(&mut self) -> FileSystemResult { - self.0.open_volume().map_err(|err| { + match &mut self.0 { + FileSystemInner::WithLifetime(proto) => proto.open_volume(), + FileSystemInner::WithoutLifetime(proto) => proto.open_volume(), + } + .map_err(|err| { Error::Io(IoError { path: { let mut path = PathBuf::new(); @@ -434,8 +446,22 @@ impl<'a> FileSystem<'a> { impl<'a> Debug for FileSystem<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_tuple("FileSystem(<>))") - .field(&(self.0.deref() as *const _)) - .finish() + let ptr: *const _ = match &self.0 { + FileSystemInner::WithLifetime(proto) => proto.deref(), + FileSystemInner::WithoutLifetime(proto) => proto.deref(), + }; + f.debug_tuple("FileSystem").field(&ptr).finish() + } +} + +impl<'a> From> for FileSystem<'a> { + fn from(proto: uefi::table::boot::ScopedProtocol<'a, SimpleFileSystemProtocol>) -> Self { + Self(FileSystemInner::WithLifetime(proto)) + } +} + +impl<'a> From> for FileSystem<'a> { + fn from(proto: uefi::boot::ScopedProtocol) -> Self { + Self(FileSystemInner::WithoutLifetime(proto)) } } From 9aa5ed7af15cd51bff45eac937c131ec58c4168d Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 12:25:31 -0400 Subject: [PATCH 031/512] uefi: Fix compilation of minimal example This turns out to be easier than I expected: just add `extern crate std;` so that the panic handler and global allocator are set. The line is hidden so that it doesn't appear in the rendered docs. This allows the code block to `no_run` instead of `ignore`, so it will be compiled (but not run, so there's no `main` linker error), and that also has the nice side effect of removing the orange `!` warning bubble in the rendered docs. --- uefi/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 3368cd27c..69829d03b 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -12,7 +12,7 @@ //! Minimal example for an UEFI application using functionality of the //! `uefi` crate: //! -//! ```ignore +//! ```no_run //! #![no_main] //! #![no_std] //! @@ -24,6 +24,7 @@ //! //! Status::SUCCESS //! } +//! # extern crate std; //! ``` //! //! Please find more info in our [Rust UEFI Book]. From 3c02e268b48777082630a18a24cd1dce06fbfc04 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 10:49:42 -0400 Subject: [PATCH 032/512] book: Update boot_stages and tables Drop remaining references to SystemTable/BootServices/RuntimeServices. --- book/src/concepts/boot_stages.md | 31 ++++++++-------- book/src/concepts/tables.md | 64 +++++++++++++++----------------- 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/book/src/concepts/boot_stages.md b/book/src/concepts/boot_stages.md index acb81db67..c3fbca796 100644 --- a/book/src/concepts/boot_stages.md +++ b/book/src/concepts/boot_stages.md @@ -2,23 +2,22 @@ A UEFI system goes through several distinct phases during the boot process. 1. **Platform Initialization.** This early-boot phase is mostly outside - the scope of `uefi-rs`. It is described by the [UEFI Platform + the scope of the `uefi` crate. It is described by the [UEFI Platform Initialization Specification], which is separate from the main UEFI Specification. -2. **Boot Services.** This is when UEFI drivers and applications are - loaded. Both the [`BootServices`] and [`RuntimeServices`] tables are - accessible. This stage typically culminates in running a bootloader - that loads an operating system. The stage ends when - [`SystemTable::exit_boot_services`] is called, putting the system in - Runtime mode. -3. **Runtime.** This stage is typically active when running an operating - system such as Linux or Windows. UEFI functionality is much more - limited in the Runtime mode. The [`BootServices`] table is no longer - accessible, but the [`RuntimeServices`] table is still - available. Once the system is in Runtime mode, it cannot return to - the Boot Services stage until after a system reset. +2. **Boot Services.** This is when UEFI drivers and applications are loaded. + Functions in both the [`boot`] module and [`runtime`] module can be used. + This stage typically culminates in running a bootloader that loads an + operating system. The stage ends when [`boot::exit_boot_services`] is called, + putting the system in Runtime mode. +3. **Runtime.** This stage is typically active when running an operating system + such as Linux or Windows. UEFI functionality is much more limited in the + Runtime mode. Functions in the [`boot`] module can no longer be used, but + functions in the [`runtime`] module are still available. Once the system is + in Runtime mode, it cannot return to the Boot Services stage until after a + system reset. [UEFI Platform Initialization Specification]: https://uefi.org/specifications -[`BootServices`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html -[`RuntimeServices`]: https://docs.rs/uefi/latest/uefi/table/runtime/struct.RuntimeServices.html -[`SystemTable::exit_boot_services`]: https://docs.rs/uefi/latest/uefi/table/struct.SystemTable.html#method.exit_boot_services +[`boot`]: https://docs.rs/uefi/latest/uefi/boot/index.html +[`runtime`]: https://docs.rs/uefi/latest/uefi/runtime/index.html +[`boot::exit_boot_services`]: https://docs.rs/uefi/latest/uefi/boot/fn.exit_boot_services.html diff --git a/book/src/concepts/tables.md b/book/src/concepts/tables.md index 8e072c710..ac00ec7cd 100644 --- a/book/src/concepts/tables.md +++ b/book/src/concepts/tables.md @@ -1,37 +1,31 @@ # Tables -UEFI has a few table structures. These tables are how you get access to -UEFI services. - -[`SystemTable`] (`EFI_SYSTEM_TABLE` in the specification) is the -top-level table that provides access to the other tables. - -[`BootServices`] (`EFI_BOOT_SERVICES` in the specification) provides -access to a wide array of services such as memory allocation, executable -loading, and optional extension interfaces called protocols. This table -is only accessible while in the Boot Services stage. - -[`RuntimeServices`] (`EFI_RUNTIME_SERVICES` in the specification) -provides access to a fairly limited set of services, including variable -storage, system time, and virtual-memory mapping. This table is -accessible during both the Boot Services and Runtime stages. - -When writing a UEFI application, you get access to the system table from -one of the arguments to the `main` entry point: - -```rust,ignore -fn main(handle: Handle, mut system_table: SystemTable) -> Status; -``` - -Then use [`SystemTable::boot_services`] and -[`SystemTable::runtime_services`] to get access to the other -tables. Once [`SystemTable::exit_boot_services`] is called, the original -system table is consumed and a new system table is returned that only -provides access to the [`RuntimeServices`] table. - -[`BootServices`]: https://docs.rs/uefi/latest/uefi/table/boot/struct.BootServices.html -[`RuntimeServices`]: https://docs.rs/uefi/latest/uefi/table/runtime/struct.RuntimeServices.html -[`SystemTable::boot_services`]: https://docs.rs/uefi/latest/uefi/table/struct.SystemTable.html#method.boot_services -[`SystemTable::exit_boot_services`]: https://docs.rs/uefi/latest/uefi/table/struct.SystemTable.html#method.exit_boot_services -[`SystemTable::runtime_services`]: https://docs.rs/uefi/latest/uefi/table/struct.SystemTable.html#method.runtime_services -[`SystemTable`]: https://docs.rs/uefi/latest/uefi/table/struct.SystemTable.html +UEFI has a few table structures. These tables are how you get access to UEFI +services. In the specification and C API, `EFI_SYSTEM_TABLE` is the top-level +table that provides access to the other tables, `EFI_BOOT_SERVICES` and +`EFI_RUNTIME_SERVICES`. + +In the `uefi` crate, these tables are modeled as modules rather than structs. The +functions in each module make use of a global pointer to the system table that +is set automatically by the [`entry`] macro. + +* [`uefi::system`] (`EFI_SYSTEM_TABLE` in the specification) provides access to +system information such as the firmware vendor and version. It can also be used +to access stdout/stderr/stdin. + +* [`uefi::boot`] (`EFI_BOOT_SERVICES` in the specification) provides access to a +wide array of services such as memory allocation, executable loading, and +optional extension interfaces called protocols. Functions in this module can +only be used while in the Boot Services stage. After [`exit_boot_services`] has +been called, these functions will panic. + +* [`uefi::runtime`] (`EFI_RUNTIME_SERVICES` in the specification) provides access +to a fairly limited set of services, including variable storage, system time, +and virtual-memory mapping. Functions in this module are accessible during both +the Boot Services and Runtime stages. + +[`entry`]: https://docs.rs/uefi/latest/uefi/attr.entry.html +[`exit_boot_services`]: https://docs.rs/uefi/latest/uefi/boot/fn.exit_boot_services.html +[`uefi::boot`]: https://docs.rs/uefi/latest/uefi/boot/index.html +[`uefi::runtime`]: https://docs.rs/uefi/latest/uefi/runtime/index.html +[`uefi::system`]: https://docs.rs/uefi/latest/uefi/system/index.html From 6b9fed1bca1c92539634a8622d8aeac1dc652d68 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 12:51:50 -0400 Subject: [PATCH 033/512] uefi-macros: Use uefi::boot::set_image_handle --- uefi-macros/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uefi-macros/src/lib.rs b/uefi-macros/src/lib.rs index 8e4f48c7e..ee175824d 100644 --- a/uefi-macros/src/lib.rs +++ b/uefi-macros/src/lib.rs @@ -229,7 +229,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { 0, parse_quote! { unsafe { - #system_table_ident.boot_services().set_image_handle(#image_handle_ident); + ::uefi::boot::set_image_handle(#image_handle_ident); ::uefi::table::set_system_table(#system_table_ident.as_ptr().cast()); } }, From 060f2f03a636b79f2a30630200fee0b2432e02d0 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 12:53:33 -0400 Subject: [PATCH 034/512] uefi: Drop args from main in the example --- uefi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 69829d03b..2e1d4926a 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -19,7 +19,7 @@ //! use uefi::prelude::*; //! //! #[entry] -//! fn main(_handle: Handle, system_table: SystemTable) -> Status { +//! fn main() -> Status { //! uefi::helpers::init().unwrap(); //! //! Status::SUCCESS From fee9386bd7e9bd3532e825b01caf088cc7280d5b Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 13:38:44 -0400 Subject: [PATCH 035/512] template: Drop args to main --- template/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/src/main.rs b/template/src/main.rs index d3bb8ad5f..4330a71fe 100644 --- a/template/src/main.rs +++ b/template/src/main.rs @@ -4,7 +4,7 @@ use uefi::prelude::*; #[entry] -fn main(_handle: Handle, system_table: SystemTable) -> Status { +fn main() -> Status { uefi::helpers::init().unwrap(); Status::SUCCESS From fc26521f30eb089380c76e30e7d33b8002ce3511 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 01:05:29 -0400 Subject: [PATCH 036/512] uefi-macros: Use raw pointer for system table when generating args When applying `entry` to a no-arg main, generate the system table pointer as `*const c_void` rather than `SystemTable`. This will avoid unwanted deprecation warnings after `SystemTable` is deprecated. --- uefi-macros/src/lib.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/uefi-macros/src/lib.rs b/uefi-macros/src/lib.rs index ee175824d..fdcc3cff9 100644 --- a/uefi-macros/src/lib.rs +++ b/uefi-macros/src/lib.rs @@ -200,11 +200,12 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { // If the user doesn't specify any arguments to the entry function, fill in // the image handle and system table arguments automatically. - if f.sig.inputs.is_empty() { + let generated_args = f.sig.inputs.is_empty(); + if generated_args { f.sig.inputs = parse_quote_spanned!( signature_span=> internal_image_handle: ::uefi::Handle, - internal_system_table: ::uefi::table::SystemTable<::uefi::table::Boot> + internal_system_table: *const ::core::ffi::c_void, ); } @@ -225,12 +226,20 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { // Set the global image handle. If `image_handle_ident` is `None` // then the typecheck is going to fail anyway. if let Some(image_handle_ident) = image_handle_ident { + // Convert the system table arg (either `SystemTable` or + // `*const c_void`) to a pointer of the correct type. + let system_table_ptr = if generated_args { + quote!(#system_table_ident.cast()) + } else { + quote!(#system_table_ident.as_ptr().cast()) + }; + f.block.stmts.insert( 0, parse_quote! { unsafe { ::uefi::boot::set_image_handle(#image_handle_ident); - ::uefi::table::set_system_table(#system_table_ident.as_ptr().cast()); + ::uefi::table::set_system_table(#system_table_ptr); } }, ); @@ -249,6 +258,16 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { }); let fn_output = &f.sig.output; + // Get the expected argument types for the main function. + let expected_args = if generated_args { + quote!(::uefi::Handle, *const core::ffi::c_void) + } else { + quote!( + ::uefi::Handle, + ::uefi::table::SystemTable<::uefi::table::Boot> + ) + }; + let fn_type_check = quote_spanned! {signature_span=> // Cast from the function type to a function pointer with the same // signature first, then try to assign that to an unnamed constant with @@ -260,7 +279,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { // specifically in the function signature is incorrect. const _: // The expected fn pointer type. - #unsafety extern "efiapi" fn(::uefi::Handle, ::uefi::table::SystemTable<::uefi::table::Boot>) -> ::uefi::Status = + #unsafety extern "efiapi" fn(#expected_args) -> ::uefi::Status = // Cast from a fn item to a function pointer. #fn_ident as #unsafety extern "efiapi" fn(#(#fn_inputs),*) #fn_output; }; From 54157533e0e931f27a59fd82455372b59bd037ab Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 15:23:17 -0400 Subject: [PATCH 037/512] uefi: Update logger to use the global system table --- uefi/src/helpers/logger.rs | 8 +++++--- uefi/src/helpers/mod.rs | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/uefi/src/helpers/logger.rs b/uefi/src/helpers/logger.rs index cb01a1ae4..080403b3b 100644 --- a/uefi/src/helpers/logger.rs +++ b/uefi/src/helpers/logger.rs @@ -12,8 +12,8 @@ //! The last part also means that some Unicode characters might not be //! supported by the UEFI console. Don't expect emoji output support. -use crate::prelude::{Boot, SystemTable}; use crate::proto::console::text::Output; +use crate::system; use core::fmt::{self, Write}; use core::ptr; use core::sync::atomic::{AtomicPtr, Ordering}; @@ -25,9 +25,11 @@ static LOGGER: Logger = Logger::new(); /// /// This is unsafe because you must arrange for the logger to be reset with /// disable() on exit from UEFI boot services. -pub unsafe fn init(st: &mut SystemTable) { +pub unsafe fn init() { // Connect the logger to stdout. - LOGGER.set_output(st.stdout()); + system::with_stdout(|stdout| { + LOGGER.set_output(stdout); + }); // Set the logger. log::set_logger(&LOGGER).unwrap(); // Can only fail if already initialized. diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index 3b1ac1db2..237e2fd22 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -58,8 +58,7 @@ pub fn init() -> Result<()> { // Set up logging. #[cfg(feature = "logger")] unsafe { - let mut st = table::system_table_boot().expect("boot services are not active"); - logger::init(&mut st); + logger::init(); } Ok(()) From da0908d5e2a13fc5e72926324f1c867da5614a92 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 15:47:31 -0400 Subject: [PATCH 038/512] uefi: Update panic handler to use the global system table --- uefi/src/helpers/panic_handler.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/uefi/src/helpers/panic_handler.rs b/uefi/src/helpers/panic_handler.rs index 5918395b8..79359b726 100644 --- a/uefi/src/helpers/panic_handler.rs +++ b/uefi/src/helpers/panic_handler.rs @@ -1,5 +1,4 @@ -use crate::println; -use crate::table::system_table_boot; +use crate::{boot, println}; use cfg_if::cfg_if; #[panic_handler] @@ -7,8 +6,8 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { println!("[PANIC]: {}", info); // Give the user some time to read the message - if let Some(st) = system_table_boot() { - st.boot_services().stall(10_000_000); + if boot::are_boot_services_active() { + boot::stall(10_000_000); } else { let mut dummy = 0u64; // FIXME: May need different counter values in debug & release builds @@ -28,10 +27,10 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { qemu_exit_handle.exit_failure(); } else { // If the system table is available, use UEFI's standard shutdown mechanism - if let Some(st) = system_table_boot() { - use crate::table::runtime::ResetType; - st.runtime_services() - .reset(ResetType::SHUTDOWN, crate::Status::ABORTED, None); + if let Some(st) = crate::table::system_table_raw() { + if !unsafe { st.as_ref().runtime_services }.is_null() { + crate::runtime::reset(crate::runtime::ResetType::SHUTDOWN, crate::Status::ABORTED, None); + } } // If we don't have any shutdown mechanism handy, the best we can do is loop From 13206914fea0c6a3eec1f10b1ac26602c2dc08ba Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 16:02:15 -0400 Subject: [PATCH 039/512] uefi: Update println to use the global system table --- uefi/src/helpers/println.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/uefi/src/helpers/println.rs b/uefi/src/helpers/println.rs index 2b9903e92..35972f415 100644 --- a/uefi/src/helpers/println.rs +++ b/uefi/src/helpers/println.rs @@ -1,13 +1,13 @@ -use crate::table::system_table_boot; +use crate::{boot, system}; use core::fmt::Write; /// INTERNAL API! Helper for print macros. #[doc(hidden)] pub fn _print(args: core::fmt::Arguments) { - if let Some(mut bs) = system_table_boot() { - bs.stdout() - .write_fmt(args) - .expect("Failed to write to stdout"); + if boot::are_boot_services_active() { + system::with_stdout(|stdout| { + stdout.write_fmt(args).expect("Failed to write to stdout"); + }); } else { // Ease debugging: Depending on logger, this might write to serial or // debugcon. @@ -25,8 +25,7 @@ pub fn _print(args: core::fmt::Arguments) { /// prevent a circular runtime dependency. /// /// # Panics -/// Will panic if `SYSTEM_TABLE` is `None` (Before [`uefi::helpers::init()`] and -/// after [`uefi::prelude::SystemTable::exit_boot_services()`]). +/// Will panic if the system table's `stdout` is not set, or if writing fails. /// /// # Examples /// ``` @@ -50,8 +49,7 @@ macro_rules! print { /// prevent a circular runtime dependency. /// /// # Panics -/// Will panic if `SYSTEM_TABLE` is `None` (Before [`uefi::helpers::init()`] and -/// after [`uefi::prelude::SystemTable::exit_boot_services()`]). +/// Will panic if the system table's `stdout` is not set, or if writing fails. /// /// # Examples /// ``` From 416a1db37b338779cf877c4c142c142a5043bc7b Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 20:18:11 -0400 Subject: [PATCH 040/512] uefi: Simplify MemoryMapBackingMemory It's not necessary to gate on `cfg(test)`, the system table will not be set in that case so the drop will just do nothing. --- uefi/src/mem/memory_map/impl_.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/uefi/src/mem/memory_map/impl_.rs b/uefi/src/mem/memory_map/impl_.rs index a0fd463dc..b9b53d56d 100644 --- a/uefi/src/mem/memory_map/impl_.rs +++ b/uefi/src/mem/memory_map/impl_.rs @@ -339,7 +339,6 @@ impl MemoryMapBackingMemory { } // Don't drop when we use this in unit tests. -#[cfg(not(test))] impl Drop for MemoryMapBackingMemory { fn drop(&mut self) { if let Some(bs) = system_table_boot() { @@ -348,11 +347,7 @@ impl Drop for MemoryMapBackingMemory { log::error!("Failed to deallocate memory map: {e:?}"); } } else { - #[cfg(test)] - log::debug!("Boot services are not available in unit tests."); - - #[cfg(not(test))] - log::debug!("Boot services are excited. Memory map won't be freed using the UEFI boot services allocator."); + log::debug!("Boot services are exited. Memory map won't be freed using the UEFI boot services allocator."); } } } From 5227fc04b7da50dbbe850d96ce3690d4359edfe4 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 20:22:22 -0400 Subject: [PATCH 041/512] uefi: Use global system table in MemoryMapBackingMemory::drop --- uefi/src/mem/memory_map/impl_.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/uefi/src/mem/memory_map/impl_.rs b/uefi/src/mem/memory_map/impl_.rs index b9b53d56d..f3cdfd2fb 100644 --- a/uefi/src/mem/memory_map/impl_.rs +++ b/uefi/src/mem/memory_map/impl_.rs @@ -2,6 +2,7 @@ //! as well as relevant helper types, such as [`MemoryMapBackingMemory`]. use super::*; +use crate::boot; use crate::table::system_table_boot; use core::fmt::{Debug, Display, Formatter}; use core::ops::{Index, IndexMut}; @@ -341,8 +342,8 @@ impl MemoryMapBackingMemory { // Don't drop when we use this in unit tests. impl Drop for MemoryMapBackingMemory { fn drop(&mut self) { - if let Some(bs) = system_table_boot() { - let res = unsafe { bs.boot_services().free_pool(self.0.as_ptr().cast()) }; + if boot::are_boot_services_active() { + let res = unsafe { boot::free_pool(self.0.cast()) }; if let Err(e) = res { log::error!("Failed to deallocate memory map: {e:?}"); } From 21d03f63528ac24b5d3cfc4df213ea799f869649 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 20:24:47 -0400 Subject: [PATCH 042/512] uefi: Use global system table in MemoryMapBackingMemory::new Move `get_memory_map` from `uefi::table::boot` to `uefi::boot`, and update `MemoryMapBackingMemory::new` accordingly. --- uefi/src/boot.rs | 45 ++++++++++++++++++++++++++++++++ uefi/src/mem/memory_map/impl_.rs | 8 ++---- uefi/src/table/boot.rs | 42 ----------------------------- 3 files changed, 47 insertions(+), 48 deletions(-) diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index c1764c83f..6543258ea 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -178,6 +178,51 @@ pub unsafe fn free_pool(ptr: NonNull) -> Result { unsafe { (bt.free_pool)(ptr.as_ptr()) }.to_result() } +/// Queries the `get_memory_map` function of UEFI to retrieve the current +/// size of the map. Returns a [`MemoryMapMeta`]. +/// +/// It is recommended to add a few more bytes for a subsequent allocation +/// for the memory map, as the memory map itself also needs heap memory, +/// and other allocations might occur before that call. +#[must_use] +pub(crate) fn memory_map_size() -> MemoryMapMeta { + let bt = boot_services_raw_panicking(); + let bt = unsafe { bt.as_ref() }; + + let mut map_size = 0; + let mut map_key = MemoryMapKey(0); + let mut desc_size = 0; + let mut desc_version = 0; + + let status = unsafe { + (bt.get_memory_map)( + &mut map_size, + ptr::null_mut(), + &mut map_key.0, + &mut desc_size, + &mut desc_version, + ) + }; + assert_eq!(status, Status::BUFFER_TOO_SMALL); + + assert_eq!( + map_size % desc_size, + 0, + "Memory map must be a multiple of the reported descriptor size." + ); + + let mmm = MemoryMapMeta { + desc_size, + map_size, + map_key, + desc_version, + }; + + mmm.assert_sanity_checks(); + + mmm +} + /// Stores the current UEFI memory map in an UEFI-heap allocated buffer /// and returns a [`MemoryMapOwned`]. /// diff --git a/uefi/src/mem/memory_map/impl_.rs b/uefi/src/mem/memory_map/impl_.rs index f3cdfd2fb..9ceab3658 100644 --- a/uefi/src/mem/memory_map/impl_.rs +++ b/uefi/src/mem/memory_map/impl_.rs @@ -3,7 +3,6 @@ use super::*; use crate::boot; -use crate::table::system_table_boot; use core::fmt::{Debug, Display, Formatter}; use core::ops::{Index, IndexMut}; use core::ptr::NonNull; @@ -275,12 +274,9 @@ impl MemoryMapBackingMemory { /// - `memory_type`: The memory type for the memory map allocation. /// Typically, [`MemoryType::LOADER_DATA`] for regular UEFI applications. pub(crate) fn new(memory_type: MemoryType) -> crate::Result { - let st = system_table_boot().expect("Should have boot services activated"); - let bs = st.boot_services(); - - let memory_map_meta = bs.memory_map_size(); + let memory_map_meta = boot::memory_map_size(); let len = Self::safe_allocation_size_hint(memory_map_meta); - let ptr = bs.allocate_pool(memory_type, len)?.as_ptr(); + let ptr = boot::allocate_pool(memory_type, len)?.as_ptr(); // Should be fine as UEFI always has allocations with a guaranteed // alignment of 8 bytes. diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 43379c31e..e03269559 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -168,48 +168,6 @@ impl BootServices { unsafe { (self.0.free_pages)(addr, count) }.to_result() } - /// Queries the `get_memory_map` function of UEFI to retrieve the current - /// size of the map. Returns a [`MemoryMapMeta`]. - /// - /// It is recommended to add a few more bytes for a subsequent allocation - /// for the memory map, as the memory map itself also needs heap memory, - /// and other allocations might occur before that call. - #[must_use] - pub(crate) fn memory_map_size(&self) -> MemoryMapMeta { - let mut map_size = 0; - let mut map_key = MemoryMapKey(0); - let mut desc_size = 0; - let mut desc_version = 0; - - let status = unsafe { - (self.0.get_memory_map)( - &mut map_size, - ptr::null_mut(), - &mut map_key.0, - &mut desc_size, - &mut desc_version, - ) - }; - assert_eq!(status, Status::BUFFER_TOO_SMALL); - - assert_eq!( - map_size % desc_size, - 0, - "Memory map must be a multiple of the reported descriptor size." - ); - - let mmm = MemoryMapMeta { - desc_size, - map_size, - map_key, - desc_version, - }; - - mmm.assert_sanity_checks(); - - mmm - } - /// Stores the current UEFI memory map in an UEFI-heap allocated buffer /// and returns a [`MemoryMapOwned`]. /// From 2228e312f2f719e57fb1c1c31ff50596cc8b4fb1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 00:35:56 +0000 Subject: [PATCH 043/512] chore(deps): lock file maintenance --- Cargo.lock | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89f95123a..0ce58586f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,10 +3,10 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" @@ -97,9 +97,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.13" +version = "1.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" dependencies = [ "shlex", ] @@ -231,9 +231,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fatfs" @@ -260,9 +260,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", "miniz_oxide", @@ -368,9 +368,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "libc" -version = "0.2.157" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374af5f94e54fa97cf75e945cce8a6b201e88a1a07e688b47dfd2a59c66dbd86" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libredox" @@ -426,11 +426,11 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -504,9 +504,9 @@ checksum = "8bb0fd6580eeed0103c054e3fba2c2618ff476943762f28a645b63b8692b21c9" [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -632,9 +632,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] @@ -650,9 +650,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -661,9 +661,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.125" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", "memchr", From c3415adc4c3fcd6608d442e7aac5df8d710f2b22 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 25 Aug 2024 20:42:21 -0400 Subject: [PATCH 044/512] uefi: Deprecate RuntimeServices --- uefi-test-runner/src/main.rs | 3 +++ uefi/src/prelude.rs | 1 + uefi/src/table/runtime.rs | 3 +++ uefi/src/table/system.rs | 2 ++ 4 files changed, 9 insertions(+) diff --git a/uefi-test-runner/src/main.rs b/uefi-test-runner/src/main.rs index 569b36e91..d6af3b28a 100644 --- a/uefi-test-runner/src/main.rs +++ b/uefi-test-runner/src/main.rs @@ -1,5 +1,8 @@ #![no_std] #![no_main] +// TODO: temporarily allow deprecated code so that we can continue to test +// SystemTable/BootServices/RuntimeServices. +#![allow(deprecated)] #[macro_use] extern crate log; diff --git a/uefi/src/prelude.rs b/uefi/src/prelude.rs index f32f9903c..a4ec0e55f 100644 --- a/uefi/src/prelude.rs +++ b/uefi/src/prelude.rs @@ -6,5 +6,6 @@ pub use crate::{cstr16, cstr8, entry, Handle, ResultExt, Status, StatusExt}; // Import the basic table types. pub use crate::table::boot::BootServices; +#[allow(deprecated)] pub use crate::table::runtime::RuntimeServices; pub use crate::table::{Boot, SystemTable}; diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index 5b14808a3..2c9d4d22a 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -1,5 +1,7 @@ //! UEFI services available at runtime, even after the OS boots. +#![allow(deprecated)] + pub use crate::runtime::{ CapsuleInfo, Time, TimeByteConversionError, TimeError, TimeParams, VariableStorageInfo, }; @@ -35,6 +37,7 @@ use { /// A reference to `RuntimeServices` can only be accessed by calling [`SystemTable::runtime_services`]. /// /// [`SystemTable::runtime_services`]: crate::table::SystemTable::runtime_services +#[deprecated = "Use the uefi::runtime module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] #[derive(Debug)] #[repr(C)] pub struct RuntimeServices(uefi_raw::table::runtime::RuntimeServices); diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index afdf242f2..53eb4cd58 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use super::boot::BootServices; use super::runtime::{ResetType, RuntimeServices}; use super::{cfg, Revision}; From 5aff4680cadaf80c2ca029960172a7f258324847 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 03:53:57 +0000 Subject: [PATCH 045/512] chore(deps): update crate-ci/typos action to v1.24.1 --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index cd37d3e64..4b49cb338 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -7,4 +7,4 @@ jobs: steps: - uses: actions/checkout@v4 # Executes "typos ." - - uses: crate-ci/typos@v1.23.6 + - uses: crate-ci/typos@v1.24.1 From 5828189e2461d47f467fb634e68a7fb07aa78823 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 26 Aug 2024 10:20:14 -0400 Subject: [PATCH 046/512] uefi: Deprecate BootServices --- uefi/CHANGELOG.md | 5 +++++ uefi/src/prelude.rs | 1 + uefi/src/table/boot.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 86d118ddc..9b01c4ab6 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,5 +1,8 @@ # uefi - [Unreleased] +See [Deprecating SystemTable/BootServices/RuntimeServices][funcmigrate] for +details of the deprecation in this release. + We added documentation to `lib.rs` and the [uefi-rs book] about how `uefi` compares to "standard Rust binaries" for UEFI (those using `std`), and how to integrate the `uefi` crate into them. @@ -8,6 +11,8 @@ how to integrate the `uefi` crate into them. - Added `Handle::new` ## Changed +- The `BootServices` and `RuntimeServices` structs have been deprecated. Use + the `uefi::runtime` and `uefi::boot` modules instead. - **Breaking:** The conversion functions between device paths and text no longer take a `BootServices` argument. The global system table is used instead. - **Breaking:** `GraphicsOutput::modes` no longer takes a `BootServices` diff --git a/uefi/src/prelude.rs b/uefi/src/prelude.rs index a4ec0e55f..5c9e108b5 100644 --- a/uefi/src/prelude.rs +++ b/uefi/src/prelude.rs @@ -5,6 +5,7 @@ pub use crate::{cstr16, cstr8, entry, Handle, ResultExt, Status, StatusExt}; // Import the basic table types. +#[allow(deprecated)] pub use crate::table::boot::BootServices; #[allow(deprecated)] pub use crate::table::runtime::RuntimeServices; diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index e03269559..614a26614 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -1,5 +1,7 @@ //! UEFI services available during boot. +#![allow(deprecated)] + pub use crate::boot::{ AllocateType, EventNotifyFn, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams, ProtocolSearchKey, SearchType, TimerTrigger, @@ -79,6 +81,7 @@ pub const PAGE_SIZE: usize = 4096; /// /// [`Output`]: crate::proto::console::text::Output /// [`open_protocol`]: BootServices::open_protocol +#[deprecated = "Use the uefi::boot module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] #[derive(Debug)] #[repr(transparent)] pub struct BootServices(uefi_raw::table::boot::BootServices); From 65bc12c72a4bd830cad392149c50241a4e326412 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 26 Aug 2024 10:48:06 -0400 Subject: [PATCH 047/512] uefi: Update FS docstring example code --- uefi/src/fs/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/uefi/src/fs/mod.rs b/uefi/src/fs/mod.rs index b66acbfcc..22df15f04 100644 --- a/uefi/src/fs/mod.rs +++ b/uefi/src/fs/mod.rs @@ -27,13 +27,12 @@ //! ```no_run //! use uefi::CString16; //! use uefi::fs::{FileSystem, FileSystemResult}; -//! use uefi::prelude::BootServices; //! use uefi::proto::media::fs::SimpleFileSystem; -//! use uefi::table::boot::ScopedProtocol; +//! use uefi::boot::{self, ScopedProtocol}; //! -//! fn read_file(bs: BootServices, path: &str) -> FileSystemResult> { +//! fn read_file(path: &str) -> FileSystemResult> { //! let path: CString16 = CString16::try_from(path).unwrap(); -//! let fs: ScopedProtocol = bs.get_image_file_system(bs.image_handle()).unwrap(); +//! let fs: ScopedProtocol = boot::get_image_file_system(boot::image_handle()).unwrap(); //! let mut fs = FileSystem::new(fs); //! fs.read(path.as_ref()) //! } From 31492e0917d599294a9f3e3ab9315a6b3dca2d44 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 26 Aug 2024 11:56:42 -0400 Subject: [PATCH 048/512] uefi: Copy 'Accessing Protocols' docs to uefi::boot The new section is copied from the BootServices docstring. Also update various places that link to that doc. --- uefi/src/boot.rs | 17 +++++++++++++++++ uefi/src/lib.rs | 2 +- uefi/src/proto/console/text/output.rs | 4 ++-- uefi/src/proto/media/fs.rs | 8 ++++---- uefi/src/proto/mod.rs | 5 ++--- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index 6543258ea..a165ca358 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -1,6 +1,23 @@ //! UEFI boot services. //! //! These functions will panic if called after exiting boot services. +//! +//! # Accessing protocols +//! +//! Protocols can be opened using several methods of `BootServices`. Most +//! commonly, [`open_protocol_exclusive`] should be used. This ensures that +//! nothing else can use the protocol until it is closed, and returns a +//! [`ScopedProtocol`] that takes care of closing the protocol when it is +//! dropped. +//! +//! Other methods for opening protocols: +//! +//! * [`open_protocol`] +//! * [`get_image_file_system`] +//! +//! For protocol definitions, see the [`proto`] module. +//! +//! [`proto`]: crate::proto pub use uefi_raw::table::boot::{EventType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl}; diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 2e1d4926a..62d34f24d 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -116,7 +116,7 @@ //! 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 +//! 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. //! diff --git a/uefi/src/proto/console/text/output.rs b/uefi/src/proto/console/text/output.rs index 5a2ac3524..a4c5c4cfe 100644 --- a/uefi/src/proto/console/text/output.rs +++ b/uefi/src/proto/console/text/output.rs @@ -14,12 +14,12 @@ use uefi_raw::protocol::console::{SimpleTextOutputMode, SimpleTextOutputProtocol /// using [`SystemTable::stdout`] and [`SystemTable::stderr`], respectively. /// /// An `Output` protocol can also be accessed like any other UEFI protocol. -/// See the [`BootServices`] documentation for more details of how to open a +/// See the [`boot`] documentation for more details of how to open a /// protocol. /// /// [`SystemTable::stdout`]: crate::table::SystemTable::stdout /// [`SystemTable::stderr`]: crate::table::SystemTable::stderr -/// [`BootServices`]: crate::table::boot::BootServices#accessing-protocols +/// [`boot`]: crate::boot#accessing-protocols #[derive(Debug)] #[repr(transparent)] #[unsafe_protocol(SimpleTextOutputProtocol::GUID)] diff --git a/uefi/src/proto/media/fs.rs b/uefi/src/proto/media/fs.rs index b624732e7..7d2c0ee5d 100644 --- a/uefi/src/proto/media/fs.rs +++ b/uefi/src/proto/media/fs.rs @@ -13,13 +13,13 @@ use uefi_raw::protocol::file_system::SimpleFileSystemProtocol; /// /// # Accessing `SimpleFileSystem` protocol /// -/// Use [`BootServices::get_image_file_system`] to retrieve the `SimpleFileSystem` +/// Use [`boot::get_image_file_system`] to retrieve the `SimpleFileSystem` /// protocol associated with a given image handle. /// -/// See the [`BootServices`] documentation for more details of how to open a protocol. +/// See the [`boot`] documentation for more details of how to open a protocol. /// -/// [`BootServices::get_image_file_system`]: crate::table::boot::BootServices::get_image_file_system -/// [`BootServices`]: crate::table::boot::BootServices#accessing-protocols +/// [`boot::get_image_file_system`]: crate::boot::get_image_file_system +/// [`boot`]: crate::boot#accessing-protocols #[derive(Debug)] #[repr(transparent)] #[unsafe_protocol(SimpleFileSystemProtocol::GUID)] diff --git a/uefi/src/proto/mod.rs b/uefi/src/proto/mod.rs index 218f3ffb0..c317d282c 100644 --- a/uefi/src/proto/mod.rs +++ b/uefi/src/proto/mod.rs @@ -4,10 +4,9 @@ //! ID. They can be implemented by a UEFI driver or occasionally by a //! UEFI application. //! -//! See the [`BootServices`] documentation for details of how to open a -//! protocol. +//! See the [`boot`] documentation for details of how to open a protocol. //! -//! [`BootServices`]: crate::table::boot::BootServices#accessing-protocols +//! [`boot`]: crate::boot#accessing-protocols pub mod console; pub mod debug; From 468edca0843076e91ae60cc994d3d6a82ec610ee Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 26 Aug 2024 13:31:28 -0400 Subject: [PATCH 049/512] uefi/mem: Update docs referring to BootServices --- uefi/src/mem/memory_map/impl_.rs | 4 ++-- uefi/src/mem/memory_map/mod.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/uefi/src/mem/memory_map/impl_.rs b/uefi/src/mem/memory_map/impl_.rs index 9ceab3658..21814cae5 100644 --- a/uefi/src/mem/memory_map/impl_.rs +++ b/uefi/src/mem/memory_map/impl_.rs @@ -259,10 +259,10 @@ impl IndexMut for MemoryMapRefMut<'_> { /// # Usage /// The type is intended to be used like this: /// 1. create it using [`MemoryMapBackingMemory::new`] -/// 2. pass it to [`BootServices::get_memory_map`] +/// 2. pass it to [`boot::get_memory_map`] /// 3. construct a [`MemoryMapOwned`] from it /// -/// [`BootServices::get_memory_map`]: crate::table::boot::BootServices::get_memory_map +/// [`boot::get_memory_map`]: crate::boot::get_memory_map #[derive(Debug)] #[allow(clippy::len_without_is_empty)] // this type is never empty pub(crate) struct MemoryMapBackingMemory(NonNull<[u8]>); diff --git a/uefi/src/mem/memory_map/mod.rs b/uefi/src/mem/memory_map/mod.rs index 45d66de41..232c54e4e 100644 --- a/uefi/src/mem/memory_map/mod.rs +++ b/uefi/src/mem/memory_map/mod.rs @@ -8,8 +8,8 @@ //! //! # Usecase: Obtain UEFI Memory Map //! -//! You can use [`SystemTable::exit_boot_services`] or -//! [`BootServices::memory_map`], which returns an properly initialized +//! You can use [`boot::exit_boot_services`] or +//! [`boot::memory_map`], which returns an properly initialized //! [`MemoryMapOwned`]. //! //! # Usecase: Parse Memory Slice as UEFI Memory Map @@ -28,8 +28,8 @@ //! [`MemoryMapMeta`], //! - re-exports [`MemoryDescriptor`], [`MemoryType`], and [`MemoryAttribute`]. //! -//! [`SystemTable::exit_boot_services`]: uefi::table::SystemTable::exit_boot_services -//! [`BootServices::memory_map`]: uefi::table::boot::BootServices::memory_map +//! [`boot::exit_boot_services`]: crate::table::SystemTable::exit_boot_services +//! [`boot::memory_map`]: crate::boot::memory_map mod api; mod impl_; @@ -49,7 +49,7 @@ impl Align for MemoryDescriptor { } } -/// A unique identifier of a UEFI memory map, used to tell the firmware that one +/// A unique identifier of a UEFI memory map, used to tell the firmware that one /// has the latest valid memory map when exiting boot services. /// /// If the memory map changes, due to any allocation or deallocation, this value From ec84d348d6a09bf115b7625c73cc0614cec76df9 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 26 Aug 2024 23:36:22 -0400 Subject: [PATCH 050/512] uefi: Update input protocol docs --- uefi/src/proto/console/text/input.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/uefi/src/proto/console/text/input.rs b/uefi/src/proto/console/text/input.rs index e681c97cf..622e44bb3 100644 --- a/uefi/src/proto/console/text/input.rs +++ b/uefi/src/proto/console/text/input.rs @@ -24,10 +24,10 @@ impl Input { /// Reads the next keystroke from the input device, if any. /// - /// Use [`wait_for_key_event`] with the [`BootServices::wait_for_event`] + /// Use [`wait_for_key_event`] with the [`boot::wait_for_event`] /// interface in order to wait for a key to be pressed. /// - /// [`BootServices::wait_for_event`]: uefi::table::boot::BootServices::wait_for_event + /// [`boot::wait_for_event`]: crate::boot::wait_for_event /// [`wait_for_key_event`]: Self::wait_for_key_event /// /// # Errors @@ -39,16 +39,13 @@ impl Input { /// ``` /// use log::info; /// use uefi::proto::console::text::{Input, Key, ScanCode}; - /// use uefi::table::boot::BootServices; - /// use uefi::{Char16, Result, ResultExt}; + /// use uefi::{boot, Char16, Result, ResultExt}; /// - /// fn read_keyboard_events(boot_services: &BootServices, input: &mut Input) -> Result { + /// fn read_keyboard_events(input: &mut Input) -> Result { /// loop { /// // Pause until a keyboard event occurs. /// let mut events = unsafe { [input.wait_for_key_event().unwrap()] }; - /// boot_services - /// .wait_for_event(&mut events) - /// .discard_errdata()?; + /// boot::wait_for_event(&mut events).discard_errdata()?; /// /// let u_key = Char16::try_from('u').unwrap(); /// match input.read_key()? { @@ -79,8 +76,10 @@ impl Input { } } - /// Event to be used with `BootServices::wait_for_event()` in order to wait + /// Event to be used with [`boot::wait_for_event`] in order to wait /// for a key to be available + /// + /// [`boot::wait_for_event`]: crate::boot::wait_for_event #[must_use] pub fn wait_for_key_event(&self) -> Option { unsafe { Event::from_ptr(self.0.wait_for_key) } From 9e4fb463eef8966bf3d8fdce96f4038641a190a0 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 26 Aug 2024 23:38:50 -0400 Subject: [PATCH 051/512] uefi: Update ResetNotification protocol docs --- uefi/src/proto/misc.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/uefi/src/proto/misc.rs b/uefi/src/proto/misc.rs index 92666fd08..e329aff8e 100644 --- a/uefi/src/proto/misc.rs +++ b/uefi/src/proto/misc.rs @@ -44,8 +44,7 @@ impl ResetNotification { /// /// ```rust /// use log::info; - /// use uefi::Handle; - /// use uefi::prelude::BootServices; + /// use uefi::{boot, Handle}; /// use uefi::proto::misc::{ResetNotification}; /// use uefi_raw::Status; /// use uefi_raw::table::runtime; @@ -62,10 +61,9 @@ impl ResetNotification { /// info!("do what you want"); /// } /// - /// pub fn test(image: Handle, bt: &BootServices) { + /// pub fn test(image: Handle) { /// - /// let mut rn = bt - /// .open_protocol_exclusive::(image) + /// let mut rn = boot::open_protocol_exclusive::(image) /// .expect("Failed to open Timestamp protocol"); /// /// rn.register_reset_notify(efi_reset_fn) From 50df766862a9d9a36878894a9fdb47afed7c022e Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 26 Aug 2024 23:41:03 -0400 Subject: [PATCH 052/512] uefi: Update LoadedImage protocol docs --- uefi/src/proto/loaded_image.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/uefi/src/proto/loaded_image.rs b/uefi/src/proto/loaded_image.rs index 7e1bf2071..057cfa4de 100644 --- a/uefi/src/proto/loaded_image.rs +++ b/uefi/src/proto/loaded_image.rs @@ -139,14 +139,14 @@ impl LoadedImage { /// Drivers that wish to support unloading have to register their unload handler /// using this protocol. It is responsible for cleaning up any resources the /// image is using before returning. Unloading a driver is done with - /// [`BootServices::unload_image`]. + /// [`boot::unload_image`]. /// /// # Safety /// /// Only the driver that this [`LoadedImage`] is attached to should register an /// unload handler. /// - /// [`BootServices::unload_image`]: crate::table::boot::BootServices + /// [`boot::unload_image`]: crate::boot::unload_image pub unsafe fn set_unload( &mut self, unload: extern "efiapi" fn(image_handle: Handle) -> Status, @@ -157,7 +157,7 @@ impl LoadedImage { } /// Set the load options for the image. This can be used prior to - /// calling `BootServices.start_image` to control the command line + /// calling [`boot::start_image`] to control the command line /// passed to the image. /// /// `size` is in bytes. @@ -167,6 +167,8 @@ impl LoadedImage { /// This function takes `options` as a raw pointer because the /// load options data is not owned by `LoadedImage`. The caller /// must ensure that the memory lives long enough. + /// + /// [`boot::start_image`]: crate::boot::start_image pub unsafe fn set_load_options(&mut self, options: *const u8, size: u32) { self.0.load_options = options.cast(); self.0.load_options_size = size; From 6b079abaeda42cc92608c5023ef3b1dca3349b50 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 26 Aug 2024 23:47:57 -0400 Subject: [PATCH 053/512] uefi: Deprecate ancillary types in uefi::table::boot --- uefi/CHANGELOG.md | 3 +++ uefi/src/fs/file_system/fs.rs | 2 ++ uefi/src/table/boot.rs | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 9b01c4ab6..add607a9c 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -13,6 +13,9 @@ how to integrate the `uefi` crate into them. ## Changed - The `BootServices` and `RuntimeServices` structs have been deprecated. Use the `uefi::runtime` and `uefi::boot` modules instead. +- In `uefi::table::boot`, `ScopedProtocol`, `TplGuard`, `ProtocolsPerHandle`, + and `HandleBuffer` have been deprecated. Use the structs of the same name in + `uefi::boot` instead. - **Breaking:** The conversion functions between device paths and text no longer take a `BootServices` argument. The global system table is used instead. - **Breaking:** `GraphicsOutput::modes` no longer takes a `BootServices` diff --git a/uefi/src/fs/file_system/fs.rs b/uefi/src/fs/file_system/fs.rs index be0b3abfc..e0b6807b8 100644 --- a/uefi/src/fs/file_system/fs.rs +++ b/uefi/src/fs/file_system/fs.rs @@ -18,6 +18,7 @@ pub type FileSystemResult = Result; /// associated `ScopedProtocol<'a>` structs are removed this inner type can be /// removed as well. enum FileSystemInner<'a> { + #[allow(deprecated)] WithLifetime(uefi::table::boot::ScopedProtocol<'a, SimpleFileSystemProtocol>), WithoutLifetime(uefi::boot::ScopedProtocol), } @@ -454,6 +455,7 @@ impl<'a> Debug for FileSystem<'a> { } } +#[allow(deprecated)] impl<'a> From> for FileSystem<'a> { fn from(proto: uefi::table::boot::ScopedProtocol<'a, SimpleFileSystemProtocol>) -> Self { Self(FileSystemInner::WithLifetime(proto)) diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 614a26614..69635d685 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -1329,6 +1329,7 @@ impl super::Table for BootServices { /// RAII guard for task priority level changes /// /// Will automatically restore the former task priority level when dropped. +#[deprecated = "Use uefi::boot::TplGuard instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] #[derive(Debug)] pub struct TplGuard<'boot> { boot_services: &'boot BootServices, @@ -1359,6 +1360,7 @@ impl Drop for TplGuard<'_> { /// [`LoadedImageDevicePath`]: crate::proto::device_path::LoadedImageDevicePath /// [`get`]: ScopedProtocol::get /// [`get_mut`]: ScopedProtocol::get_mut +#[deprecated = "Use uefi::boot::ScopedProtocol instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] #[derive(Debug)] pub struct ScopedProtocol<'a, P: Protocol + ?Sized> { /// The protocol interface. @@ -1421,6 +1423,7 @@ impl<'a, P: Protocol + ?Sized> ScopedProtocol<'a, P> { /// Protocol interface [`Guids`][Guid] that are installed on a [`Handle`] as /// returned by [`BootServices::protocols_per_handle`]. +#[deprecated = "Use uefi::boot::ProtocolsPerHandle instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] #[derive(Debug)] pub struct ProtocolsPerHandle<'a> { // The pointer returned by `protocols_per_handle` has to be free'd with @@ -1461,6 +1464,7 @@ impl<'a> ProtocolsPerHandle<'a> { /// A buffer that contains an array of [`Handles`][Handle] that support the /// requested protocol. Returned by [`BootServices::locate_handle_buffer`]. +#[deprecated = "Use uefi::boot::HandleBuffer instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] #[derive(Debug)] pub struct HandleBuffer<'a> { // The pointer returned by `locate_handle_buffer` has to be freed with From 0ce4985e97397f4455619236e3c81d459451c63b Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 27 Aug 2024 11:26:59 -0400 Subject: [PATCH 054/512] uefi: Update pointer protocol docs --- uefi/src/proto/console/pointer/mod.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/uefi/src/proto/console/pointer/mod.rs b/uefi/src/proto/console/pointer/mod.rs index dfb6fc9ea..7d5ca335c 100644 --- a/uefi/src/proto/console/pointer/mod.rs +++ b/uefi/src/proto/console/pointer/mod.rs @@ -26,11 +26,13 @@ impl Pointer { /// Retrieves the pointer device's current state, if a state change occurred /// since the last time this function was called. /// - /// Use `wait_for_input_event()` with the `BootServices::wait_for_event()` + /// Use `wait_for_input_event()` with the [`boot::wait_for_event`] /// interface in order to wait for input from the pointer device. /// /// # Errors /// - `DeviceError` if there was an issue with the pointer device. + /// + /// [`boot::wait_for_event`]: crate::boot::wait_for_event pub fn read_state(&mut self) -> Result> { let mut pointer_state = PointerState::default(); let pointer_state_ptr: *mut _ = &mut pointer_state; @@ -41,8 +43,10 @@ impl Pointer { } } - /// Event to be used with `BootServices::wait_for_event()` in order to wait + /// Event to be used with [`boot::wait_for_event`] in order to wait /// for input from the pointer device + /// + /// [`boot::wait_for_event`]: crate::boot::wait_for_event #[must_use] pub fn wait_for_input_event(&self) -> Option { unsafe { Event::from_ptr(self.0.wait_for_input) } From 83a7ea5e5d1a093659dfe1c17b684258b1c92e5e Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 26 Aug 2024 13:31:07 -0400 Subject: [PATCH 055/512] uefi: Remove BootServices from more docstrings --- uefi/src/boot.rs | 4 ++-- uefi/src/data_types/mod.rs | 4 +++- uefi/src/lib.rs | 1 - uefi/src/proto/device_path/mod.rs | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index a165ca358..b6abf4a10 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -4,7 +4,7 @@ //! //! # Accessing protocols //! -//! Protocols can be opened using several methods of `BootServices`. Most +//! Protocols can be opened using several functions in this module. Most //! commonly, [`open_protocol_exclusive`] should be used. This ensures that //! nothing else can use the protocol until it is closed, and returns a //! [`ScopedProtocol`] that takes care of closing the protocol when it is @@ -1510,7 +1510,7 @@ impl Drop for TplGuard { // TestProtocol (0x04) excluded because it doesn't actually open the // protocol, just tests if it's present on the handle. Since that // changes the interface significantly, that's exposed as a separate -// method: `BootServices::test_protocol`. +// method: `test_protocol`. /// Attributes for [`open_protocol`]. #[repr(u32)] diff --git a/uefi/src/data_types/mod.rs b/uefi/src/data_types/mod.rs index 463fa7ff7..a5720d2a4 100644 --- a/uefi/src/data_types/mod.rs +++ b/uefi/src/data_types/mod.rs @@ -70,9 +70,11 @@ impl Event { /// Clone this `Event` /// /// # Safety - /// When an event is closed by calling `BootServices::close_event`, that event and ALL references + /// When an event is closed by calling [`boot::close_event`], that event and ALL references /// to it are invalidated and the underlying memory is freed by firmware. The caller must ensure /// that any clones of a closed `Event` are never used again. + /// + /// [`boot::close_event`]: crate::boot::close_event #[must_use] pub const unsafe fn unsafe_clone(&self) -> Self { Self(self.0) diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 62d34f24d..84e99bc1a 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -203,7 +203,6 @@ //! [Rust UEFI Book]: https://rust-osdev.github.io/uefi-rs/HEAD/ //! [UEFI]: https://uefi.org/ //! [Zulip]: https://rust-osdev.zulipchat.com -//! [`BootServices`]: table::boot::BootServices //! [`GlobalAlloc`]: alloc::alloc::GlobalAlloc //! [`SystemTable`]: table::SystemTable //! [`ctr16!`]: crate::cstr16 diff --git a/uefi/src/proto/device_path/mod.rs b/uefi/src/proto/device_path/mod.rs index 49462c0f5..cc24450b0 100644 --- a/uefi/src/proto/device_path/mod.rs +++ b/uefi/src/proto/device_path/mod.rs @@ -812,7 +812,7 @@ pub enum NodeConversionError { /// /// The layout of this type is the same as a [`DevicePath`]. /// -/// [`load_image`]: crate::table::boot::BootServices::load_image +/// [`load_image`]: crate::boot::load_image #[repr(transparent)] #[unsafe_protocol("bc62157e-3e33-4fec-9920-2d3b36d750df")] #[derive(Debug, Pointee)] From 682eaf50a0bc8a06ecaccf064f9c1c7bf0aa1349 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 27 Aug 2024 11:55:13 -0400 Subject: [PATCH 056/512] uefi: Deprecate table::{system_table_boot,system_table_runtime} --- uefi/CHANGELOG.md | 2 ++ uefi/src/helpers/mod.rs | 1 + uefi/src/table/mod.rs | 2 ++ 3 files changed, 5 insertions(+) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index add607a9c..1d670be84 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -16,6 +16,8 @@ how to integrate the `uefi` crate into them. - In `uefi::table::boot`, `ScopedProtocol`, `TplGuard`, `ProtocolsPerHandle`, and `HandleBuffer` have been deprecated. Use the structs of the same name in `uefi::boot` instead. +- `uefi::table::system_table_boot` and `uefi::table::system_table_runtime` have + been deprecated. Use the `uefi::runtime` and `uefi::boot` modules instead. - **Breaking:** The conversion functions between device paths and text no longer take a `BootServices` argument. The global system table is used instead. - **Breaking:** `GraphicsOutput::modes` no longer takes a `BootServices` diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index 237e2fd22..36fc5760e 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -42,6 +42,7 @@ mod println; #[must_use] #[deprecated(note = "use uefi::table::system_table_boot instead")] pub fn system_table() -> SystemTable { + #[allow(deprecated)] table::system_table_boot().expect("boot services are not active") } diff --git a/uefi/src/table/mod.rs b/uefi/src/table/mod.rs index fcf4fa7ad..34ece6da3 100644 --- a/uefi/src/table/mod.rs +++ b/uefi/src/table/mod.rs @@ -60,6 +60,7 @@ pub unsafe fn set_system_table(ptr: *const uefi_raw::table::system::SystemTable) } /// Get the system table while boot services are active. +#[deprecated = "Use the uefi::boot module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] pub fn system_table_boot() -> Option> { let st = SYSTEM_TABLE.load(Ordering::Acquire); if st.is_null() { @@ -77,6 +78,7 @@ pub fn system_table_boot() -> Option> { } /// Get the system table while runtime services are active. +#[deprecated = "Use the uefi::runtime module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] pub fn system_table_runtime() -> Option> { let st = SYSTEM_TABLE.load(Ordering::Acquire); if st.is_null() { From 13e8b3458740bbf1196c6815108914d32d5f963f Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 27 Aug 2024 14:15:57 -0400 Subject: [PATCH 057/512] uefi: Deprecate SystemTable --- uefi-macros/tests/ui/fail/entry_bad_abi.rs | 1 + uefi-macros/tests/ui/fail/entry_bad_abi.stderr | 4 ++-- uefi-macros/tests/ui/fail/entry_bad_arg.rs | 1 + uefi-macros/tests/ui/fail/entry_bad_arg.stderr | 4 ++-- uefi-macros/tests/ui/fail/entry_bad_return_type.rs | 1 + uefi-macros/tests/ui/fail/entry_bad_return_type.stderr | 4 ++-- uefi-macros/tests/ui/pass/entry.rs | 2 ++ uefi-macros/tests/ui/pass/entry_docstring.rs | 2 ++ uefi-macros/tests/ui/pass/entry_unsafe.rs | 2 ++ uefi/CHANGELOG.md | 5 +++-- uefi/src/allocator.rs | 3 ++- uefi/src/helpers/mod.rs | 3 ++- uefi/src/prelude.rs | 1 + uefi/src/table/mod.rs | 3 +++ uefi/src/table/system.rs | 3 ++- 15 files changed, 28 insertions(+), 11 deletions(-) diff --git a/uefi-macros/tests/ui/fail/entry_bad_abi.rs b/uefi-macros/tests/ui/fail/entry_bad_abi.rs index 5c43cd273..9baa4bf49 100644 --- a/uefi-macros/tests/ui/fail/entry_bad_abi.rs +++ b/uefi-macros/tests/ui/fail/entry_bad_abi.rs @@ -1,5 +1,6 @@ #![allow(unused_imports)] #![no_main] +#![allow(deprecated)] use uefi::prelude::*; use uefi_macros::entry; diff --git a/uefi-macros/tests/ui/fail/entry_bad_abi.stderr b/uefi-macros/tests/ui/fail/entry_bad_abi.stderr index 424d8c52f..6bbc0742b 100644 --- a/uefi-macros/tests/ui/fail/entry_bad_abi.stderr +++ b/uefi-macros/tests/ui/fail/entry_bad_abi.stderr @@ -1,5 +1,5 @@ error: Entry method must have no ABI modifier - --> tests/ui/fail/entry_bad_abi.rs:8:1 + --> tests/ui/fail/entry_bad_abi.rs:9:1 | -8 | extern "C" fn main(_handle: Handle, _st: SystemTable) -> Status { +9 | extern "C" fn main(_handle: Handle, _st: SystemTable) -> Status { | ^^^^^^ diff --git a/uefi-macros/tests/ui/fail/entry_bad_arg.rs b/uefi-macros/tests/ui/fail/entry_bad_arg.rs index 8bd8f2453..941d1177d 100644 --- a/uefi-macros/tests/ui/fail/entry_bad_arg.rs +++ b/uefi-macros/tests/ui/fail/entry_bad_arg.rs @@ -1,5 +1,6 @@ #![allow(unused_imports)] #![no_main] +#![allow(deprecated)] use uefi::prelude::*; use uefi_macros::entry; diff --git a/uefi-macros/tests/ui/fail/entry_bad_arg.stderr b/uefi-macros/tests/ui/fail/entry_bad_arg.stderr index 9d292cf66..db4f2c15b 100644 --- a/uefi-macros/tests/ui/fail/entry_bad_arg.stderr +++ b/uefi-macros/tests/ui/fail/entry_bad_arg.stderr @@ -1,7 +1,7 @@ error[E0308]: mismatched types - --> tests/ui/fail/entry_bad_arg.rs:8:1 + --> tests/ui/fail/entry_bad_arg.rs:9:1 | -8 | fn main(_handle: Handle, _st: SystemTable, _x: usize) -> Status { +9 | fn main(_handle: Handle, _st: SystemTable, _x: usize) -> Status { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | = note: expected fn pointer `extern "efiapi" fn(uefi::Handle, uefi::prelude::SystemTable) -> uefi::Status` diff --git a/uefi-macros/tests/ui/fail/entry_bad_return_type.rs b/uefi-macros/tests/ui/fail/entry_bad_return_type.rs index e2ac39960..6988431df 100644 --- a/uefi-macros/tests/ui/fail/entry_bad_return_type.rs +++ b/uefi-macros/tests/ui/fail/entry_bad_return_type.rs @@ -1,5 +1,6 @@ #![allow(unused_imports)] #![no_main] +#![allow(deprecated)] use uefi::prelude::*; use uefi_macros::entry; diff --git a/uefi-macros/tests/ui/fail/entry_bad_return_type.stderr b/uefi-macros/tests/ui/fail/entry_bad_return_type.stderr index 6e718c631..4c719972d 100644 --- a/uefi-macros/tests/ui/fail/entry_bad_return_type.stderr +++ b/uefi-macros/tests/ui/fail/entry_bad_return_type.stderr @@ -1,7 +1,7 @@ error[E0308]: mismatched types - --> tests/ui/fail/entry_bad_return_type.rs:8:1 + --> tests/ui/fail/entry_bad_return_type.rs:9:1 | -8 | fn main(_handle: Handle, _st: SystemTable) -> bool { +9 | fn main(_handle: Handle, _st: SystemTable) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Status`, found `bool` | = note: expected fn pointer `extern "efiapi" fn(uefi::Handle, uefi::prelude::SystemTable) -> Status` diff --git a/uefi-macros/tests/ui/pass/entry.rs b/uefi-macros/tests/ui/pass/entry.rs index f8d7aba72..928c46066 100644 --- a/uefi-macros/tests/ui/pass/entry.rs +++ b/uefi-macros/tests/ui/pass/entry.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use uefi::table::{Boot, SystemTable}; use uefi::{entry, Handle, Status}; diff --git a/uefi-macros/tests/ui/pass/entry_docstring.rs b/uefi-macros/tests/ui/pass/entry_docstring.rs index dd44ad20e..82f0e2185 100644 --- a/uefi-macros/tests/ui/pass/entry_docstring.rs +++ b/uefi-macros/tests/ui/pass/entry_docstring.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use uefi::table::{Boot, SystemTable}; use uefi::{entry, Handle, Status}; diff --git a/uefi-macros/tests/ui/pass/entry_unsafe.rs b/uefi-macros/tests/ui/pass/entry_unsafe.rs index e792aea4c..b0ea0c015 100644 --- a/uefi-macros/tests/ui/pass/entry_unsafe.rs +++ b/uefi-macros/tests/ui/pass/entry_unsafe.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use uefi::table::{Boot, SystemTable}; use uefi::{entry, Handle, Status}; diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 1d670be84..c723046fe 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -11,8 +11,9 @@ how to integrate the `uefi` crate into them. - Added `Handle::new` ## Changed -- The `BootServices` and `RuntimeServices` structs have been deprecated. Use - the `uefi::runtime` and `uefi::boot` modules instead. +- The `BootServices`, `RuntimeServices`, and `SystemTable` structs have been + deprecated. Use the `uefi::boot` and `uefi::runtime`, and `uefi::system` + modules instead. - In `uefi::table::boot`, `ScopedProtocol`, `TplGuard`, `ProtocolsPerHandle`, and `HandleBuffer` have been deprecated. Use the structs of the same name in `uefi::boot` instead. diff --git a/uefi/src/allocator.rs b/uefi/src/allocator.rs index bd00d468a..3401262ee 100644 --- a/uefi/src/allocator.rs +++ b/uefi/src/allocator.rs @@ -14,11 +14,12 @@ use core::sync::atomic::{AtomicU32, Ordering}; use crate::boot; use crate::mem::memory_map::MemoryType; use crate::proto::loaded_image::LoadedImage; +#[allow(deprecated)] use crate::table::{Boot, SystemTable}; /// Deprecated; this function is now a no-op. #[deprecated = "this function is now a no-op"] -#[allow(unused_unsafe, clippy::missing_safety_doc)] +#[allow(deprecated, unused_unsafe, clippy::missing_safety_doc)] pub unsafe fn init(_: &mut SystemTable) {} /// Deprecated; this function is now a no-op. diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index 36fc5760e..8779092ce 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -18,6 +18,7 @@ //! [print_macro]: uefi::print! //! [println_macro]: uefi::println! +#[allow(deprecated)] use crate::prelude::{Boot, SystemTable}; use crate::{table, Result}; #[doc(hidden)] @@ -41,8 +42,8 @@ mod println; /// The returned pointer is only valid until boot services are exited. #[must_use] #[deprecated(note = "use uefi::table::system_table_boot instead")] +#[allow(deprecated)] pub fn system_table() -> SystemTable { - #[allow(deprecated)] table::system_table_boot().expect("boot services are not active") } diff --git a/uefi/src/prelude.rs b/uefi/src/prelude.rs index 5c9e108b5..6b973c471 100644 --- a/uefi/src/prelude.rs +++ b/uefi/src/prelude.rs @@ -9,4 +9,5 @@ pub use crate::{cstr16, cstr8, entry, Handle, ResultExt, Status, StatusExt}; pub use crate::table::boot::BootServices; #[allow(deprecated)] pub use crate::table::runtime::RuntimeServices; +#[allow(deprecated)] pub use crate::table::{Boot, SystemTable}; diff --git a/uefi/src/table/mod.rs b/uefi/src/table/mod.rs index 34ece6da3..6cb848a62 100644 --- a/uefi/src/table/mod.rs +++ b/uefi/src/table/mod.rs @@ -8,6 +8,7 @@ mod header; mod system; pub use header::Header; +#[allow(deprecated)] pub use system::{Boot, Runtime, SystemTable}; pub use uefi_raw::table::Revision; @@ -61,6 +62,7 @@ pub unsafe fn set_system_table(ptr: *const uefi_raw::table::system::SystemTable) /// Get the system table while boot services are active. #[deprecated = "Use the uefi::boot module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] +#[allow(deprecated)] pub fn system_table_boot() -> Option> { let st = SYSTEM_TABLE.load(Ordering::Acquire); if st.is_null() { @@ -79,6 +81,7 @@ pub fn system_table_boot() -> Option> { /// Get the system table while runtime services are active. #[deprecated = "Use the uefi::runtime module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] +#[allow(deprecated)] pub fn system_table_runtime() -> Option> { let st = SYSTEM_TABLE.load(Ordering::Acquire); if st.is_null() { diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index 53eb4cd58..6896bae39 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -46,7 +46,8 @@ impl SystemTableView for Runtime {} /// documented in the UEFI spec. At that point, the boot view of the system /// table will be destroyed (which conveniently invalidates all references to /// UEFI boot services in the eye of the Rust borrow checker) and a runtime view -/// will be provided to replace it. +/// will be provided to replace it +#[deprecated = "Use the uefi::system, uefi::boot, and uefi::runtime modules instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] #[derive(Debug)] #[repr(transparent)] pub struct SystemTable { From bc69bd10872162caf0d9a42ac71ad9f60b6533ef Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 27 Aug 2024 15:31:28 -0400 Subject: [PATCH 058/512] uefi: Drop references to SystemTable from docstrings --- uefi/src/lib.rs | 10 +++------- uefi/src/mem/memory_map/mod.rs | 2 +- uefi/src/proto/console/text/output.rs | 6 +++--- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 84e99bc1a..7a7ce8a65 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -100,12 +100,9 @@ //! //! ## Tables //! -//! The [`SystemTable`] provides access to almost everything in UEFI. It comes -//! in two flavors: -//! - `SystemTable`: for boot-time applications such as bootloaders, -//! provides access to both boot and runtime services. -//! - `SystemTable`: for operating systems after boot services have -//! been exited. +//! Most UEFI functionality comes from the system, boot, and runtime +//! tables. These can be accessed via the [`system`], [`boot`], and [`runtime`] +//! modules. //! //! ## Protocols //! @@ -204,7 +201,6 @@ //! [UEFI]: https://uefi.org/ //! [Zulip]: https://rust-osdev.zulipchat.com //! [`GlobalAlloc`]: alloc::alloc::GlobalAlloc -//! [`SystemTable`]: table::SystemTable //! [`ctr16!`]: crate::cstr16 //! [`entry-macro`]: uefi_macros::entry //! [`r-efi`]: https://crates.io/crates/r-efi diff --git a/uefi/src/mem/memory_map/mod.rs b/uefi/src/mem/memory_map/mod.rs index 232c54e4e..46cd82903 100644 --- a/uefi/src/mem/memory_map/mod.rs +++ b/uefi/src/mem/memory_map/mod.rs @@ -28,7 +28,7 @@ //! [`MemoryMapMeta`], //! - re-exports [`MemoryDescriptor`], [`MemoryType`], and [`MemoryAttribute`]. //! -//! [`boot::exit_boot_services`]: crate::table::SystemTable::exit_boot_services +//! [`boot::exit_boot_services`]: crate::boot::exit_boot_services //! [`boot::memory_map`]: crate::boot::memory_map mod api; diff --git a/uefi/src/proto/console/text/output.rs b/uefi/src/proto/console/text/output.rs index a4c5c4cfe..5dd599d27 100644 --- a/uefi/src/proto/console/text/output.rs +++ b/uefi/src/proto/console/text/output.rs @@ -11,14 +11,14 @@ use uefi_raw::protocol::console::{SimpleTextOutputMode, SimpleTextOutputProtocol /// # Accessing `Output` protocol /// /// The standard output and standard error output protocols can be accessed -/// using [`SystemTable::stdout`] and [`SystemTable::stderr`], respectively. +/// using [`system::stdout`] and [`system::stderr`], respectively. /// /// An `Output` protocol can also be accessed like any other UEFI protocol. /// See the [`boot`] documentation for more details of how to open a /// protocol. /// -/// [`SystemTable::stdout`]: crate::table::SystemTable::stdout -/// [`SystemTable::stderr`]: crate::table::SystemTable::stderr +/// [`system::stdout`]: crate::system::with_stdout +/// [`system::stderr`]: crate::system::with_stderr /// [`boot`]: crate::boot#accessing-protocols #[derive(Debug)] #[repr(transparent)] From 1de90fcf43273f15c56ce8980dcbe150e2b99ee4 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 27 Aug 2024 15:59:42 -0400 Subject: [PATCH 059/512] docs: Update timeline for the API migration --- docs/funcs_migration.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/funcs_migration.md b/docs/funcs_migration.md index 8459e633d..4c88cb8cf 100644 --- a/docs/funcs_migration.md +++ b/docs/funcs_migration.md @@ -35,9 +35,13 @@ on [Zulip] or file an [issue]. ## Timeline -As of uefi-0.31, the new API has been introduced alongside the old struct-based -API. We plan to deprecate the old API in the release after that, and then fully -remove the old API in a later release. +In uefi-0.31, the new API was introduced alongside the old struct-based API. + +In uefi-0.32, the old struct-based API was deprecated. In addition, some +breaking changes were made to the API to remove `BootServices` parameters from +various functions. + +We plan to entirely remove the deprecated API in uefi-0.33 or thereabouts. ## Reason for the change From 91b245efbf13232b8bf6873f64c3200e9fd81a83 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 29 Aug 2024 12:49:45 -0400 Subject: [PATCH 060/512] Revert "ci: check if crate can be packaged" This reverts commit fc5c0a98c7f19acb9ccada14cd6a63d4c85e9b62. When `cargo package` builds `uefi`, it does so with dependencies from crates.io. That causes a problem if `uefi` depends on some not-yet-released API changes in `uefi-raw` or `uefi-macros`. For example, see: https://github.com/rust-osdev/uefi-rs/pull/1383#issuecomment-2315661178 I couldn't find a way to force it to use local deps, so revert the job for now. --- .github/workflows/rust.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5eda89577..71015b0dc 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -127,16 +127,6 @@ jobs: # library packages. Note that xtask isn't used or built here; since it's # just a dev tool we don't care about the MSRV for that package. run: cargo build --target x86_64-unknown-uefi -p uefi-test-runner - # Tests that the published crates keep being package-able (thus, releasable). - package: - name: Package Crates - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - uses: Swatinem/rust-cache@v2 - - name: Build - run: cargo package -p uefi -p uefi-raw -p uefi-macros # This job requires the nightly channel, but keep it as a separate job from # `nightly_channel` because it takes a while to run. build_feature_permutations: From d478e100b880da324c15cb397b28539e6a6ed167 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 29 Aug 2024 13:05:39 -0400 Subject: [PATCH 061/512] uefi: Deprecate SystemTableView, Boot, and Runtime --- uefi/CHANGELOG.md | 5 +++-- uefi/src/table/system.rs | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index c723046fe..bca63668d 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -12,8 +12,9 @@ how to integrate the `uefi` crate into them. ## Changed - The `BootServices`, `RuntimeServices`, and `SystemTable` structs have been - deprecated. Use the `uefi::boot` and `uefi::runtime`, and `uefi::system` - modules instead. + deprecated (as well as related types `Boot`, `Runtime`, and + `SystemTableView`). Use the `uefi::boot` and `uefi::runtime`, and + `uefi::system` modules instead. - In `uefi::table::boot`, `ScopedProtocol`, `TplGuard`, `ProtocolsPerHandle`, and `HandleBuffer` have been deprecated. Use the structs of the same name in `uefi::boot` instead. diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index 6896bae39..9fc0b8054 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -14,14 +14,17 @@ use uefi::mem::memory_map::{ }; /// Marker trait used to provide different views of the UEFI System Table. +#[deprecated = "Use the uefi::system, uefi::boot, and uefi::runtime modules instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] pub trait SystemTableView {} /// Marker struct associated with the boot view of the UEFI System Table. +#[deprecated = "Use the uefi::boot module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] #[derive(Debug)] pub struct Boot; impl SystemTableView for Boot {} /// Marker struct associated with the run-time view of the UEFI System Table. +#[deprecated = "Use the uefi::runtime module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] #[derive(Debug)] pub struct Runtime; impl SystemTableView for Runtime {} From 6bc9d74193902c31b6b21bed1db80db7e5244eb9 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Wed, 28 Aug 2024 11:13:19 -0400 Subject: [PATCH 062/512] uefi-raw: Add PAGE_SIZE constant --- uefi-raw/CHANGELOG.md | 4 ++++ uefi-raw/src/table/boot.rs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index 489bc8ca8..dcd9ff3ef 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -1,5 +1,9 @@ # uefi-raw - [Unreleased] +## Added + +- Added `PAGE_SIZE` constant. + # uefi-raw - 0.7.0 (2024-08-20) diff --git a/uefi-raw/src/table/boot.rs b/uefi-raw/src/table/boot.rs index d197d424a..8559a4c28 100644 --- a/uefi-raw/src/table/boot.rs +++ b/uefi-raw/src/table/boot.rs @@ -478,3 +478,9 @@ pub enum Tpl: usize => { /// Even processor interrupts are disable at this level. HIGH_LEVEL = 31, }} + +/// Size in bytes of a UEFI page. +/// +/// Note that this is not necessarily the processor's page size. The UEFI page +/// size is always 4 KiB. +pub const PAGE_SIZE: usize = 4096; From 98da3901f1dc3598b8e1274256752d55334fb6bc Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Wed, 28 Aug 2024 11:14:10 -0400 Subject: [PATCH 063/512] uefi: Reexport uefi-raw PAGE_SIZE constant from boot modules --- uefi/src/boot.rs | 2 +- uefi/src/table/boot.rs | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index b6abf4a10..04faca5c2 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -19,7 +19,7 @@ //! //! [`proto`]: crate::proto -pub use uefi_raw::table::boot::{EventType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl}; +pub use uefi_raw::table::boot::{EventType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl, PAGE_SIZE}; use crate::data_types::PhysicalAddress; use crate::mem::memory_map::{MemoryMapBackingMemory, MemoryMapKey, MemoryMapMeta, MemoryMapOwned}; diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 69635d685..055ea60d2 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -7,7 +7,7 @@ pub use crate::boot::{ ProtocolSearchKey, SearchType, TimerTrigger, }; pub use uefi_raw::table::boot::{ - EventType, InterfaceType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl, + EventType, InterfaceType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl, PAGE_SIZE, }; use super::Revision; @@ -29,12 +29,6 @@ use core::ops::{Deref, DerefMut}; use core::ptr::NonNull; use core::{ptr, slice}; -/// Size in bytes of a UEFI page. -/// -/// Note that this is not necessarily the processor's page size. The UEFI page -/// size is always 4 KiB. -pub const PAGE_SIZE: usize = 4096; - /// Contains pointers to all of the boot services. /// /// # Accessing `BootServices` From 3cd79c166b952bcc71583102d05106da6bad7e13 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 30 Aug 2024 18:15:51 -0400 Subject: [PATCH 064/512] uefi: Clean up imports of uefi::table::runtime Use `uefi::runtime` instead. --- uefi/src/boot.rs | 4 +++- uefi/src/proto/media/file/info.rs | 4 ++-- uefi/src/proto/media/file/mod.rs | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index 04faca5c2..c52276f51 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -19,7 +19,9 @@ //! //! [`proto`]: crate::proto -pub use uefi_raw::table::boot::{EventType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl, PAGE_SIZE}; +pub use uefi_raw::table::boot::{ + EventType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl, PAGE_SIZE, +}; use crate::data_types::PhysicalAddress; use crate::mem::memory_map::{MemoryMapBackingMemory, MemoryMapKey, MemoryMapMeta, MemoryMapOwned}; diff --git a/uefi/src/proto/media/file/info.rs b/uefi/src/proto/media/file/info.rs index adce16c4d..1ed1df8bf 100644 --- a/uefi/src/proto/media/file/info.rs +++ b/uefi/src/proto/media/file/info.rs @@ -1,6 +1,6 @@ use super::FileAttribute; use crate::data_types::Align; -use crate::table::runtime::Time; +use crate::runtime::Time; use crate::{CStr16, Char16, Guid, Identify}; use core::ffi::c_void; use core::fmt::{self, Display, Formatter}; @@ -426,7 +426,7 @@ impl FileProtocolInfo for FileSystemVolumeLabel {} #[cfg(test)] mod tests { use super::*; - use crate::table::runtime::{Daylight, Time, TimeParams}; + use crate::runtime::{Daylight, Time, TimeParams}; use crate::CString16; use alloc::vec; diff --git a/uefi/src/proto/media/file/mod.rs b/uefi/src/proto/media/file/mod.rs index bbb6d365d..0c7d215f5 100644 --- a/uefi/src/proto/media/file/mod.rs +++ b/uefi/src/proto/media/file/mod.rs @@ -348,7 +348,7 @@ pub enum FileMode { #[cfg(test)] mod tests { use super::*; - use crate::table::runtime::Time; + use crate::runtime::Time; use crate::{CString16, Guid, Identify}; use ::alloc::vec; use uefi_raw::protocol::file_system::FileProtocolRevision; From c9983a2ef8035421860c894149286e73e3e121ce Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 01:50:15 +0000 Subject: [PATCH 065/512] chore(deps): update crate-ci/typos action to v1.24.3 --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 4b49cb338..a1e42ff7a 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -7,4 +7,4 @@ jobs: steps: - uses: actions/checkout@v4 # Executes "typos ." - - uses: crate-ci/typos@v1.24.1 + - uses: crate-ci/typos@v1.24.3 From a172ab395296bb4e794020b59f193350704cd5fa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 01:51:29 +0000 Subject: [PATCH 066/512] chore(deps): lock file maintenance --- Cargo.lock | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0ce58586f..d10b38d56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,9 +97,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.14" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ "shlex", ] @@ -145,7 +145,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -248,9 +248,9 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", @@ -343,9 +343,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -572,9 +572,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ "bitflags 2.6.0", "errno", @@ -606,9 +606,9 @@ checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" dependencies = [ "ring", "rustls-pki-types", @@ -656,7 +656,7 @@ checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -722,9 +722,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.76" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -787,7 +787,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", ] [[package]] @@ -889,7 +889,7 @@ version = "0.15.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.76", + "syn 2.0.77", "trybuild", "uefi", ] @@ -1011,9 +1011,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" dependencies = [ "rustls-pki-types", ] @@ -1157,7 +1157,7 @@ dependencies = [ "regex", "serde_json", "sha2", - "syn 2.0.76", + "syn 2.0.77", "tar", "tempfile", "ureq", From eeaba6f3860408bc5a5edade23cb21288cfe9bd0 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 2 Sep 2024 20:10:32 -0400 Subject: [PATCH 067/512] uefi: Fix unused warnings if log-debugcon is not enabled --- uefi/src/helpers/logger.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/uefi/src/helpers/logger.rs b/uefi/src/helpers/logger.rs index 080403b3b..2c7a8a565 100644 --- a/uefi/src/helpers/logger.rs +++ b/uefi/src/helpers/logger.rs @@ -46,16 +46,25 @@ pub fn disable() { /// cloud-hypervisor. /// /// More info: -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + feature = "log-debugcon" +))] #[derive(Copy, Clone, Debug)] struct DebugconWriter; -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + feature = "log-debugcon" +))] impl DebugconWriter { const IO_PORT: u16 = 0xe9; } -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + feature = "log-debugcon" +))] impl core::fmt::Write for DebugconWriter { fn write_str(&mut self, s: &str) -> fmt::Result { for &byte in s.as_bytes() { From 8c51602bc3fb40d5f0e8198eabced2c0f2de05ca Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 2 Sep 2024 20:13:55 -0400 Subject: [PATCH 068/512] xtask: Add support for log-debugcon feature This ensures `cargo xtask build --feature-permutations` tests `log-debugcon` both enabled and disabled. --- xtask/src/cargo.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/xtask/src/cargo.rs b/xtask/src/cargo.rs index 8039d6a91..c54cc6530 100644 --- a/xtask/src/cargo.rs +++ b/xtask/src/cargo.rs @@ -49,6 +49,7 @@ pub enum Feature { // `uefi` features. Alloc, GlobalAllocator, + LogDebugcon, Logger, Unstable, PanicHandler, @@ -68,6 +69,7 @@ impl Feature { match self { Self::Alloc => "alloc", Self::GlobalAllocator => "global_allocator", + Self::LogDebugcon => "log-debugcon", Self::Logger => "logger", Self::Unstable => "unstable", Self::PanicHandler => "panic_handler", @@ -88,6 +90,7 @@ impl Feature { Package::Uefi => vec![ Self::Alloc, Self::GlobalAllocator, + Self::LogDebugcon, Self::Logger, Self::Unstable, Self::PanicHandler, @@ -112,7 +115,7 @@ impl Feature { /// - `include_unstable` - add all functionality behind the `unstable` feature /// - `runtime_features` - add all functionality that effect the runtime of Rust pub fn more_code(include_unstable: bool, runtime_features: bool) -> Vec { - let mut base_features = vec![Self::Alloc, Self::Logger]; + let mut base_features = vec![Self::Alloc, Self::LogDebugcon, Self::Logger]; if include_unstable { base_features.extend([Self::Unstable]) } @@ -293,6 +296,10 @@ impl Cargo { cmd.arg(sub_action); } + // Turn off default features so that `--feature-permutations` can test + // with each feature enabled and disabled. + cmd.arg("--no-default-features"); + if self.release { cmd.arg("--release"); } @@ -337,19 +344,19 @@ mod tests { fn test_comma_separated_features() { assert_eq!( Feature::comma_separated_string(&Feature::more_code(false, false)), - "alloc,logger" + "alloc,log-debugcon,logger" ); assert_eq!( Feature::comma_separated_string(&Feature::more_code(false, true)), - "alloc,logger,global_allocator" + "alloc,log-debugcon,logger,global_allocator" ); assert_eq!( Feature::comma_separated_string(&Feature::more_code(true, false)), - "alloc,logger,unstable" + "alloc,log-debugcon,logger,unstable" ); assert_eq!( Feature::comma_separated_string(&Feature::more_code(true, true)), - "alloc,logger,unstable,global_allocator" + "alloc,log-debugcon,logger,unstable,global_allocator" ); } @@ -380,7 +387,7 @@ mod tests { }; assert_eq!( command_to_string(&cargo.command().unwrap()), - "RUSTDOCFLAGS=-Dwarnings cargo doc --package uefi --package xtask --features global_allocator --no-deps --document-private-items --open" + "RUSTDOCFLAGS=-Dwarnings cargo doc --no-default-features --package uefi --package xtask --features global_allocator --no-deps --document-private-items --open" ); } } From 39201bada713d309d72275718acbda61671a8c9d Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 2 Sep 2024 20:20:08 -0400 Subject: [PATCH 069/512] Add uefi::{boot,runtime,system} modules to the prelude --- uefi/CHANGELOG.md | 4 +++- uefi/src/prelude.rs | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index bca63668d..c0faa59e5 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -8,7 +8,9 @@ We added documentation to `lib.rs` and the [uefi-rs book] about how how to integrate the `uefi` crate into them. ## Added -- Added `Handle::new` +- Added `Handle::new`. +- Added the `uefi::boot`, `uefi::runtime`, and `uefi::system` modules to the + prelude. ## Changed - The `BootServices`, `RuntimeServices`, and `SystemTable` structs have been diff --git a/uefi/src/prelude.rs b/uefi/src/prelude.rs index 6b973c471..c346023b2 100644 --- a/uefi/src/prelude.rs +++ b/uefi/src/prelude.rs @@ -1,8 +1,10 @@ //! This module is used to simplify importing the most common UEFI types. //! -//! This includes the system table types, `Status` codes, etc. +//! This includes the system table modules, `Status` codes, etc. -pub use crate::{cstr16, cstr8, entry, Handle, ResultExt, Status, StatusExt}; +pub use crate::{ + boot, cstr16, cstr8, entry, runtime, system, Handle, ResultExt, Status, StatusExt, +}; // Import the basic table types. #[allow(deprecated)] From 1cc31898c66bb3718a9ab999fd68813283219c00 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 3 Sep 2024 13:26:47 -0400 Subject: [PATCH 070/512] uefi: Add panic doc to uefi::helpers::init This function may panic if called more than once, because `log::set_logger` panics if called more than once. Document this panic. --- uefi/src/helpers/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index 8779092ce..d0a385891 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -55,6 +55,10 @@ pub fn system_table() -> SystemTable { /// **PLEASE NOTE** that these helpers are meant for the pre exit boot service /// epoch. Limited functionality might work after exiting them, such as logging /// to the debugcon device. +/// +/// # Panics +/// +/// This function may panic if called more than once. #[allow(clippy::missing_const_for_fn)] pub fn init() -> Result<()> { // Set up logging. From 4e513f00d47b35574643c1769609433ee1c01e13 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 7 Sep 2024 18:23:50 -0400 Subject: [PATCH 071/512] uefi: Add uefi::runtime::variable_exists This is a slightly more convenient alternative to `get_variable` when you only want to know if a variable exists. Useful if you want to set a variable only if it is not already set. --- uefi-test-runner/src/runtime/vars.rs | 5 ++++ uefi/CHANGELOG.md | 1 + uefi/src/runtime.rs | 41 ++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/uefi-test-runner/src/runtime/vars.rs b/uefi-test-runner/src/runtime/vars.rs index ebd57e08f..208a628fe 100644 --- a/uefi-test-runner/src/runtime/vars.rs +++ b/uefi-test-runner/src/runtime/vars.rs @@ -73,9 +73,13 @@ fn test_variables(rt: &RuntimeServices) { /// Test the variable functions in `uefi::runtime`. fn test_variables_freestanding() { + assert!(!runtime::variable_exists(NAME, VENDOR).unwrap()); + // Create the test variable. runtime::set_variable(NAME, VENDOR, ATTRS, VALUE).expect("failed to set variable"); + assert!(runtime::variable_exists(NAME, VENDOR).unwrap()); + // Test `get_variable` with too small of a buffer. let mut buf = [0u8; 0]; assert_eq!( @@ -106,6 +110,7 @@ fn test_variables_freestanding() { // Delete the variable and verify it can no longer be read. runtime::delete_variable(NAME, VENDOR).expect("failed to delete variable"); + assert!(!runtime::variable_exists(NAME, VENDOR).unwrap()); assert_eq!( runtime::get_variable(NAME, VENDOR, &mut buf) .unwrap_err() diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index c0faa59e5..e76dfd899 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -11,6 +11,7 @@ how to integrate the `uefi` crate into them. - Added `Handle::new`. - Added the `uefi::boot`, `uefi::runtime`, and `uefi::system` modules to the prelude. +- Added `runtime::variable_exists`. ## Changed - The `BootServices`, `RuntimeServices`, and `SystemTable` structs have been diff --git a/uefi/src/runtime.rs b/uefi/src/runtime.rs index 48c51380c..1d7d4545b 100644 --- a/uefi/src/runtime.rs +++ b/uefi/src/runtime.rs @@ -72,6 +72,47 @@ pub unsafe fn set_time(time: &Time) -> Result { (rt.set_time)(time.cast()).to_result() } +/// Checks if a variable exists. +/// +/// Returns `Ok(true)` if the variable exists, `Ok(false)` if the variable does +/// not exist, or `Err` if the existence of the variable could not be determined. +/// +/// # Errors +/// +/// * [`Status::DEVICE_ERROR`]: variable could not be read due to a hardware error. +/// * [`Status::SECURITY_VIOLATION`]: variable could not be read due to an +/// authentication error. +/// * [`Status::UNSUPPORTED`]: this platform does not support variable storage +/// after exiting boot services. +pub fn variable_exists(name: &CStr16, vendor: &VariableVendor) -> Result { + let rt = runtime_services_raw_panicking(); + let rt = unsafe { rt.as_ref() }; + + let attributes = ptr::null_mut(); + let data = ptr::null_mut(); + let mut data_size = 0; + + let status = unsafe { + (rt.get_variable)( + name.as_ptr().cast(), + &vendor.0, + attributes, + &mut data_size, + data, + ) + }; + + match status { + // If the variable exists, the status will be BUFFER_TOO_SMALL because + // data_size is 0. Empty variables do not exist, because setting a + // variable with empty data deletes the variable. In other words, the + // status will never be SUCCESS. + Status::BUFFER_TOO_SMALL => Ok(true), + Status::NOT_FOUND => Ok(false), + _ => Err(Error::from(status)), + } +} + /// Gets the contents and attributes of a variable. The size of `buf` must be at /// least as big as the variable's size, although it can be larger. /// From 00e6eb1d1f99d23b6605f7b5c1f9a971fda0ab69 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 00:53:28 +0000 Subject: [PATCH 072/512] chore(deps): update crate-ci/typos action to v1.24.5 --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index a1e42ff7a..4914715e4 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -7,4 +7,4 @@ jobs: steps: - uses: actions/checkout@v4 # Executes "typos ." - - uses: crate-ci/typos@v1.24.3 + - uses: crate-ci/typos@v1.24.5 From 6975d81ab1729b864312f2e91ce3ec4084afd009 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 00:54:16 +0000 Subject: [PATCH 073/512] chore(deps): lock file maintenance --- Cargo.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d10b38d56..9643b4505 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,9 +25,9 @@ checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" [[package]] name = "autocfg" @@ -97,9 +97,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.15" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" dependencies = [ "shlex", ] @@ -118,9 +118,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" -version = "4.5.16" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -128,9 +128,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstyle", "clap_lex", @@ -156,9 +156,9 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -572,9 +572,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" dependencies = [ "bitflags 2.6.0", "errno", @@ -632,9 +632,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -650,9 +650,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -661,9 +661,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", From b69db1ed1322b5c0aa381210a53d9a70778b8eb5 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Mon, 9 Sep 2024 09:07:07 +0200 Subject: [PATCH 074/512] niv: update --- nix/sources.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index 632c1fc44..02da6e43e 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -5,10 +5,10 @@ "homepage": null, "owner": "NixOS", "repo": "nixpkgs", - "rev": "12bf09802d77264e441f48e25459c10c93eada2e", - "sha256": "077p0zni9hh5gx2hmi6fy1k5xy1hbz9bdd8i4x8flvygp95bs1mj", + "rev": "68e7dce0a6532e876980764167ad158174402c6f", + "sha256": "024vd8hqdakvhyzxw6zpm6awkxm9bx0xg5hmrpsfl16nnrwy3z34", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/12bf09802d77264e441f48e25459c10c93eada2e.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/68e7dce0a6532e876980764167ad158174402c6f.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "rust-overlay": { @@ -17,10 +17,10 @@ "homepage": "", "owner": "oxalica", "repo": "rust-overlay", - "rev": "c02e7d32607e4e16c80152a40ee141c4877b00cb", - "sha256": "035wx6sbm19mwrnc5cfycqpm1vykfwrcxrabafah9xwdbxsnrjzp", + "rev": "2ef910a6276a2f34513d18f2f826a8dea72c3b3f", + "sha256": "0pjgvqi1l0y2chzjs9lh6qvx962k71ny8c1c2rn6h4afxfpl52dv", "type": "tarball", - "url": "https://github.com/oxalica/rust-overlay/archive/c02e7d32607e4e16c80152a40ee141c4877b00cb.tar.gz", + "url": "https://github.com/oxalica/rust-overlay/archive/2ef910a6276a2f34513d18f2f826a8dea72c3b3f.tar.gz", "url_template": "https://github.com///archive/.tar.gz" } } From af7b3063fbf8bca93156a307c100703e530e637a Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Mon, 9 Sep 2024 09:07:31 +0200 Subject: [PATCH 075/512] nix: use nixfmt instead of nixpkgs-fmt nixpkgs-fmt is deprecated --- shell.nix | 3 ++- xtask/src/main.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/shell.nix b/shell.nix index 72d5f9328..f5766dbbd 100644 --- a/shell.nix +++ b/shell.nix @@ -11,7 +11,8 @@ pkgs.mkShell { nativeBuildInputs = with pkgs; [ # nix related stuff (such as dependency management) niv - nixpkgs-fmt + # TODO use "nixfmt" once it is stable - likely in nixpkgs @ NixOS 24.11 + nixfmt-rfc-style # Integration test dependencies swtpm diff --git a/xtask/src/main.rs b/xtask/src/main.rs index b9133d81e..f735486cd 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -261,9 +261,9 @@ fn run_fmt_project(fmt_opt: &FmtOpt) -> Result<()> { } // fmt nix - if has_cmd("nixpkgs-fmt") { + if has_cmd("nixfmt") { eprintln!("Formatting: nix"); - let mut command = Command::new("nixpkgs-fmt"); + let mut command = Command::new("nixfmt"); if fmt_opt.check { command.arg("--check"); } From e6300e95919c71e61c831f94248f6886eb0c362f Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Mon, 9 Sep 2024 09:08:17 +0200 Subject: [PATCH 076/512] ci: use nixpkgs-unstable channel instead of a pinned one No need to pin this to a specific release, it just creates more confusion. --- .github/workflows/developer_productivity.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/developer_productivity.yml b/.github/workflows/developer_productivity.yml index 944727247..1f9d98713 100644 --- a/.github/workflows/developer_productivity.yml +++ b/.github/workflows/developer_productivity.yml @@ -37,7 +37,7 @@ jobs: with: # This channel is only required to invoke "nix-shell". # Everything inside that nix-shell will use a pinned version of nixpkgs. - nix_path: nixpkgs=channel:nixos-23.05 + nix_path: nixpkgs=channel:nixpkgs-unstable # Dedicated step to separate all the # "copying path '/nix/store/...' from 'https://cache.nixos.org'." # messages from the actual build output. This job takes ~60secs. From 73fc03406a042b5fc22bb88ea8c45133f66750b7 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Mon, 9 Sep 2024 09:08:41 +0200 Subject: [PATCH 077/512] nix: run nixfmt Formatted nix files by running `cargo xtask fmt` --- nix/nixpkgs.nix | 1 - nix/rust-toolchain.nix | 2 +- nix/sources.nix | 229 +++++++++++++++++++++++++---------------- shell.nix | 2 +- 4 files changed, 143 insertions(+), 91 deletions(-) diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix index 68090c5b8..aced2d386 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix @@ -3,4 +3,3 @@ let rust-overlay = import sources.rust-overlay; in import sources.nixpkgs { overlays = [ rust-overlay ]; } - diff --git a/nix/rust-toolchain.nix b/nix/rust-toolchain.nix index b3acb0c32..d73681544 100644 --- a/nix/rust-toolchain.nix +++ b/nix/rust-toolchain.nix @@ -3,7 +3,7 @@ { # Comes from rust-overlay - rust-bin + rust-bin, }: # Includes rustc, cargo, rustfmt, etc diff --git a/nix/sources.nix b/nix/sources.nix index 23ab29b03..757b3125f 100644 --- a/nix/sources.nix +++ b/nix/sources.nix @@ -6,133 +6,177 @@ let # The fetchers. fetch_ fetches specs of type . # - fetch_file = pkgs: name: spec: + fetch_file = + pkgs: name: spec: let name' = sanitizeName name + "-src"; in if spec.builtin or true then - builtins_fetchurl { inherit (spec) url sha256; name = name'; } + builtins_fetchurl { + inherit (spec) url sha256; + name = name'; + } else - pkgs.fetchurl { inherit (spec) url sha256; name = name'; }; + pkgs.fetchurl { + inherit (spec) url sha256; + name = name'; + }; - fetch_tarball = pkgs: name: spec: + fetch_tarball = + pkgs: name: spec: let name' = sanitizeName name + "-src"; in if spec.builtin or true then - builtins_fetchTarball { name = name'; inherit (spec) url sha256; } + builtins_fetchTarball { + name = name'; + inherit (spec) url sha256; + } else - pkgs.fetchzip { name = name'; inherit (spec) url sha256; }; + pkgs.fetchzip { + name = name'; + inherit (spec) url sha256; + }; - fetch_git = name: spec: + fetch_git = + name: spec: let ref = - if spec ? ref then spec.ref else - if spec ? branch then "refs/heads/${spec.branch}" else - if spec ? tag then "refs/tags/${spec.tag}" else - abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; + if spec ? ref then + spec.ref + else if spec ? branch then + "refs/heads/${spec.branch}" + else if spec ? tag then + "refs/tags/${spec.tag}" + else + abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; submodules = if spec ? submodules then spec.submodules else false; submoduleArg = let nixSupportsSubmodules = builtins.compareVersions builtins.nixVersion "2.4" >= 0; emptyArgWithWarning = - if submodules == true - then - builtins.trace - ( - "The niv input \"${name}\" uses submodules " - + "but your nix's (${builtins.nixVersion}) builtins.fetchGit " - + "does not support them" - ) - { } - else { }; + if submodules == true then + builtins.trace ( + "The niv input \"${name}\" uses submodules " + + "but your nix's (${builtins.nixVersion}) builtins.fetchGit " + + "does not support them" + ) { } + else + { }; in - if nixSupportsSubmodules - then { inherit submodules; } - else emptyArgWithWarning; + if nixSupportsSubmodules then { inherit submodules; } else emptyArgWithWarning; in - builtins.fetchGit - ({ url = spec.repo; inherit (spec) rev; inherit ref; } // submoduleArg); + builtins.fetchGit ( + { + url = spec.repo; + inherit (spec) rev; + inherit ref; + } + // submoduleArg + ); fetch_local = spec: spec.path; - fetch_builtin-tarball = name: throw - ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=tarball -a builtin=true''; + fetch_builtin-tarball = + name: + throw '' + [${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=tarball -a builtin=true''; - fetch_builtin-url = name: throw - ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=file -a builtin=true''; + fetch_builtin-url = + name: + throw '' + [${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=file -a builtin=true''; # # Various helpers # # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 - sanitizeName = name: - ( - concatMapStrings (s: if builtins.isList s then "-" else s) - ( - builtins.split "[^[:alnum:]+._?=-]+" - ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) - ) - ); + sanitizeName = + name: + (concatMapStrings (s: if builtins.isList s then "-" else s) ( + builtins.split "[^[:alnum:]+._?=-]+" ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) + )); # The set of packages used when specs are fetched using non-builtins. - mkPkgs = sources: system: + mkPkgs = + sources: system: let - sourcesNixpkgs = - import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; }; + sourcesNixpkgs = import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { + inherit system; + }; hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; hasThisAsNixpkgsPath = == ./.; in - if builtins.hasAttr "nixpkgs" sources - then sourcesNixpkgs - else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then + if builtins.hasAttr "nixpkgs" sources then + sourcesNixpkgs + else if hasNixpkgsPath && !hasThisAsNixpkgsPath then import { } else - abort - '' - Please specify either (through -I or NIX_PATH=nixpkgs=...) or - add a package called "nixpkgs" to your sources.json. - ''; + abort '' + Please specify either (through -I or NIX_PATH=nixpkgs=...) or + add a package called "nixpkgs" to your sources.json. + ''; # The actual fetching function. - fetch = pkgs: name: spec: + fetch = + pkgs: name: spec: - if ! builtins.hasAttr "type" spec then + if !builtins.hasAttr "type" spec then abort "ERROR: niv spec ${name} does not have a 'type' attribute" - else if spec.type == "file" then fetch_file pkgs name spec - else if spec.type == "tarball" then fetch_tarball pkgs name spec - else if spec.type == "git" then fetch_git name spec - else if spec.type == "local" then fetch_local spec - else if spec.type == "builtin-tarball" then fetch_builtin-tarball name - else if spec.type == "builtin-url" then fetch_builtin-url name + else if spec.type == "file" then + fetch_file pkgs name spec + else if spec.type == "tarball" then + fetch_tarball pkgs name spec + else if spec.type == "git" then + fetch_git name spec + else if spec.type == "local" then + fetch_local spec + else if spec.type == "builtin-tarball" then + fetch_builtin-tarball name + else if spec.type == "builtin-url" then + fetch_builtin-url name else abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; # If the environment variable NIV_OVERRIDE_${name} is set, then use # the path directly as opposed to the fetched source. - replace = name: drv: + replace = + name: drv: let saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; in - if ersatz == "" then drv else - # this turns the string into an actual Nix path (for both absolute and - # relative paths) - if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}"; + if ersatz == "" then + drv + else + # this turns the string into an actual Nix path (for both absolute and + # relative paths) + if builtins.substring 0 1 ersatz == "/" then + /. + ersatz + else + /. + builtins.getEnv "PWD" + "/${ersatz}"; # Ports of functions for older nix versions # a Nix version of mapAttrs if the built-in doesn't exist - mapAttrs = builtins.mapAttrs or ( - f: set: with builtins; - listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)) - ); + mapAttrs = + builtins.mapAttrs or ( + f: set: + with builtins; + listToAttrs ( + map (attr: { + name = attr; + value = f attr set.${attr}; + }) (attrNames set) + ) + ); # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 - range = first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1); + range = + first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1); # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); @@ -146,7 +190,12 @@ let optionalAttrs = cond: as: if cond then as else { }; # fetchTarball version that is compatible between all the versions of Nix - builtins_fetchTarball = { url, name ? null, sha256 }@attrs: + builtins_fetchTarball = + { + url, + name ? null, + sha256, + }@attrs: let inherit (builtins) lessThan nixVersion fetchTarball; in @@ -156,7 +205,12 @@ let fetchTarball attrs; # fetchurl version that is compatible between all the versions of Nix - builtins_fetchurl = { url, name ? null, sha256 }@attrs: + builtins_fetchurl = + { + url, + name ? null, + sha256, + }@attrs: let inherit (builtins) lessThan nixVersion fetchurl; in @@ -166,26 +220,25 @@ let fetchurl attrs; # Create the final "sources" from the config - mkSources = config: - mapAttrs - ( - name: spec: - if builtins.hasAttr "outPath" spec - then - abort - "The values in sources.json should not have an 'outPath' attribute" - else - spec // { outPath = replace name (fetch config.pkgs name spec); } - ) - config.sources; + mkSources = + config: + mapAttrs ( + name: spec: + if builtins.hasAttr "outPath" spec then + abort "The values in sources.json should not have an 'outPath' attribute" + else + spec // { outPath = replace name (fetch config.pkgs name spec); } + ) config.sources; # The "config" used by the fetchers mkConfig = - { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null - , sources ? if isNull sourcesFile then { } else builtins.fromJSON (builtins.readFile sourcesFile) - , system ? builtins.currentSystem - , pkgs ? mkPkgs sources system - }: rec { + { + sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null, + sources ? if isNull sourcesFile then { } else builtins.fromJSON (builtins.readFile sourcesFile), + system ? builtins.currentSystem, + pkgs ? mkPkgs sources system, + }: + rec { # The sources, i.e. the attribute set of spec name to spec inherit sources; diff --git a/shell.nix b/shell.nix index f5766dbbd..6453a0140 100644 --- a/shell.nix +++ b/shell.nix @@ -5,7 +5,7 @@ let sources = import ./nix/sources.nix; pkgs = import ./nix/nixpkgs.nix; - rustToolchain = pkgs.callPackage ./nix/rust-toolchain.nix {}; + rustToolchain = pkgs.callPackage ./nix/rust-toolchain.nix { }; in pkgs.mkShell { nativeBuildInputs = with pkgs; [ From 9845db5abfbb36d75a79c204e44143439a1615f1 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 9 Sep 2024 14:44:28 -0400 Subject: [PATCH 078/512] release: uefi-raw-0.8.0, uefi-macros-0.16.0, uefi-0.32.0 --- Cargo.lock | 6 +++--- book/src/tutorial/app.md | 2 +- template/Cargo.toml | 2 +- uefi-macros/CHANGELOG.md | 10 ++++++++++ uefi-macros/Cargo.toml | 2 +- uefi-raw/CHANGELOG.md | 3 +++ uefi-raw/Cargo.toml | 2 +- uefi/CHANGELOG.md | 5 ++++- uefi/Cargo.toml | 6 +++--- 9 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9643b4505..415167fcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -870,7 +870,7 @@ dependencies = [ [[package]] name = "uefi" -version = "0.31.0" +version = "0.32.0" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -885,7 +885,7 @@ dependencies = [ [[package]] name = "uefi-macros" -version = "0.15.0" +version = "0.16.0" dependencies = [ "proc-macro2", "quote", @@ -896,7 +896,7 @@ dependencies = [ [[package]] name = "uefi-raw" -version = "0.7.0" +version = "0.8.0" dependencies = [ "bitflags 2.6.0", "ptr_meta", diff --git a/book/src/tutorial/app.md b/book/src/tutorial/app.md index adfc58285..0d5a4049d 100644 --- a/book/src/tutorial/app.md +++ b/book/src/tutorial/app.md @@ -24,7 +24,7 @@ to your `Cargo.toml`. The resulting `Cargo.toml` should look like that: ```toml [dependencies] log = "0.4.21" -uefi = { version = "0.31.0", features = [ "panic_handler", "logger" ] } +uefi = { version = "0.32.0", features = [ "panic_handler", "logger" ] } ``` Replace the contents of `src/main.rs` with this: diff --git a/template/Cargo.toml b/template/Cargo.toml index 2d6b3f013..8d04fdfcc 100644 --- a/template/Cargo.toml +++ b/template/Cargo.toml @@ -5,4 +5,4 @@ edition = "2021" publish = false [dependencies] -uefi = { version = "0.31.0", features = ["panic_handler"] } +uefi = { version = "0.32.0", features = ["panic_handler"] } diff --git a/uefi-macros/CHANGELOG.md b/uefi-macros/CHANGELOG.md index 3ba8f832a..ff98b3cf5 100644 --- a/uefi-macros/CHANGELOG.md +++ b/uefi-macros/CHANGELOG.md @@ -1,6 +1,16 @@ # uefi-macros - [Unreleased] +# uefi-macros - 0.16.0 (2024-09-09) + +## Changed + +- Internal updates to the `entry` macro related to + [Deprecating SystemTable/BootServices/RuntimeServices][funcmigrate]. + +[funcmigrate]: ../docs/funcs_migration.md + + # uefi-macros - 0.15.0 (2024-08-20) ## Changed diff --git a/uefi-macros/Cargo.toml b/uefi-macros/Cargo.toml index e1ef9ffbf..e8dc9c573 100644 --- a/uefi-macros/Cargo.toml +++ b/uefi-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "uefi-macros" -version = "0.15.0" +version = "0.16.0" readme = "README.md" description = "Procedural macros for the `uefi` crate." diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index dcd9ff3ef..9bf48d15b 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -1,5 +1,8 @@ # uefi-raw - [Unreleased] + +# uefi-raw - 0.8.0 (2024-09-09) + ## Added - Added `PAGE_SIZE` constant. diff --git a/uefi-raw/Cargo.toml b/uefi-raw/Cargo.toml index c567f81d1..d13013354 100644 --- a/uefi-raw/Cargo.toml +++ b/uefi-raw/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "uefi-raw" -version = "0.7.0" +version = "0.8.0" readme = "README.md" description = """ Raw UEFI types and bindings for protocols, boot, and runtime services. This can diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index e76dfd899..2d11704c9 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,7 +1,10 @@ # uefi - [Unreleased] + +# uefi - 0.32.0 (2024-09-09) + See [Deprecating SystemTable/BootServices/RuntimeServices][funcmigrate] for -details of the deprecation in this release. +details of the deprecations in this release. We added documentation to `lib.rs` and the [uefi-rs book] about how `uefi` compares to "standard Rust binaries" for UEFI (those using `std`), and diff --git a/uefi/Cargo.toml b/uefi/Cargo.toml index dc5e1be0f..1c63a31f4 100644 --- a/uefi/Cargo.toml +++ b/uefi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "uefi" -version = "0.31.0" +version = "0.32.0" readme = "README.md" description = """ This crate makes it easy to develop Rust software that leverages safe, @@ -43,8 +43,8 @@ ptr_meta.workspace = true uguid.workspace = true cfg-if = "1.0.0" ucs2 = "0.3.3" -uefi-macros = "0.15.0" -uefi-raw = "0.7.0" +uefi-macros = "0.16.0" +uefi-raw = "0.8.0" qemu-exit = { version = "3.0.2", optional = true } [package.metadata.docs.rs] From 8d066f93fc6a5456abb7c843f14d290f5ad81303 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Wed, 11 Sep 2024 23:50:48 -0400 Subject: [PATCH 079/512] examples: Remove unnecessary import The uefi::boot module is in the prelude. --- uefi-test-runner/examples/hello_world.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/uefi-test-runner/examples/hello_world.rs b/uefi-test-runner/examples/hello_world.rs index 98a346e54..769eb3556 100644 --- a/uefi-test-runner/examples/hello_world.rs +++ b/uefi-test-runner/examples/hello_world.rs @@ -6,7 +6,6 @@ // ANCHOR: use use log::info; -use uefi::boot; use uefi::prelude::*; // ANCHOR_END: use From b7130a3b87ab78ef80deca325b97afc52ce0b26b Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Wed, 11 Sep 2024 23:51:15 -0400 Subject: [PATCH 080/512] book: Update the tutorial This page was a little out of date; it still referred to `main` taking multiple arguments, and to the `uefi_services` crate. --- book/src/tutorial/app.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/book/src/tutorial/app.md b/book/src/tutorial/app.md index 0d5a4049d..bdd567105 100644 --- a/book/src/tutorial/app.md +++ b/book/src/tutorial/app.md @@ -50,7 +50,7 @@ used. Next up are some `use` lines. Nothing too exciting here; the `uefi::prelude` module is intended to be glob-imported, and exports a -number of commonly-used types. +number of commonly-used macros, modules, and types. ```rust {{#include ../../../uefi-test-runner/examples/hello_world.rs:use}} @@ -63,23 +63,18 @@ a little different from a standard Rust program. {{#include ../../../uefi-test-runner/examples/hello_world.rs:entry}} ``` -The `main` function in a Uefi application always takes two arguments, -the image handle and the system table. The image [handle] represents the -currently-running executable, and the system [table] provides access to -many different UEFI services. The `main` function returns a [`Status`], -which is essentially a numeric error (or success) code defined by UEFI. +The `main` function in a UEFI application takes no arguments and returns +a [`Status`], which is essentially a numeric error (or success) code +defined by UEFI. The `main` function must be marked with the `#[entry]` +macro. -The first thing we do inside of `main` is initialize `uefi_services`: +The first thing we do inside of `main` is initialize the `helpers` +module, which initializes logging: ```rust {{#include ../../../uefi-test-runner/examples/hello_world.rs:services}} ``` -The `uefi_services` crate is not strictly required to make a UEFI -application with the `uefi` crate, but it makes things much simpler by -setting a simple memory allocator, initializing the logger, and -providing a panic handler. - Next we use the standard `log` crate to output "Hello world!". Then we call `stall` to make the system pause for 10 seconds. This just ensures you have enough time to see the output. From e50facdbad6ae6a0bedd748de3569256bbd37444 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 12 Sep 2024 00:05:55 -0400 Subject: [PATCH 081/512] uefi: Delete the deprecated helpers::system_table function --- uefi/CHANGELOG.md | 3 +++ uefi/src/helpers/mod.rs | 19 +------------------ 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 2d11704c9..4514fb30a 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,5 +1,8 @@ # uefi - [Unreleased] +## Changed +- **Breaking:** Deleted deprecated function `helpers::system_table`. + # uefi - 0.32.0 (2024-09-09) diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index d0a385891..dbd3b513c 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -18,9 +18,7 @@ //! [print_macro]: uefi::print! //! [println_macro]: uefi::println! -#[allow(deprecated)] -use crate::prelude::{Boot, SystemTable}; -use crate::{table, Result}; +use crate::Result; #[doc(hidden)] pub use println::_print; @@ -32,21 +30,6 @@ mod logger; mod panic_handler; mod println; -/// Obtains a pointer to the system table. -/// -/// This is meant to be used by higher-level libraries, -/// which want a convenient way to access the system table singleton. -/// -/// `init` must have been called first by the UEFI app. -/// -/// The returned pointer is only valid until boot services are exited. -#[must_use] -#[deprecated(note = "use uefi::table::system_table_boot instead")] -#[allow(deprecated)] -pub fn system_table() -> SystemTable { - table::system_table_boot().expect("boot services are not active") -} - /// Initialize all helpers defined in [`uefi::helpers`] whose Cargo features /// are activated. /// From 6896037dbcab253b2ee9f01ecc13e6eb6044a312 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 12 Sep 2024 21:38:59 -0400 Subject: [PATCH 082/512] uefi-test-runner: Use lifetime-less ScopedProtocol with FileSystem --- uefi-test-runner/src/boot/mod.rs | 4 +--- uefi-test-runner/src/fs/mod.rs | 2 +- uefi-test-runner/src/proto/media.rs | 10 ++++------ 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/uefi-test-runner/src/boot/mod.rs b/uefi-test-runner/src/boot/mod.rs index 512b6ab98..47fd1a187 100644 --- a/uefi-test-runner/src/boot/mod.rs +++ b/uefi-test-runner/src/boot/mod.rs @@ -95,9 +95,7 @@ fn test_load_image(bt: &BootServices) { // Variant A: FromBuffer { - let fs = bt - .get_image_file_system(bt.image_handle()) - .expect("should open file system"); + let fs = boot::get_image_file_system(bt.image_handle()).expect("should open file system"); let path = CString16::try_from(image_device_path_file_path.as_str()).unwrap(); let image_data = FileSystem::new(fs) .read(&*path) diff --git a/uefi-test-runner/src/fs/mod.rs b/uefi-test-runner/src/fs/mod.rs index 8d2c39038..04b1bfa2b 100644 --- a/uefi-test-runner/src/fs/mod.rs +++ b/uefi-test-runner/src/fs/mod.rs @@ -2,9 +2,9 @@ use alloc::string::{String, ToString}; use alloc::vec::Vec; +use uefi::boot::ScopedProtocol; use uefi::fs::{FileSystem, IoError, IoErrorContext, PathBuf}; use uefi::proto::media::fs::SimpleFileSystem; -use uefi::table::boot::ScopedProtocol; use uefi::{cstr16, fs, Status}; /// Tests functionality from the `uefi::fs` module. This test relies on a diff --git a/uefi-test-runner/src/proto/media.rs b/uefi-test-runner/src/proto/media.rs index 16a99c909..3ba3a00e7 100644 --- a/uefi-test-runner/src/proto/media.rs +++ b/uefi-test-runner/src/proto/media.rs @@ -1,7 +1,9 @@ use alloc::string::ToString; use core::cell::RefCell; use core::ptr::NonNull; -use uefi::boot; +use uefi::boot::{ + self, EventType, OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol, Tpl, +}; use uefi::data_types::Align; use uefi::prelude::*; use uefi::proto::media::block::BlockIO; @@ -11,9 +13,6 @@ use uefi::proto::media::file::{ }; use uefi::proto::media::fs::SimpleFileSystem; use uefi::proto::media::partition::{MbrOsType, PartitionInfo}; -use uefi::table::boot::{ - EventType, OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol, Tpl, -}; use uefi::table::runtime::{Daylight, Time, TimeParams}; /// Test directory entry iteration. @@ -370,8 +369,7 @@ fn find_test_disk(bt: &BootServices) -> (Handle, ScopedProtocol(handle) + let mut sfs = boot::open_protocol_exclusive::(handle) .expect("Failed to get simple file system"); let mut root_directory = sfs.open_volume().unwrap(); From cf5299946eb039e17dc5edc7236cd0b6b6594113 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 12 Sep 2024 22:23:59 -0400 Subject: [PATCH 083/512] uefi: Drop FileSystem conversion from table::boot::ScopedProtocol --- uefi/CHANGELOG.md | 3 +++ uefi/src/fs/file_system/fs.rs | 40 +++++++---------------------------- 2 files changed, 11 insertions(+), 32 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 4514fb30a..d6dafc190 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -2,6 +2,9 @@ ## Changed - **Breaking:** Deleted deprecated function `helpers::system_table`. +- **Breaking:** `FileSystem` no longer has a lifetime parameter, and the + deprecated conversion from `uefi::table::boot::ScopedProtocol` has been + removed. # uefi - 0.32.0 (2024-09-09) diff --git a/uefi/src/fs/file_system/fs.rs b/uefi/src/fs/file_system/fs.rs index e0b6807b8..f3bdbc7ae 100644 --- a/uefi/src/fs/file_system/fs.rs +++ b/uefi/src/fs/file_system/fs.rs @@ -8,21 +8,11 @@ use alloc::vec; use alloc::vec::Vec; use core::fmt; use core::fmt::{Debug, Formatter}; -use core::ops::Deref; +use uefi::boot::ScopedProtocol; /// Return type for public [`FileSystem`] operations. pub type FileSystemResult = Result; -/// Contents of the `FileSystem` struct, allowing either variant of -/// `ScopedProtocol` to be used. This is temporary; once `BootServices` and the -/// associated `ScopedProtocol<'a>` structs are removed this inner type can be -/// removed as well. -enum FileSystemInner<'a> { - #[allow(deprecated)] - WithLifetime(uefi::table::boot::ScopedProtocol<'a, SimpleFileSystemProtocol>), - WithoutLifetime(uefi::boot::ScopedProtocol), -} - /// High-level file-system abstraction for UEFI volumes with an API that is /// close to `std::fs`. It acts as convenient accessor around the /// [`SimpleFileSystemProtocol`]. @@ -30,9 +20,9 @@ enum FileSystemInner<'a> { /// Please refer to the [module documentation] for more information. /// /// [module documentation]: uefi::fs -pub struct FileSystem<'a>(FileSystemInner<'a>); +pub struct FileSystem(ScopedProtocol); -impl<'a> FileSystem<'a> { +impl FileSystem { /// Constructor. #[must_use] pub fn new(proto: impl Into) -> Self { @@ -396,11 +386,7 @@ impl<'a> FileSystem<'a> { /// Opens a fresh handle to the root directory of the volume. fn open_root(&mut self) -> FileSystemResult { - match &mut self.0 { - FileSystemInner::WithLifetime(proto) => proto.open_volume(), - FileSystemInner::WithoutLifetime(proto) => proto.open_volume(), - } - .map_err(|err| { + self.0.open_volume().map_err(|err| { Error::Io(IoError { path: { let mut path = PathBuf::new(); @@ -445,25 +431,15 @@ impl<'a> FileSystem<'a> { } } -impl<'a> Debug for FileSystem<'a> { +impl Debug for FileSystem { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let ptr: *const _ = match &self.0 { - FileSystemInner::WithLifetime(proto) => proto.deref(), - FileSystemInner::WithoutLifetime(proto) => proto.deref(), - }; + let ptr: *const _ = &self.0; f.debug_tuple("FileSystem").field(&ptr).finish() } } -#[allow(deprecated)] -impl<'a> From> for FileSystem<'a> { - fn from(proto: uefi::table::boot::ScopedProtocol<'a, SimpleFileSystemProtocol>) -> Self { - Self(FileSystemInner::WithLifetime(proto)) - } -} - -impl<'a> From> for FileSystem<'a> { +impl From> for FileSystem { fn from(proto: uefi::boot::ScopedProtocol) -> Self { - Self(FileSystemInner::WithoutLifetime(proto)) + Self(proto) } } From 2efc2b7a6df1721d781564fdb26ca91432d98915 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 01:33:27 +0000 Subject: [PATCH 084/512] chore(deps): lock file maintenance --- Cargo.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 415167fcd..82f8bd5ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,9 +25,9 @@ checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anyhow" -version = "1.0.87" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "autocfg" @@ -97,9 +97,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.18" +version = "1.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" dependencies = [ "shlex", ] @@ -447,9 +447,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" [[package]] name = "os_info" @@ -519,9 +519,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" dependencies = [ "bitflags 2.6.0", ] @@ -572,9 +572,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.36" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", @@ -585,9 +585,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "log", "once_cell", @@ -606,9 +606,9 @@ checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -941,9 +941,9 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" From f52d60da5fb707407f014c8e058af4145500d3e5 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 20 Sep 2024 00:48:01 -0400 Subject: [PATCH 085/512] test-runner: Remove tests for RuntimeServices --- uefi-test-runner/src/main.rs | 4 +- uefi-test-runner/src/runtime/mod.rs | 5 +- uefi-test-runner/src/runtime/vars.rs | 72 +++------------------------- 3 files changed, 11 insertions(+), 70 deletions(-) diff --git a/uefi-test-runner/src/main.rs b/uefi-test-runner/src/main.rs index d6af3b28a..6cb046a9e 100644 --- a/uefi-test-runner/src/main.rs +++ b/uefi-test-runner/src/main.rs @@ -1,7 +1,7 @@ #![no_std] #![no_main] // TODO: temporarily allow deprecated code so that we can continue to test -// SystemTable/BootServices/RuntimeServices. +// SystemTable/BootServices. #![allow(deprecated)] #[macro_use] @@ -63,7 +63,7 @@ fn efi_main(image: Handle, mut st: SystemTable) -> Status { // probably want to test them after exit_boot_services. However, // exit_boot_services is currently called during shutdown. - runtime::test(st.runtime_services()); + runtime::test(); shutdown(st); } diff --git a/uefi-test-runner/src/runtime/mod.rs b/uefi-test-runner/src/runtime/mod.rs index 92769bfe4..7b233ab3c 100644 --- a/uefi-test-runner/src/runtime/mod.rs +++ b/uefi-test-runner/src/runtime/mod.rs @@ -1,11 +1,10 @@ mod vars; use uefi::runtime::{self, Daylight, Time, TimeParams}; -use uefi::table::runtime::RuntimeServices; -pub fn test(rt: &RuntimeServices) { +pub fn test() { info!("Testing runtime services"); - vars::test(rt); + vars::test(); test_time(); } diff --git a/uefi-test-runner/src/runtime/vars.rs b/uefi-test-runner/src/runtime/vars.rs index 208a628fe..0e750976b 100644 --- a/uefi-test-runner/src/runtime/vars.rs +++ b/uefi-test-runner/src/runtime/vars.rs @@ -16,63 +16,8 @@ const VALUE: &[u8] = b"TestValue"; const ATTRS: VariableAttributes = VariableAttributes::BOOTSERVICE_ACCESS.union(VariableAttributes::RUNTIME_ACCESS); -fn test_variables(rt: &RuntimeServices) { - info!("Testing set_variable"); - rt.set_variable(NAME, VENDOR, ATTRS, VALUE) - .expect("failed to set variable"); - - info!("Testing get_variable_size"); - let size = rt - .get_variable_size(NAME, VENDOR) - .expect("failed to get variable size"); - assert_eq!(size, VALUE.len()); - - info!("Testing get_variable"); - let mut buf = [0u8; 9]; - let (data, attrs) = rt - .get_variable(NAME, VENDOR, &mut buf) - .expect("failed to get variable"); - assert_eq!(data, VALUE); - assert_eq!(attrs, ATTRS); - - info!("Testing get_variable_boxed"); - let (data, attrs) = rt - .get_variable_boxed(NAME, VENDOR) - .expect("failed to get variable"); - assert_eq!(&*data, VALUE); - assert_eq!(attrs, ATTRS); - - info!("Testing variable_keys"); - let variable_keys = rt.variable_keys().expect("failed to get variable keys"); - info!("Found {} variables", variable_keys.len()); - // There are likely a bunch of variables, only print out the first one - // during the test to avoid spamming the log. - if let Some(key) = variable_keys.first() { - info!("First variable: {}", key); - } - - // Test that the `runtime::variable_keys` iterator gives exactly the same - // list as the `RuntimeServices::variable_keys` function. - assert_eq!( - runtime::variable_keys() - .map(|k| k.unwrap()) - .collect::>(), - variable_keys - ); - - info!("Testing delete_variable()"); - rt.delete_variable(NAME, VENDOR) - .expect("failed to delete variable"); - assert_eq!( - rt.get_variable(NAME, VENDOR, &mut buf) - .unwrap_err() - .status(), - Status::NOT_FOUND - ); -} - /// Test the variable functions in `uefi::runtime`. -fn test_variables_freestanding() { +fn test_variables() { assert!(!runtime::variable_exists(NAME, VENDOR).unwrap()); // Create the test variable. @@ -121,20 +66,17 @@ fn test_variables_freestanding() { assert!(!find_by_key()); } -fn test_variable_info(rt: &RuntimeServices) { +fn test_variable_info() { let attr = VariableAttributes::BOOTSERVICE_ACCESS | VariableAttributes::NON_VOLATILE; - let info = rt.query_variable_info(attr).unwrap(); + let info = runtime::query_variable_info(attr).unwrap(); info!("Storage for non-volatile boot-services variables: {info:?}"); - assert_eq!(info, runtime::query_variable_info(attr).unwrap()); let attr = VariableAttributes::BOOTSERVICE_ACCESS | VariableAttributes::RUNTIME_ACCESS; - let info = rt.query_variable_info(attr).unwrap(); + let info = runtime::query_variable_info(attr).unwrap(); info!("Storage for volatile runtime variables: {info:?}"); - assert_eq!(info, runtime::query_variable_info(attr).unwrap()); } -pub fn test(rt: &RuntimeServices) { - test_variables(rt); - test_variable_info(rt); - test_variables_freestanding(); +pub fn test() { + test_variable_info(); + test_variables(); } From 23948cf6152cdbf6135eee3c5046beacbbaf4e45 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 20 Sep 2024 00:58:06 -0400 Subject: [PATCH 086/512] uefi: Delete the deprecated table::system_table_runtime function --- uefi/CHANGELOG.md | 3 ++- uefi/src/table/mod.rs | 19 ------------------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index d6dafc190..01fc2eb05 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,7 +1,8 @@ # uefi - [Unreleased] ## Changed -- **Breaking:** Deleted deprecated function `helpers::system_table`. +- **Breaking:** Deleted deprecated functions `helpers::system_table` and + `table::system_table_runtime`. - **Breaking:** `FileSystem` no longer has a lifetime parameter, and the deprecated conversion from `uefi::table::boot::ScopedProtocol` has been removed. diff --git a/uefi/src/table/mod.rs b/uefi/src/table/mod.rs index 6cb848a62..114fcf117 100644 --- a/uefi/src/table/mod.rs +++ b/uefi/src/table/mod.rs @@ -79,25 +79,6 @@ pub fn system_table_boot() -> Option> { } } -/// Get the system table while runtime services are active. -#[deprecated = "Use the uefi::runtime module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] -#[allow(deprecated)] -pub fn system_table_runtime() -> Option> { - let st = SYSTEM_TABLE.load(Ordering::Acquire); - if st.is_null() { - return None; - } - - // SAFETY: the system table is valid per the requirements of `set_system_table`. - unsafe { - if (*st).runtime_services.is_null() { - None - } else { - Some(SystemTable::::from_ptr(st.cast()).unwrap()) - } - } -} - /// Common trait implemented by all standard UEFI tables. pub trait Table { /// A unique number assigned by the UEFI specification From 36d9b5139905646e0e146a0754dcda6b03a75242 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 20 Sep 2024 00:59:37 -0400 Subject: [PATCH 087/512] uefi: Delete `impl SystemTable` --- uefi/src/table/runtime.rs | 10 ------ uefi/src/table/system.rs | 65 ++------------------------------------- 2 files changed, 2 insertions(+), 73 deletions(-) diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index 2c9d4d22a..76eb256c8 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -288,16 +288,6 @@ impl RuntimeServices { unsafe { (self.0.reset_system)(rt, status, size, data) } } - pub(crate) unsafe fn set_virtual_address_map( - &self, - map_size: usize, - desc_size: usize, - desc_version: u32, - virtual_map: *mut crate::mem::memory_map::MemoryDescriptor, - ) -> Status { - (self.0.set_virtual_address_map)(map_size, desc_size, desc_version, virtual_map) - } - /// Passes capsules to the firmware. Capsules are most commonly used to update system firmware. pub fn update_capsule( &self, diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index 9fc0b8054..80c3b107d 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -4,14 +4,12 @@ use super::boot::BootServices; use super::runtime::{ResetType, RuntimeServices}; use super::{cfg, Revision}; use crate::proto::console::text; -use crate::{CStr16, Result, Status, StatusExt}; +use crate::{CStr16, Result, Status}; use core::ffi::c_void; use core::marker::PhantomData; use core::ptr::NonNull; use core::slice; -use uefi::mem::memory_map::{ - MemoryDescriptor, MemoryMapBackingMemory, MemoryMapMeta, MemoryMapOwned, MemoryType, -}; +use uefi::mem::memory_map::{MemoryMapBackingMemory, MemoryMapMeta, MemoryMapOwned, MemoryType}; /// Marker trait used to provide different views of the UEFI System Table. #[deprecated = "Use the uefi::system, uefi::boot, and uefi::runtime modules instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] @@ -291,65 +289,6 @@ impl SystemTable { } } -// These parts of the SystemTable struct are only visible after exit from UEFI -// boot services. They provide unsafe access to the UEFI runtime services, which -// which were already available before but in safe form. -impl SystemTable { - /// Access runtime services - /// - /// # Safety - /// - /// This is unsafe because UEFI runtime services require an elaborate - /// CPU configuration which may not be preserved by OS loaders. See the - /// "Calling Conventions" chapter of the UEFI specification for details. - #[must_use] - pub const unsafe fn runtime_services(&self) -> &RuntimeServices { - &*(*self.table).runtime_services.cast_const().cast() - } - - /// Changes the runtime addressing mode of EFI firmware from physical to virtual. - /// It is up to the caller to translate the old SystemTable address to a new virtual - /// address and provide it for this function. - /// See [`get_current_system_table_addr`] - /// - /// # Safety - /// - /// Setting new virtual memory map is unsafe and may cause undefined behaviors. - /// - /// [`get_current_system_table_addr`]: SystemTable::get_current_system_table_addr - pub unsafe fn set_virtual_address_map( - self, - map: &mut [MemoryDescriptor], - new_system_table_virtual_addr: u64, - ) -> Result { - // Unsafe Code Guidelines guarantees that there is no padding in an array or a slice - // between its elements if the element type is `repr(C)`, which is our case. - // - // See https://rust-lang.github.io/unsafe-code-guidelines/layout/arrays-and-slices.html - let map_size = core::mem::size_of_val(map); - let entry_size = core::mem::size_of::(); - let entry_version = MemoryDescriptor::VERSION; - let map_ptr = map.as_mut_ptr(); - self.runtime_services() - .set_virtual_address_map(map_size, entry_size, entry_version, map_ptr) - .to_result_with_val(|| { - let new_table_ref = &mut *(new_system_table_virtual_addr as usize - as *mut uefi_raw::table::system::SystemTable); - Self { - table: new_table_ref, - _marker: PhantomData, - } - }) - } - - /// Return the address of the SystemTable that resides in a UEFI runtime services - /// memory region. - #[must_use] - pub fn get_current_system_table_addr(&self) -> u64 { - self.table as u64 - } -} - impl super::Table for SystemTable { const SIGNATURE: u64 = 0x5453_5953_2049_4249; } From d8d24d2a3010ae4c5df7b98ab6f46e26aae34f93 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 20 Sep 2024 01:02:43 -0400 Subject: [PATCH 088/512] test-runner: Switch exit_boot_services to freestanding version --- uefi-test-runner/src/main.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/uefi-test-runner/src/main.rs b/uefi-test-runner/src/main.rs index 6cb046a9e..594b9cad5 100644 --- a/uefi-test-runner/src/main.rs +++ b/uefi-test-runner/src/main.rs @@ -218,7 +218,7 @@ fn shutdown(mut st: SystemTable) -> ! { info!("Testing complete, exiting boot services..."); // Exit boot services as a proof that it works :) - let (st, mmap) = unsafe { st.exit_boot_services(MemoryType::LOADER_DATA) }; + let mmap = unsafe { uefi::boot::exit_boot_services(MemoryType::LOADER_DATA) }; info!("Memory Map:"); for desc in mmap.entries() { @@ -235,9 +235,6 @@ fn shutdown(mut st: SystemTable) -> ! { #[cfg(target_arch = "x86_64")] { - // Prevent unused variable warning. - let _ = st; - use qemu_exit::QEMUExit; let custom_exit_success = 3; let qemu_exit_handle = qemu_exit::X86::new(0xF4, custom_exit_success); @@ -247,11 +244,6 @@ fn shutdown(mut st: SystemTable) -> ! { #[cfg(not(target_arch = "x86_64"))] { // Shut down the system - let rt = unsafe { st.runtime_services() }; - rt.reset( - uefi::table::runtime::ResetType::SHUTDOWN, - Status::SUCCESS, - None, - ); + uefi::runtime::reset(uefi::runtime::ResetType::SHUTDOWN, Status::SUCCESS, None); } } From 0e545910d44d5e232ede789710a17f9797058f81 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 20 Sep 2024 01:04:19 -0400 Subject: [PATCH 089/512] uefi: Drop exit boot services from SystemTable --- uefi/src/table/boot.rs | 24 -------- uefi/src/table/system.rs | 121 +-------------------------------------- 2 files changed, 2 insertions(+), 143 deletions(-) diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 055ea60d2..9f491b1c6 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -882,30 +882,6 @@ impl BootServices { ) } - /// Exits the UEFI boot services - /// - /// This unsafe method is meant to be an implementation detail of the safe - /// `SystemTable::exit_boot_services()` method, which is why it is not - /// public. - /// - /// Everything that is explained in the documentation of the high-level - /// `SystemTable` method is also true here, except that this function - /// is one-shot (no automatic retry) and does not prevent you from shooting - /// yourself in the foot by calling invalid boot services after a failure. - /// - /// # Errors - /// - /// See section `EFI_BOOT_SERVICES.ExitBootServices()` in the UEFI Specification for more details. - /// - /// * [`uefi::Status::INVALID_PARAMETER`] - pub(super) unsafe fn exit_boot_services( - &self, - image: Handle, - mmap_key: MemoryMapKey, - ) -> Result { - (self.0.exit_boot_services)(image.as_ptr(), mmap_key.0).to_result() - } - /// Stalls the processor for an amount of time. /// /// The time is in microseconds. diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index 80c3b107d..0125525ee 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -1,15 +1,14 @@ #![allow(deprecated)] use super::boot::BootServices; -use super::runtime::{ResetType, RuntimeServices}; +use super::runtime::RuntimeServices; use super::{cfg, Revision}; use crate::proto::console::text; -use crate::{CStr16, Result, Status}; +use crate::CStr16; use core::ffi::c_void; use core::marker::PhantomData; use core::ptr::NonNull; use core::slice; -use uefi::mem::memory_map::{MemoryMapBackingMemory, MemoryMapMeta, MemoryMapOwned, MemoryType}; /// Marker trait used to provide different views of the UEFI System Table. #[deprecated = "Use the uefi::system, uefi::boot, and uefi::runtime modules instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] @@ -156,122 +155,6 @@ impl SystemTable { unsafe { &*(*self.table).boot_services.cast_const().cast() } } - /// Get the current memory map and exit boot services. - unsafe fn get_memory_map_and_exit_boot_services( - &self, - buf: &mut [u8], - ) -> Result { - let boot_services = self.boot_services(); - - // Get the memory map. - let memory_map = boot_services.get_memory_map(buf)?; - - // Try to exit boot services using the memory map key. Note that after - // the first call to `exit_boot_services`, there are restrictions on - // what boot services functions can be called. In UEFI 2.8 and earlier, - // only `get_memory_map` and `exit_boot_services` are allowed. Starting - // in UEFI 2.9 other memory allocation functions may also be called. - boot_services - .exit_boot_services(boot_services.image_handle(), memory_map.map_key) - .map(move |()| memory_map) - } - - /// Exit the UEFI boot services. - /// - /// After this function completes, UEFI hands over control of the hardware - /// to the executing OS loader, which implies that the UEFI boot services - /// are shut down and cannot be used anymore. Only UEFI configuration tables - /// and run-time services can be used, and the latter requires special care - /// from the OS loader. We model this situation by consuming the - /// `SystemTable` view of the System Table and returning a more - /// restricted `SystemTable` view as an output. - /// - /// The memory map at the time of exiting boot services is also - /// returned. The map is backed by a allocation with given `memory_type`. - /// Since the boot services function to free that memory is no - /// longer available after calling `exit_boot_services`, the allocation is - /// live until the program ends. The lifetime of the memory map is therefore - /// `'static`. - /// - /// Note that once the boot services are exited, associated loggers and - /// allocators can't use the boot services anymore. For the corresponding - /// abstractions provided by this crate (see the [`helpers`] module), - /// invoking this function will automatically disable them. If the - /// `global_allocator` feature is enabled, attempting to use the allocator - /// after exiting boot services will panic. - /// - /// # Safety - /// - /// The caller is responsible for ensuring that no references to - /// boot-services data remain. A non-exhaustive list of resources to check: - /// - /// * All protocols will be invalid after exiting boot services. This - /// includes the [`Output`] protocols attached to stdout/stderr. The - /// caller must ensure that no protocol references remain. - /// * The pool allocator is not usable after exiting boot services. Types - /// such as [`PoolString`] which call [`BootServices::free_pool`] on drop - /// must be cleaned up before calling `exit_boot_services`, or leaked to - /// avoid drop ever being called. - /// * All data in the memory map marked as - /// [`MemoryType::BOOT_SERVICES_CODE`] and - /// [`MemoryType::BOOT_SERVICES_DATA`] will become free memory, the caller - /// must ensure that no references to such memory exist. - /// - /// # Errors - /// - /// This function will fail if it is unable to allocate memory for - /// the memory map, if it fails to retrieve the memory map, or if - /// exiting boot services fails (with up to one retry). - /// - /// All errors are treated as unrecoverable because the system is - /// now in an undefined state. Rather than returning control to the - /// caller, the system will be reset. - /// - /// [`helpers`]: crate::helpers - /// [`Output`]: crate::proto::console::text::Output - /// [`PoolString`]: crate::proto::device_path::text::PoolString - #[must_use] - pub unsafe fn exit_boot_services( - self, - memory_type: MemoryType, - ) -> (SystemTable, MemoryMapOwned) { - crate::helpers::exit(); - - // Reboot the device. - let reset = |status| -> ! { - { - log::warn!("Resetting the machine"); - self.runtime_services().reset(ResetType::COLD, status, None) - } - }; - - let mut buf = MemoryMapBackingMemory::new(memory_type).expect("Failed to allocate memory"); - - // Calling `exit_boot_services` can fail if the memory map key is not - // current. Retry a second time if that occurs. This matches the - // behavior of the Linux kernel: - // https://github.com/torvalds/linux/blob/e544a0743/drivers/firmware/efi/libstub/efi-stub-helper.c#L375 - let mut status = Status::ABORTED; - for _ in 0..2 { - match unsafe { self.get_memory_map_and_exit_boot_services(buf.as_mut_slice()) } { - Ok(memory_map) => { - let st = SystemTable { - table: self.table, - _marker: PhantomData, - }; - return (st, MemoryMapOwned::from_initialized_mem(buf, memory_map)); - } - Err(err) => { - log::error!("Error retrieving the memory map for exiting the boot services"); - status = err.status() - } - } - } - - // Failed to exit boot services. - reset(status) - } - /// Clone this boot-time UEFI system table interface /// /// # Safety From 8bfa226321ca846f4a7f18ecc59cf0ba11c59783 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 20 Sep 2024 01:05:02 -0400 Subject: [PATCH 090/512] uefi: Delete SystemTable --- uefi/src/table/mod.rs | 2 +- uefi/src/table/system.rs | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/uefi/src/table/mod.rs b/uefi/src/table/mod.rs index 114fcf117..07eb1a8f2 100644 --- a/uefi/src/table/mod.rs +++ b/uefi/src/table/mod.rs @@ -9,7 +9,7 @@ mod system; pub use header::Header; #[allow(deprecated)] -pub use system::{Boot, Runtime, SystemTable}; +pub use system::{Boot, SystemTable}; pub use uefi_raw::table::Revision; use core::ptr::{self, NonNull}; diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index 0125525ee..2d32219f1 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -1,7 +1,6 @@ #![allow(deprecated)] use super::boot::BootServices; -use super::runtime::RuntimeServices; use super::{cfg, Revision}; use crate::proto::console::text; use crate::CStr16; @@ -20,12 +19,6 @@ pub trait SystemTableView {} pub struct Boot; impl SystemTableView for Boot {} -/// Marker struct associated with the run-time view of the UEFI System Table. -#[deprecated = "Use the uefi::runtime module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] -#[derive(Debug)] -pub struct Runtime; -impl SystemTableView for Runtime {} - /// UEFI System Table interface /// /// The UEFI System Table is the gateway to all UEFI services which an UEFI @@ -143,12 +136,6 @@ impl SystemTable { unsafe { &mut *(*self.table).stderr.cast() } } - /// Access runtime services - #[must_use] - pub const fn runtime_services(&self) -> &RuntimeServices { - unsafe { &*(*self.table).runtime_services.cast_const().cast() } - } - /// Access boot services #[must_use] pub const fn boot_services(&self) -> &BootServices { From 44ca8892198d775b45d267ca7b4cef667f92ada6 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 20 Sep 2024 01:07:37 -0400 Subject: [PATCH 091/512] test-runner: Clean up a few old imports of uefi::table::runtime --- uefi-test-runner/src/proto/media.rs | 2 +- uefi-test-runner/src/proto/misc.rs | 4 ++-- uefi-test-runner/src/runtime/vars.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/uefi-test-runner/src/proto/media.rs b/uefi-test-runner/src/proto/media.rs index 3ba3a00e7..c4be2a0bd 100644 --- a/uefi-test-runner/src/proto/media.rs +++ b/uefi-test-runner/src/proto/media.rs @@ -13,7 +13,7 @@ use uefi::proto::media::file::{ }; use uefi::proto::media::fs::SimpleFileSystem; use uefi::proto::media::partition::{MbrOsType, PartitionInfo}; -use uefi::table::runtime::{Daylight, Time, TimeParams}; +use uefi::runtime::{Daylight, Time, TimeParams}; /// Test directory entry iteration. fn test_existing_dir(directory: &mut Directory) { diff --git a/uefi-test-runner/src/proto/misc.rs b/uefi-test-runner/src/proto/misc.rs index c7b1664f7..6fd55b624 100644 --- a/uefi-test-runner/src/proto/misc.rs +++ b/uefi-test-runner/src/proto/misc.rs @@ -1,6 +1,6 @@ use uefi::prelude::*; use uefi::proto::misc::ResetNotification; -use uefi::table::runtime; +use uefi::runtime::ResetType; pub fn test(bt: &BootServices) { test_reset_notification(bt); @@ -19,7 +19,7 @@ pub fn test_reset_notification(bt: &BootServices) { // value efi_reset_fn is the type of ResetSystemFn, a function pointer unsafe extern "efiapi" fn efi_reset_fn( - rt: runtime::ResetType, + rt: ResetType, status: Status, data_size: usize, data: *const u8, diff --git a/uefi-test-runner/src/runtime/vars.rs b/uefi-test-runner/src/runtime/vars.rs index 0e750976b..930141c02 100644 --- a/uefi-test-runner/src/runtime/vars.rs +++ b/uefi-test-runner/src/runtime/vars.rs @@ -1,6 +1,6 @@ use log::info; use uefi::prelude::*; -use uefi::table::runtime::{VariableAttributes, VariableVendor}; +use uefi::runtime::{VariableAttributes, VariableVendor}; use uefi::{guid, runtime, CStr16, Error}; /// Test variable name. From bdb925cd7acb52219cc9f71743a2b0302b915620 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 20 Sep 2024 01:07:52 -0400 Subject: [PATCH 092/512] uefi: Delete the uefi::table::runtime module --- uefi/CHANGELOG.md | 4 + uefi/src/prelude.rs | 2 - uefi/src/table/mod.rs | 1 - uefi/src/table/runtime.rs | 412 -------------------------------------- 4 files changed, 4 insertions(+), 415 deletions(-) delete mode 100644 uefi/src/table/runtime.rs diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 01fc2eb05..bde43e5cc 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,6 +1,10 @@ # uefi - [Unreleased] +See [Deprecating SystemTable/BootServices/RuntimeServices][funcmigrate] for +details of the deprecated items that were removed in this release. + ## Changed +- **Breaking:** Deleted the deprecated `RuntimeServices` struct. - **Breaking:** Deleted deprecated functions `helpers::system_table` and `table::system_table_runtime`. - **Breaking:** `FileSystem` no longer has a lifetime parameter, and the diff --git a/uefi/src/prelude.rs b/uefi/src/prelude.rs index c346023b2..77dd0218f 100644 --- a/uefi/src/prelude.rs +++ b/uefi/src/prelude.rs @@ -10,6 +10,4 @@ pub use crate::{ #[allow(deprecated)] pub use crate::table::boot::BootServices; #[allow(deprecated)] -pub use crate::table::runtime::RuntimeServices; -#[allow(deprecated)] pub use crate::table::{Boot, SystemTable}; diff --git a/uefi/src/table/mod.rs b/uefi/src/table/mod.rs index 07eb1a8f2..c991743c9 100644 --- a/uefi/src/table/mod.rs +++ b/uefi/src/table/mod.rs @@ -2,7 +2,6 @@ pub mod boot; pub mod cfg; -pub mod runtime; mod header; mod system; diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs deleted file mode 100644 index 76eb256c8..000000000 --- a/uefi/src/table/runtime.rs +++ /dev/null @@ -1,412 +0,0 @@ -//! UEFI services available at runtime, even after the OS boots. - -#![allow(deprecated)] - -pub use crate::runtime::{ - CapsuleInfo, Time, TimeByteConversionError, TimeError, TimeParams, VariableStorageInfo, -}; -pub use uefi_raw::capsule::{CapsuleBlockDescriptor, CapsuleFlags, CapsuleHeader}; -pub use uefi_raw::table::runtime::{ - ResetType, TimeCapabilities, VariableAttributes, VariableVendor, -}; -pub use uefi_raw::time::Daylight; -pub use uefi_raw::PhysicalAddress; - -#[cfg(feature = "alloc")] -pub use crate::runtime::VariableKey; - -use super::Revision; -use crate::{CStr16, Error, Result, Status, StatusExt}; -use core::mem::MaybeUninit; -use core::ptr; -#[cfg(feature = "alloc")] -use { - crate::Guid, - alloc::boxed::Box, - alloc::{vec, vec::Vec}, - core::mem, -}; - -/// Contains pointers to all of the runtime services. -/// -/// This table, and the function pointers it contains are valid -/// even after the UEFI OS loader and OS have taken control of the platform. -/// -/// # Accessing `RuntimeServices` -/// -/// A reference to `RuntimeServices` can only be accessed by calling [`SystemTable::runtime_services`]. -/// -/// [`SystemTable::runtime_services`]: crate::table::SystemTable::runtime_services -#[deprecated = "Use the uefi::runtime module instead. See https://github.com/rust-osdev/uefi-rs/blob/HEAD/docs/funcs_migration.md"] -#[derive(Debug)] -#[repr(C)] -pub struct RuntimeServices(uefi_raw::table::runtime::RuntimeServices); - -impl RuntimeServices { - /// Query the current time and date information - pub fn get_time(&self) -> Result