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: 完善他的功能,并且逐步把kinfo等宏,迁移到这个logger上面来。 94 struct CustomLogger; 95 96 impl Log for CustomLogger { 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 CustomLogger { 116 fn iodisplay(record: &log::Record) { 117 match record.level() { 118 Level::Debug | Level::Info => { 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 Level::Trace => { 128 todo!() 129 } 130 } 131 .unwrap(); 132 writeln!( 133 PrintkWriter, 134 "({}:{})\t {}", 135 record.file().unwrap_or(""), 136 record.line().unwrap_or(0), 137 record.args() 138 ) 139 .unwrap(); 140 } 141 142 fn kernel_log(record: &log::Record) { 143 match record.level() { 144 Level::Debug => Logger.log( 145 7, 146 format_args!( 147 "({}:{})\t {}\n", 148 record.file().unwrap_or(""), 149 record.line().unwrap_or(0), 150 record.args() 151 ), 152 ), 153 Level::Error => Logger.log( 154 3, 155 format_args!( 156 "({}:{})\t {}\n", 157 record.file().unwrap_or(""), 158 record.line().unwrap_or(0), 159 record.args() 160 ), 161 ), 162 Level::Info => Logger.log( 163 6, 164 format_args!( 165 "({}:{})\t {}\n", 166 record.file().unwrap_or(""), 167 record.line().unwrap_or(0), 168 record.args() 169 ), 170 ), 171 Level::Warn => Logger.log( 172 4, 173 format_args!( 174 "({}:{})\t {}\n", 175 record.file().unwrap_or(""), 176 record.line().unwrap_or(0), 177 record.args() 178 ), 179 ), 180 Level::Trace => { 181 todo!() 182 } 183 } 184 } 185 } 186 187 pub fn early_init_logging() { 188 log::set_logger(&CustomLogger).unwrap(); 189 log::set_max_level(log::LevelFilter::Debug); 190 info!("Logging initialized"); 191 } 192