Skip to content

Commit 3435207

Browse files
authored
Unrolled build for #149134
Rollup merge of #149134 - Ayush1325:uefi-tcp4-vector, r=joboet std: sys: net: uefi: Implement read_vectored - Basically a copy of write_vectored [0] - Tested on QEMU ovmf. [0]: #146301
2 parents 5f7653d + 3f08502 commit 3435207

File tree

3 files changed

+69
-16
lines changed

3 files changed

+69
-16
lines changed

library/std/src/sys/net/connection/uefi/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,11 @@ impl TcpStream {
6969
}
7070

7171
pub fn read_vectored(&self, buf: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
72-
// FIXME: UEFI does support vectored read, so implement that.
73-
crate::io::default_read_vectored(|b| self.read(b), buf)
72+
self.inner.read_vectored(buf, self.read_timeout()?)
7473
}
7574

7675
pub fn is_read_vectored(&self) -> bool {
77-
false
76+
true
7877
}
7978

8079
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {

library/std/src/sys/net/connection/uefi/tcp.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::tcp4;
2-
use crate::io::{self, IoSlice};
2+
use crate::io::{self, IoSlice, IoSliceMut};
33
use crate::net::SocketAddr;
44
use crate::ptr::NonNull;
55
use crate::sys::{helpers, unsupported};
@@ -44,6 +44,16 @@ impl Tcp {
4444
}
4545
}
4646

47+
pub(crate) fn read_vectored(
48+
&self,
49+
buf: &mut [IoSliceMut<'_>],
50+
timeout: Option<Duration>,
51+
) -> io::Result<usize> {
52+
match self {
53+
Self::V4(client) => client.read_vectored(buf, timeout),
54+
}
55+
}
56+
4757
pub(crate) fn ttl(&self) -> io::Result<u32> {
4858
match self {
4959
Self::V4(client) => client.get_mode_data().map(|x| x.time_to_live.into()),

library/std/src/sys/net/connection/uefi/tcp4.rs

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use r_efi::efi::{self, Status};
22
use r_efi::protocols::tcp4;
33

4-
use crate::io::{self, IoSlice};
4+
use crate::io::{self, IoSlice, IoSliceMut};
55
use crate::net::SocketAddrV4;
66
use crate::ptr::NonNull;
77
use crate::sync::atomic::{AtomicBool, Ordering};
@@ -193,30 +193,74 @@ impl Tcp4 {
193193
}
194194

195195
pub(crate) fn read(&self, buf: &mut [u8], timeout: Option<Duration>) -> io::Result<usize> {
196-
let evt = unsafe { self.create_evt() }?;
197-
let completion_token =
198-
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
199196
let data_len = u32::try_from(buf.len()).unwrap_or(u32::MAX);
200197

201198
let fragment = tcp4::FragmentData {
202199
fragment_length: data_len,
203200
fragment_buffer: buf.as_mut_ptr().cast::<crate::ffi::c_void>(),
204201
};
205-
let mut tx_data = tcp4::ReceiveData {
202+
let mut rx_data = tcp4::ReceiveData {
206203
urgent_flag: r_efi::efi::Boolean::FALSE,
207204
data_length: data_len,
208205
fragment_count: 1,
209206
fragment_table: [fragment],
210207
};
211208

212-
let protocol = self.protocol.as_ptr();
213-
let mut token = tcp4::IoToken {
214-
completion_token,
215-
packet: tcp4::IoTokenPacket {
216-
rx_data: (&raw mut tx_data).cast::<tcp4::ReceiveData<0>>(),
217-
},
209+
self.read_inner((&raw mut rx_data).cast(), timeout).map(|_| data_len as usize)
210+
}
211+
212+
pub(crate) fn read_vectored(
213+
&self,
214+
buf: &[IoSliceMut<'_>],
215+
timeout: Option<Duration>,
216+
) -> io::Result<usize> {
217+
let mut data_length = 0u32;
218+
let mut fragment_count = 0u32;
219+
220+
// Calculate how many IoSlice in buf can be transmitted.
221+
for i in buf {
222+
// IoSlice length is always <= u32::MAX in UEFI.
223+
match data_length.checked_add(u32::try_from(i.len()).expect("value is stored as a u32"))
224+
{
225+
Some(x) => data_length = x,
226+
None => break,
227+
}
228+
fragment_count += 1;
229+
}
230+
231+
let rx_data_size = size_of::<tcp4::ReceiveData<0>>()
232+
+ size_of::<tcp4::FragmentData>() * (fragment_count as usize);
233+
let mut rx_data = helpers::UefiBox::<tcp4::ReceiveData>::new(rx_data_size)?;
234+
rx_data.write(tcp4::ReceiveData {
235+
urgent_flag: r_efi::efi::Boolean::FALSE,
236+
data_length,
237+
fragment_count,
238+
fragment_table: [],
239+
});
240+
unsafe {
241+
// SAFETY: IoSlice and FragmentData are guaranteed to have same layout.
242+
crate::ptr::copy_nonoverlapping(
243+
buf.as_ptr().cast(),
244+
(*rx_data.as_mut_ptr()).fragment_table.as_mut_ptr(),
245+
fragment_count as usize,
246+
);
218247
};
219248

249+
self.read_inner(rx_data.as_mut_ptr(), timeout).map(|_| data_length as usize)
250+
}
251+
252+
pub(crate) fn read_inner(
253+
&self,
254+
rx_data: *mut tcp4::ReceiveData,
255+
timeout: Option<Duration>,
256+
) -> io::Result<()> {
257+
let evt = unsafe { self.create_evt() }?;
258+
let completion_token =
259+
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
260+
261+
let protocol = self.protocol.as_ptr();
262+
let mut token = tcp4::IoToken { completion_token, packet: tcp4::IoTokenPacket { rx_data } };
263+
220264
let r = unsafe { ((*protocol).receive)(protocol, &mut token) };
221265
if r.is_error() {
222266
return Err(io::Error::from_raw_os_error(r.as_usize()));
@@ -227,7 +271,7 @@ impl Tcp4 {
227271
if completion_token.status.is_error() {
228272
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
229273
} else {
230-
Ok(data_len as usize)
274+
Ok(())
231275
}
232276
}
233277

0 commit comments

Comments
 (0)