From e9ebf1cfa64ec55ad5c97500102abcd1656965df Mon Sep 17 00:00:00 2001 From: Elia Soldati Date: Tue, 3 Mar 2026 13:12:27 +0100 Subject: [PATCH] Handle network media loss --- pixie-uefi/src/os/executor/mod.rs | 7 ++----- pixie-uefi/src/os/input.rs | 10 ++++++++++ pixie-uefi/src/os/mod.rs | 1 + pixie-uefi/src/os/net/interface.rs | 16 +++++++++++++++- pixie-uefi/src/os/ui.rs | 10 ++++++++++ pixie-uefi/src/os/util.rs | 7 +++++++ 6 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 pixie-uefi/src/os/util.rs diff --git a/pixie-uefi/src/os/executor/mod.rs b/pixie-uefi/src/os/executor/mod.rs index 7ea0bbc..0bd65a6 100644 --- a/pixie-uefi/src/os/executor/mod.rs +++ b/pixie-uefi/src/os/executor/mod.rs @@ -15,6 +15,7 @@ use futures::channel::oneshot; use spin::Mutex; use uefi::proto::console::text::Color; +use crate::os; use crate::os::executor::event::{Event, EventTrigger}; use crate::os::send_wrapper::SendWrapper; use crate::os::timer::Timer; @@ -239,11 +240,7 @@ impl Executor { let task = EXECUTOR.lock().ready_tasks.pop_front(); let Some(task) = task else { // If we don't have anything ready, sleep until the next interrupt. - // SAFETY: hlt is available on all reasonable x86 processors and has no safety - // requirements. - unsafe { - core::arch::asm!("hlt"); - } + os::util::hlt(); do_wake(true); continue; }; diff --git a/pixie-uefi/src/os/input.rs b/pixie-uefi/src/os/input.rs index ffb8208..1c752cd 100644 --- a/pixie-uefi/src/os/input.rs +++ b/pixie-uefi/src/os/input.rs @@ -3,6 +3,7 @@ use spin::Mutex; use uefi::boot::ScopedProtocol; use uefi::proto::console::text::{Input, Key}; +use crate::os; use crate::os::error::Result; use crate::os::executor::Executor; use crate::os::send_wrapper::SendWrapper; @@ -21,3 +22,12 @@ pub async fn read_key() -> Result { Executor::wait_for_interrupt().await; } } + +pub fn wait_for_key() -> Result<()> { + loop { + os::util::hlt(); + if INPUT.lock().read_key()?.is_some() { + return Ok(()); + } + } +} diff --git a/pixie-uefi/src/os/mod.rs b/pixie-uefi/src/os/mod.rs index c2093ad..db07ff1 100644 --- a/pixie-uefi/src/os/mod.rs +++ b/pixie-uefi/src/os/mod.rs @@ -22,6 +22,7 @@ pub mod net; mod send_wrapper; mod timer; pub mod ui; +pub mod util; static INITIALIZED: AtomicBool = AtomicBool::new(false); diff --git a/pixie-uefi/src/os/net/interface.rs b/pixie-uefi/src/os/net/interface.rs index 9ca40f8..0b7e6cc 100644 --- a/pixie-uefi/src/os/net/interface.rs +++ b/pixie-uefi/src/os/net/interface.rs @@ -6,6 +6,8 @@ use uefi::Status; use super::ETH_PACKET_SIZE; use crate::os::send_wrapper::SendWrapper; +use crate::os::{input, ui}; +use crate::power_control; type Snp = SendWrapper>; @@ -68,7 +70,19 @@ impl TxToken for SnpTxToken<'_> { snp.transmit(0, payload, None, None, None) .expect("Failed to transmit frame"); // Wait until sending is complete. - while snp.get_recycled_transmit_buffer_status().unwrap().is_none() {} + while snp.get_recycled_transmit_buffer_status().unwrap().is_none() { + if snp.mode().media_present.0 == 0 { + let err = uefi::boot::set_watchdog_timer(0, 0x10000, None); + if let Err(err) = err { + if err.status() != Status::UNSUPPORTED { + log::error!("Error disabling watchdog: {err:?}"); + } + } + ui::red_screen(); + input::wait_for_key().expect("Failed to wait for input"); + power_control::reset(); + } + } ret } } diff --git a/pixie-uefi/src/os/ui.rs b/pixie-uefi/src/os/ui.rs index ae69ac8..b275602 100644 --- a/pixie-uefi/src/os/ui.rs +++ b/pixie-uefi/src/os/ui.rs @@ -307,3 +307,13 @@ pub fn update_content(f: F) { .try_lock() .expect("content draw area is locked")); } + +pub fn red_screen() { + let mut s = SCREEN.lock(); + s.back_buffer.fill(ScreenChar { + c: ' '.try_into().unwrap(), + fg: Color::Red, + bg: Color::Red, + }); + s.flush(); +} diff --git a/pixie-uefi/src/os/util.rs b/pixie-uefi/src/os/util.rs new file mode 100644 index 0000000..bacdf2f --- /dev/null +++ b/pixie-uefi/src/os/util.rs @@ -0,0 +1,7 @@ +pub fn hlt() { + // SAFETY: hlt is available on all reasonable x86 processors and has no safety + // requirements. + unsafe { + core::arch::asm!("hlt"); + } +}