diff --git a/library/std/src/sys/net/connection/uefi/mod.rs b/library/std/src/sys/net/connection/uefi/mod.rs index 46d67c8e51019..dce044f21b49a 100644 --- a/library/std/src/sys/net/connection/uefi/mod.rs +++ b/library/std/src/sys/net/connection/uefi/mod.rs @@ -7,7 +7,7 @@ use crate::time::Duration; mod tcp; pub(crate) mod tcp4; -pub struct TcpStream(#[expect(dead_code)] tcp::Tcp); +pub struct TcpStream(tcp::Tcp); impl TcpStream { pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result { @@ -54,12 +54,13 @@ impl TcpStream { false } - pub fn write(&self, _: &[u8]) -> io::Result { - unsupported() + pub fn write(&self, buf: &[u8]) -> io::Result { + self.0.write(buf) } - pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result { - unsupported() + pub fn write_vectored(&self, buf: &[IoSlice<'_>]) -> io::Result { + // FIXME: UEFI does support vectored write, so implment that. + crate::io::default_write_vectored(|b| self.write(b), buf) } pub fn is_write_vectored(&self) -> bool { diff --git a/library/std/src/sys/net/connection/uefi/tcp.rs b/library/std/src/sys/net/connection/uefi/tcp.rs index f87accdc41de8..9c3462e3468cd 100644 --- a/library/std/src/sys/net/connection/uefi/tcp.rs +++ b/library/std/src/sys/net/connection/uefi/tcp.rs @@ -3,7 +3,7 @@ use crate::io; use crate::net::SocketAddr; pub(crate) enum Tcp { - V4(#[expect(dead_code)] tcp4::Tcp4), + V4(tcp4::Tcp4), } impl Tcp { @@ -18,4 +18,10 @@ impl Tcp { SocketAddr::V6(_) => todo!(), } } + + pub(crate) fn write(&self, buf: &[u8]) -> io::Result { + match self { + Self::V4(client) => client.write(buf), + } + } } diff --git a/library/std/src/sys/net/connection/uefi/tcp4.rs b/library/std/src/sys/net/connection/uefi/tcp4.rs index f7ca373b52b5a..98751606212fa 100644 --- a/library/std/src/sys/net/connection/uefi/tcp4.rs +++ b/library/std/src/sys/net/connection/uefi/tcp4.rs @@ -88,6 +88,44 @@ impl Tcp4 { } } + pub(crate) fn write(&self, buf: &[u8]) -> io::Result { + let evt = unsafe { self.create_evt() }?; + let completion_token = + tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS }; + let data_len = crate::cmp::min(u32::MAX as u64, buf.len() as u64) as u32; + + let fragment = tcp4::FragmentData { + fragment_length: data_len, + fragment_buffer: buf.as_ptr() as *mut _, + }; + let mut tx_data = tcp4::TransmitData { + push: r_efi::efi::Boolean::FALSE, + urgent: r_efi::efi::Boolean::FALSE, + data_length: data_len, + fragment_count: 1, + fragment_table: [fragment], + }; + + let protocol = self.protocol.as_ptr(); + let mut token = tcp4::IoToken { + completion_token, + packet: tcp4::IoTokenPacket { tx_data: &mut tx_data as *mut _ as *mut _ }, + }; + + let r = unsafe { ((*protocol).transmit)(protocol, &mut token) }; + if r.is_error() { + return Err(io::Error::from_raw_os_error(r.as_usize())); + } + + self.wait_for_flag(); + + if completion_token.status.is_error() { + Err(io::Error::from_raw_os_error(completion_token.status.as_usize())) + } else { + Ok(data_len as usize) + } + } + unsafe fn create_evt(&self) -> io::Result { self.flag.store(false, Ordering::Relaxed); helpers::OwnedEvent::new(