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