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