xref: /DragonOS/kernel/src/libs/printk.rs (revision dd8e74ef0d7f91a141bd217736bef4fe7dc6df3d)
1 use core::{
2     fmt::{self, Write},
3     sync::atomic::Ordering,
4 };
5 
6 use alloc::string::ToString;
7 use log::{info, 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 #[macro_export]
37 macro_rules! kdebug {
38     ($($arg:tt)*) => {
39         $crate::libs::printk::Logger.log(7,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
40         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ DEBUG ] ({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)))
41     }
42 }
43 
44 #[macro_export]
45 macro_rules! kinfo {
46     ($($arg:tt)*) => {
47         $crate::libs::printk::Logger.log(6,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
48         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ INFO ] ({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)))
49     }
50 }
51 
52 #[macro_export]
53 macro_rules! kwarn {
54     ($($arg:tt)*) => {
55         $crate::libs::printk::Logger.log(4,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
56         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[1;33m[ WARN ] \x1B[0m"));
57         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
58     }
59 }
60 
61 #[macro_export]
62 macro_rules! kerror {
63     ($($arg:tt)*) => {
64         $crate::libs::printk::Logger.log(3,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
65         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[41m[ ERROR ] \x1B[0m"));
66         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
67     }
68 }
69 
70 #[macro_export]
71 macro_rules! kBUG {
72     ($($arg:tt)*) => {
73         $crate::libs::printk::Logger.log(1,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
74         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[41m[ BUG ] \x1B[0m"));
75         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
76     }
77 }
78 
79 pub struct PrintkWriter;
80 
81 impl PrintkWriter {
82     #[inline]
83     pub fn __write_fmt(&mut self, args: fmt::Arguments) {
84         self.write_fmt(args).ok();
85     }
86 
87     /// 并输出白底黑字
88     /// @param str: 要写入的字符
89     pub fn __write_string(&mut self, s: &str) {
90         let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst);
91         if current_vcnum != -1 {
92             // tty已经初始化了之后才输出到屏幕
93             let port = tty_port(current_vcnum as usize);
94             let tty = port.port_data().internal_tty();
95             if let Some(tty) = tty {
96                 let _ = tty.write(tty.core(), s.as_bytes(), s.len());
97             } else {
98                 let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK);
99             }
100         } else {
101             let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK);
102         }
103     }
104 }
105 
106 /// 为Printk Writer实现core::fmt::Write, 使得能够借助Rust自带的格式化组件,格式化字符并输出
107 impl fmt::Write for PrintkWriter {
108     fn write_str(&mut self, s: &str) -> fmt::Result {
109         self.__write_string(s);
110         Ok(())
111     }
112 }
113 
114 #[doc(hidden)]
115 pub fn __printk(args: fmt::Arguments) {
116     PrintkWriter.write_fmt(args).unwrap();
117 }
118 
119 pub struct Logger;
120 
121 impl Logger {
122     pub fn log(&self, log_level: usize, message: fmt::Arguments) {
123         if unsafe { KMSG.is_some() } {
124             let timestamp: PosixTimeSpec = PosixTimeSpec::now_cpu_time();
125             let log_level = LogLevel::from(log_level);
126 
127             let log_message = LogMessage::new(timestamp, log_level, message.to_string());
128 
129             unsafe { KMSG.as_ref().unwrap().lock_irqsave().push(log_message) };
130         }
131     }
132 }
133 
134 /// 内核自定义日志器
135 ///
136 /// todo: 完善他的功能,并且逐步把kinfo等宏,迁移到这个logger上面来。
137 struct CustomLogger;
138 
139 impl Log for CustomLogger {
140     fn enabled(&self, _metadata: &log::Metadata) -> bool {
141         // 这里可以自定义日志过滤规则
142         true
143     }
144 
145     fn log(&self, record: &log::Record) {
146         if self.enabled(record.metadata()) {
147             // todo: 接入kmsg
148 
149             writeln!(
150                 PrintkWriter,
151                 "[ {} ] {} ({}:{}) {}",
152                 record.level(),
153                 record.target(),
154                 record.file().unwrap_or(""),
155                 record.line().unwrap_or(0),
156                 record.args()
157             )
158             .unwrap();
159         }
160     }
161 
162     fn flush(&self) {
163         // 如果需要的话,可以在这里实现缓冲区刷新逻辑
164     }
165 }
166 
167 pub fn early_init_logging() {
168     log::set_logger(&CustomLogger).unwrap();
169     log::set_max_level(log::LevelFilter::Debug);
170     info!("Logging initialized");
171 }
172