1212//! The last part also means that some Unicode characters might not be
1313//! supported by the UEFI console. Don't expect emoji output support.
1414
15- use crate :: proto:: console:: text:: Output ;
16-
1715use crate :: prelude:: { Boot , SystemTable } ;
16+ use crate :: proto:: console:: text:: Output ;
1817use core:: fmt:: { self , Write } ;
1918use core:: ptr;
2019use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
@@ -43,6 +42,31 @@ pub fn disable() {
4342 LOGGER . disable ( ) ;
4443}
4544
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+
4670/// Logging implementation which writes to a UEFI output stream.
4771///
4872/// If this logger is used as a global logger, you must disable it using the
@@ -99,15 +123,13 @@ impl Logger {
99123
100124impl log:: Log for Logger {
101125 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
103129 }
104130
105131 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 ( ) } {
111133 // Ignore all errors. Since we're in the logger implementation we
112134 // can't log the error. We also don't want to panic, since logging
113135 // is generally not critical functionality.
@@ -119,6 +141,23 @@ impl log::Log for Logger {
119141 record. line ( ) . unwrap_or ( 0 ) ,
120142 ) ;
121143 }
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+ }
122161 }
123162
124163 fn flush ( & self ) {
0 commit comments