Skip to content

Updating Uefi Raw for EFI Shell Protocol #1680

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions uefi-raw/src/protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub mod nvme;
pub mod pci;
pub mod rng;
pub mod scsi;
pub mod shell;
pub mod shell_params;
pub mod string;
pub mod tcg;
Expand Down
181 changes: 181 additions & 0 deletions uefi-raw/src/protocol/shell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

//! EFI Shell Protocol v2.2

use core::ffi::c_void;

use crate::{Char8, Char16, Event, Guid, Handle, Status, guid};

use super::device_path::DevicePathProtocol;
use super::file_system::FileInfo;
use super::shell_params::ShellFileHandle;

use bitflags::bitflags;

/// List Entry for File Lists
#[derive(Debug)]
#[repr(C)]
pub struct ListEntry {
pub f_link: *mut ListEntry,
pub b_link: *mut ListEntry,
}

/// ShellFileInfo for File Lists
#[derive(Debug)]
#[repr(C)]
pub struct ShellFileInfo {
pub link: ListEntry,
pub status: Status,
pub full_name: *mut Char16,
pub file_name: *mut Char16,
pub handle: ShellFileHandle,
pub info: FileInfo,
}

bitflags! {
/// Specifies the source of the component name
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct ShellDeviceNameFlags: u32 {
/// Use Component Name
const USE_COMPONENT_NAME = 0x0000001;
/// Use Device Path
const USE_DEVICE_PATH = 0x0000002;
}
}

/// Shell Protocol
#[derive(Debug)]
#[repr(C)]
pub struct ShellProtocol {
pub execute: unsafe extern "efiapi" fn(
parent_image_handle: *const Handle,
command_line: *const Char16,
Copy link
Member

@phip1611 phip1611 May 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicholasbishop, I think we should use

Suggested change
command_line: *const Char16,
command_line: Option<*const Char16>,

here and other optional parameters, right? I know that this is not streamlined across the code base for all OPTIONAL parameters. What do you say?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uefi-raw should stick close to the C API, so it should not use Option. (Personally I think the UEFI spec should just remove the OPTIONAL annotation, as they use it quite inconsistently and it doesn't have a clear purpose.)

(Also, it wouldn't be compatible with the C ABI unless we also switched from a raw pointer to NonNull. Option<NonNull> is ABI compatible with a raw pointer, but Option<const*> is not, because it can't use the niche optimization.)

environment: *const *const Char16,
status_code: *mut Status,
) -> Status,
pub get_env: unsafe extern "efiapi" fn(name: *const Char16) -> *const Char16,
pub set_env: unsafe extern "efiapi" fn(
name: *const Char16,
value: *const Char16,
volatile: bool,
) -> Status,
pub get_alias: unsafe extern "efiapi" fn(alias: *const Char16, volatile: bool) -> *const Char16,
pub set_alias: unsafe extern "efiapi" fn(
command: *const Char16,
alias: *const Char16,
replace: bool,
volatile: bool,
) -> Status,
pub get_help_text: unsafe extern "efiapi" fn(
command: *const Char16,
sections: *const Char16,
help_text: *mut *mut Char16,
) -> Status,
pub get_device_path_from_map:
unsafe extern "efiapi" fn(mapping: *const Char16) -> *const DevicePathProtocol,
pub get_map_from_device_path:
unsafe extern "efiapi" fn(device_path: *mut *mut DevicePathProtocol) -> *const Char16,
pub get_device_path_from_file_path:
unsafe extern "efiapi" fn(path: *const Char16) -> *const DevicePathProtocol,
pub get_file_path_from_device_path:
unsafe extern "efiapi" fn(path: *const DevicePathProtocol) -> *const Char16,
pub set_map: unsafe extern "efiapi" fn(
device_path: *const DevicePathProtocol,
mapping: *const Char16,
) -> Status,

pub get_cur_dir: unsafe extern "efiapi" fn(file_system_mapping: *const Char16) -> *const Char16,
pub set_cur_dir:
unsafe extern "efiapi" fn(file_system: *const Char16, dir: *const Char16) -> Status,
pub open_file_list: unsafe extern "efiapi" fn(
path: *const Char16,
open_mode: u64,
file_list: *mut *mut ShellFileInfo,
) -> Status,
pub free_file_list: unsafe extern "efiapi" fn(file_list: *const *const ShellFileInfo) -> Status,
pub remove_dup_in_file_list:
unsafe extern "efiapi" fn(file_list: *const *const ShellFileInfo) -> Status,

pub batch_is_active: unsafe extern "efiapi" fn() -> bool,
pub is_root_shell: unsafe extern "efiapi" fn() -> bool,
pub enable_page_break: unsafe extern "efiapi" fn(),
pub disable_page_break: unsafe extern "efiapi" fn(),
pub get_page_break: unsafe extern "efiapi" fn() -> bool,
pub get_device_name: unsafe extern "efiapi" fn(
device_handle: Handle,
flags: ShellDeviceNameFlags,
language: *const Char8,
best_device_name: *mut *mut Char16,
) -> Status,

pub get_file_info: unsafe extern "efiapi" fn(file_handle: ShellFileHandle) -> *const FileInfo,
pub set_file_info: unsafe extern "efiapi" fn(
file_handle: ShellFileHandle,
file_info: *const FileInfo,
) -> Status,
pub open_file_by_name: unsafe extern "efiapi" fn(
file_name: *const Char16,
file_handle: *mut ShellFileHandle,
open_mode: u64,
) -> Status,
pub close_file: unsafe extern "efiapi" fn(file_handle: ShellFileHandle) -> Status,
pub create_file: unsafe extern "efiapi" fn(
file_name: *const Char16,
file_attribs: u64,
file_handle: *mut ShellFileHandle,
) -> Status,
pub read_file: unsafe extern "efiapi" fn(
file_handle: ShellFileHandle,
read_size: *mut usize,
buffer: *mut c_void,
) -> Status,
pub write_file: unsafe extern "efiapi" fn(
file_handle: ShellFileHandle,
buffer_size: *mut usize,
buffer: *mut c_void,
) -> Status,
pub delete_file: unsafe extern "efiapi" fn(file_handle: ShellFileHandle) -> Status,
pub delete_file_by_name: unsafe extern "efiapi" fn(file_name: *const Char16) -> Status,
pub get_file_position:
unsafe extern "efiapi" fn(file_handle: ShellFileHandle, position: *mut u64) -> Status,
pub set_file_position:
unsafe extern "efiapi" fn(file_handle: ShellFileHandle, position: u64) -> Status,
pub flush_file: unsafe extern "efiapi" fn(file_handle: ShellFileHandle) -> Status,
pub find_files: unsafe extern "efiapi" fn(
file_pattern: *const Char16,
file_list: *mut *mut ShellFileInfo,
) -> Status,
pub find_files_in_dir: unsafe extern "efiapi" fn(
file_dir_handle: ShellFileHandle,
file_list: *mut *mut ShellFileInfo,
) -> Status,
pub get_file_size:
unsafe extern "efiapi" fn(file_handle: ShellFileHandle, size: *mut u64) -> Status,

pub open_root: unsafe extern "efiapi" fn(
device_path: *const DevicePathProtocol,
file_handle: *mut ShellFileHandle,
) -> Status,
pub open_root_by_handle: unsafe extern "efiapi" fn(
device_handle: Handle,
file_handle: *mut ShellFileHandle,
) -> Status,

pub execution_break: Event,

pub major_version: u32,
pub minor_version: u32,
pub register_guid_name:
unsafe extern "efiapi" fn(guid: *const Guid, guid_name: *const Char16) -> Status,
pub get_guid_name:
unsafe extern "efiapi" fn(guid: *const Guid, guid_name: *mut *mut Char16) -> Status,
pub get_guid_from_name:
unsafe extern "efiapi" fn(guid_name: *const Char16, guid: *mut Guid) -> Status,
pub get_env_ex:
unsafe extern "efiapi" fn(name: *const Char16, attributes: *mut u32) -> *const Char16,
}

impl ShellProtocol {
pub const GUID: Guid = guid!("6302d008-7f9b-4f30-87ac-60c9fef5da4e");
}
4 changes: 3 additions & 1 deletion uefi-test-runner/src/proto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub fn test() {
target_arch = "aarch64"
))]
shim::test();
shell::test();
tcg::test();
}

