hermit/fd/
stdio.rs

1use alloc::boxed::Box;
2use core::future;
3use core::mem::MaybeUninit;
4use core::task::Poll;
5
6use async_trait::async_trait;
7use uhyve_interface::parameters::WriteParams;
8use uhyve_interface::{GuestVirtAddr, Hypercall};
9use zerocopy::IntoBytes;
10
11use crate::console::CONSOLE;
12use crate::fd::{ObjectInterface, PollEvent, STDERR_FILENO, STDOUT_FILENO};
13use crate::io;
14use crate::syscalls::interfaces::uhyve_hypercall;
15
16#[derive(Debug)]
17pub struct GenericStdin;
18
19#[async_trait]
20impl ObjectInterface for GenericStdin {
21	async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
22		let available = if CONSOLE.lock().is_empty() {
23			PollEvent::empty()
24		} else {
25			PollEvent::POLLIN | PollEvent::POLLRDNORM | PollEvent::POLLRDBAND
26		};
27
28		Ok(event & available)
29	}
30
31	async fn read(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
32		future::poll_fn(|cx| {
33			let mut read_bytes = 0;
34			let mut guard = CONSOLE.lock();
35
36			while let Some(byte) = guard.read() {
37				let c = unsafe { char::from_u32_unchecked(byte.into()) };
38				guard.write(c.as_bytes());
39
40				buf[read_bytes].write(byte);
41				read_bytes += 1;
42
43				if read_bytes >= buf.len() {
44					return Poll::Ready(Ok(read_bytes));
45				}
46			}
47
48			if read_bytes > 0 {
49				Poll::Ready(Ok(read_bytes))
50			} else {
51				guard.register_waker(cx.waker());
52				Poll::Pending
53			}
54		})
55		.await
56	}
57
58	async fn isatty(&self) -> io::Result<bool> {
59		Ok(true)
60	}
61}
62
63impl GenericStdin {
64	pub const fn new() -> Self {
65		Self {}
66	}
67}
68
69#[derive(Debug)]
70pub struct GenericStdout;
71
72#[async_trait]
73impl ObjectInterface for GenericStdout {
74	async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
75		let available = PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND;
76		Ok(event & available)
77	}
78
79	async fn write(&self, buf: &[u8]) -> io::Result<usize> {
80		CONSOLE.lock().write(buf);
81		Ok(buf.len())
82	}
83
84	async fn isatty(&self) -> io::Result<bool> {
85		Ok(true)
86	}
87}
88
89impl GenericStdout {
90	pub const fn new() -> Self {
91		Self {}
92	}
93}
94
95#[derive(Debug)]
96pub struct GenericStderr;
97
98#[async_trait]
99impl ObjectInterface for GenericStderr {
100	async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
101		let available = PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND;
102		Ok(event & available)
103	}
104
105	async fn write(&self, buf: &[u8]) -> io::Result<usize> {
106		CONSOLE.lock().write(buf);
107		Ok(buf.len())
108	}
109
110	async fn isatty(&self) -> io::Result<bool> {
111		Ok(true)
112	}
113}
114
115impl GenericStderr {
116	pub const fn new() -> Self {
117		Self {}
118	}
119}
120
121#[derive(Debug)]
122pub struct UhyveStdin;
123
124#[async_trait]
125impl ObjectInterface for UhyveStdin {
126	async fn isatty(&self) -> io::Result<bool> {
127		Ok(true)
128	}
129}
130
131impl UhyveStdin {
132	pub const fn new() -> Self {
133		Self {}
134	}
135}
136
137#[derive(Debug)]
138pub struct UhyveStdout;
139
140#[async_trait]
141impl ObjectInterface for UhyveStdout {
142	async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
143		let available = PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND;
144		Ok(event & available)
145	}
146
147	async fn write(&self, buf: &[u8]) -> io::Result<usize> {
148		let write_params = WriteParams {
149			fd: STDOUT_FILENO,
150			buf: GuestVirtAddr::new(buf.as_ptr() as u64),
151			len: buf.len(),
152		};
153		uhyve_hypercall(Hypercall::FileWrite(&write_params));
154
155		Ok(write_params.len)
156	}
157
158	async fn isatty(&self) -> io::Result<bool> {
159		Ok(true)
160	}
161}
162
163impl UhyveStdout {
164	pub const fn new() -> Self {
165		Self {}
166	}
167}
168
169#[derive(Debug)]
170pub struct UhyveStderr;
171
172#[async_trait]
173impl ObjectInterface for UhyveStderr {
174	async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
175		let available = PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND;
176		Ok(event & available)
177	}
178
179	async fn write(&self, buf: &[u8]) -> io::Result<usize> {
180		let write_params = WriteParams {
181			fd: STDERR_FILENO,
182			buf: GuestVirtAddr::new(buf.as_ptr() as u64),
183			len: buf.len(),
184		};
185		uhyve_hypercall(Hypercall::FileWrite(&write_params));
186
187		Ok(write_params.len)
188	}
189
190	async fn isatty(&self) -> io::Result<bool> {
191		Ok(true)
192	}
193}
194
195impl UhyveStderr {
196	pub const fn new() -> Self {
197		Self {}
198	}
199}