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,63 @@ 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_length = 0u32 ;
133+ let mut fragment_count = 0u32 ;
134+
135+ // Calculate how many IoSlice in buf can be transmitted.
136+ for i in buf {
137+ // IoSlice length is always <= u32::MAX in UEFI.
138+ match data_length
139+ . checked_add ( u32:: try_from ( i. as_slice ( ) . len ( ) ) . expect ( "value is stored as a u32" ) )
140+ {
141+ Some ( x) => data_length = x,
142+ None => break ,
143+ }
144+ fragment_count += 1 ;
145+ }
146+
147+ let tx_data_size = size_of :: < tcp4:: TransmitData < 0 > > ( )
148+ + size_of :: < tcp4:: FragmentData > ( ) * ( fragment_count as usize ) ;
149+ let mut tx_data = helpers:: UefiBox :: < tcp4:: TransmitData > :: new ( tx_data_size) ?;
150+ tx_data. write ( tcp4:: TransmitData {
151+ push : r_efi:: efi:: Boolean :: FALSE ,
152+ urgent : r_efi:: efi:: Boolean :: FALSE ,
153+ data_length,
154+ fragment_count,
155+ fragment_table : [ ] ,
156+ } ) ;
157+ unsafe {
158+ // SAFETY: IoSlice and FragmentData are guaranteed to have same layout.
159+ crate :: ptr:: copy_nonoverlapping (
160+ buf. as_ptr ( ) . cast ( ) ,
161+ ( * tx_data. as_mut_ptr ( ) ) . fragment_table . as_mut_ptr ( ) ,
162+ fragment_count as usize ,
163+ ) ;
134164 } ;
135165
166+ self . write_inner ( tx_data. as_mut_ptr ( ) , timeout) . map ( |_| data_length as usize )
167+ }
168+
169+ fn write_inner (
170+ & self ,
171+ tx_data : * mut tcp4:: TransmitData ,
172+ timeout : Option < Duration > ,
173+ ) -> io:: Result < ( ) > {
174+ let evt = unsafe { self . create_evt ( ) } ?;
175+ let completion_token =
176+ tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
177+
178+ let protocol = self . protocol . as_ptr ( ) ;
179+ let mut token = tcp4:: IoToken { completion_token, packet : tcp4:: IoTokenPacket { tx_data } } ;
180+
136181 let r = unsafe { ( ( * protocol) . transmit ) ( protocol, & mut token) } ;
137182 if r. is_error ( ) {
138183 return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
@@ -143,7 +188,7 @@ impl Tcp4 {
143188 if completion_token. status . is_error ( ) {
144189 Err ( io:: Error :: from_raw_os_error ( completion_token. status . as_usize ( ) ) )
145190 } else {
146- Ok ( data_len as usize )
191+ Ok ( ( ) )
147192 }
148193 }
149194
0 commit comments