Skip to content

system table can get debug-formatted (including boot and runtime services) #248

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
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
2 changes: 1 addition & 1 deletion src/data_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use core::{ffi::c_void, mem::MaybeUninit};

/// Opaque handle to an UEFI entity (protocol, image...)
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
#[repr(transparent)]
pub struct Handle(*mut c_void);

Expand Down
30 changes: 30 additions & 0 deletions src/proto/console/text/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::prelude::*;
use crate::proto::Protocol;
use crate::{unsafe_guid, CStr16, Char16, Completion, Result, Status};
use core::fmt;
use core::fmt::{Debug, Formatter};

/// Interface for text-based output devices.
///
Expand Down Expand Up @@ -197,6 +198,35 @@ impl<'boot> fmt::Write for Output<'boot> {
}
}

impl<'boot> Debug for Output<'boot> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Output")
.field("reset (fn ptr)", &(self.reset as *const u64))
.field(
"output_string (fn ptr)",
&(self.output_string as *const u64),
)
.field("test_string (fn ptr)", &(self.test_string as *const u64))
.field("query_mode (fn ptr)", &(self.query_mode as *const u64))
.field("set_mode (fn ptr)", &(self.set_mode as *const u64))
.field(
"set_attribute (fn ptr)",
&(self.set_attribute as *const u64),
)
.field("clear_screen (fn ptr)", &(self.clear_screen as *const u64))
.field(
"set_cursor_position (fn ptr)",
&(self.set_cursor_position as *const u64),
)
.field(
"enable_cursor (fn ptr)",
&(self.enable_cursor as *const u64),
)
.field("data", &self.data)
.finish()
}
}

/// The text mode (resolution) of the output device.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct OutputMode {
Expand Down
127 changes: 127 additions & 0 deletions src/table/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use alloc_api::vec::Vec;
use bitflags::bitflags;
use core::cell::UnsafeCell;
use core::ffi::c_void;
use core::fmt::{Debug, Formatter};
use core::mem::{self, MaybeUninit};
use core::{ptr, slice};

Expand Down Expand Up @@ -702,6 +703,132 @@ impl super::Table for BootServices {
const SIGNATURE: u64 = 0x5652_4553_544f_4f42;
}

impl Debug for BootServices {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("BootServices")
.field("header", &self.header)
.field("raise_tpl (fn ptr)", &(self.raise_tpl as *const usize))
.field("restore_tpl (fn ptr)", &(self.restore_tpl as *const usize))
.field(
"allocate_pages (fn ptr)",
&(self.allocate_pages as *const usize),
)
.field("free_pages (fn ptr)", &(self.free_pages as *const usize))
.field(
"get_memory_map (fn ptr)",
&(self.get_memory_map as *const usize),
)
.field(
"allocate_pool (fn ptr)",
&(self.allocate_pool as *const usize),
)
.field("free_pool (fn ptr)", &(self.free_pool as *const usize))
.field(
"create_event (fn ptr)",
&(self.create_event as *const usize),
)
.field("set_timer (fn ptr)", &(self.set_timer as *const usize))
.field(
"wait_for_event (fn ptr)",
&(self.wait_for_event as *const usize),
)
.field("signal_event", &(self.signal_event as *const usize))
.field("close_event", &(self.close_event as *const usize))
.field("check_event", &(self.check_event as *const usize))
.field(
"install_protocol_interface",
&(self.install_protocol_interface as *const usize),
)
.field(
"reinstall_protocol_interface",
&(self.reinstall_protocol_interface as *const usize),
)
.field(
"uninstall_protocol_interface",
&(self.uninstall_protocol_interface as *const usize),
)
.field(
"handle_protocol (fn ptr)",
&(self.handle_protocol as *const usize),
)
.field(
"register_protocol_notify",
&(self.register_protocol_notify as *const usize),
)
.field(
"locate_handle (fn ptr)",
&(self.locate_handle as *const usize),
)
.field(
"locate_device_path (fn ptr)",
&(self.locate_device_path as *const usize),
)
.field(
"install_configuration_table",
&(self.install_configuration_table as *const usize),
)
.field("load_image (fn ptr)", &(self.load_image as *const usize))
.field("start_image (fn ptr)", &(self.start_image as *const usize))
.field("exit", &(self.exit as *const usize))
.field(
"unload_image (fn ptr)",
&(self.unload_image as *const usize),
)
.field(
"exit_boot_services (fn ptr)",
&(self.exit_boot_services as *const usize),
)
.field(
"get_next_monotonic_count",
&(self.get_next_monotonic_count as *const usize),
)
.field("stall (fn ptr)", &(self.stall as *const usize))
.field(
"set_watchdog_timer (fn ptr)",
&(self.set_watchdog_timer as *const usize),
)
.field(
"connect_controller",
&(self.connect_controller as *const usize),
)
.field(
"disconnect_controller",
&(self.disconnect_controller as *const usize),
)
.field("open_protocol", &(self.open_protocol as *const usize))
.field("close_protocol", &(self.close_protocol as *const usize))
.field(
"open_protocol_information",
&(self.open_protocol_information as *const usize),
)
.field(
"protocols_per_handle",
&(self.protocols_per_handle as *const usize),
)
.field(
"locate_handle_buffer",
&(self.locate_handle_buffer as *const usize),
)
.field(
"locate_protocol (fn ptr)",
&(self.locate_protocol as *const usize),
)
.field(
"install_multiple_protocol_interfaces",
&(self.install_multiple_protocol_interfaces as *const usize),
)
.field(
"uninstall_multiple_protocol_interfaces",
&(self.uninstall_multiple_protocol_interfaces as *const usize),
)
.field("calculate_crc32", &(self.calculate_crc32 as *const usize))
.field("copy_mem (fn ptr)", &(self.copy_mem as *const usize))
.field("set_mem (fn ptr)", &(self.set_mem as *const usize))
.field("create_event_ex", &(self.create_event_ex as *const usize))
.finish()
}
}

