|
1 | 1 | use r_efi::efi::{self, Status}; |
2 | 2 | use r_efi::protocols::tcp4; |
3 | 3 |
|
4 | | -use crate::io; |
| 4 | +use crate::io::{self, IoSlice}; |
5 | 5 | use crate::net::SocketAddrV4; |
6 | 6 | use crate::ptr::NonNull; |
7 | 7 | use crate::sync::atomic::{AtomicBool, Ordering}; |
@@ -147,6 +147,62 @@ impl Tcp4 { |
147 | 147 | } |
148 | 148 | } |
149 | 149 |
|
| 150 | + pub(crate) fn write_vectored( |
| 151 | + &self, |
| 152 | + buf: &[IoSlice<'_>], |
| 153 | + timeout: Option<Duration>, |
| 154 | + ) -> io::Result<usize> { |
| 155 | + let evt = unsafe { self.create_evt() }?; |
| 156 | + let completion_token = |
| 157 | + tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS }; |
| 158 | + let mut data_len = 0u32; |
| 159 | + let mut fragment_count = 0u32; |
| 160 | + |
| 161 | + // Calculate how many IoSlice in buf can be transmitted. |
| 162 | + for i in buf { |
| 163 | + match data_len.checked_add(i.as_slice().len() as u32) { |
| 164 | + Some(x) => data_len = x, |
| 165 | + None => break, |
| 166 | + } |
| 167 | + fragment_count += 1; |
| 168 | + } |
| 169 | + |
| 170 | + let tx_data_size = crate::mem::size_of::<tcp4::TransmitData<0>>() |
| 171 | + + crate::mem::size_of::<tcp4::FragmentData>() * (fragment_count as usize); |
| 172 | + let mut tx_data = helpers::UefiBox::<tcp4::TransmitData>::new(tx_data_size); |
| 173 | + unsafe { |
| 174 | + (*tx_data.as_mut_ptr()).push = r_efi::efi::Boolean::FALSE; |
| 175 | + (*tx_data.as_mut_ptr()).urgent = r_efi::efi::Boolean::FALSE; |
| 176 | + (*tx_data.as_mut_ptr()).data_length = data_len; |
| 177 | + (*tx_data.as_mut_ptr()).fragment_count = fragment_count; |
| 178 | + // SAFETY: IoSlice and FragmentData are guaranteed to have same layout. |
| 179 | + crate::ptr::copy_nonoverlapping( |
| 180 | + buf.as_ptr().cast(), |
| 181 | + (*tx_data.as_mut_ptr()).fragment_table.as_mut_ptr(), |
| 182 | + fragment_count as usize, |
| 183 | + ); |
| 184 | + }; |
| 185 | + |
| 186 | + let protocol = self.protocol.as_ptr(); |
| 187 | + let mut token = tcp4::IoToken { |
| 188 | + completion_token, |
| 189 | + packet: tcp4::IoTokenPacket { tx_data: tx_data.as_mut_ptr() }, |
| 190 | + }; |
| 191 | + |
| 192 | + let r = unsafe { ((*protocol).transmit)(protocol, &mut token) }; |
| 193 | + if r.is_error() { |
| 194 | + return Err(io::Error::from_raw_os_error(r.as_usize())); |
| 195 | + } |
| 196 | + |
| 197 | + unsafe { self.wait_or_cancel(timeout, &mut token.completion_token) }?; |
| 198 | + |
| 199 | + if completion_token.status.is_error() { |
| 200 | + Err(io::Error::from_raw_os_error(completion_token.status.as_usize())) |
| 201 | + } else { |
| 202 | + Ok(data_len as usize) |
| 203 | + } |
| 204 | + } |
| 205 | + |
150 | 206 | pub(crate) fn read(&self, buf: &mut [u8], timeout: Option<Duration>) -> io::Result<usize> { |
151 | 207 | let evt = unsafe { self.create_evt() }?; |
152 | 208 | let completion_token = |
|
0 commit comments