增加内核日志功能 #3

Merged
pointer-to-bios merged 17 commits from pointer-to-bios/metaverse-dev:main into main 2024-02-05 22:10:26 +08:00
10 changed files with 233 additions and 169 deletions
Showing only changes of commit d931f612f8 - Show all commits

View File

@ -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

View File

@ -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
)
}

View File

@ -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
}
}

View File

@ -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);
}

View File

@ -405,7 +405,7 @@ u64 font[256][64] = {
0b00000000,
0b00011000, ///
0b00101000,
0b01001000,
0b00001000,
0b00001000,
0b00001000,
0b00001000,

View File

@ -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()
}};
}

View File

@ -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),
});

View File

@ -0,0 +1 @@
pub mod string;

View File

@ -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);
}
}

1
src/libk/string/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod format;