Skip to content

Commit cf9cadb

Browse files
authored
Merge pull request #1315 from nicholasbishop/bishop-migration-doc
Add doc on freestanding function migration
2 parents 22616fb + 5e6c046 commit cf9cadb

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

docs/funcs_migration.md

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# API migration: Deprecating SystemTable/BootServices/RuntimeServices
2+
3+
Starting in uefi-0.31.0, a significant API change has been introduced. We are
4+
transitioning away from modeling UEFI tables with structs, and instead providing
5+
an API based on freestanding functions. These functions make use of a global
6+
system table pointer that is set automatically by the `entry` macro.
7+
8+
A short example:
9+
10+
```rust
11+
// Old API:
12+
use uefi::table::boot::{BootServices, HandleBuffer};
13+
fn find_loaded_image_handles(bt: &BootServices) -> Result<HandleBuffer> {
14+
bt.locate_handle_buffer(SearchType::from_proto::<LoadedImage>())
15+
}
16+
17+
// New API:
18+
use uefi::boot::{self, HandleBuffer};
19+
fn find_loaded_image_handles() -> Result<HandleBuffer> {
20+
boot::locate_handle_buffer(SearchType::from_proto::<LoadedImage>())
21+
}
22+
```
23+
24+
The new functions generally have almost the same signature as the methods they
25+
are replacing, so in most cases migration should be as simple as updating
26+
imports and calling the freestanding function instead of a method on
27+
`SystemTable`, `BootServices`, or `RuntimeServices`.
28+
29+
As of uefi-0.31.0, a few places in the API still require a reference to
30+
`BootServices`. You can retrieve one by calling
31+
`uefi::table::system_table_boot().boot_services()`.
32+
33+
In uefi-0.31.0, the old API has been deprecated, but can still be used. It will
34+
be fully removed in a later release.
35+
36+
If you run into any issues with this migration, please feel free to chat with us
37+
on [Zulip] or file an [issue].
38+
39+
## Reason for the change
40+
41+
See [issue #893][RFC] for the discussion that lead to this change.
42+
43+
### Safety of `exit_boot_services`
44+
45+
One of the main motivations for the old API was to make transitioning from boot
46+
services to runtime services a safe operation. Calling `exit_boot_services`
47+
would consume `SystemTable<Boot>` and return a `SystemTable<Runtime>`, ensuring
48+
that it was no longer possible to call boot services methods.
49+
50+
That was the theory, but in practice it didn't always work. Many real-world
51+
programs had to call `SystemTable::unsafe_clone` in order to get another handle
52+
to the system table, and that immediately reintroduced the possibility of
53+
unintentionally accessing boot services after calling `exit_boot_services`.
54+
55+
In addition, there are a great many kinds of resources that should not be
56+
accessed after calling `exit_boot_services`, so even if the `SystemTable<Boot>`
57+
was gone, it's very hard to _statically_ ensure that all references to
58+
boot-services resources are dropped.
59+
60+
Realistically the `exit_boot_services` operation is just too complex to model as
61+
part of Rust's safety guarantees. So in the end, we decided it is better to make
62+
`exit_boot_services` an `unsafe` operation. We do make use of runtime checks
63+
when possible to help catch mistakes (for example, calling a `boot` function
64+
after exiting boot services will panic).
65+
66+
### API complexity
67+
68+
Some parts of the API need to free a pool allocation on drop, or do some other
69+
type of resource cleanup. [`DevicePathToText`] is one example. The user has to
70+
pass in a reference to `BootServices`, and that means the object containing the
71+
allocation needs to hang on to that reference, so it needs a lifetime
72+
parameter. That may "infect" other parts of the API, requiring adding references
73+
and lifetimes to calling functions and to types containing the returned
74+
value. By using a global table pointer instead, this complexity is hidden and
75+
the API becomes simpler.
76+
77+
[`DevicePathToText`]: https://docs.rs/uefi/latest/uefi/proto/device_path/text/struct.DevicePathToText.html
78+
[RFC]: https://github.com/rust-osdev/uefi-rs/issues/893
79+
[Zulip]: https://rust-osdev.zulipchat.com/#narrow/stream/426438-uefi-rs
80+
[issue]: https://github.com/rust-osdev/uefi-rs/issues/new

uefi/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# uefi - [Unreleased]
22

3+
See [Deprecating SystemTable/BootServices/RuntimeServices][funcmigrate] for
4+
details of a significant change to the API in this release.
5+
36
## Added
47
- `uefi::system` is a new module that provides freestanding functions for
58
accessing fields of the global system table.
@@ -39,6 +42,7 @@
3942
> use uefi::table::boot::BootServices;
4043
```
4144

45+
[funcmigrate]: ../docs/funcs_migration.md
4246

4347
# uefi - 0.30.0 (2024-08-02)
4448

0 commit comments

Comments
 (0)