11use r_efi:: efi:: { self , Status } ;
22use r_efi:: protocols:: tcp4;
33
4- use crate :: io:: { self , IoSlice } ;
4+ use crate :: io:: { self , IoSlice , IoSliceMut } ;
55use crate :: net:: SocketAddrV4 ;
66use crate :: ptr:: NonNull ;
77use 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