From 6fffe57a6349cbd6f2eb71b78a9f5719d163589f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 5 Apr 2023 14:42:47 +0300 Subject: [PATCH] uefi: debug: add DebugPort protocol DebugPort might be useful for some uefi applications. --- uefi-test-runner/src/proto/debug.rs | 66 ++++++++++++++++++++++++++- uefi/src/proto/debug/mod.rs | 69 +++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/uefi-test-runner/src/proto/debug.rs b/uefi-test-runner/src/proto/debug.rs index 40b0cc50d..d3ce523f9 100644 --- a/uefi-test-runner/src/proto/debug.rs +++ b/uefi-test-runner/src/proto/debug.rs @@ -1,8 +1,72 @@ +use alloc::vec::Vec; use core::ffi::c_void; -use uefi::proto::debug::{DebugSupport, ExceptionType, ProcessorArch, SystemContext}; +use uefi::proto::debug::{DebugPort, DebugSupport, ExceptionType, ProcessorArch, SystemContext}; use uefi::table::boot::BootServices; pub fn test(bt: &BootServices) { + test_debug_support(bt); + test_debug_port(bt); +} + +fn test_debug_port(bt: &BootServices) { + info!("Running UEFI debug port protocol test"); + if let Ok(handles) = bt.find_handles::() { + for handle in handles { + if let Ok(debug_port) = bt.open_protocol_exclusive::(handle) { + let timeout = 1000; + + debug_port + .reset() + .expect("Error while resetting debug port"); + let data: Vec<_> = r##" + .. .=- . + . :##+ .*##= -*#+ .. + =#*=:.*####+#####**####-.-*## + .=-. *############################: :-: + -###**##############################*###* + :. -#######################################* .:: + =################################################## + .#################################################= + -====#################################################+====. + =##########################################################. + +########################################################. + -==+#########################################################*+=-. + +######################=:=@@%#########+:-%@%####################*: + =####################+ +@@@%######%. -@@@##################*. + :+#####################@-.:%@@@@#####%@*::#@@@%###################+: + +#######################@@@@@@@@@######@@@@@@@@%#####################- + -#########################@@@@@@@########@@@@@@%####################### + -#######%%%##################%##############################%%%%######* + +########%%%%############################################*%%%%#######: + =######+=%%%#####***##%%#####################%#**++####=:%%%#######: + :*#####:.*%#-####+==*########+-::::::=*#######*=+###*- *%*:-####*. + -####* .+. -*###############= .*#############*- .*: *###+ + =###: *##############+ .##############+ .###= + .+#* -######*=+++**** =###***++######- :#*. + .- -######- .*#####- .- + =*####*. =####+- + .:--: ::::. +"## + .bytes() + .collect(); + + debug_port + .write(timeout, &data) + .expect("Error while writing to debug port"); + + debug_port.poll().expect("Error while polling debug port"); + + let mut data = Vec::with_capacity(4096); + + debug_port + .read(timeout, &mut data) + .expect("Error while reading from debug port"); + } + } + } +} + +fn test_debug_support(bt: &BootServices) { info!("Running UEFI debug connection protocol test"); let handles = bt .find_handles::() diff --git a/uefi/src/proto/debug/mod.rs b/uefi/src/proto/debug/mod.rs index 776b43497..22ad4983b 100644 --- a/uefi/src/proto/debug/mod.rs +++ b/uefi/src/proto/debug/mod.rs @@ -170,3 +170,72 @@ pub enum ProcessorArch: u32 => { /// RISC-V 128-bit RISCV_128 = 0x5128, }} + +/// The debug port protocol abstracts the underlying debug port +/// hardware, whether it is a regular Serial port or something else. +#[repr(C)] +#[unsafe_protocol("eba4e8d2-3858-41ec-a281-2647ba9660d0")] +pub struct DebugPort { + reset: extern "efiapi" fn(this: &DebugPort) -> Status, + write: extern "efiapi" fn( + this: &DebugPort, + timeout: u32, + buffer_size: &mut usize, + buffer: *const c_void, + ) -> Status, + read: extern "efiapi" fn( + this: &DebugPort, + timeout: u32, + buffer_size: &mut usize, + buffer: *mut c_void, + ) -> Status, + poll: extern "efiapi" fn(this: &DebugPort) -> Status, +} + +impl DebugPort { + /// Resets the debugport device. + pub fn reset(&self) -> Result { + (self.reset)(self).into() + } + + /// Write data to the debugport device. + /// + /// Note: `timeout` is given in microseconds + pub fn write(&self, timeout: u32, data: &[u8]) -> Result<(), usize> { + let mut buffer_size = data.len(); + + (self.write)( + self, + timeout, + &mut buffer_size, + data.as_ptr().cast::(), + ) + .into_with( + || debug_assert_eq!(buffer_size, data.len()), + |_| buffer_size, + ) + } + + /// Read data from the debugport device. + /// + /// Note: `timeout` is given in microseconds + pub fn read(&self, timeout: u32, data: &mut [u8]) -> Result<(), usize> { + let mut buffer_size = data.len(); + + (self.read)( + self, + timeout, + &mut buffer_size, + data.as_mut_ptr().cast::(), + ) + .into_with( + || debug_assert_eq!(buffer_size, data.len()), + |_| buffer_size, + ) + } + + /// Check to see if any data is available to be read from the debugport device. + pub fn poll(&self) -> Result { + (self.poll)(self).into() + } +}