Skip to content

Commit

Permalink
uefi: Make FileSystem work with both variants of ScopedProtocol
Browse files Browse the repository at this point in the history
To help ease the API transition, make `FileSystem::new` accept either variant of
ScopedProtocol.
  • Loading branch information
nicholasbishop committed Aug 25, 2024
1 parent f529325 commit 02e5f0e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
2 changes: 2 additions & 0 deletions uefi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
42 changes: 34 additions & 8 deletions uefi/src/fs/file_system/fs.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -14,20 +13,29 @@ use core::ops::Deref;
/// Return type for public [`FileSystem`] operations.
pub type FileSystemResult<T> = Result<T, Error>;

/// 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<SimpleFileSystemProtocol>),
}

/// 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`].
///
/// 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>) -> Self {
proto.into()
}

/// Returns `Ok(true)` if the path points at an existing file.
Expand Down Expand Up @@ -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<UefiDirectoryHandle> {
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();
Expand Down Expand Up @@ -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<uefi::table::boot::ScopedProtocol<'a, SimpleFileSystemProtocol>> for FileSystem<'a> {
fn from(proto: uefi::table::boot::ScopedProtocol<'a, SimpleFileSystemProtocol>) -> Self {
Self(FileSystemInner::WithLifetime(proto))
}
}

impl<'a> From<uefi::boot::ScopedProtocol<SimpleFileSystemProtocol>> for FileSystem<'a> {
fn from(proto: uefi::boot::ScopedProtocol<SimpleFileSystemProtocol>) -> Self {
Self(FileSystemInner::WithoutLifetime(proto))
}
}

0 comments on commit 02e5f0e

Please sign in to comment.