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]
__write_fmt(&mut self, args: fmt::Arguments)40 pub fn __write_fmt(&mut self, args: fmt::Arguments) {
41 self.write_fmt(args).ok();
42 }
43
44 /// 并输出白底黑字
45 /// @param str: 要写入的字符
__write_string(&mut self, s: &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 {
write_str(&mut self, s: &str) -> fmt::Result65 fn write_str(&mut self, s: &str) -> fmt::Result {
66 self.__write_string(s);
67 Ok(())
68 }
69 }
70
71 #[doc(hidden)]
__printk(args: fmt::Arguments)72 pub fn __printk(args: fmt::Arguments) {
73 PrintkWriter.write_fmt(args).unwrap();
74 }
75
76 pub struct Logger;
77
78 impl Logger {
log(&self, log_level: usize, message: fmt::Arguments)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 {
enabled(&self, _metadata: &log::Metadata) -> bool97 fn enabled(&self, _metadata: &log::Metadata) -> bool {
98 // 这里可以自定义日志过滤规则
99 true
100 }
101
log(&self, record: &log::Record)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
flush(&self)110 fn flush(&self) {
111 // 如果需要的话,可以在这里实现缓冲区刷新逻辑
112 }
113 }
114
115 impl KernelLogger {
iodisplay(record: &log::Record)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
kernel_log(record: &log::Record)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
early_init_logging()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