newtype_enum! {
/// Task priority level.
///
Expand Down
13 changes: 12 additions & 1 deletion src/table/header.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::Revision;
use core::fmt::{Debug, Formatter};

/// All standard UEFI tables begin with a common header.
#[derive(Debug)]
#[repr(C)]
pub struct Header {
/// Unique identifier for this table.
Expand All @@ -16,3 +16,14 @@ pub struct Header {
/// Reserved field that must be set to 0.
_reserved: u32,
}

impl Debug for Header {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Header")
.field("signature", &(self.size as *const u64))
.field("revision", &self.revision)
.field("size", &self.size)
.field("crc", &self.crc)
.finish()
}
}
17 changes: 16 additions & 1 deletion src/table/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{CStr16, Char16, Guid, Result, Status};
#[cfg(feature = "exts")]
use alloc_api::{vec, vec::Vec};
use bitflags::bitflags;
use core::fmt::Formatter;
use core::fmt::{Debug, Formatter};
#[cfg(feature = "exts")]
use core::mem;
use core::mem::MaybeUninit;
Expand Down Expand Up @@ -250,6 +250,21 @@ impl super::Table for RuntimeServices {
const SIGNATURE: u64 = 0x5652_4553_544e_5552;
}

impl Debug for RuntimeServices {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("RuntimeServices")
.field("header", &self.header)
.field("get_time", &(self.get_time as *const u64))
.field("set_time", &(self.set_time as *const u64))
.field(
"set_virtual_address_map",
&(self.set_virtual_address_map as *const u64),
)
.field("reset", &(self.reset as *const u64))
.finish()
}
}

/// The current time information
#[derive(Copy, Clone)]
#[repr(C)]
Expand Down
34 changes: 32 additions & 2 deletions src/table/system.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use core::marker::PhantomData;
use core::slice;
use core::{ptr, slice};

use crate::proto::console::text;
use crate::{CStr16, Char16, Handle, Result, ResultExt, Status};

use super::boot::{BootServices, MemoryDescriptor};
use super::runtime::RuntimeServices;
use super::{cfg, Header, Revision};
use core::fmt::{Debug, Formatter};

/// Marker trait used to provide different views of the UEFI System Table
pub trait SystemTableView {}
Expand Down Expand Up @@ -41,6 +42,7 @@ impl SystemTableView for Runtime {}
/// UEFI boot services in the eye of the Rust borrow checker) and a runtime view
/// will be provided to replace it.
#[repr(transparent)]
#[derive(Debug)]
pub struct SystemTable<View: SystemTableView> {
table: &'static SystemTableImpl,
_marker: PhantomData<View>,
Expand Down Expand Up @@ -186,6 +188,12 @@ impl SystemTable<Boot> {
}
}

impl Debug for SystemTable<Boot> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
self.table.fmt(f)
}
}

// These parts of the SystemTable struct are only visible after exit from UEFI
// boot services. They provide unsafe access to the UEFI runtime services, which
// which were already available before but in safe form.
Expand Down Expand Up @@ -220,7 +228,7 @@ struct SystemTableImpl {
runtime: &'static RuntimeServices,
/// Boot services table.
boot: *const BootServices,
/// Number of entires in the configuration table.
/// Number of entries in the configuration table.
nr_cfg: usize,
/// Pointer to beginning of the array.
cfg_table: *const cfg::ConfigTableEntry,
Expand All @@ -229,3 +237,25 @@ struct SystemTableImpl {
impl<View: SystemTableView> super::Table for SystemTable<View> {
const SIGNATURE: u64 = 0x5453_5953_2049_4249;
}

impl Debug for SystemTableImpl {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("UefiSystemTable")
.field("header", &self.header)
.field("fw_vendor", &(unsafe { CStr16::from_ptr(self.fw_vendor) }))
.field("fw_revision", &self.fw_revision)
.field("stdin_handle", &self.stdin_handle)
.field("stdin", &self.stdin)
.field("stdout_handle", &self.stdout_handle)
.field("stdout", &self.stdout)
.field("stderr_handle", &self.stderr_handle)
.field("stderr", &self.stderr)
.field("runtime", &self.runtime)
// a little bit of extra work needed to call debug-fmt on the BootServices
// instead of printing the raw pointer
.field("boot", &(unsafe { ptr::read(self.boot) }))
.field("nf_cfg", &self.nr_cfg)
.field("cfg_table", &self.cfg_table)
.finish()
}
}