Skip to content

Commit d292040

Browse files
authored
Rollup merge of #139254 - Ayush1325:uefi-tcp4-connect, r=joboet
std: sys: net: uefi: Implement TCP4 connect - Implement TCP4 connect using EFI_TCP4_PROTOCOL. - Tested on QEMU setup with connecting to TCP server on host.
2 parents 334d7bd + e21aab5 commit d292040

4 files changed

Lines changed: 178 additions & 30 deletions

File tree

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

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,117 +4,120 @@ use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
44
usecrate::sys::unsupported;
55
usecrate::time::Duration;
66

7-
pubstructTcpStream(!);
7+
mod tcp;
8+
pub(crate)mod tcp4;
9+
10+
pubstructTcpStream(#[expect(dead_code)] tcp::Tcp);
811

912
implTcpStream{
10-
pubfnconnect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream>{
11-
unsupported()
13+
pubfnconnect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream>{
14+
tcp::Tcp::connect(addr?).map(Self)
1215
}
1316

1417
pubfnconnect_timeout(_:&SocketAddr, _:Duration) -> io::Result<TcpStream>{
1518
unsupported()
1619
}
1720

1821
pubfnset_read_timeout(&self, _:Option<Duration>) -> io::Result<()>{
19-
self.0
22+
unsupported()
2023
}
2124

2225
pubfnset_write_timeout(&self, _:Option<Duration>) -> io::Result<()>{
23-
self.0
26+
unsupported()
2427
}
2528

2629
pubfnread_timeout(&self) -> io::Result<Option<Duration>>{
27-
self.0
30+
unsupported()
2831
}
2932

3033
pubfnwrite_timeout(&self) -> io::Result<Option<Duration>>{
31-
self.0
34+
unsupported()
3235
}
3336

3437
pubfnpeek(&self, _:&mut[u8]) -> io::Result<usize>{
35-
self.0
38+
unsupported()
3639
}
3740

3841
pubfnread(&self, _:&mut[u8]) -> io::Result<usize>{
39-
self.0
42+
unsupported()
4043
}
4144

4245
pubfnread_buf(&self,_buf:BorrowedCursor<'_>) -> io::Result<()>{
43-
self.0
46+
unsupported()
4447
}
4548

4649
pubfnread_vectored(&self, _:&mut[IoSliceMut<'_>]) -> io::Result<usize>{
47-
self.0
50+
unsupported()
4851
}
4952

5053
pubfnis_read_vectored(&self) -> bool{
51-
self.0
54+
false
5255
}
5356

5457
pubfnwrite(&self, _:&[u8]) -> io::Result<usize>{
55-
self.0
58+
unsupported()
5659
}
5760

5861
pubfnwrite_vectored(&self, _:&[IoSlice<'_>]) -> io::Result<usize>{
59-
self.0
62+
unsupported()
6063
}
6164

6265
pubfnis_write_vectored(&self) -> bool{
63-
self.0
66+
false
6467
}
6568

6669
pubfnpeer_addr(&self) -> io::Result<SocketAddr>{
67-
self.0
70+
unsupported()
6871
}
6972

7073
pubfnsocket_addr(&self) -> io::Result<SocketAddr>{
71-
self.0
74+
unsupported()
7275
}
7376

7477
pubfnshutdown(&self, _:Shutdown) -> io::Result<()>{
75-
self.0
78+
unsupported()
7679
}
7780

7881
pubfnduplicate(&self) -> io::Result<TcpStream>{
79-
self.0
82+
unsupported()
8083
}
8184

8285
pubfnset_linger(&self, _:Option<Duration>) -> io::Result<()>{
83-
self.0
86+
unsupported()
8487
}
8588

8689
pubfnlinger(&self) -> io::Result<Option<Duration>>{
87-
self.0
90+
unsupported()
8891
}
8992

9093
pubfnset_nodelay(&self, _:bool) -> io::Result<()>{
91-
self.0
94+
unsupported()
9295
}
9396

9497
pubfnnodelay(&self) -> io::Result<bool>{
95-
self.0
98+
unsupported()
9699
}
97100

98101
pubfnset_ttl(&self, _:u32) -> io::Result<()>{
99-
self.0
102+
unsupported()
100103
}
101104

102105
pubfnttl(&self) -> io::Result<u32>{
103-
self.0
106+
unsupported()
104107
}
105108

106109
pubfntake_error(&self) -> io::Result<Option<io::Error>>{
107-
self.0
110+
unsupported()
108111
}
109112

110113
pubfnset_nonblocking(&self, _:bool) -> io::Result<()>{
111-
self.0
114+
unsupported()
112115
}
113116
}
114117

115118
impl fmt::DebugforTcpStream{
116119
fnfmt(&self,_f:&mut fmt::Formatter<'_>) -> fmt::Result{
117-
self.0
120+
todo!()
118121
}
119122
}
120123

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
usesuper::tcp4;
2+
usecrate::io;
3+
usecrate::net::SocketAddr;
4+
5+
pub(crate)enumTcp{
6+
V4(#[expect(dead_code)] tcp4::Tcp4),
7+
}
8+
9+
implTcp{
10+
pub(crate)fnconnect(addr:&SocketAddr) -> io::Result<Self>{
11+
match addr {
12+
SocketAddr::V4(x) => {
13+
let temp = tcp4::Tcp4::new()?;
14+
temp.configure(true,Some(x),None)?;
15+
temp.connect()?;
16+
Ok(Tcp::V4(temp))
17+
}
18+
SocketAddr::V6(_) => todo!(),
19+
}
20+
}
21+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
use r_efi::efi::{self,Status};
2+
use r_efi::protocols::tcp4;
3+
4+
usecrate::io;
5+
usecrate::net::SocketAddrV4;
6+
usecrate::ptr::NonNull;
7+
usecrate::sync::atomic::{AtomicBool,Ordering};
8+
usecrate::sys::pal::helpers;
9+
10+
constTYPE_OF_SERVICE:u8 = 8;
11+
constTIME_TO_LIVE:u8 = 255;
12+
13+
pub(crate)structTcp4{
14+
protocol:NonNull<tcp4::Protocol>,
15+
flag:AtomicBool,
16+
#[expect(dead_code)]
17+
service_binding: helpers::ServiceProtocol,
18+
}
19+
20+
constDEFAULT_ADDR: efi::Ipv4Address = efi::Ipv4Address{addr:[0u8;4]};
21+
22+
implTcp4{
23+
pub(crate)fnnew() -> io::Result<Self>{
24+
let service_binding = helpers::ServiceProtocol::open(tcp4::SERVICE_BINDING_PROTOCOL_GUID)?;
25+
let protocol = helpers::open_protocol(service_binding.child_handle(), tcp4::PROTOCOL_GUID)?;
26+
27+
Ok(Self{ service_binding, protocol,flag:AtomicBool::new(false)})
28+
}
29+
30+
pub(crate)fnconfigure(
31+
&self,
32+
active:bool,
33+
remote_address:Option<&SocketAddrV4>,
34+
station_address:Option<&SocketAddrV4>,
35+
) -> io::Result<()>{
36+
let protocol = self.protocol.as_ptr();
37+
38+
let(remote_address, remote_port) = ifletSome(x) = remote_address {
39+
(helpers::ipv4_to_r_efi(*x.ip()), x.port())
40+
}else{
41+
(DEFAULT_ADDR,0)
42+
};
43+
44+
// FIXME: Remove when passive connections with proper subnet handling are added
45+
assert!(station_address.is_none());
46+
let use_default_address = efi::Boolean::TRUE;
47+
let(station_address, station_port) = (DEFAULT_ADDR,0);
48+
let subnet_mask = helpers::ipv4_to_r_efi(crate::net::Ipv4Addr::new(0,0,0,0));
49+
50+
letmut config_data = tcp4::ConfigData{
51+
type_of_service:TYPE_OF_SERVICE,
52+
time_to_live:TIME_TO_LIVE,
53+
access_point: tcp4::AccessPoint{
54+
use_default_address,
55+
remote_address,
56+
remote_port,
57+
active_flag: active.into(),
58+
station_address,
59+
station_port,
60+
subnet_mask,
61+
},
62+
control_option:crate::ptr::null_mut(),
63+
};
64+
65+
let r = unsafe{((*protocol).configure)(protocol,&mut config_data)};
66+
if r.is_error(){Err(crate::io::Error::from_raw_os_error(r.as_usize()))}else{Ok(())}
67+
}
68+
69+
pub(crate)fnconnect(&self) -> io::Result<()>{
70+
let evt = unsafe{self.create_evt()}?;
71+
let completion_token =
72+
tcp4::CompletionToken{event: evt.as_ptr(),status:Status::SUCCESS};
73+
74+
let protocol = self.protocol.as_ptr();
75+
letmut conn_token = tcp4::ConnectionToken{ completion_token };
76+
77+
let r = unsafe{((*protocol).connect)(protocol,&mut conn_token)};
78+
if r.is_error(){
79+
returnErr(io::Error::from_raw_os_error(r.as_usize()));
80+
}
81+
82+
self.wait_for_flag();
83+
84+
if completion_token.status.is_error(){
85+
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
86+
}else{
87+
Ok(())
88+
}
89+
}
90+
91+
unsafefncreate_evt(&self) -> io::Result<helpers::OwnedEvent>{
92+
self.flag.store(false,Ordering::Relaxed);
93+
helpers::OwnedEvent::new(
94+
efi::EVT_NOTIFY_SIGNAL,
95+
efi::TPL_CALLBACK,
96+
Some(toggle_atomic_flag),
97+
Some(unsafe{NonNull::new_unchecked(self.flag.as_ptr().cast())}),
98+
)
99+
}
100+
101+
fnwait_for_flag(&self){
102+
while !self.flag.load(Ordering::Relaxed){
103+
let _ = self.poll();
104+
}
105+
}
106+
107+
fnpoll(&self) -> io::Result<()>{
108+
let protocol = self.protocol.as_ptr();
109+
let r = unsafe{((*protocol).poll)(protocol)};
110+
111+
if r.is_error(){Err(io::Error::from_raw_os_error(r.as_usize()))}else{Ok(())}
112+
}
113+
}
114+
115+
extern"efiapi"fntoggle_atomic_flag(_: r_efi::efi::Event,ctx:*mutcrate::ffi::c_void){
116+
let flag = unsafe{AtomicBool::from_ptr(ctx.cast())};
117+
flag.store(true,Ordering::Relaxed);
118+
}

‎library/std/src/sys/pal/uefi/helpers.rs‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,6 @@ pub(crate) struct ServiceProtocol {
653653
}
654654

655655
implServiceProtocol{
656-
#[expect(dead_code)]
657656
pub(crate)fnopen(service_guid: r_efi::efi::Guid) -> io::Result<Self>{
658657
let handles = locate_handles(service_guid)?;
659658

@@ -670,7 +669,6 @@ impl ServiceProtocol {
670669
Err(io::const_error!(io::ErrorKind::NotFound,"no service binding protocol found"))
671670
}
672671

673-
#[expect(dead_code)]
674672
pub(crate)fnchild_handle(&self) -> NonNull<crate::ffi::c_void>{
675673
self.child_handle
676674
}
@@ -732,6 +730,10 @@ impl OwnedEvent {
732730
}
733731
}
734732

733+
pub(crate)fnas_ptr(&self) -> efi::Event{
734+
self.0.as_ptr()
735+
}
736+
735737
pub(crate)fninto_raw(self) -> *mutcrate::ffi::c_void{
736738
let r = self.0.as_ptr();
737739
crate::mem::forget(self);
@@ -755,3 +757,7 @@ impl Drop for OwnedEvent {
755757
}
756758
}
757759
}
760+
761+
pub(crate)constfnipv4_to_r_efi(addr:crate::net::Ipv4Addr) -> efi::Ipv4Address{
762+
efi::Ipv4Address{addr: addr.octets()}
763+
}

0 commit comments

Comments
 (0)