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