1use core::fmt;
2use x86_64::instructions::port::Port;
3
4pub struct QemuDebug;
5
6impl fmt::Write for QemuDebug {
7 fn write_str(&mut self, s: &str) -> fmt::Result {
8 let mut port = Port::new(0xe9);
9 for &byte in s.as_bytes() {
10 unsafe {
11 port.write(byte);
12 }
13 }
14 Ok(())
15 }
16}
17
18#[macro_export]
19macro_rules! e9_print {
20 ($($arg:tt)*) => {
21 {
22 use core::fmt::Write;
23 let _ = write!($crate::debug::QemuDebug, $($arg)*);
24 }
25 };
26}
27
28#[macro_export]
29macro_rules! e9_println {
30 () => ($crate::e9_print!("\n"));
31 ($($arg:tt)*) => ($crate::e9_print!("{}\n", format_args!($($arg)*)));
32}
33
34#[macro_export]
38macro_rules! boot_milestone {
39 ($($arg:tt)*) => {
40 $crate::serial_println!(
41 "[boot +{:>6}ms] {}",
42 $crate::arch::x86_64::boot_timestamp::elapsed_ms(),
43 format_args!($($arg)*)
44 );
45 if $crate::arch::x86_64::vga::is_available() {
46 let mut vbuf = [0u8; $crate::arch::x86_64::vgabuf::VGABUF_LINE_LEN];
47 let mut vpos = 0usize;
48 use core::fmt::Write;
49 struct VgaBufWriter<'a> {
50 buf: &'a mut [u8],
51 pos: &'a mut usize,
52 }
53 impl Write for VgaBufWriter<'_> {
54 fn write_str(&mut self, s: &str) -> core::fmt::Result {
55 let bytes = s.as_bytes();
56 let remaining = self.buf.len().saturating_sub(*self.pos);
57 let n = bytes.len().min(remaining);
58 self.buf[*self.pos..*self.pos + n].copy_from_slice(&bytes[..n]);
59 *self.pos += n;
60 Ok(())
61 }
62 }
63 let _ = write!(
64 VgaBufWriter { buf: &mut vbuf, pos: &mut vpos },
65 "[boot +{:>6}ms] {}\n",
66 $crate::arch::x86_64::boot_timestamp::elapsed_ms(),
67 format_args!($($arg)*)
68 );
69 if vpos > 0 {
70 $crate::arch::x86_64::vgabuf::vgabuf_write(&vbuf[..vpos]);
71 }
72 }
73 };
74}