1//! Abstraction over byte stream devices, also known as serial I/O devices.
2
3use core::fmt::Write;
4
5use crate::proto::unsafe_protocol;
6use crate::{Result, Status};
7use bitflags::bitflags;
8
9/// Provides access to a serial I/O device.
10///
11/// This can include standard UART devices, serial ports over a USB interface,
12/// or any other character-based communication device.
13///
14/// Since UEFI drivers are implemented through polling, if you fail to regularly
15/// check for input/output, some data might be lost.
16#[repr(C)]
17#[unsafe_protocol("bb25cf6f-f1d4-11d2-9a0c-0090273fc1fd")]
18pub struct Serial {
19 // Revision of this protocol, only 1.0 is currently defined.
20 // Future versions will be backwards compatible.
21 revision: u32,
22 reset: extern "efiapi" fn(&mut Serial) -> Status,
23 set_attributes: extern "efiapi" fn(
24 &Serial,
25 baud_rate: u64,
26 receive_fifo_depth: u32,
27 timeout: u32,
28 parity: Parity,
29 data_bits: u8,
30 stop_bits_type: StopBits,
31 ) -> Status,
32 set_control_bits: extern "efiapi" fn(&mut Serial, ControlBits) -> Status,
33 get_control_bits: extern "efiapi" fn(&Serial, &mut ControlBits) -> Status,
34 write: unsafe extern "efiapi" fn(&mut Serial, &mut usize, *const u8) -> Status,
35 read: unsafe extern "efiapi" fn(&mut Serial, &mut usize, *mut u8) -> Status,
36 io_mode: *const IoMode,
37}
38
39impl Serial {
40 /// Reset the device.
41 pub fn reset(&mut self) -> Result {
42 (self.reset)(self).into()
43 }
44
45 /// Returns the current I/O mode.
46 #[must_use]
47 pub const fn io_mode(&self) -> &IoMode {
48 unsafe { &*self.io_mode }
49 }
50
51 /// Sets the device's new attributes.
52 ///
53 /// The given `IoMode` will become the device's new `IoMode`,
54 /// with some exceptions:
55 ///
56 /// - `control_mask` is ignored, since it's a read-only field;
57 ///
58 /// - values set to `0` / `Default` will be filled with the device's
59 /// default parameters
60 ///
61 /// - if either `baud_rate` or `receive_fifo_depth` is less than
62 /// the device's minimum, an error will be returned;
63 /// this value will be rounded down to the nearest value supported by the device;
64 pub fn set_attributes(&mut self, mode: &IoMode) -> Result {
65 (self.set_attributes)(
66 self,
67 mode.baud_rate,
68 mode.receive_fifo_depth,
69 mode.timeout,
70 mode.parity,
71 mode.data_bits as u8,
72 mode.stop_bits,
73 )
74 .into()
75 }
76
77 /// Retrieve the device's current control bits.
78 pub fn get_control_bits(&self) -> Result<ControlBits> {
79 let mut bits = ControlBits::empty();
80 (self.get_control_bits)(self, &mut bits).into_with_val(|| bits)
81 }
82
83 /// Sets the device's new control bits.
84 ///
85 /// Not all bits can be modified with this function. A mask of the allowed
86 /// bits is stored in the [`ControlBits::SETTABLE`] constant.
87 pub fn set_control_bits(&mut self, bits: ControlBits) -> Result {
88 (self.set_control_bits)(self, bits).into()
89 }
90
91 /// Reads data from this device.
92 ///
93 /// This operation will block until the buffer has been filled with data or
94 /// an error occurs. In the latter case, the error will indicate how many
95 /// bytes were actually read from the device.
96 pub fn read(&mut self, data: &mut [u8]) -> Result<(), usize> {
97 let mut buffer_size = data.len();
98 unsafe { (self.read)(self, &mut buffer_size, data.as_mut_ptr()) }.into_with(
99 || debug_assert_eq!(buffer_size, data.len()),
100 |_| buffer_size,
101 )
102 }
103
104 /// Writes data to this device.
105 ///
106 /// This operation will block until the data has been fully written or an
107 /// error occurs. In the latter case, the error will indicate how many bytes
108 /// were actually written to the device.
109 pub fn write(&mut self, data: &[u8]) -> Result<(), usize> {
110 let mut buffer_size = data.len();
111 unsafe { (self.write)(self, &mut buffer_size, data.as_ptr()) }.into_with(
112 || debug_assert_eq!(buffer_size, data.len()),
113 |_| buffer_size,
114 )
115 }
116}
117
118impl Write for Serial {
119 fn write_str(&mut self, s: &str) -> core::fmt::Result {
120 self.write(s.as_bytes()).map_err(|_| core::fmt::Error)
121 }
122}
123
124/// Structure representing the device's current parameters.
125///
126/// The default values for all UART-like devices is:
127/// - 115,200 baud
128/// - 1 byte receive FIFO
129/// - 1'000'000 microsecond timeout
130/// - no parity
131/// - 8 data bits
132/// - 1 stop bit
133///
134/// The software is responsible for flow control.
135#[derive(Debug, Copy, Clone)]
136#[repr(C)]
137pub struct IoMode {
138 /// Bitmask of the control bits that this device supports.
139 pub control_mask: ControlBits,
140 /// If applicable, the number of microseconds to wait before assuming an
141 /// operation timed out.
142 pub timeout: u32,
143 /// Device's baud rate, or 0 if unknown.
144 pub baud_rate: u64,
145 /// Size in character's of the device's buffer.
146 pub receive_fifo_depth: u32,
147 /// Number of data bits in each character.
148 pub data_bits: u32,
149 /// If applicable, the parity that is computed or checked for each character.
150 pub parity: Parity,
151 /// If applicable, the number of stop bits per character.
152 pub stop_bits: StopBits,
153}
154
155bitflags! {
156 /// The control bits of a device. These are defined in the [RS-232] standard.
157 ///
158 /// [RS-232]: https://en.wikipedia.org/wiki/RS-232
159 pub struct ControlBits: u32 {
160 /// Clear to send
161 const CLEAR_TO_SEND = 0x10;
162 /// Data set ready
163 const DATA_SET_READY = 0x20;
164 /// Indicates that a phone line is ringing
165 const RING_INDICATE = 0x40;
166 /// Indicates the connection is still connected
167 const CARRIER_DETECT = 0x80;
168 /// The input buffer is empty
169 const INPUT_BUFFER_EMPTY = 0x100;
170 /// The output buffer is empty
171 const OUTPUT_BUFFER_EMPTY = 0x200;
172
173 /// Terminal is ready for communications
174 const DATA_TERMINAL_READY = 0x1;
175 /// Request the device to send data
176 const REQUEST_TO_SEND = 0x2;
177 /// Enable hardware loop-back
178 const HARDWARE_LOOPBACK_ENABLE = 0x1000;
179 /// Enable software loop-back
180 const SOFTWARE_LOOPBACK_ENABLE = 0x2000;
181 /// Allow the hardware to handle flow control
182 const HARDWARE_FLOW_CONTROL_ENABLE = 0x4000;
183
184 /// Bitmask of the control bits that can be set.
185 ///
186 /// Up to date as of UEFI 2.7 / Serial protocol v1
187 const SETTABLE =
188 ControlBits::DATA_TERMINAL_READY.bits
189 | ControlBits::REQUEST_TO_SEND.bits
190 | ControlBits::HARDWARE_LOOPBACK_ENABLE.bits
191 | ControlBits::SOFTWARE_LOOPBACK_ENABLE.bits
192 | ControlBits::HARDWARE_FLOW_CONTROL_ENABLE.bits;
193 }
194}
195
196/// The parity of the device.
197#[derive(Debug, Copy, Clone, Eq, PartialEq)]
198#[repr(u32)]
199pub enum Parity {
200 /// Device default
201 Default = 0,
202 /// No parity
203 None,
204 /// Even parity
205 Even,
206 /// Odd parity
207 Odd,
208 /// Mark parity
209 Mark,
210 /// Space parity
211 Space,
212 // SAFETY: The serial protocol is very old, and new parity modes are very
213 // unlikely to be added at this point in time. Therefore, modeling
214 // this C enum as a Rust enum seems safe.
215}
216
217/// Number of stop bits per character.
218#[derive(Debug, Copy, Clone, Eq, PartialEq)]
219#[repr(u32)]
220pub enum StopBits {
221 /// Device default
222 Default = 0,
223 /// 1 stop bit
224 One,
225 /// 1.5 stop bits
226 OneFive,
227 /// 2 stop bits
228 Two,
229 // SAFETY: The serial protocol is very old, and new stop bit modes are very
230 // unlikely to be added at this point in time. Therefore, modeling
231 // this C enum as a Rust enum seems safe.
232}
233