debugcon.rs 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. //! Driver for QEMU's debugcon device.
  2. use core::fmt::{Arguments, Write};
  3. use log::{LevelFilter, Log, Metadata, Record};
  4. static LOGGER: DebugconLogger = DebugconLogger;
  5. struct Debugcon;
  6. /// Internal API for the `println!` macro.
  7. pub fn _print(args: Arguments) {
  8. Debugcon.write_fmt(args).unwrap();
  9. }
  10. impl Debugcon {
  11. /// I/O port of QEMUs debugcon device on x86.
  12. const IO_PORT: u16 = 0xe9;
  13. pub fn write_byte(byte: u8) {
  14. unsafe {
  15. core::arch::asm!(
  16. "outb %al, %dx",
  17. in("al") byte,
  18. in("dx") Self::IO_PORT,
  19. options(att_syntax, nomem, nostack, preserves_flags)
  20. )
  21. }
  22. }
  23. }
  24. impl Write for Debugcon {
  25. fn write_str(&mut self, s: &str) -> core::fmt::Result {
  26. for &byte in s.as_bytes() {
  27. Debugcon::write_byte(byte);
  28. }
  29. Ok(())
  30. }
  31. }
  32. pub struct DebugconLogger;
  33. impl DebugconLogger {
  34. pub fn init() {
  35. // Ignore, as we can't do anything about it here.
  36. let _ = log::set_logger(&LOGGER);
  37. log::set_max_level(LevelFilter::Trace);
  38. }
  39. }
  40. impl Log for DebugconLogger {
  41. fn enabled(&self, _metadata: &Metadata) -> bool {
  42. true
  43. }
  44. fn log(&self, record: &Record) {
  45. // Ignore result as we can't do anything about it.
  46. let _ = writeln!(
  47. Debugcon,
  48. "[{:>5}: {}@{}]: {}",
  49. record.level(),
  50. record.file().unwrap_or("<unknown>"),
  51. record.line().unwrap_or(0),
  52. record.args()
  53. );
  54. }
  55. fn flush(&self) {}
  56. }