1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
//! # Serial Logging Library for x86_64 Kernels
//!
//! This crate provides robust serial port logging for kernel and bootloader environments, with a focus on QEMU usage. It offers macros and functions for formatted and raw serial output, as well as a minimal `kprint!` macro for early boot or no_std contexts where dependencies are limited.
//!
//! ## QEMU Serial Logging
//!
//! QEMU can redirect the guest's serial port (COM1, 0x3F8) to the host's standard output or a file. This allows you to see kernel logs by running QEMU with `-serial stdio` or `-serial file:output.log`. All output sent to the serial port will appear in your terminal or the specified file, making debugging much easier, especially before graphics or higher-level logging is available.
//!
//! ## When to Use `serial_log!`/`serial_print!` vs `kprint!`
//!
//! - Use `serial_log!`, `serial_print!`, and related macros for most kernel logging. These use a full-featured serial driver (with buffering, formatting, and thread safety) and are suitable once the kernel is initialized.
//! - Use `kprint!` for minimal, dependency-free output in very early boot stages, or in environments where only core formatting is available. `kprint!` writes directly to the serial port using inline assembly, bypassing all higher-level abstractions.
//!
//! ## Features
//! - Thread-safe, formatted serial output via `serial_print!`, `serial_log!`, etc.
//! - Log level macros for info, warning, and error messages.
//! - Hexadecimal logging support.
//! - Minimal `kprint!` macro for direct serial output.
//! - Enable/disable logging at runtime.
//!
//! ## Example (QEMU):
//!
//! ```sh
//! qemu-system-x86_64 -serial stdio -kernel path/to/kernel
//! ```
//!
//! In your kernel code:
//!
//! ```no_run
//! use polished_serial_logging::{serial_println, serial_log};
//!
//! serial_println!("Hello, QEMU serial!");
//! serial_log!("[INFO] ", "Boot complete");
//! ```
use lazy_static;
use Mutex;
use SerialPort;
use Port;
pub use crateDebugSerial;
lazy_static!
/// Prints to the host through the serial interface (COM1, 0x3F8).
///
/// This macro uses the main serial driver, which is thread-safe and supports formatting.
/// Output will appear in QEMU's terminal if run with `-serial stdio`.
/// Prints to the host through the serial interface, appending a newline.
///
/// Equivalent to `serial_print!` but adds a `\n` at the end.
/// Logs a message to the serial port with a given log level prefix.
///
/// - `$level`: Prefix string (e.g., "[INFO] ").
/// - `$msg`: Message string or format string.
/// - Additional arguments are formatted as in `format!`.
///
/// # Examples
/// ```no_run
/// use polished_serial_logging::serial_log;
///
/// serial_log!("[INFO] ", "Hello, world!");
/// serial_log!("[DEBUG] ", "Value: {}", 42);
/// ```
/// Logs a hexadecimal value to the serial port with a given log level prefix.
///
/// - `$level`: Prefix string (e.g., "[INFO] ").
/// - `$value`: Value to print in hexadecimal.
///
/// # Examples
/// ```no_run
/// use polished_serial_logging::serial_log_hex;
///
/// serial_log_hex!("[INFO] ", 0xdeadbeef);
/// ```
const SERIAL_PORT: u16 = 0x3F8; // COM1
static mut LOGGING_ENABLED: bool = true;
/// Enables serial logging output.
///
/// When disabled, all serial output functions become no-ops.
/// Disables serial logging output.
///
/// When disabled, all serial output functions become no-ops.
/// Returns whether serial logging is currently enabled.
///
/// This can be used to temporarily silence serial output.
/// Writes a single byte to the serial port (COM1, 0x3F8).
///
/// Blocks until the port is ready to accept a byte. Used internally by all higher-level output functions.
///
/// # QEMU
/// Output will appear in the QEMU terminal if run with `-serial stdio`.
/// Writes a string to the serial port, byte by byte.
///
/// Used by all higher-level output macros and functions.
/// Writes a hexadecimal representation of a `u64` value to the serial port.
///
/// Does not include a `0x` prefix. Used by `serial_log_hex!` and similar macros.
/// Logs an info-level message to the serial port.
///
/// Equivalent to `serial_log!("[INFO] ", ...)`.
///
/// # Examples
/// ```no_run
/// use polished_serial_logging::info;
///
/// info("System started");
/// ```
/// Logs an info-level hexadecimal value to the serial port.
///
/// Equivalent to `serial_log_hex!("[INFO] ", value)`.
///
/// # Examples
/// ```no_run
/// use polished_serial_logging::info_hex;
///
/// info_hex(0xdeadbeef);
/// ```
/// Logs an error-level message to the serial port.
///
/// Equivalent to `serial_log!("[ERROR] ", ...)`.
///
/// # Examples
/// ```no_run
/// use polished_serial_logging::error;
///
/// error("An error occurred");
/// ```
/// Logs a warning-level message to the serial port.
///
/// Equivalent to `serial_log!("[WARNING] ", ...)`.
///
/// # Examples
/// ```no_run
/// use polished_serial_logging::warn;
/// warn("Low disk space");
/// ```
/// Logs an error-level message to the serial port with formatting support.
///
/// Equivalent to `serial_log!("[ERROR] ", ...)` but as a macro for formatting.
///
/// # Examples
/// ```no_run
/// use polished_serial_logging::error;
///
/// error!("Failed: {}", 42);
/// ```