12
12
//! The last part also means that some Unicode characters might not be
13
13
//! supported by the UEFI console. Don't expect emoji output support.
14
14
15
- use crate :: proto:: console:: text:: Output ;
16
-
17
15
use crate :: prelude:: { Boot , SystemTable } ;
16
+ use crate :: proto:: console:: text:: Output ;
18
17
use core:: fmt:: { self , Write } ;
19
18
use core:: ptr;
20
19
use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
@@ -43,6 +42,31 @@ pub fn disable() {
43
42
LOGGER . disable ( ) ;
44
43
}
45
44
45
+ /// Writer to the QEMU debugcon device and the debug-console of
46
+ /// cloud-hypervisor.
47
+ ///
48
+ /// More info: <https://phip1611.de/blog/how-to-use-qemus-debugcon-feature/>
49
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
50
+ #[ derive( Copy , Clone , Debug ) ]
51
+ struct DebugconWriter ;
52
+
53
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
54
+ impl DebugconWriter {
55
+ const IO_PORT : u16 = 0xe9 ;
56
+ }
57
+
58
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
59
+ impl core:: fmt:: Write for DebugconWriter {
60
+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
61
+ for & byte in s. as_bytes ( ) {
62
+ unsafe {
63
+ core:: arch:: asm!( "outb %al, %dx" , in( "al" ) byte, in( "dx" ) DebugconWriter :: IO_PORT , options( att_syntax) )
64
+ } ;
65
+ }
66
+ Ok ( ( ) )
67
+ }
68
+ }
69
+
46
70
/// Logging implementation which writes to a UEFI output stream.
47
71
///
48
72
/// If this logger is used as a global logger, you must disable it using the
@@ -99,15 +123,13 @@ impl Logger {
99
123
100
124
impl log:: Log for Logger {
101
125
fn enabled ( & self , _metadata : & log:: Metadata ) -> bool {
102
- !self . output ( ) . is_null ( )
126
+ // We decide in `log` already if something is printed. We do not
127
+ // need micro optimizations here.
128
+ true
103
129
}
104
130
105
131
fn log ( & self , record : & log:: Record ) {
106
- let output = self . output ( ) ;
107
-
108
- if !output. is_null ( ) {
109
- let writer = unsafe { & mut * output } ;
110
-
132
+ if let Some ( writer) = unsafe { self . output ( ) . as_mut ( ) } {
111
133
// Ignore all errors. Since we're in the logger implementation we
112
134
// can't log the error. We also don't want to panic, since logging
113
135
// is generally not critical functionality.
@@ -119,6 +141,23 @@ impl log::Log for Logger {
119
141
record. line ( ) . unwrap_or ( 0 ) ,
120
142
) ;
121
143
}
144
+
145
+ #[ cfg( all(
146
+ any( target_arch = "x86" , target_arch = "x86_64" ) ,
147
+ feature = "log-debugcon"
148
+ ) ) ]
149
+ {
150
+ // Ignore all errors. Since we're in the logger implementation we
151
+ // can't log the error. We also don't want to panic, since logging
152
+ // is generally not critical functionality.
153
+ let _ = DecoratedLog :: write (
154
+ & mut DebugconWriter ,
155
+ record. level ( ) ,
156
+ record. args ( ) ,
157
+ record. file ( ) . unwrap_or ( "<unknown file>" ) ,
158
+ record. line ( ) . unwrap_or ( 0 ) ,
159
+ ) ;
160
+ }
122
161
}
123
162
124
163
fn flush ( & self ) {
0 commit comments