Skip to content

Commit 59790f8

Browse files
Merge pull request #1326 from phip1611/boot-policy
uefi: add BootPolicy type
2 parents e508cd9 + b3d031a commit 59790f8

File tree

7 files changed

+194
-89
lines changed

7 files changed

+194
-89
lines changed

uefi-test-runner/src/bin/shell_launcher.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use uefi::prelude::*;
1818
use uefi::proto::device_path::build::{self, DevicePathBuilder};
1919
use uefi::proto::device_path::{DevicePath, DeviceSubType, DeviceType, LoadedImageDevicePath};
2020
use uefi::proto::loaded_image::LoadedImage;
21+
use uefi::proto::BootPolicy;
2122

2223
/// Get the device path of the shell app. This is the same as the
2324
/// currently-loaded image's device path, but with the file path part changed.
@@ -53,7 +54,7 @@ fn efi_main() -> Status {
5354
boot::image_handle(),
5455
LoadImageSource::FromDevicePath {
5556
device_path: shell_image_path,
56-
from_boot_manager: false,
57+
boot_policy: BootPolicy::ExactMatch,
5758
},
5859
)
5960
.expect("failed to load shell app");

uefi-test-runner/src/boot/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use uefi::fs::FileSystem;
33
use uefi::proto::console::text::Output;
44
use uefi::proto::device_path::media::FilePath;
55
use uefi::proto::device_path::{DevicePath, LoadedImageDevicePath};
6+
use uefi::proto::BootPolicy;
67
use uefi::table::boot::{BootServices, LoadImageSource, SearchType};
78
use uefi::table::{Boot, SystemTable};
89
use uefi::{boot, CString16, Identify};
@@ -122,7 +123,7 @@ fn test_load_image(bt: &BootServices) {
122123
{
123124
let load_source = LoadImageSource::FromDevicePath {
124125
device_path: image_device_path,
125-
from_boot_manager: false,
126+
boot_policy: BootPolicy::ExactMatch,
126127
};
127128
let _ = bt
128129
.load_image(bt.image_handle(), load_source)

uefi/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ details of the new `system`/`boot`/`runtime` modules, and upcoming deprecations.
4343
> use uefi::mem::memory_map::{MemoryMap, MemoryMapMut, MemoryType};
4444
> use uefi::table::boot::BootServices;
4545
```
46+
- **Breaking:** Added a new `BootPolicy` type which breaks existing usages
47+
of `LoadImageSource`.
4648

4749
[funcmigrate]: ../docs/funcs_migration.md
4850

uefi/src/boot.rs

+11-35
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,35 @@
22
//!
33
//! These functions will panic if called after exiting boot services.
44
5+
pub use crate::table::boot::{
6+
AllocateType, EventNotifyFn, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams,
7+
ProtocolSearchKey, SearchType, TimerTrigger,
8+
};
9+
pub use uefi_raw::table::boot::{EventType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl};
10+
511
use crate::data_types::PhysicalAddress;
612
use crate::mem::memory_map::{MemoryMapBackingMemory, MemoryMapKey, MemoryMapMeta, MemoryMapOwned};
713
use crate::polyfill::maybe_uninit_slice_assume_init_ref;
814
use crate::proto::device_path::DevicePath;
15+
#[cfg(doc)]
16+
use crate::proto::device_path::LoadedImageDevicePath;
917
use crate::proto::loaded_image::LoadedImage;
1018
use crate::proto::media::fs::SimpleFileSystem;
1119
use crate::proto::{Protocol, ProtocolPointer};
1220
use crate::runtime::{self, ResetType};
1321
use crate::table::Revision;
1422
use crate::util::opt_nonnull_to_ptr;
23+
use crate::{table, Char16, Error, Event, Guid, Handle, Result, Status, StatusExt};
1524
use core::ffi::c_void;
1625
use core::mem::MaybeUninit;
1726
use core::ops::{Deref, DerefMut};
1827
use core::ptr::{self, NonNull};
1928
use core::sync::atomic::{AtomicPtr, Ordering};
2029
use core::{mem, slice};
21-
use uefi::{table, Char16, Error, Event, Guid, Handle, Result, Status, StatusExt};
2230
use uefi_raw::table::boot::InterfaceType;
23-
2431
#[cfg(feature = "alloc")]
2532
use {alloc::vec::Vec, uefi::ResultExt};
2633

27-
#[cfg(doc)]
28-
use crate::proto::device_path::LoadedImageDevicePath;
29-
30-
pub use uefi::table::boot::{
31-
AllocateType, EventNotifyFn, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams,
32-
ProtocolSearchKey, SearchType, TimerTrigger,
33-
};
34-
pub use uefi_raw::table::boot::{EventType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl};
35-
3634
/// Global image handle. This is only set by [`set_image_handle`], and it is
3735
/// only read by [`image_handle`].
3836
static IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
@@ -995,34 +993,12 @@ pub fn load_image(parent_image_handle: Handle, source: LoadImageSource) -> Resul
995993
let bt = boot_services_raw_panicking();
996994
let bt = unsafe { bt.as_ref() };
997995

998-
let boot_policy;
999-
let device_path;
1000-
let source_buffer;
1001-
let source_size;
1002-
match source {
1003-
LoadImageSource::FromBuffer { buffer, file_path } => {
1004-
// Boot policy is ignored when loading from source buffer.
1005-
boot_policy = 0;
1006-
1007-
device_path = file_path.map(|p| p.as_ffi_ptr()).unwrap_or(ptr::null());
1008-
source_buffer = buffer.as_ptr();
1009-
source_size = buffer.len();
1010-
}
1011-
LoadImageSource::FromDevicePath {
1012-
device_path: file_path,
1013-
from_boot_manager,
1014-
} => {
1015-
boot_policy = u8::from(from_boot_manager);
1016-
device_path = file_path.as_ffi_ptr();
1017-
source_buffer = ptr::null();
1018-
source_size = 0;
1019-
}
1020-
};
996+
let (boot_policy, device_path, source_buffer, source_size) = source.to_ffi_params();
1021997

1022998
let mut image_handle = ptr::null_mut();
1023999
unsafe {
10241000
(bt.load_image)(
1025-
boot_policy,
1001+
boot_policy.into(),
10261002
parent_image_handle.as_ptr(),
10271003
device_path.cast(),
10281004
source_buffer,

uefi/src/proto/boot_policy.rs

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//! Module for the [`BootPolicy`] helper type.
2+
3+
use core::fmt::{Display, Formatter};
4+
5+
/// Errors that can happen when working with [`BootPolicy`].
6+
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq, Ord)]
7+
pub enum BootPolicyError {
8+
/// Only `0` and `1` are valid integers, all other values are undefined.
9+
InvalidInteger(u8),
10+
}
11+
12+
impl Display for BootPolicyError {
13+
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
14+
let s = match self {
15+
Self::InvalidInteger(_) => {
16+
"Only `0` and `1` are valid integers, all other values are undefined."
17+
}
18+
};
19+
f.write_str(s)
20+
}
21+
}
22+
23+
#[cfg(feature = "unstable")]
24+
impl core::error::Error for BootPolicyError {}
25+
26+
/// The UEFI boot policy is a property that influences the behaviour of
27+
/// various UEFI functions that load files (typically UEFI images).
28+
///
29+
/// This type is not ABI compatible. On the ABI level, this is an UEFI
30+
/// boolean.
31+
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
32+
pub enum BootPolicy {
33+
/// Indicates that the request originates from the boot manager, and that
34+
/// the boot manager is attempting to load the provided `file_path` as a
35+
/// boot selection.
36+
///
37+
/// Boot selection refers to what a user has chosen in the (GUI) boot menu.
38+
///
39+
/// This corresponds to the `TRUE` value in the UEFI spec.
40+
BootSelection,
41+
/// The provided `file_path` must match an exact file to be loaded.
42+
///
43+
/// This corresponds to the `FALSE` value in the UEFI spec.
44+
#[default]
45+
ExactMatch,
46+
}
47+
48+
impl From<BootPolicy> for bool {
49+
fn from(value: BootPolicy) -> Self {
50+
match value {
51+
BootPolicy::BootSelection => true,
52+
BootPolicy::ExactMatch => false,
53+
}
54+
}
55+
}
56+
57+
impl From<bool> for BootPolicy {
58+
fn from(value: bool) -> Self {
59+
match value {
60+
true => Self::BootSelection,
61+
false => Self::ExactMatch,
62+
}
63+
}
64+
}
65+
66+
impl From<BootPolicy> for u8 {
67+
fn from(value: BootPolicy) -> Self {
68+
match value {
69+
BootPolicy::BootSelection => 1,
70+
BootPolicy::ExactMatch => 0,
71+
}
72+
}
73+
}
74+
75+
impl TryFrom<u8> for BootPolicy {
76+
type Error = BootPolicyError;
77+
fn try_from(value: u8) -> Result<Self, Self::Error> {
78+
match value {
79+
0 => Ok(Self::ExactMatch),
80+
1 => Ok(Self::BootSelection),
81+
err => Err(Self::Error::InvalidInteger(err)),
82+
}
83+
}
84+
}
85+
86+
#[cfg(test)]
87+
mod tests {
88+
use super::*;
89+
90+
#[test]
91+
fn boot_policy() {
92+
assert_eq!(bool::from(BootPolicy::ExactMatch), false);
93+
assert_eq!(bool::from(BootPolicy::BootSelection), true);
94+
95+
assert_eq!(BootPolicy::from(false), BootPolicy::ExactMatch);
96+
assert_eq!(BootPolicy::from(true), BootPolicy::BootSelection);
97+
98+
assert_eq!(u8::from(BootPolicy::ExactMatch), 0);
99+
assert_eq!(u8::from(BootPolicy::BootSelection), 1);
100+
101+
assert_eq!(BootPolicy::try_from(0), Ok(BootPolicy::ExactMatch));
102+
assert_eq!(BootPolicy::try_from(1), Ok(BootPolicy::BootSelection));
103+
assert_eq!(
104+
BootPolicy::try_from(2),
105+
Err(BootPolicyError::InvalidInteger(2))
106+
);
107+
}
108+
}

uefi/src/proto/mod.rs

+21-18
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,27 @@
99
//!
1010
//! [`BootServices`]: crate::table::boot::BootServices#accessing-protocols
1111
12+
pub mod console;
13+
pub mod debug;
14+
pub mod device_path;
15+
pub mod driver;
16+
pub mod loaded_image;
17+
pub mod media;
18+
pub mod misc;
19+
pub mod network;
20+
pub mod pi;
21+
pub mod rng;
22+
pub mod security;
23+
pub mod shell_params;
24+
pub mod shim;
25+
pub mod string;
26+
pub mod tcg;
27+
28+
mod boot_policy;
29+
30+
pub use boot_policy::{BootPolicy, BootPolicyError};
31+
pub use uefi_macros::unsafe_protocol;
32+
1233
use crate::Identify;
1334
use core::ffi::c_void;
1435

@@ -63,21 +84,3 @@ where
6384
ptr.cast::<Self>()
6485
}
6586
}
66-
67-
pub use uefi_macros::unsafe_protocol;
68-
69-
pub mod console;
70-
pub mod debug;
71-
pub mod device_path;
72-
pub mod driver;
73-
pub mod loaded_image;
74-
pub mod media;
75-
pub mod misc;
76-
pub mod network;
77-
pub mod pi;
78-
pub mod rng;
79-
pub mod security;
80-
pub mod shell_params;
81-
pub mod shim;
82-
pub mod string;
83-
pub mod tcg;

0 commit comments

Comments
 (0)