1 use core::{ 2 fmt::{self, Write}, 3 sync::atomic::Ordering, 4 }; 5 6 use alloc::string::ToString; 7 use log::{info, Level, Log}; 8 9 use super::lib_ui::textui::{textui_putstr, FontColor}; 10 11 use crate::{ 12 driver::tty::{ 13 tty_driver::TtyOperation, tty_port::tty_port, 14 virtual_terminal::virtual_console::CURRENT_VCNUM, 15 }, 16 filesystem::procfs::{ 17 kmsg::KMSG, 18 log::{LogLevel, LogMessage}, 19 }, 20 time::PosixTimeSpec, 21 }; 22 23 #[macro_export] 24 macro_rules! print { 25 ($($arg:tt)*) => ($crate::libs::printk::__printk(format_args!($($arg)*))); 26 } 27 28 #[macro_export] 29 macro_rules! println { 30 () => { 31 $crate::print!("\n"); 32 }; 33 ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); 34 } 35 36 pub struct PrintkWriter; 37 38 impl PrintkWriter { 39 #[inline] 40 pub fn __write_fmt(&mut self, args: fmt::Arguments) { 41 self.write_fmt(args).ok(); 42 } 43 44 /// 并输出白底黑字 45 /// @param str: 要写入的字符 46 pub fn __write_string(&mut self, s: &str) { 47 let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst); 48 if current_vcnum != -1 { 49 // tty已经初始化了之后才输出到屏幕 50 let port = tty_port(current_vcnum as usize); 51 let tty = port.port_data().internal_tty(); 52 if let Some(tty) = tty { 53 let _ = tty.write(tty.core(), s.as_bytes(), s.len()); 54 } else { 55 let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK); 56 } 57 } else { 58 let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK); 59 } 60 } 61 } 62 63 /// 为Printk Writer实现core::fmt::Write, 使得能够借助Rust自带的格式化组件,格式化字符并输出 64 impl fmt::Write for PrintkWriter { 65 fn write_str(&mut self, s: &str) -> fmt::Result { 66 self.__write_string(s); 67 Ok(()) 68 } 69 } 70 71 #[doc(hidden)] 72 pub fn __printk(args: fmt::Arguments) { 73 PrintkWriter.write_fmt(args).unwrap(); 74 } 75 76 pub struct Logger; 77 78 impl Logger { 79 pub fn log(&self, log_level: usize, message: fmt::Arguments) { 80 if unsafe { KMSG.is_some() } { 81 let timestamp: PosixTimeSpec = PosixTimeSpec::now_cpu_time(); 82 let log_level = LogLevel::from(log_level); 83 84 let log_message = LogMessage::new(timestamp, log_level, message.to_string()); 85 86 unsafe { KMSG.as_ref().unwrap().lock_irqsave().push(log_message) }; 87 } 88 } 89 } 90 91 /// 内核自定义日志器 92 /// 93 /// todo: https://github.com/DragonOS-Community/DragonOS/issues/762 94 struct KernelLogger; 95 96 impl Log for KernelLogger { 97 fn enabled(&self, _metadata: &log::Metadata) -> bool { 98 // 这里可以自定义日志过滤规则 99 true 100 } 101 102 fn log(&self, record: &log::Record) { 103 if self.enabled(record.metadata()) { 104 // todo: 接入kmsg 105 Self::kernel_log(record); 106 Self::iodisplay(record) 107 } 108 } 109 110 fn flush(&self) { 111 // 如果需要的话,可以在这里实现缓冲区刷新逻辑 112 } 113 } 114 115 impl KernelLogger { 116 fn iodisplay(record: &log::Record) { 117 match record.level() { 118 Level::Debug | Level::Info | Level::Trace => { 119 write!(PrintkWriter, "[ {} ] ", record.level(),) 120 } 121 Level::Error => { 122 write!(PrintkWriter, "\x1B[41m[ ERROR ] \x1B[0m",) 123 } 124 Level::Warn => { 125 write!(PrintkWriter, "\x1B[1;33m[ WARN ] \x1B[0m",) 126 } 127 } 128 .unwrap(); 129 writeln!( 130 PrintkWriter, 131 "({}:{})\t {}", 132 record.file().unwrap_or(""), 133 record.line().unwrap_or(0), 134 record.args() 135 ) 136 .unwrap(); 137 } 138 139 fn kernel_log(record: &log::Record) { 140 match record.level() { 141 Level::Debug => Logger.log( 142 7, 143 format_args!( 144 "({}:{})\t {}\n", 145 record.file().unwrap_or(""), 146 record.line().unwrap_or(0), 147 record.args() 148 ), 149 ), 150 Level::Error => Logger.log( 151 3, 152 format_args!( 153 "({}:{})\t {}\n", 154 record.file().unwrap_or(""), 155 record.line().unwrap_or(0), 156 record.args() 157 ), 158 ), 159 Level::Info => Logger.log( 160 6, 161 format_args!( 162 "({}:{})\t {}\n", 163 record.file().unwrap_or(""), 164 record.line().unwrap_or(0), 165 record.args() 166 ), 167 ), 168 Level::Warn => Logger.log( 169 4, 170 format_args!( 171 "({}:{})\t {}\n", 172 record.file().unwrap_or(""), 173 record.line().unwrap_or(0), 174 record.args() 175 ), 176 ), 177 Level::Trace => { 178 todo!() 179 } 180 } 181 } 182 } 183 184 pub fn early_init_logging() { 185 log::set_logger(&KernelLogger).unwrap(); 186 log::set_max_level(log::LevelFilter::Debug); 187 info!("Logging initialized"); 188 } 189