From 98ae4aeb6ddf58a18cec0368aa9591fad8c612ef Mon Sep 17 00:00:00 2001 From: Luca Versari Date: Sun, 30 Nov 2025 10:39:30 +0100 Subject: [PATCH 1/6] Remove Timer from the main OS struct. --- pixie-uefi/src/os/executor.rs | 10 +++--- pixie-uefi/src/os/mod.rs | 27 ++++++--------- pixie-uefi/src/os/net.rs | 6 ++-- pixie-uefi/src/os/timer.rs | 62 +++++++++++++++++++---------------- 4 files changed, 53 insertions(+), 52 deletions(-) diff --git a/pixie-uefi/src/os/executor.rs b/pixie-uefi/src/os/executor.rs index b4a782a6..816aaebb 100644 --- a/pixie-uefi/src/os/executor.rs +++ b/pixie-uefi/src/os/executor.rs @@ -1,4 +1,6 @@ -use super::{sync::SyncRefCell, UefiOS}; +use crate::os::timer::Timer; + +use super::sync::SyncRefCell; use alloc::{boxed::Box, collections::VecDeque, sync::Arc, task::Wake}; use core::{ cell::RefCell, @@ -63,7 +65,7 @@ pub struct Executor { } impl Executor { - pub fn run(os: UefiOS) -> ! { + pub fn run() -> ! { loop { let task = EXECUTOR .borrow_mut() @@ -75,9 +77,9 @@ impl Executor { let waker = Waker::from(task.clone()); let mut context = Context::from_waker(&waker); let mut fut = task.inner.borrow_mut().future.take().unwrap(); - let begin = os.timer().micros(); + let begin = Timer::micros(); let status = fut.as_mut().poll(&mut context); - let end = os.timer().micros(); + let end = Timer::micros(); task.inner.borrow_mut().micros += end - begin; if status.is_pending() { task.inner.borrow_mut().future = Some(fut); diff --git a/pixie-uefi/src/os/mod.rs b/pixie-uefi/src/os/mod.rs index 27af756e..13782fce 100644 --- a/pixie-uefi/src/os/mod.rs +++ b/pixie-uefi/src/os/mod.rs @@ -57,7 +57,6 @@ mod timer; pub use net::{TcpStream, UdpHandle, PACKET_SIZE}; struct UefiOSImpl { - timer: Timer, rng: Rng, tasks: Vec>, input: ScopedProtocol, @@ -163,7 +162,7 @@ impl UefiOS { .unwrap(); } - let timer = Timer::new(); + Timer::ensure_init(); let rng = Rng::new(); let input_handles = uefi::boot::find_handles::().unwrap(); @@ -179,7 +178,6 @@ impl UefiOS { vga.clear().unwrap(); *OS.borrow_mut() = Some(UefiOSImpl { - timer, rng, tasks: Vec::new(), input, @@ -227,9 +225,8 @@ impl UefiOS { os.spawn( "[net_poll]", poll_fn(move |cx| { - let (mut net, timer) = - RefMut::map_split(os.borrow_mut(), |os| (&mut os.net, &mut os.timer)); - net.as_mut().unwrap().poll(&timer); + let mut os = os.borrow_mut(); + os.net.as_mut().unwrap().poll(); // TODO(veluca): figure out whether we can suspend the task. cx.waker().wake_by_ref(); Poll::Pending @@ -239,10 +236,10 @@ impl UefiOS { os.spawn("[net_speed]", async move { let mut prx = 0; let mut ptx = 0; - let mut ptm = os.timer().instant(); + let mut ptm = Timer::instant(); loop { { - let now = os.timer().instant(); + let now = Timer::instant(); let dt = (now - ptm).total_micros() as f64 / 1_000_000.0; ptm = now; @@ -263,7 +260,7 @@ impl UefiOS { } }); - Executor::run(os) + Executor::run() } fn borrow(&self) -> Ref<'static, UefiOSImpl> { @@ -274,10 +271,6 @@ impl UefiOS { RefMut::map(OS.borrow_mut(), |f| f.as_mut().unwrap()) } - pub fn timer(&self) -> Ref<'static, Timer> { - Ref::map(self.borrow(), |f| &f.timer) - } - pub fn rng(&self) -> RefMut<'static, Rng> { RefMut::map(self.borrow_mut(), |f| &mut f.rng) } @@ -317,9 +310,9 @@ impl UefiOS { } pub fn sleep_us(self, us: u64) -> impl Future { - let tgt = self.timer().micros() as u64 + us; + let tgt = Timer::micros() as u64 + us; poll_fn(move |cx| { - let now = self.timer().micros() as u64; + let now = Timer::micros() as u64; if now >= tgt { Poll::Ready(()) } else { @@ -431,7 +424,7 @@ impl UefiOS { fn draw_ui(&self) { // Write the header. { - let time = self.timer().micros() as f32 * 0.000_001; + let time = Timer::micros() as f32 * 0.000_001; let ip = self.net().ip(); let mut os = self.borrow_mut(); @@ -572,7 +565,7 @@ impl log::Log for UefiOS { } fn log(&self, record: &log::Record) { - let now = self.timer().micros() as f64 * 0.000_001; + let now = Timer::micros() as f64 * 0.000_001; self.append_message( now, record.level(), diff --git a/pixie-uefi/src/os/net.rs b/pixie-uefi/src/os/net.rs index 7cad4af3..cce285f5 100644 --- a/pixie-uefi/src/os/net.rs +++ b/pixie-uefi/src/os/net.rs @@ -183,7 +183,7 @@ impl NetworkInterface { let mut interface_config = Config::new(hw_addr); interface_config.random_seed = os.rng().rand_u64(); - let now = Instant::from_micros(os.timer().micros()); + let now = Timer::instant(); let interface = Interface::new(interface_config, &mut device, now); let mut dhcp_socket = Dhcpv4Socket::new(); dhcp_socket.set_outgoing_options(&[DhcpOption { @@ -220,8 +220,8 @@ impl NetworkInterface { self.interface.ipv4_addr() } - pub(super) fn poll(&mut self, timer: &Timer) -> bool { - let now = timer.instant(); + pub(super) fn poll(&mut self) -> bool { + let now = Timer::instant(); let status = self .interface .poll(now, &mut self.device, &mut self.socket_set); diff --git a/pixie-uefi/src/os/timer.rs b/pixie-uefi/src/os/timer.rs index 4fa2bafa..619c4664 100644 --- a/pixie-uefi/src/os/timer.rs +++ b/pixie-uefi/src/os/timer.rs @@ -1,43 +1,49 @@ -use core::arch::x86_64::_rdtsc; +use core::{ + arch::x86_64::_rdtsc, + sync::atomic::{AtomicBool, AtomicI64, Ordering}, +}; use smoltcp::time::Instant; -pub struct Timer { - ticks_at_start: i64, - ticks_per_micro: i64, +static TICKS_AT_START: AtomicI64 = AtomicI64::new(0); +static TICKS_PER_MICRO: AtomicI64 = AtomicI64::new(0); +static INITIALIZED: AtomicBool = AtomicBool::new(false); + +pub struct Timer {} + +fn rdtsc() -> i64 { + // SAFETY: modern x86 CPUs have this instruction. + unsafe { _rdtsc() as i64 } } impl Timer { - fn rdtsc() -> i64 { - // SAFETY: modern x86 CPUs have this instruction. - unsafe { _rdtsc() as i64 } - } - - pub fn new() -> Timer { + pub(super) fn ensure_init() { + if INITIALIZED.load(Ordering::Relaxed) { + return; + } // Read timer clock & wait to stabilize the counter. - Self::rdtsc(); + rdtsc(); uefi::boot::stall(20000); - let tsc_before = Self::rdtsc(); + let tsc_before = rdtsc(); uefi::boot::stall(20000); - let tsc_after = Self::rdtsc(); + let tsc_after = rdtsc(); - Timer { - ticks_at_start: tsc_after, - // TICKS_PER_MICRO is a multiple of 10 on every reasonable system. - ticks_per_micro: (tsc_after - tsc_before) / (20000 * 10) * 10, - } - } - - pub fn micros(&self) -> i64 { - (Self::rdtsc() - self.ticks_at_start) / self.ticks_per_micro + TICKS_AT_START.store(tsc_after, Ordering::Relaxed); + // TICKS_PER_MICRO is a multiple of 10 on every reasonable system. + TICKS_PER_MICRO.store( + (tsc_after - tsc_before) / (20000 * 10) * 10, + Ordering::Relaxed, + ); + INITIALIZED.store(true, Ordering::Relaxed); } - pub fn instant(&self) -> Instant { - Instant::from_micros(self.micros()) + pub fn micros() -> i64 { + Self::ensure_init(); + let ticks_at_start = TICKS_AT_START.load(Ordering::Relaxed); + let ticks_per_micro = TICKS_PER_MICRO.load(Ordering::Relaxed); + (rdtsc() - ticks_at_start) / ticks_per_micro } -} -impl Default for Timer { - fn default() -> Self { - Self::new() + pub fn instant() -> Instant { + Instant::from_micros(Timer::micros()) } } From 7358e20a281ad8ddc3420ef5aebcac3b509543ed Mon Sep 17 00:00:00 2001 From: Luca Versari Date: Sun, 30 Nov 2025 11:24:45 +0100 Subject: [PATCH 2/6] Use thingbuf instead of a custom "m"psc. --- pixie-shared/src/lib.rs | 2 +- pixie-uefi/Cargo.lock | 30 ++++++++++++++ pixie-uefi/Cargo.toml | 1 + pixie-uefi/src/flash.rs | 8 ++-- pixie-uefi/src/os/mod.rs | 1 - pixie-uefi/src/os/mpsc.rs | 84 --------------------------------------- pixie-uefi/src/store.rs | 30 ++++++++------ 7 files changed, 53 insertions(+), 103 deletions(-) delete mode 100644 pixie-uefi/src/os/mpsc.rs diff --git a/pixie-shared/src/lib.rs b/pixie-shared/src/lib.rs index 6b362844..fa30b0cc 100644 --- a/pixie-shared/src/lib.rs +++ b/pixie-shared/src/lib.rs @@ -39,7 +39,7 @@ pub type ChunkHash = [u8; OUT_LEN]; pub type Offset = usize; /// Describes one chunk from a disk. -#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default)] pub struct Chunk { pub hash: ChunkHash, pub start: Offset, diff --git a/pixie-uefi/Cargo.lock b/pixie-uefi/Cargo.lock index f6f6ab88..942f4b4e 100644 --- a/pixie-uefi/Cargo.lock +++ b/pixie-uefi/Cargo.lock @@ -334,6 +334,26 @@ dependencies = [ "walkdir", ] +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "pin-project-lite" version = "0.2.15" @@ -374,6 +394,7 @@ dependencies = [ "rand", "rand_xoshiro", "smoltcp", + "thingbuf", "uefi", ] @@ -560,6 +581,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thingbuf" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662b54ef6f7b4e71f683dadc787bbb2d8e8ef2f91b682ebed3164a5a7abca905" +dependencies = [ + "pin-project", +] + [[package]] name = "thiserror" version = "2.0.17" diff --git a/pixie-uefi/Cargo.toml b/pixie-uefi/Cargo.toml index 6cae3362..3958ca6d 100644 --- a/pixie-uefi/Cargo.toml +++ b/pixie-uefi/Cargo.toml @@ -27,6 +27,7 @@ postcard = { version = "1.1.3", default-features = false, features = ["alloc"] } rand = { version = "0.8.5", default-features = false } rand_xoshiro = { version = "0.6.0", default-features = false } smoltcp = { version = "0.12.0", default-features = false, features = ["alloc", "proto-ipv4", "medium-ethernet", "socket-udp", "socket-tcp", "socket-dhcpv4", "async", "socket-tcp-cubic"] } +thingbuf = { version = "0.1.6", default-features = false, features = ["alloc"] } uefi = { version = "0.33.0", features = ["alloc", "global_allocator", "panic_handler"] } [dependencies.pixie-shared] diff --git a/pixie-uefi/src/flash.rs b/pixie-uefi/src/flash.rs index 3a8e9dec..5c75d7d2 100644 --- a/pixie-uefi/src/flash.rs +++ b/pixie-uefi/src/flash.rs @@ -1,7 +1,7 @@ use crate::{ os::{ error::{Error, Result}, - mpsc, TcpStream, UefiOS, PACKET_SIZE, + TcpStream, UefiOS, PACKET_SIZE, }, MIN_MEMORY, }; @@ -162,10 +162,10 @@ pub async fn flash(os: UefiOS, server_addr: SocketAddrV4) -> Result<()> { let mut received = BTreeMap::new(); - let (tx, mut rx) = mpsc::channel(128); + let (tx, rx) = thingbuf::mpsc::channel(128); let task1 = async { - let mut tx = tx; + let tx = tx; let mut last_seen = Vec::new(); let total_mem = os.get_total_mem(); let max_chunks = (total_mem.saturating_sub(MIN_MEMORY) as usize / MAX_CHUNK_SIZE).max(128); @@ -184,7 +184,7 @@ pub async fn flash(os: UefiOS, server_addr: SocketAddrV4) -> Result<()> { let chunk = handle_packet(buf, &mut chunks_info, &mut received, &mut last_seen)?; if let Some((pos, data)) = chunk { - tx.send((pos, data)).await; + tx.send((pos, data)).await.expect("receiver was dropped"); } assert_eq!(last_seen.len(), received.len()); diff --git a/pixie-uefi/src/os/mod.rs b/pixie-uefi/src/os/mod.rs index 13782fce..cb24f3e9 100644 --- a/pixie-uefi/src/os/mod.rs +++ b/pixie-uefi/src/os/mod.rs @@ -48,7 +48,6 @@ mod boot_options; pub mod disk; pub mod error; mod executor; -pub mod mpsc; mod net; mod rng; mod sync; diff --git a/pixie-uefi/src/os/mpsc.rs b/pixie-uefi/src/os/mpsc.rs deleted file mode 100644 index 256d95e4..00000000 --- a/pixie-uefi/src/os/mpsc.rs +++ /dev/null @@ -1,84 +0,0 @@ -use alloc::{collections::VecDeque, rc::Rc}; -use core::{cell::RefCell, future::poll_fn, task::Poll, task::Waker}; - -struct Data { - size: usize, - tx_count: usize, - tx_waker: Option, - rx_waker: Option, - queue: VecDeque, -} - -pub struct Sender { - inner: Rc>>, -} - -impl Sender { - pub async fn send(&mut self, value: T) { - let mut value = Some(value); - poll_fn(|cx| { - let mut inner = self.inner.borrow_mut(); - if inner.queue.len() < inner.size { - inner.queue.push_back(value.take().unwrap()); - if let Some(waker) = inner.rx_waker.take() { - waker.wake(); - } - Poll::Ready(()) - } else { - inner.tx_waker = Some(cx.waker().clone()); - Poll::Pending - } - }) - .await - } -} - -impl Drop for Sender { - fn drop(&mut self) { - let mut inner = self.inner.borrow_mut(); - inner.tx_count -= 1; - if let Some(waker) = inner.rx_waker.take() { - waker.wake(); - } - } -} - -pub struct Receiver { - inner: Rc>>, -} - -impl Receiver { - pub async fn recv(&mut self) -> Option { - poll_fn(|cx| { - let mut inner = self.inner.borrow_mut(); - if let Some(value) = inner.queue.pop_front() { - if let Some(waker) = inner.tx_waker.take() { - waker.wake(); - } - Poll::Ready(Some(value)) - } else if inner.tx_count == 0 { - Poll::Ready(None) - } else { - inner.rx_waker = Some(cx.waker().clone()); - Poll::Pending - } - }) - .await - } -} - -pub fn channel(size: usize) -> (Sender, Receiver) { - let inner = Rc::new(RefCell::new(Data { - size, - tx_count: 1, - tx_waker: None, - rx_waker: None, - queue: VecDeque::new(), - })); - ( - Sender { - inner: inner.clone(), - }, - Receiver { inner }, - ) -} diff --git a/pixie-uefi/src/store.rs b/pixie-uefi/src/store.rs index 2ef84377..8d6dfb75 100644 --- a/pixie-uefi/src/store.rs +++ b/pixie-uefi/src/store.rs @@ -1,7 +1,7 @@ use crate::{ os::{ error::{Error, Result}, - mpsc, TcpStream, UefiOS, + TcpStream, UefiOS, }, parse_disk, MIN_MEMORY, }; @@ -92,13 +92,13 @@ pub async fn store(os: UefiOS, server_address: SocketAddrV4) -> Result<()> { BytesFmt(total_mem) ); - let (tx1, mut rx1) = mpsc::channel(channel_size); - let (tx2, mut rx2) = mpsc::channel(channel_size); - let (tx3, mut rx3) = mpsc::channel(channel_size); - let (tx4, mut rx4) = mpsc::channel(channel_size); + let (tx1, rx1) = thingbuf::mpsc::channel(channel_size); + let (tx2, rx2) = thingbuf::mpsc::channel(channel_size); + let (tx3, rx3) = thingbuf::mpsc::channel(channel_size); + let (tx4, rx4) = thingbuf::mpsc::channel(channel_size); let task1 = async { - let mut tx1 = tx1; + let tx1 = tx1; for chunk_info in chunks { let mut data = vec![0; chunk_info.size]; disk.read(chunk_info.start as u64, &mut data).await?; @@ -110,37 +110,39 @@ pub async fn store(os: UefiOS, server_address: SocketAddrV4) -> Result<()> { size: chunk_info.size, csize: cdata.len(), }; - tx1.send((chunk, cdata)).await; + tx1.send((chunk, cdata)).await.expect("receiver dropped"); } Ok::<_, Error>(()) }; let task2 = async { - let mut tx2 = tx2; + let tx2 = tx2; while let Some((chunk, cdata)) = rx1.recv().await { let req = TcpRequest::HasChunk(chunk.hash); let buf = postcard::to_allocvec(&req)?; stream_get_csize.send_u64_le(buf.len() as u64).await?; stream_get_csize.send(&buf).await?; - tx2.send((chunk, cdata)).await; + tx2.send((chunk, cdata)).await.expect("receiver dropped"); } Ok(()) }; let task3 = async { - let mut tx3 = tx3; + let tx3 = tx3; while let Some((chunk, cdata)) = rx2.recv().await { let len = stream_get_csize.recv_u64_le().await?; let mut buf = vec![0; len as usize]; stream_get_csize.recv(&mut buf).await?; let has_chunk: bool = postcard::from_bytes(&buf)?; - tx3.send((chunk, cdata, has_chunk)).await; + tx3.send((chunk, cdata, has_chunk)) + .await + .expect("receiver dropped"); } Ok(()) }; let task4 = async { - let mut tx4 = tx4; + let tx4 = tx4; while let Some((chunk, cdata, has_chunk)) = rx3.recv().await { if !has_chunk { let req = TcpRequest::UploadChunk(cdata); @@ -148,7 +150,9 @@ pub async fn store(os: UefiOS, server_address: SocketAddrV4) -> Result<()> { stream_upload_chunk.send_u64_le(buf.len() as u64).await?; stream_upload_chunk.send(&buf).await?; } - tx4.send((chunk, has_chunk)).await; + tx4.send((chunk, has_chunk)) + .await + .expect("receiver dropped"); } Ok(()) }; From 65ed6f892ed02bca9b2dea741f4971ce8aacdbf9 Mon Sep 17 00:00:00 2001 From: Luca Versari Date: Sun, 30 Nov 2025 12:12:53 +0100 Subject: [PATCH 3/6] More general error types. --- pixie-uefi/Cargo.lock | 21 ---------------- pixie-uefi/Cargo.toml | 1 - pixie-uefi/src/flash.rs | 4 +-- pixie-uefi/src/os/disk.rs | 21 +++++----------- pixie-uefi/src/os/error.rs | 42 ++++++++++++++++++------------- pixie-uefi/src/os/mod.rs | 4 +-- pixie-uefi/src/os/net.rs | 4 +-- pixie-uefi/src/parse_disk/ntfs.rs | 12 +++------ pixie-uefi/src/register.rs | 2 +- 9 files changed, 41 insertions(+), 70 deletions(-) diff --git a/pixie-uefi/Cargo.lock b/pixie-uefi/Cargo.lock index 942f4b4e..16a43779 100644 --- a/pixie-uefi/Cargo.lock +++ b/pixie-uefi/Cargo.lock @@ -160,26 +160,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "derive_more" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - [[package]] name = "embedded-io" version = "0.4.0" @@ -382,7 +362,6 @@ dependencies = [ "anstyle", "blake3", "core_detect", - "derive_more", "futures", "gpt_disk_io", "log", diff --git a/pixie-uefi/Cargo.toml b/pixie-uefi/Cargo.toml index 3958ca6d..6063b563 100644 --- a/pixie-uefi/Cargo.toml +++ b/pixie-uefi/Cargo.toml @@ -16,7 +16,6 @@ coverage = ["dep:minicov"] anstyle = { version = "1.0.13", default-features = false } blake3 = { version = "1.8.2", default-features = false, features = ["prefer_intrinsics", "no_avx512", "pure"] } core_detect = "1.0.0" -derive_more = { version = "2.0.1", features = ["from"], default-features = false } futures = { version = "0.3.29", default-features = false, features = ["alloc", "async-await"] } gpt_disk_io = "0.16.2" log = "0.4.28" diff --git a/pixie-uefi/src/flash.rs b/pixie-uefi/src/flash.rs index 5c75d7d2..60cbe6e3 100644 --- a/pixie-uefi/src/flash.rs +++ b/pixie-uefi/src/flash.rs @@ -5,7 +5,7 @@ use crate::{ }, MIN_MEMORY, }; -use alloc::{boxed::Box, collections::BTreeMap, rc::Rc, string::ToString, vec::Vec}; +use alloc::{boxed::Box, collections::BTreeMap, rc::Rc, vec::Vec}; use core::{cell::RefCell, mem, net::SocketAddrV4}; use futures::future::{select, Either}; use log::info; @@ -64,7 +64,7 @@ fn handle_packet( received.remove(&hash).unwrap(); last_seen.retain(|x| x != &hash); - let data = decompress(&cdata, size).map_err(|e| Error::Generic(e.to_string()))?; + let data = decompress(&cdata, size)?; assert_eq!(data.len(), size); Ok(Some((pos, data))) diff --git a/pixie-uefi/src/os/disk.rs b/pixie-uefi/src/os/disk.rs index 6185a551..e65ddd3c 100644 --- a/pixie-uefi/src/os/disk.rs +++ b/pixie-uefi/src/os/disk.rs @@ -1,7 +1,4 @@ -use super::{ - error::{Error, Result}, - UefiOS, -}; +use super::{error::Result, UefiOS}; use alloc::{ string::{String, ToString}, vec::Vec, @@ -170,19 +167,14 @@ impl Disk { pub fn partitions(&mut self) -> Result> { let block_size = self.block_size().to_u64(); - let mut disk = gpt_disk_io::Disk::new(self).map_err(|e| Error::Generic(e.to_string()))?; + let mut disk = gpt_disk_io::Disk::new(self)?; let mut buf = [0; 1 << 14]; - let header = disk - .read_primary_gpt_header(&mut buf) - .map_err(|e| Error::Generic(e.to_string()))?; + let header = disk.read_primary_gpt_header(&mut buf)?; // TODO(veluca): bubble up this error. - let part_array_layout = header - .get_partition_entry_array_layout() - .map_err(|e| Error::Generic(e.to_string()))?; + let part_array_layout = header.get_partition_entry_array_layout()?; let mut buf = [0; 1 << 14]; let x = disk - .gpt_partition_entry_array_iter(part_array_layout, &mut buf) - .map_err(|e| Error::Generic(e.to_string()))? + .gpt_partition_entry_array_iter(part_array_layout, &mut buf)? .filter_map(|part| { let part = if let Err(err) = part { return Some(Err(err)); @@ -201,8 +193,7 @@ impl Disk { None } }) - .collect::>() - .map_err(|e| Error::Generic(e.to_string()))?; + .collect::>()?; Ok(x) } diff --git a/pixie-uefi/src/os/error.rs b/pixie-uefi/src/os/error.rs index 9c010c22..cc1acaff 100644 --- a/pixie-uefi/src/os/error.rs +++ b/pixie-uefi/src/os/error.rs @@ -1,31 +1,39 @@ use alloc::{borrow::ToOwned, string::String}; use core::fmt::{Display, Formatter}; -use derive_more::From; -use smoltcp::socket::{ - tcp::{self, ConnectError, RecvError}, - udp::{self, BindError}, -}; +use gpt_disk_io::gpt_disk_types; pub type Result = core::result::Result; -#[derive(Debug, From)] -pub enum Error { - Connect(#[from] ConnectError), - TcpSend(#[from] tcp::SendError), - UdpSend(#[from] udp::SendError), - Recv(#[from] RecvError), - Bind(#[from] BindError), - Postcard(#[from] postcard::Error), - Uefi(#[from] uefi::Error), - Generic(String), -} +#[derive(Debug)] +pub struct Error(pub String); impl Error { pub fn msg(s: &str) -> Error { - Error::Generic(s.to_owned()) + Self(s.to_owned()) } } +macro_rules! err { + ($ty: ty) => { + impl From<$ty> for Error { + fn from(value: $ty) -> Self { + Self(format!("{}: {value}", stringify!($ty))) + } + } + }; +} + +err!(uefi::Error); +err!(smoltcp::socket::tcp::ConnectError); +err!(smoltcp::socket::tcp::RecvError); +err!(smoltcp::socket::tcp::SendError); +err!(smoltcp::socket::udp::BindError); +err!(smoltcp::socket::udp::SendError); +err!(postcard::Error); +err!(lz4_flex::block::DecompressError); +err!(gpt_disk_io::DiskError); +err!(gpt_disk_types::GptPartitionEntrySizeError); + impl Display for Error { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { write!(fmt, "{self:?}") diff --git a/pixie-uefi/src/os/mod.rs b/pixie-uefi/src/os/mod.rs index cb24f3e9..d9a6ade4 100644 --- a/pixie-uefi/src/os/mod.rs +++ b/pixie-uefi/src/os/mod.rs @@ -340,7 +340,7 @@ impl UefiOS { let mut name_buf = vec![0u16; name.len() * 2 + 16]; let name = CStr16::from_str_with_buf(name, &mut name_buf).unwrap(); let (var, attrs) = uefi::runtime::get_variable_boxed(name, vendor) - .map_err(|e| Error::Generic(format!("Error getting variable: {e:?}")))?; + .map_err(|e| Error(format!("Error getting variable: {e:?}")))?; Ok((var.to_vec(), attrs)) } @@ -355,7 +355,7 @@ impl UefiOS { let mut name_buf = vec![0u16; name.len() * 2 + 16]; let name = CStr16::from_str_with_buf(name, &mut name_buf).unwrap(); uefi::runtime::set_variable(name, vendor, attrs, data) - .map_err(|e| Error::Generic(format!("Error setting variable: {e:?}")))?; + .map_err(|e| Error(format!("Error setting variable: {e:?}")))?; Ok(()) } diff --git a/pixie-uefi/src/os/net.rs b/pixie-uefi/src/os/net.rs index cce285f5..e69e30c6 100644 --- a/pixie-uefi/src/os/net.rs +++ b/pixie-uefi/src/os/net.rs @@ -341,7 +341,7 @@ impl TcpStream { let socket = net.socket_set.get_mut::(self.handle); let sent = socket.send_slice(&data[pos..]); if let Err(err) = sent { - return Poll::Ready(Err(Error::TcpSend(err))); + return Poll::Ready(Err(err.into())); } pos += sent.unwrap(); if pos < data.len() { @@ -374,7 +374,7 @@ impl TcpStream { return Poll::Ready(Ok(0)); } if let Err(err) = recvd { - return Poll::Ready(Err(Error::Recv(err))); + return Poll::Ready(Err(err.into())); } if recvd.unwrap() == 0 { socket.register_recv_waker(cx.waker()); diff --git a/pixie-uefi/src/parse_disk/ntfs.rs b/pixie-uefi/src/parse_disk/ntfs.rs index 50c8c8f1..207e4a8e 100644 --- a/pixie-uefi/src/parse_disk/ntfs.rs +++ b/pixie-uefi/src/parse_disk/ntfs.rs @@ -1,9 +1,6 @@ use super::{le16, le32, le64}; use crate::{ - os::{ - disk::Disk, - error::{Error, Result}, - }, + os::{disk::Disk, error::Result}, store::ChunkInfo, }; use alloc::vec::Vec; @@ -42,8 +39,7 @@ pub async fn get_ntfs_chunks(disk: &Disk, start: u64, end: u64) -> Result