1static LOGGER: VMWLogger = VMWLogger::new();
2
3fn default_formatter(buffer: &mut dyn core::fmt::Write, record: &log::Record) -> Result<(), core::fmt::Error> {
4 writeln!(
5 buffer,
6 "[{}:{} - {}] {}",
7 record.file().unwrap_or("<unknown>"),
8 record.line().unwrap_or(0),
9 record.level(),
10 record.args(),
11 )
12}
13
14struct VMWLogger;
15
16impl VMWLogger {
17 const fn new() -> Self {
18 Self
19 }
20}
21
22impl core::fmt::Write for VMWLogger {
23 fn write_str(&mut self, s: &str) -> core::fmt::Result {
24 for c in s.chars() {
26 unsafe {
27 core::arch::asm!(r#"
28 xchg rbx, {0}
29 mov eax, 0x564D5868
30 mov edx, 0x5658
31 mov ecx, 0x19
32 in eax, dx
33 xchg rbx, {0}
34 "#,
35 in(reg) c as usize,
38 out("rax") _,
39 out("rdx") _,
40 out("rcx") _,
41 );
42 }
43 }
44
45 Ok(())
46 }
47}
48
49impl log::Log for VMWLogger {
50 fn enabled(&self, _m: &log::Metadata) -> bool {
51 unsafe {
53 let mut rbx: u64 = 0;
56 core::arch::asm!(r#"
57 xchg rbx, {_rbx}
58 xchg {_rbp}, rbp
59 xor rbp, rbp
60 mov eax, 0x564D5868
61 mov edx, 0x5658
62 mov ecx, 0xA
63 in eax, dx
64 xchg rbp, {_rbp}
65 xchg rbx, {_rbx}
66 "#,
67 in("rax") 0x564D5868,
68 _rbx = inout(reg) rbx,
69 in("rcx") 0xA,
70 in("rdx") 0x5658,
71 _rbp = in(reg) 0u64,
72 in("rdi") 0,
73 in("rsi") 0,
74 );
75 rbx == 0x564D5868
76 }
77 }
78
79 fn log(&self, record: &log::Record) {
80 let _ = default_formatter(&mut VMWLogger::new(), record); }
82
83 fn flush(&self) {}
84}
85
86pub struct Builder {
87 filter: log::LevelFilter,
88}
89
90impl Builder {
91 pub fn new() -> Self {
93 Self {
94 filter: log::LevelFilter::Info,
95 }
96 }
97
98 pub fn filter(mut self, filter: log::LevelFilter) -> Self {
100 self.filter = filter;
101 self
102 }
103
104 pub fn setup(self) {
106 log::set_logger(&LOGGER).unwrap();
107
108 log::set_max_level(self.filter);
109 }
110}
111
112pub fn builder() -> Builder {
113 Builder::new()
114}
115
116pub fn init() {
117 builder().filter(log::LevelFilter::Info).setup();
118}
119
120pub fn init_with_filter(filter: log::LevelFilter) {
121 builder().filter(filter).setup();
122}