增加内核日志功能 #3
|
@ -46,7 +46,6 @@ metaverse.elf: kernel libk rust metaverse.lds
|
|||
@echo -e "\e[1;33mld\e[0m \e[1;32m$@\e[0m \e[34m<--\e[0m \e[32m${SUBOBJS}\e[0m"
|
||||
@ld -T metaverse.lds -Map=metaverse.map -unresolved-symbols=ignore-all -o $@ ${SUBOBJS} ${RUST_LIBS} \
|
||||
2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow"
|
||||
@strip $@
|
||||
|
||||
.PHONY: kernel libk all clear postproc rust
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use core::{cmp::Ordering, ops::Sub, time::Duration};
|
||||
|
||||
use alloc::{format, string::ToString};
|
||||
use alloc::string::ToString;
|
||||
|
||||
use crate::format;
|
||||
|
||||
extern "C" {
|
||||
fn system_time_get() -> usize;
|
||||
|
@ -96,7 +98,7 @@ impl ToString for SystemTime {
|
|||
let milisec = second % second_dur;
|
||||
second /= second_dur;
|
||||
format!(
|
||||
"[{:02}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}]",
|
||||
"[ {}-{}-{} {}:{}:{}.{} ]",
|
||||
year, month, day, hour, minute, second, milisec
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use alloc::string::ToString;
|
||||
use alloc::{format, vec::Vec};
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use super::{
|
||||
clock::time::SystemTime,
|
||||
|
@ -40,125 +40,157 @@ impl KernelLogger {
|
|||
|
||||
pub fn fatal(&mut self, msg: Message) {
|
||||
let msg = MessageBuilder::new()
|
||||
.message("Fatal: ".to_string())
|
||||
.message("Fatal: ")
|
||||
.foreground_color(Color(0xee, 0xa, 0xa))
|
||||
.append(MessageBuilder::from_message(&msg))
|
||||
.append(MessageBuilder::from_message(msg))
|
||||
.build();
|
||||
self.fatal_queue.push((SystemTime::now(), msg));
|
||||
}
|
||||
|
||||
pub fn error(&mut self, msg: Message) {
|
||||
let msg = MessageBuilder::new()
|
||||
.message("Error: ".to_string())
|
||||
.message("Error: ")
|
||||
.foreground_color(Color(0xaa, 0x22, 0x22))
|
||||
.append(MessageBuilder::from_message(&msg))
|
||||
.append(MessageBuilder::from_message(msg))
|
||||
.build();
|
||||
self.error_queue.push((SystemTime::now(), msg));
|
||||
}
|
||||
|
||||
pub fn warning(&mut self, msg: Message) {
|
||||
let msg = MessageBuilder::new()
|
||||
.message("Warning: ".to_string())
|
||||
.message("Warning: ")
|
||||
.foreground_color(Color(0xaa, 0xa, 0xaa))
|
||||
.append(MessageBuilder::from_message(&msg))
|
||||
.append(MessageBuilder::from_message(msg))
|
||||
.build();
|
||||
self.warning_queue.push((SystemTime::now(), msg));
|
||||
}
|
||||
|
||||
pub fn info(&mut self, msg: Message) {
|
||||
let msg = MessageBuilder::new()
|
||||
.message("Info: ".to_string())
|
||||
.message("Info: ")
|
||||
.foreground_color(Color(0xa, 0xee, 0xa))
|
||||
.append(MessageBuilder::from_message(&msg))
|
||||
.append(MessageBuilder::from_message(msg))
|
||||
.build();
|
||||
self.info_queue.push((SystemTime::now(), msg));
|
||||
}
|
||||
|
||||
pub fn debug(&mut self, msg: Message) {
|
||||
let msg = MessageBuilder::new()
|
||||
.message("Debug: ".to_string())
|
||||
.message("Debug: ")
|
||||
.foreground_color(Color(0xee, 0xee, 0xee))
|
||||
.append(MessageBuilder::from_message(&msg))
|
||||
.append(MessageBuilder::from_message(msg))
|
||||
.build();
|
||||
self.debug_queue.push((SystemTime::now(), msg));
|
||||
}
|
||||
|
||||
pub fn trace(&mut self, msg: Message) {
|
||||
let msg = MessageBuilder::new()
|
||||
.message("Trace: ".to_string())
|
||||
.message("Trace: ")
|
||||
.foreground_color(Color(0xee, 0xee, 0xee))
|
||||
.append(MessageBuilder::from_message(&msg))
|
||||
.append(MessageBuilder::from_message(msg))
|
||||
.build();
|
||||
self.trace_queue.push((SystemTime::now(), msg));
|
||||
}
|
||||
|
||||
pub fn iter(&self, level: LoggerLevel) -> LogIterator {
|
||||
let mut logs = vec![];
|
||||
if level == LoggerLevel::Fatal {
|
||||
match level {
|
||||
LoggerLevel::Fatal => {
|
||||
logs.push(&self.fatal_queue);
|
||||
}
|
||||
if level == LoggerLevel::Fatal || level == LoggerLevel::Error {
|
||||
LoggerLevel::Error => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
}
|
||||
if level == LoggerLevel::Fatal
|
||||
|| level == LoggerLevel::Error
|
||||
|| level == LoggerLevel::Warning
|
||||
{
|
||||
LoggerLevel::Warning => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
logs.push(&self.warning_queue);
|
||||
}
|
||||
if level == LoggerLevel::Fatal
|
||||
|| level == LoggerLevel::Error
|
||||
|| level == LoggerLevel::Warning
|
||||
|| level == LoggerLevel::Info
|
||||
{
|
||||
LoggerLevel::Info => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
logs.push(&self.warning_queue);
|
||||
logs.push(&self.info_queue);
|
||||
}
|
||||
if level == LoggerLevel::Fatal
|
||||
|| level == LoggerLevel::Error
|
||||
|| level == LoggerLevel::Warning
|
||||
|| level == LoggerLevel::Info
|
||||
|| level == LoggerLevel::Debug
|
||||
{
|
||||
LoggerLevel::Debug => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
logs.push(&self.warning_queue);
|
||||
logs.push(&self.info_queue);
|
||||
logs.push(&self.debug_queue);
|
||||
}
|
||||
if level == LoggerLevel::Fatal
|
||||
|| level == LoggerLevel::Error
|
||||
|| level == LoggerLevel::Warning
|
||||
|| level == LoggerLevel::Info
|
||||
|| level == LoggerLevel::Debug
|
||||
|| level == LoggerLevel::Trace
|
||||
{
|
||||
LoggerLevel::Trace => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
logs.push(&self.warning_queue);
|
||||
logs.push(&self.info_queue);
|
||||
logs.push(&self.debug_queue);
|
||||
logs.push(&self.trace_queue);
|
||||
}
|
||||
}
|
||||
let mut res = vec![];
|
||||
while let Some(msg) = {
|
||||
logs.iter_mut()
|
||||
.filter_map(|&mut l| l.first().cloned())
|
||||
.min_by_key(|&(syst, _)| syst)
|
||||
} {
|
||||
res.push(msg);
|
||||
let mut indeces = Vec::new();
|
||||
for _ in 0..logs.len() {
|
||||
indeces.push(0usize);
|
||||
}
|
||||
let all_end = |indeces: &Vec<usize>, logs: &Vec<&Vec<(SystemTime, Message)>>| {
|
||||
for i in 0..indeces.len() {
|
||||
if indeces[i] < logs.len() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
while !all_end(&indeces, &logs) {
|
||||
let mut min_ind = None;
|
||||
let mut min = None;
|
||||
for i in 0..indeces.len() {
|
||||
if indeces[i] >= logs[i].len() {
|
||||
continue;
|
||||
}
|
||||
if let Some(minx) = min.as_mut() {
|
||||
if logs[i][indeces[i]].0 < *minx {
|
||||
*minx = logs[i][indeces[i]].0;
|
||||
min_ind = Some(i);
|
||||
}
|
||||
} else {
|
||||
min = Some(logs[i][indeces[i]].0);
|
||||
min_ind = Some(i);
|
||||
}
|
||||
}
|
||||
if let Some(mini) = min_ind {
|
||||
res.push(&logs[mini][indeces[mini]]);
|
||||
indeces[mini] += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
LogIterator { logs: res }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LogIterator {
|
||||
logs: Vec<(SystemTime, Message)>,
|
||||
pub struct LogIterator<'a> {
|
||||
logs: Vec<&'a (SystemTime, Message)>,
|
||||
}
|
||||
|
||||
impl Iterator for LogIterator {
|
||||
impl<'a> Iterator for LogIterator<'a> {
|
||||
type Item = Message;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some((time, msg)) = self.logs.first() {
|
||||
let res = if let Some((time, msg)) = self.logs.first() {
|
||||
Some(
|
||||
MessageBuilder::new()
|
||||
.message(format!("{}", time.to_string()))
|
||||
.append(MessageBuilder::from_message(msg))
|
||||
.message(&time.to_string())
|
||||
.append(MessageBuilder::from_message(msg.clone()))
|
||||
.build(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
if let Some(_) = res {
|
||||
self.logs.remove(0);
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
use crate::message;
|
||||
|
||||
use super::{
|
||||
klog::{KernelLogger, LoggerLevel},
|
||||
tty::tty::{Color, ColorPair, Message, Tty},
|
||||
tty::tty::{BuilderFunctions::*, Color, Tty},
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn kmain_rust() {
|
||||
let mut logger = KernelLogger::new();
|
||||
logger.info(Message::from(format!(
|
||||
"Hello, {:?}Metaverse{:?}!",
|
||||
ColorPair::color(Color(0xa, 0xee, 0xa), Color(0, 0, 0)),
|
||||
ColorPair::Reset
|
||||
)));
|
||||
extern "C" fn kmain_rust() -> ! {
|
||||
let tty = Tty::from_id(0).unwrap();
|
||||
tty.enable();
|
||||
let mut logger = KernelLogger::new();
|
||||
logger.info(message!(
|
||||
Msg("Hello, "),
|
||||
Msg("Metaverse"),
|
||||
FgColor(Color(0xa, 0xee, 0xa)),
|
||||
Msg("!\n")
|
||||
));
|
||||
for msg in logger.iter(LoggerLevel::Info) {
|
||||
tty.print(msg);
|
||||
}
|
||||
|
|
|
@ -405,7 +405,7 @@ u64 font[256][64] = {
|
|||
0b00000000,
|
||||
0b00011000, ///
|
||||
0b00101000,
|
||||
0b01001000,
|
||||
0b00001000,
|
||||
0b00001000,
|
||||
0b00001000,
|
||||
0b00001000,
|
||||
|
|
|
@ -1 +1,46 @@
|
|||
pub mod tty;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! message_msg {
|
||||
() => {};
|
||||
( $builder : expr, $e : expr) => {
|
||||
$builder.message_mut($e);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! message_fgc {
|
||||
() => {};
|
||||
( $builder : expr, $e : expr) => {
|
||||
$builder.foreground_color_mut($e);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! message_bgc {
|
||||
() => {};
|
||||
( $builder : expr, $e : expr ) => {
|
||||
$builder.background_color_mut($e);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! message {
|
||||
( $( $e : expr ),* ) => {{
|
||||
use crate::{
|
||||
kernel::tty::tty::{MessageBuilder, BuilderFunctions},
|
||||
message_msg, message_fgc, message_bgc
|
||||
};
|
||||
let mut tmp_builder = MessageBuilder::new();
|
||||
$(
|
||||
if let BuilderFunctions::Msg(e) = $e {
|
||||
message_msg!(tmp_builder, e);
|
||||
} else if let BuilderFunctions::FgColor(c) = $e {
|
||||
message_fgc!(tmp_builder, c);
|
||||
} else if let BuilderFunctions::BgColor(c) = $e {
|
||||
message_bgc!(tmp_builder, c);
|
||||
}
|
||||
)*
|
||||
tmp_builder.build()
|
||||
}};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use core::ptr::null_mut;
|
||||
|
||||
use alloc::{
|
||||
format,
|
||||
string::{String, ToString},
|
||||
vec,
|
||||
vec::Vec,
|
||||
|
@ -145,38 +144,6 @@ impl Tty {
|
|||
#[derive(Clone, Copy)]
|
||||
pub struct Color(pub u8, pub u8, pub u8);
|
||||
|
||||
impl ToString for Color {
|
||||
fn to_string(&self) -> String {
|
||||
format!("{:02x}{:02x}{:02x}", self.0, self.1, self.2)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ColorPair {
|
||||
Reset,
|
||||
Color { fore: Color, back: Color },
|
||||
}
|
||||
|
||||
impl ColorPair {
|
||||
pub fn reset() -> Self {
|
||||
ColorPair::Reset
|
||||
}
|
||||
|
||||
pub fn color(fore: Color, back: Color) -> Self {
|
||||
ColorPair::Color { fore, back }
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for ColorPair {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
ColorPair::Reset => format!("\x1b{{}}"),
|
||||
ColorPair::Color { fore, back } => {
|
||||
format!("\x1b{{{}{}}}", fore.to_string(), back.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for u32 {
|
||||
fn from(value: Color) -> Self {
|
||||
let res = (value.0 as u32) << 16 | (value.1 as u32) << 8 | (value.2 as u32);
|
||||
|
@ -196,71 +163,46 @@ pub struct MessageSection {
|
|||
bgcolor: Color,
|
||||
}
|
||||
|
||||
/// ## Message
|
||||
///
|
||||
/// 用`MessageBuilder`构造一个`Message`对象
|
||||
#[derive(Clone)]
|
||||
pub struct Message(Vec<MessageSection>);
|
||||
|
||||
impl From<String> for Message {
|
||||
fn from(value: String) -> Self {
|
||||
let mut res = MessageBuilder::new();
|
||||
let mut msg = String::new();
|
||||
let mut color = ColorPair::Reset;
|
||||
let mut coloring = false;
|
||||
|
||||
let mut colorp_str = String::new();
|
||||
|
||||
for c in value.as_bytes() {
|
||||
if *c as char == '\x1b' {
|
||||
coloring = true;
|
||||
res.message_mut(msg.clone());
|
||||
msg.clear();
|
||||
if let ColorPair::Color { fore, back } = color {
|
||||
res.foreground_color_mut(fore);
|
||||
res.background_color_mut(back);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if coloring {
|
||||
if *c as char == '{' {
|
||||
colorp_str.clear();
|
||||
} else if *c as char == '}' {
|
||||
if colorp_str.is_empty() {
|
||||
color = ColorPair::Reset;
|
||||
} else {
|
||||
let bts = colorp_str.as_bytes();
|
||||
let r = bts[0] << 4 + bts[1];
|
||||
let g = bts[2] << 4 + bts[3];
|
||||
let b = bts[4] << 4 + bts[5];
|
||||
let fore = Color(r, g, b);
|
||||
let r = bts[6] << 4 + bts[7];
|
||||
let g = bts[8] << 4 + bts[9];
|
||||
let b = bts[10] << 4 + bts[11];
|
||||
let back = Color(r, g, b);
|
||||
color = ColorPair::Color { fore, back };
|
||||
}
|
||||
coloring = false;
|
||||
} else {
|
||||
colorp_str.push(*c as char);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
msg.push(*c as char);
|
||||
}
|
||||
if !msg.is_empty() {
|
||||
res.message_mut(msg.clone());
|
||||
msg.clear();
|
||||
if let ColorPair::Color { fore, back } = color {
|
||||
res.foreground_color_mut(fore);
|
||||
res.background_color_mut(back);
|
||||
}
|
||||
}
|
||||
res.build()
|
||||
}
|
||||
}
|
||||
|
||||
/// ## MessageBuilder
|
||||
///
|
||||
/// 使用链式调用模式构造一个消息.
|
||||
///
|
||||
/// 一个`Message`包含多个`MessageSection`,每个`MessageSection`以`message()`调用开始,
|
||||
/// `message()`调用后可接0个或多个属性设置。
|
||||
///
|
||||
/// ```rust
|
||||
/// MessageBuilder::new()
|
||||
/// .message("Hello, ")
|
||||
/// .message("Metaverse").foreground_color(Color(0xa, 0xee, 0xa))
|
||||
/// .message("!\n")
|
||||
/// .build();
|
||||
/// ```
|
||||
///
|
||||
/// 对于特殊情况可以使用非链式调用:
|
||||
/// ```rust
|
||||
/// let mut msg = MessageBuilder::new();
|
||||
/// msg.message_mut("Hello, ");
|
||||
/// msg.message_mut("Metaverse");
|
||||
/// msg.foreground_color(Color(0xa, 0xee, 0xa));
|
||||
/// msg.message_mut("!\n");
|
||||
/// let msg = msg.build();
|
||||
/// ```
|
||||
pub struct MessageBuilder {
|
||||
msg: Message,
|
||||
}
|
||||
|
||||
pub enum BuilderFunctions<'a> {
|
||||
Msg(&'a str),
|
||||
FgColor(Color),
|
||||
BgColor(Color),
|
||||
}
|
||||
|
||||
impl MessageBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
@ -268,22 +210,22 @@ impl MessageBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_message(msg: &Message) -> Self {
|
||||
Self { msg: msg.clone() }
|
||||
pub fn from_message(msg: Message) -> Self {
|
||||
Self { msg }
|
||||
}
|
||||
|
||||
pub fn message(mut self, msg: String) -> Self {
|
||||
pub fn message(mut self, msg: &str) -> Self {
|
||||
self.msg.0.push(MessageSection {
|
||||
msg,
|
||||
msg: msg.to_string(),
|
||||
fgcolor: Color(0xee, 0xee, 0xee),
|
||||
bgcolor: Color(0, 0, 0),
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
pub fn message_mut(&mut self, msg: String) {
|
||||
pub fn message_mut(&mut self, msg: &str) {
|
||||
self.msg.0.push(MessageSection {
|
||||
msg,
|
||||
msg: msg.to_string(),
|
||||
fgcolor: Color(0xee, 0xee, 0xee),
|
||||
bgcolor: Color(0, 0, 0),
|
||||
});
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
pub mod string;
|
|
@ -0,0 +1,38 @@
|
|||
use alloc::string::{String, ToString};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! format {
|
||||
( $s : expr, $( $e : expr ),* ) => {{
|
||||
use crate::libk::string::format::Format;
|
||||
let mut res = $s.to_string();
|
||||
$(
|
||||
res.format($e);
|
||||
)*
|
||||
res
|
||||
}};
|
||||
() => {};
|
||||
}
|
||||
|
||||
pub trait Format<T: ToString> {
|
||||
fn format(&mut self, f: T);
|
||||
}
|
||||
|
||||
impl<T: ToString> Format<T> for String {
|
||||
fn format(&mut self, f: T) {
|
||||
let mut res = String::new();
|
||||
let mut formatting = false;
|
||||
for c in self.chars().into_iter() {
|
||||
if c == '{' {
|
||||
formatting = true;
|
||||
res += &f.to_string();
|
||||
} else if c == '}' {
|
||||
formatting = false;
|
||||
}
|
||||
if !formatting {
|
||||
res.push(c);
|
||||
}
|
||||
}
|
||||
self.clear();
|
||||
self.push_str(&res);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
pub mod format;
|
Reference in New Issue