Skip to content

Commit 465e4d3

Browse files
committed
uefi: serial: fix core::fmt::Write impl
This implementation is more correct and closer to what users typcially correct. Timeout errors can occur quite often on real hardware, for example when sending data over a UART 16550. However, in this case, it is more natural to retry the transmission as it will succeed eventually. For errors that are not Status::TIMEOUT errors, we will nevertheless propagate an error. This is the more expected and natural behavior.
1 parent 3d6207a commit 465e4d3

File tree

3 files changed

+15
-2
lines changed

3 files changed

+15
-2
lines changed

uefi-test-runner/src/main.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ extern crate alloc;
1010

1111
use alloc::string::ToString;
1212
use alloc::vec::Vec;
13+
use core::fmt::Write;
1314
use uefi::mem::memory_map::MemoryMap;
1415
use uefi::prelude::*;
1516
use uefi::proto::console::serial::Serial;
@@ -115,7 +116,10 @@ fn send_request_helper(serial: &mut Serial, request: HostRequest) -> Result {
115116
serial.set_attributes(&io_mode)?;
116117

117118
// Send a screenshot request to the host.
118-
serial.write(request.as_bytes()).discard_errdata()?;
119+
//serial.write(request.as_bytes()).discard_errdata()?;
120+
serial
121+
.write_str(request.as_str())
122+
.expect("should write all bytes");
119123

120124
// Wait for the host's acknowledgement before moving forward.
121125
let mut reply = [0; 3];

uefi/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
- MSRV increased to 1.88.
2929
- `Serial::read()` and `Serial::write()` got small improvements to better
3030
match the spec. Read the documentation of these methods for further insights.
31+
- Fixed potential partial writes in `core::fmt::Write` impl of `Serial` protocol
3132

3233
# uefi - v0.36.1 (2025-11-05)
3334

uefi/src/proto/console/serial.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::{Error, Result, ResultExt, Status, StatusExt};
77
use core::fmt;
88
use core::fmt::Write;
99
use core::time::Duration;
10+
use log::error;
1011
use uefi::boot;
1112
use uefi_raw::protocol::console::serial::SerialIoProtocol;
1213
pub use uefi_raw::protocol::console::serial::{
@@ -316,6 +317,13 @@ impl Serial {
316317

317318
impl Write for Serial {
318319
fn write_str(&mut self, s: &str) -> fmt::Result {
319-
self.write(s.as_bytes()).map(|_| ()).map_err(|_| fmt::Error)
320+
// We retry on Status::TIMEOUT but propagate other errors
321+
self.write_exact(s.as_bytes()).map_err(|e| {
322+
// Note: this may cause endless recursion in case the logger
323+
// implementation writes to the serial protocol, and we end up in
324+
// another error, and again, and again.
325+
error!("failed to write to device: {e}");
326+
fmt::Error
327+
})
320328
}
321329
}

0 commit comments

Comments
 (0)