xref: /DragonOS/kernel/src/libs/printk.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
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