Skip to content

Commit 2b1e723

Browse files
committed
xxxx
1 parent c3e3e1e commit 2b1e723

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

uefi/src/proto/console/serial.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,21 +187,41 @@ impl Serial {
187187
/// # Errors
188188
///
189189
/// - [`Status::DEVICE_ERROR`]: serial device reported an error
190-
pub fn read_exact(&mut self, buffer: &mut [u8]) -> Result<()> {
190+
pub fn read_exact(&mut self, buffer: &mut [u8]) -> Result<(), usize /* read bytes */> {
191+
let stall_duration = if self.io_mode().baud_rate == 0 {
192+
Duration::from_millis(1) } else {
193+
let ms = 1_000_000 / self.io_mode().baud_rate;
194+
Duration::from_millis(ms)
195+
};
196+
// Endless loop protection.
197+
let max_timeout_count = buffer.len() * 5;
198+
199+
let mut timeout_count = 0;
191200
let mut remaining_buffer = buffer;
201+
202+
let move_buffer_by_n = |n| {
203+
remaining_buffer = &mut remaining_buffer[n..];
204+
};
205+
206+
192207
// We retry on timeout and only return other errors
193208
while !remaining_buffer.is_empty() {
194209
match self.read(remaining_buffer) {
195210
Ok(_) => {
196211
break;
197212
}
198-
Err(err) if err.status() == Status::TIMEOUT => {
199-
let n = *err.data();
200-
remaining_buffer = &mut remaining_buffer[n..];
201-
boot::stall(Duration::from_millis(1));
213+
Err(err) if err.status() == Status::TIMEOUT && timeout_count < max_timeout_count => {
214+
timeout_count += 1;
215+
move_buffer_by_n(*err.data() /* n */);
216+
boot::stall(stall_duration);
217+
},
218+
Err(err) if err.status() == Status::TIMEOUT && timeout_count >= max_timeout_count => {
219+
move_buffer_by_n(*err.data() /* n */);
220+
let n_total = buffer.len() - remaining_buffer.len();
221+
return Err(Error::new(Status::TIMEOUT, n_total));
202222
}
203223
err => {
204-
return Err(Error::from(err.status()));
224+
return err
205225
}
206226
}
207227
}

0 commit comments

Comments
 (0)