Expand Down Expand Up @@ -89,13 +90,14 @@ mod pci;
mod pi;
mod rng;
mod scsi;
mod shell_params;
#[cfg(any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "arm",
target_arch = "aarch64"
))]
mod shell;
mod shell_params;
mod shim;
mod string;
mod tcg;
Expand Down
13 changes: 13 additions & 0 deletions uefi-test-runner/src/proto/shell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

use uefi::boot;
use uefi::proto::shell::Shell;

pub fn test() {
info!("Running shell protocol tests");

let handle = boot::get_handle_for_protocol::<Shell>().expect("No Shell handles");

let mut _shell =
boot::open_protocol_exclusive::<Shell>(handle).expect("Failed to open Shell protocol");
}
1 change: 1 addition & 0 deletions uefi/src/proto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub mod rng;
#[cfg(feature = "alloc")]
pub mod scsi;
pub mod security;
pub mod shell;
pub mod shell_params;
pub mod shim;
pub mod string;
Expand Down
13 changes: 13 additions & 0 deletions uefi/src/proto/shell/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

//! EFI Shell Protocol v2.2

use crate::proto::unsafe_protocol;

pub use uefi_raw::protocol::shell::ShellProtocol;

/// Shell Protocol
#[derive(Debug)]
#[repr(transparent)]
#[unsafe_protocol(uefi_raw::protocol::shell::ShellProtocol::GUID)]
pub struct Shell(uefi_raw::protocol::shell::ShellProtocol);