xref: /DragonOS/kernel/src/libs/printk.rs (revision da152319797436368304cbc3f85a3b9ec049134b)
1 use core::{
2     fmt::{self, Write},
3     sync::atomic::Ordering,
4 };
5 
6 use alloc::string::ToString;
7 
8 use super::lib_ui::textui::{textui_putstr, FontColor};
9 
10 use crate::{
11     driver::tty::{
12         tty_driver::TtyOperation, tty_port::TTY_PORTS,
13         virtual_terminal::virtual_console::CURRENT_VCNUM,
14     },
15     filesystem::procfs::{
16         kmsg::KMSG,
17         log::{LogLevel, LogMessage},
18     },
19     time::TimeSpec,
20 };
21 
22 #[macro_export]
23 macro_rules! print {
24     ($($arg:tt)*) => ($crate::libs::printk::__printk(format_args!($($arg)*)));
25 }
26 
27 #[macro_export]
28 macro_rules! println {
29     () => {
30         $crate::print!("\n");
31     };
32     ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
33 }
34 
35 #[macro_export]
36 macro_rules! kdebug {
37     ($($arg:tt)*) => {
38         $crate::libs::printk::Logger.log(7,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
39         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ DEBUG ] ({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)))
40     }
41 }
42 
43 #[macro_export]
44 macro_rules! kinfo {
45     ($($arg:tt)*) => {
46         $crate::libs::printk::Logger.log(6,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
47         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ INFO ] ({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)))
48     }
49 }
50 
51 #[macro_export]
52 macro_rules! kwarn {
53     ($($arg:tt)*) => {
54         $crate::libs::printk::Logger.log(4,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
55         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[1;33m[ WARN ] \x1B[0m"));
56         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
57     }
58 }
59 
60 #[macro_export]
61 macro_rules! kerror {
62     ($($arg:tt)*) => {
63         $crate::libs::printk::Logger.log(3,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
64         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[41m[ ERROR ] \x1B[0m"));
65         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
66     }
67 }
68 
69 #[macro_export]
70 macro_rules! kBUG {
71     ($($arg:tt)*) => {
72         $crate::libs::printk::Logger.log(1,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
73         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("\x1B[41m[ BUG ] \x1B[0m"));
74         $crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
75     }
76 }
77 
78 pub struct PrintkWriter;
79 
80 impl PrintkWriter {
81     #[inline]
82     pub fn __write_fmt(&mut self, args: fmt::Arguments) {
83         self.write_fmt(args).ok();
84     }
85 
86     /// 并输出白底黑字
87     /// @param str: 要写入的字符
88     pub fn __write_string(&mut self, s: &str) {
89         let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst);
90         if current_vcnum != -1 {
91             // tty已经初始化了之后才输出到屏幕
92             let port = TTY_PORTS[current_vcnum as usize].clone();
93             let tty = port.port_data().tty();
94             if let Some(tty) = tty {
95                 let _ = tty.write(tty.core(), s.as_bytes(), s.len());
96             } else {
97                 let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK);
98             }
99         } else {
100             let _ = textui_putstr(s, FontColor::WHITE, FontColor::BLACK);
101         }
102     }
103 }
104 
105 /// 为Printk Writer实现core::fmt::Write, 使得能够借助Rust自带的格式化组件,格式化字符并输出
106 impl fmt::Write for PrintkWriter {
107     fn write_str(&mut self, s: &str) -> fmt::Result {
108         self.__write_string(s);
109         Ok(())
110     }
111 }
112 
113 #[doc(hidden)]
114 pub fn __printk(args: fmt::Arguments) {
115     PrintkWriter.write_fmt(args).unwrap();
116 }
117 
118 pub struct Logger;
119 
120 impl Logger {
121     pub fn log(&self, log_level: usize, message: fmt::Arguments) {
122         if unsafe { KMSG.is_some() } {
123             let timestamp: TimeSpec = TimeSpec::now();
124             let log_level = LogLevel::from(log_level);
125 
126             let log_message = LogMessage::new(timestamp, log_level, message.to_string());
127 
128             unsafe { KMSG.as_ref().unwrap().lock_irqsave().push(log_message) };
129         }
130     }
131 }
132