11use r_efi:: efi:: { self , Status } ;
22use r_efi:: protocols:: tcp4;
33
4- use crate :: io;
4+ use crate :: io:: { self , IoSlice } ;
55use crate :: net:: SocketAddrV4 ;
66use crate :: ptr:: NonNull ;
77use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
@@ -108,11 +108,7 @@ impl Tcp4 {
108108 }
109109
110110 pub ( crate ) fn write ( & self , buf : & [ u8 ] , timeout : Option < Duration > ) -> io:: Result < usize > {
111- let evt = unsafe { self . create_evt ( ) } ?;
112- let completion_token =
113- tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
114111 let data_len = u32:: try_from ( buf. len ( ) ) . unwrap_or ( u32:: MAX ) ;
115-
116112 let fragment = tcp4:: FragmentData {
117113 fragment_length : data_len,
118114 fragment_buffer : buf. as_ptr ( ) . cast :: < crate :: ffi:: c_void > ( ) . cast_mut ( ) ,
@@ -125,14 +121,57 @@ impl Tcp4 {
125121 fragment_table : [ fragment] ,
126122 } ;
127123
128- let protocol = self . protocol . as_ptr ( ) ;
129- let mut token = tcp4:: IoToken {
130- completion_token,
131- packet : tcp4:: IoTokenPacket {
132- tx_data : ( & raw mut tx_data) . cast :: < tcp4:: TransmitData < 0 > > ( ) ,
133- } ,
124+ self . write_inner ( ( & raw mut tx_data) . cast ( ) , timeout) . map ( |_| data_len as usize )
125+ }
126+
127+ pub ( crate ) fn write_vectored (
128+ & self ,
129+ buf : & [ IoSlice < ' _ > ] ,
130+ timeout : Option < Duration > ,
131+ ) -> io:: Result < usize > {
132+ let mut data_len = 0u32 ;
133+ let mut fragment_count = 0u32 ;
134+
135+ // Calculate how many IoSlice in buf can be transmitted.
136+ for i in buf {
137+ match data_len. checked_add ( i. as_slice ( ) . len ( ) as u32 ) {
138+ Some ( x) => data_len = x,
139+ None => break ,
140+ }
141+ fragment_count += 1 ;
142+ }
143+
144+ let tx_data_size = crate :: mem:: size_of :: < tcp4:: TransmitData < 0 > > ( )
145+ + crate :: mem:: size_of :: < tcp4:: FragmentData > ( ) * ( fragment_count as usize ) ;
146+ let mut tx_data = helpers:: UefiBox :: < tcp4:: TransmitData > :: new ( tx_data_size) ;
147+ unsafe {
148+ ( * tx_data. as_mut_ptr ( ) ) . push = r_efi:: efi:: Boolean :: FALSE ;
149+ ( * tx_data. as_mut_ptr ( ) ) . urgent = r_efi:: efi:: Boolean :: FALSE ;
150+ ( * tx_data. as_mut_ptr ( ) ) . data_length = data_len;
151+ ( * tx_data. as_mut_ptr ( ) ) . fragment_count = fragment_count;
152+ // SAFETY: IoSlice and FragmentData are guaranteed to have same layout.
153+ crate :: ptr:: copy_nonoverlapping (
154+ buf. as_ptr ( ) . cast ( ) ,
155+ ( * tx_data. as_mut_ptr ( ) ) . fragment_table . as_mut_ptr ( ) ,
156+ fragment_count as usize ,
157+ ) ;
134158 } ;
135159
160+ self . write_inner ( tx_data. as_mut_ptr ( ) , timeout) . map ( |_| data_len as usize )
161+ }
162+
163+ fn write_inner (
164+ & self ,
165+ tx_data : * mut tcp4:: TransmitData ,
166+ timeout : Option < Duration > ,
167+ ) -> io:: Result < ( ) > {
168+ let evt = unsafe { self . create_evt ( ) } ?;
169+ let completion_token =
170+ tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
171+
172+ let protocol = self . protocol . as_ptr ( ) ;
173+ let mut token = tcp4:: IoToken { completion_token, packet : tcp4:: IoTokenPacket { tx_data } } ;
174+
136175 let r = unsafe { ( ( * protocol) . transmit ) ( protocol, & mut token) } ;
137176 if r. is_error ( ) {
138177 return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
@@ -143,7 +182,7 @@ impl Tcp4 {
143182 if completion_token. status . is_error ( ) {
144183 Err ( io:: Error :: from_raw_os_error ( completion_token. status . as_usize ( ) ) )
145184 } else {
146- Ok ( data_len as usize )
185+ Ok ( ( ) )
147186 }
148187 }
149188
0 commit comments