diff --git a/docs/funcs_migration.md b/docs/funcs_migration.md new file mode 100644 index 000000000..950778358 --- /dev/null +++ b/docs/funcs_migration.md @@ -0,0 +1,80 @@ +# API migration: Deprecating SystemTable/BootServices/RuntimeServices + +Starting in uefi-0.31.0, a significant API change has been introduced. We are +transitioning away from modeling UEFI tables with structs, and instead providing +an API based on freestanding functions. These functions make use of a global +system table pointer that is set automatically by the `entry` macro. + +A short example: + +```rust +// Old API: +use uefi::table::boot::{BootServices, HandleBuffer}; +fn find_loaded_image_handles(bt: &BootServices) -> Result { + bt.locate_handle_buffer(SearchType::from_proto::()) +} + +// New API: +use uefi::boot::{self, HandleBuffer}; +fn find_loaded_image_handles() -> Result { + boot::locate_handle_buffer(SearchType::from_proto::()) +} +``` + +The new functions generally have almost the same signature as the methods they +are replacing, so in most cases migration should be as simple as updating +imports and calling the freestanding function instead of a method on +`SystemTable`, `BootServices`, or `RuntimeServices`. + +As of uefi-0.31.0, a few places in the API still require a reference to +`BootServices`. You can retrieve one by calling +`uefi::table::system_table_boot().boot_services()`. + +In uefi-0.31.0, the old API has been deprecated, but can still be used. It will +be fully removed in a later release. + +If you run into any issues with this migration, please feel free to chat with us +on [Zulip] or file an [issue]. + +## Reason for the change + +See [issue #893][RFC] for the discussion that lead to this change. + +### Safety of `exit_boot_services` + +One of the main motivations for the old API was to make transitioning from boot +services to runtime services a safe operation. Calling `exit_boot_services` +would consume `SystemTable` and return a `SystemTable`, ensuring +that it was no longer possible to call boot services methods. + +That was the theory, but in practice it didn't always work. Many real-world +programs had to call `SystemTable::unsafe_clone` in order to get another handle +to the system table, and that immediately reintroduced the possibility of +unintentionally accessing boot services after calling `exit_boot_services`. + +In addition, there are a great many kinds of resources that should not be +accessed after calling `exit_boot_services`, so even if the `SystemTable` +was gone, it's very hard to _statically_ ensure that all references to +boot-services resources are dropped. + +Realistically the `exit_boot_services` operation is just too complex to model as +part of Rust's safety guarantees. So in the end, we decided it is better to make +`exit_boot_services` an `unsafe` operation. We do make use of runtime checks +when possible to help catch mistakes (for example, calling a `boot` function +after exiting boot services will panic). + +### API complexity + +Some parts of the API need to free a pool allocation on drop, or do some other +type of resource cleanup. [`DevicePathToText`] is one example. The user has to +pass in a reference to `BootServices`, and that means the object containing the +allocation needs to hang on to that reference, so it needs a lifetime +parameter. That may "infect" other parts of the API, requiring adding references +and lifetimes to calling functions and to types containing the returned +value. By using a global table pointer instead, this complexity is hidden and +the API becomes simpler. + +[`DevicePathToText`]: https://docs.rs/uefi/latest/uefi/proto/device_path/text/struct.DevicePathToText.html +[RFC]: https://github.com/rust-osdev/uefi-rs/issues/893 +[Zulip]: https://rust-osdev.zulipchat.com/#narrow/stream/426438-uefi-rs +[issue]: https://github.com/rust-osdev/uefi-rs/issues/new diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 24b3e020f..4beaefb0e 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,5 +1,8 @@ # uefi - [Unreleased] +See [Deprecating SystemTable/BootServices/RuntimeServices][funcmigrate] for +details of a significant change to the API in this release. + ## Added - `uefi::system` is a new module that provides freestanding functions for accessing fields of the global system table. @@ -39,6 +42,7 @@ > use uefi::table::boot::BootServices; ``` +[funcmigrate]: ../docs/funcs_migration.md # uefi - 0.30.0 (2024-08-02)