-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
UEFI paths can be of 4 types: 1. Absolute Shell Path: Uses shell mappings 2. Absolute Device Path: this is what we want 3: Relative root: path relative to the current root. 4: Relative Absolute shell path can be identified with `:` and Absolute Device path can be identified with `/`. Relative root path will start with `\`. The algorithm is mostly taken from edk2 UEFI shell implementation and is somewhat simple. Check for the path type in order. For Absolute Shell path, use `EFI_SHELL->GetDevicePathFromMap` to get a BorrowedDevicePath for the volume. For Relative paths, we use the current working directory to construct the new path. BorrowedDevicePath abstraction is needed to interact with `EFI_SHELL->GetDevicePathFromMap` which returns a Device Path Protocol with the lifetime of UEFI shell. Absolute Shell paths cannot exist if UEFI shell is missing. Signed-off-by: Ayush Singh <ayush@beagleboard.org>
- Loading branch information
Showing
3 changed files
with
155 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
#![forbid(unsafe_op_in_unsafe_fn)] | ||
use crate::ffi::OsStr; | ||
use crate::io; | ||
use crate::path::{Path, PathBuf, Prefix}; | ||
use crate::sys::{helpers, unsupported_err}; | ||
|
||
const FORWARD_SLASH: u8 = b'/'; | ||
const COLON: u8 = b':'; | ||
|
||
#[inline] | ||
pub fn is_sep_byte(b: u8) -> bool { | ||
b == b'\\' | ||
} | ||
|
||
#[inline] | ||
pub fn is_verbatim_sep(b: u8) -> bool { | ||
b == b'\\' | ||
} | ||
|
||
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { | ||
None | ||
} | ||
|
||
pub const MAIN_SEP_STR: &str = "\\"; | ||
pub const MAIN_SEP: char = '\\'; | ||
|
||
/// UEFI paths can be of 4 types: | ||
/// | ||
/// 1. Absolute Shell Path: Uses shell mappings. Does not exist if UEFI shell not present. | ||
/// It can be identified with `:`. | ||
/// Eg: FS0:\abc\run.efi | ||
/// | ||
/// 2. Absolute Device Path: this is what we want | ||
/// It can be identified with `/`. | ||
/// Eg: PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Slave,0x0)/\abc\run.efi | ||
/// | ||
/// 3: Relative root: path relative to the current volume. | ||
/// It will start with `\`. | ||
/// Eg: \abc\run.efi | ||
/// | ||
/// 4: Relative | ||
/// Eg: run.efi | ||
/// | ||
/// The algorithm is mostly taken from edk2 UEFI shell implementation and is | ||
/// somewhat simple. Check for the path type in order. | ||
/// | ||
/// The volume mapping in Absolute Shell Path (not the rest of the path) can be converted to Device | ||
/// Path Protocol using `EFI_SHELL->GetDevicePathFromMap`. The rest of the path (Relative root | ||
/// path), can just be appended to the remaining path. | ||
/// | ||
/// For Relative root, we get the current volume (either in Shell Mapping, or Device Path Protocol | ||
/// form) and join it with the relative root path. We then recurse the function to resolve the Shell | ||
/// Mapping if present. | ||
/// | ||
/// For Relative paths, we use the current working directory to construct | ||
/// the new path and recurse the function to resolve the Shell mapping if present. | ||
pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> { | ||
// Absolute Shell Path | ||
if path.as_os_str().as_encoded_bytes().contains(&COLON) { | ||
let mut path_components = path.components(); | ||
// Since path is not empty, it has at least one Component | ||
let prefix = path_components.next().unwrap(); | ||
|
||
let dev_path = helpers::get_device_path_from_map(prefix.as_ref())?; | ||
let dev_path_text = dev_path.to_text().map_err(|_| unsupported_err())?; | ||
|
||
let mut ans = PathBuf::new(); | ||
ans.push(&dev_path_text); | ||
// The Device Path Protocol mapping text representation can sometimes miss the final | ||
// seperator (Device path protocol seperator, aka '/'). | ||
if *dev_path_text.as_encoded_bytes().last().unwrap() != FORWARD_SLASH { | ||
ans.push("/"); | ||
} | ||
ans.push(path_components); | ||
|
||
return Ok(ans); | ||
} | ||
|
||
// Absolute Device Path | ||
if path.as_os_str().as_encoded_bytes().contains(&FORWARD_SLASH) { | ||
return Ok(path.to_path_buf()); | ||
} | ||
|
||
// cur_dir() always returns something | ||
let cur_dir = crate::env::current_dir().unwrap(); | ||
let mut path_components = path.components(); | ||
|
||
// Relative Root | ||
if path_components.next().unwrap() == crate::path::Component::RootDir { | ||
let mut ans = PathBuf::new(); | ||
ans.push(cur_dir.components().next().unwrap()); | ||
ans.push(path_components); | ||
return absolute(&ans); | ||
} | ||
|
||
absolute(&cur_dir.join(path)) | ||
} | ||
|
||
pub(crate) fn is_absolute(path: &Path) -> bool { | ||
let temp = path.as_os_str().as_encoded_bytes(); | ||
temp.contains(&COLON) || temp.contains(&FORWARD_SLASH) | ||
} |