增加内核日志功能 #3
|
@ -1,3 +1,3 @@
|
|||
[submodule "rustlib"]
|
||||
path = rustlib
|
||||
url = http://git.suthby.org:2024/metaverse/kernel-release.git
|
||||
url = http://git.suthby.org:2024/metaverse/rustenv
|
||||
|
|
|
@ -2,3 +2,9 @@
|
|||
name = "metaverse"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# 此Cargo.toml仅用于rust-analyzer识别rust部分的代码
|
||||
# 不应使用cargo编译
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")']
|
||||
target = "x86_64-unknown-none"
|
||||
|
|
|
@ -56,7 +56,7 @@ make debug
|
|||
* [x] 内存分配器
|
||||
* [x] raw_allocator
|
||||
* [x] tty
|
||||
* [ ] 内核日志
|
||||
* [x] 内核日志
|
||||
* [ ] 文件系统
|
||||
* [ ] vfs
|
||||
* [ ] fat32驱动(移植)
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef TIME_H
|
||||
#define TIME_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
// 使用UNIX时间戳
|
||||
usize system_time_get();
|
||||
|
||||
// 如果硬件支持更高的计时精度,
|
||||
// 此函数提供从系统unix时间开始到现在的纳秒为单位的时间
|
||||
usize system_time_ns_get();
|
||||
|
||||
void system_time_increase();
|
||||
|
||||
#endif
|
|
@ -139,9 +139,13 @@ allocator对象在进程与内核之间传递时一律使用内核空间的映
|
|||
*/
|
||||
void *memm_allocate(usize size, usize pid);
|
||||
#define memm_addr_set_allocator(mem, allocator) \
|
||||
*(allocator_t **)(mem - 16) = allocator;
|
||||
*(allocator_t **)((void *)(mem) - 16) = allocator;
|
||||
#define memm_addr_get_allocator(mem) \
|
||||
((*(allocator_t **)(mem - 16)))
|
||||
((*(allocator_t **)((void *)(mem) - 16)))
|
||||
|
||||
void *memm_kernel_allocate(usize size);
|
||||
|
||||
void *memm_user_allocate(usize size, usize pid);
|
||||
|
||||
/*
|
||||
释放内存
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
typedef enum __tty_type
|
||||
{
|
||||
invalid = 0,
|
||||
tty_type_invalid = 0,
|
||||
// 用于在内核刚刚被引导,只有bootloader提供的显示功能时使用
|
||||
tty_type_raw_framebuffer = 1,
|
||||
// 用于图形功能初始化后,直接连接图形接口
|
||||
tty_type_display = 2,
|
||||
// 用于图形终端的终端模拟器
|
||||
tty_type_vtty = 3,
|
||||
tty_type_vterm = 3,
|
||||
} tty_type;
|
||||
|
||||
typedef enum __framebuffer_pixel_type
|
||||
|
@ -40,8 +40,9 @@ typedef struct __framebuffer framebuffer;
|
|||
// 文本模式中的字符由tty模块渲染
|
||||
typedef enum __tty_mode
|
||||
{
|
||||
tty_mode_text = 0,
|
||||
tty_mode_graphics = 1,
|
||||
tty_mode_invalid = 0,
|
||||
tty_mode_text = 1,
|
||||
tty_mode_graphics = 2,
|
||||
} tty_mode;
|
||||
|
||||
typedef struct __tty_text_state
|
||||
|
@ -55,9 +56,11 @@ typedef struct __tty_text_state
|
|||
typedef struct __tty
|
||||
{
|
||||
usize id;
|
||||
usize width, height;
|
||||
tty_type type;
|
||||
tty_typeinfo typeinfo;
|
||||
tty_mode mode;
|
||||
bool enabled;
|
||||
tty_text_state text;
|
||||
} tty;
|
||||
|
||||
|
@ -67,6 +70,7 @@ typedef struct __tty_controller_t
|
|||
#define TTY_MAX_NUM 128
|
||||
tty *ttys[TTY_MAX_NUM];
|
||||
bool map[TTY_MAX_NUM];
|
||||
tty *enabled[TTY_MAX_NUM];
|
||||
} tty_controller_t;
|
||||
|
||||
/**
|
||||
|
@ -118,6 +122,26 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor);
|
|||
|
||||
#define gen_color(r, g, b) (((r) << 16) | ((g) << 8) | (b))
|
||||
|
||||
usize tty_get_width(tty *ttyx);
|
||||
usize tty_get_height(tty *ttyx);
|
||||
|
||||
tty_type tty_get_type(tty *ttyx);
|
||||
tty_mode tty_get_mode(tty *ttyx);
|
||||
|
||||
bool tty_is_enabled(tty *ttyx);
|
||||
|
||||
/**
|
||||
* @brief 打开某个tty
|
||||
*
|
||||
* @param ttyx
|
||||
* @return true 打开成功
|
||||
* @return false 已经打开
|
||||
* 或作为raw_framebuffer类型的tty,framebuffer已被其它raw_framebuffer
|
||||
* 类型的tty占用
|
||||
*/
|
||||
bool tty_enable(tty *ttyx);
|
||||
void tty_disable(tty *ttyx);
|
||||
|
||||
#define TTY_FONT_SCALE 2
|
||||
|
||||
typedef struct __tty_font_t
|
||||
|
|
2
rustlib
2
rustlib
|
@ -1 +1 @@
|
|||
Subproject commit f8d0d53a23b5a91848d8f6491122b69f79994537
|
||||
Subproject commit 087c4795bbc23cd0baee060bda8c1159a971a542
|
29
src/Makefile
29
src/Makefile
|
@ -22,28 +22,29 @@ endif
|
|||
################################
|
||||
# rust语言环境变量
|
||||
|
||||
RSCFLAGS = --emit obj --crate-type lib \
|
||||
RSCFLAGS = --emit obj --crate-type staticlib --verbose \
|
||||
--crate-name=metaverse \
|
||||
--edition 2021 \
|
||||
-L crate="${PWD}/../rustlib/${ARCH}/src/" \
|
||||
-C code-model=large \
|
||||
-C relocation-model=static \
|
||||
-C embed-bitcode=no \
|
||||
-C opt-level=z
|
||||
-C embed-bitcode=no
|
||||
|
||||
ifeq (${ARCH},x86_64)
|
||||
RSCFLAGS := ${RSCFLAGS} -C target-feature=-sse,-avx
|
||||
RSCFLAGS := ${RSCFLAGS} --target x86_64-unknown-none
|
||||
endif
|
||||
|
||||
ifdef release
|
||||
RSCFLAGS := -O
|
||||
endif
|
||||
|
||||
ifeq (${ARCH},x86_64)
|
||||
RSCFLAGS := ${RSCFLAGS} -C target-feature=-sse
|
||||
endif
|
||||
|
||||
RUSTLIB_PATH = ../rustlib/${ARCH}/lib
|
||||
RUST_LIBS = "${RUSTLIB_PATH}/libaddr2line.rlib" "${RUSTLIB_PATH}/libadler.rlib" \
|
||||
"${RUSTLIB_PATH}/liballoc.rlib" "${RUSTLIB_PATH}/libcfg_if.rlib" "${RUSTLIB_PATH}/libcompiler_builtins.rlib" \
|
||||
"${RUSTLIB_PATH}/libcore.rlib" "${RUSTLIB_PATH}/libgetopts.rlib" "${RUSTLIB_PATH}/libgimli.rlib" \
|
||||
"${RUSTLIB_PATH}/libhashbrown.rlib" "${RUSTLIB_PATH}/libmemchr.rlib" "${RUSTLIB_PATH}/libminiz_oxide.rlib" \
|
||||
"${RUSTLIB_PATH}/libobject.rlib" "${RUSTLIB_PATH}/libpanic_abort.rlib" "${RUSTLIB_PATH}/libpanic_unwind.rlib" \
|
||||
"${RUSTLIB_PATH}/libproc_macro.rlib" "${RUSTLIB_PATH}/libprofiler_builtins.rlib" \
|
||||
"${RUSTLIB_PATH}/librustc_demangle.rlib" "${RUSTLIB_PATH}/librustc_std_workspace_alloc.rlib" \
|
||||
"${RUSTLIB_PATH}/librustc_std_workspace_core.rlib" "${RUSTLIB_PATH}/librustc_std_workspace_std.rlib" \
|
||||
"${RUSTLIB_PATH}/libstd_detect.rlib" "${RUSTLIB_PATH}/libstd.rlib" "${RUSTLIB_PATH}/libsysroot.rlib" \
|
||||
"${RUSTLIB_PATH}/libtest.rlib" "${RUSTLIB_PATH}/libunicode_width.rlib" "${RUSTLIB_PATH}/libunwind.rlib"
|
||||
RUST_LIBS = "${RUSTLIB_PATH}/liballoc.rlib" "${RUSTLIB_PATH}/libcompiler_builtins.rlib" \
|
||||
"${RUSTLIB_PATH}/libcore.rlib" "${RUSTLIB_PATH}/librustc_std_workspace_core.rlib"
|
||||
|
||||
################################
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ ifdef release
|
|||
CCFLAGS := ${CCFLAGS} -O2
|
||||
endif
|
||||
|
||||
C_SRCS = main.c tty.c font.c memm.c memm_${ARCH}.c raw.c
|
||||
C_SRCS = main.c tty.c font.c memm.c memm_${ARCH}.c raw.c time.c
|
||||
C_OBJS = ${C_SRCS:.c=.c.o}
|
||||
|
||||
################################
|
||||
|
@ -38,7 +38,7 @@ STRIP_SECS = -R .note.GNU-stack
|
|||
OBJCOPY_FLAGS = ${STRIP_SECS}
|
||||
|
||||
# 子目录
|
||||
VPATH = memm/ memm/allocator tty/ klog/ arch/${ARCH}
|
||||
VPATH = memm/ memm/allocator tty/ klog/ arch/${ARCH} clock/
|
||||
|
||||
%.c.o: %.c
|
||||
@echo -e "\e[1m\e[33m${CC}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
|
||||
|
|
|
@ -39,10 +39,6 @@ multiboot2_header:
|
|||
dd 8
|
||||
multiboot2_header_end:
|
||||
|
||||
section .kstack
|
||||
kstack:
|
||||
resb 0x1000000 - 0x400000
|
||||
|
||||
section .kend
|
||||
global kend
|
||||
kend:
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
pub mod time;
|
|
@ -0,0 +1,20 @@
|
|||
#include <kernel/clock/time.h>
|
||||
#include <types.h>
|
||||
|
||||
usize system_time;
|
||||
usize system_time_ns;
|
||||
|
||||
usize system_time_get()
|
||||
{
|
||||
return system_time;
|
||||
}
|
||||
|
||||
usize system_time_ns_get()
|
||||
{
|
||||
return system_time_ns;
|
||||
}
|
||||
|
||||
void system_time_increase()
|
||||
{
|
||||
system_time++;
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
use core::{cmp::Ordering, ops::Sub, time::Duration};
|
||||
|
||||
use alloc::{format, string::ToString};
|
||||
|
||||
extern "C" {
|
||||
fn system_time_get() -> usize;
|
||||
fn system_time_ns_get() -> usize;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SystemTimeError(Duration);
|
||||
|
||||
#[derive(Clone, Copy, Hash)]
|
||||
pub struct SystemTime {
|
||||
unix_time: usize,
|
||||
ns_time: usize,
|
||||
}
|
||||
|
||||
impl ToString for SystemTime {
|
||||
fn to_string(&self) -> alloc::string::String {
|
||||
let second_dur = 1000usize;
|
||||
let minute_dur = second_dur * 60;
|
||||
let hour_dur = minute_dur * 60;
|
||||
let day_dur = hour_dur * 24;
|
||||
let year_dur = day_dur * 365;
|
||||
let four_year_dur = day_dur * (365 * 4 + 1);
|
||||
|
||||
let year = 1970
|
||||
+ self.unix_time / four_year_dur * 4
|
||||
+ if self.unix_time % four_year_dur < day_dur * 59 {
|
||||
0
|
||||
} else {
|
||||
(self.unix_time % four_year_dur - day_dur) / year_dur
|
||||
};
|
||||
let rest = self.unix_time % four_year_dur;
|
||||
let mut leap = false;
|
||||
let rest = if rest < day_dur * 59 {
|
||||
rest
|
||||
} else {
|
||||
if rest < 60 {
|
||||
leap = true;
|
||||
}
|
||||
rest - day_dur
|
||||
};
|
||||
let month = rest % year_dur;
|
||||
let mut day = 0;
|
||||
let month = if month < 31 * day_dur {
|
||||
day = month;
|
||||
1
|
||||
} else if month < (31 + 28) * day_dur {
|
||||
day = month - 31 * day_dur;
|
||||
2
|
||||
} else if month < (31 + 28 + 31) * day_dur {
|
||||
day = month - (31 + 28) * day_dur;
|
||||
3
|
||||
} else if month < (31 + 28 + 31 + 30) * day_dur {
|
||||
day = month - (31 + 28 + 31) * day_dur;
|
||||
4
|
||||
} else if month < (31 + 28 + 31 + 30 + 31) * day_dur {
|
||||
day = month - (31 + 28 + 31 + 30) * day_dur;
|
||||
5
|
||||
} else if month < (31 + 28 + 31 + 30 + 31 + 30) * day_dur {
|
||||
day = month - (31 + 28 + 31 + 30 + 31) * day_dur;
|
||||
6
|
||||
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31) * day_dur {
|
||||
day = month - (31 + 28 + 31 + 30 + 31 + 30) * day_dur;
|
||||
7
|
||||
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31) * day_dur {
|
||||
day = month - (31 + 28 + 31 + 30 + 31 + 30 + 31) * day_dur;
|
||||
8
|
||||
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30) * day_dur {
|
||||
day = month - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31) * day_dur;
|
||||
9
|
||||
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31) * day_dur {
|
||||
day = month - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30) * day_dur;
|
||||
10
|
||||
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30) * day_dur {
|
||||
day = month - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31) * day_dur;
|
||||
11
|
||||
} else if month < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31) * day_dur {
|
||||
day = month - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30) * day_dur;
|
||||
12
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let mut hour = day % day_dur;
|
||||
day /= day_dur;
|
||||
day += 1;
|
||||
if leap {
|
||||
day += 1;
|
||||
}
|
||||
let mut minute = hour % hour_dur;
|
||||
hour /= hour_dur;
|
||||
let mut second = minute % minute_dur;
|
||||
minute /= minute_dur;
|
||||
let milisec = second % second_dur;
|
||||
second /= second_dur;
|
||||
format!(
|
||||
"[ {}-{}-{} {}:{}:{}.{} ] ",
|
||||
year, month, day, hour, minute, second, milisec
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for SystemTime {}
|
||||
impl PartialEq for SystemTime {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.unix_time == other.unix_time && self.ns_time == other.ns_time
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for SystemTime {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
match self.unix_time.cmp(&other.unix_time) {
|
||||
Ordering::Equal => self.ns_time.cmp(&other.ns_time),
|
||||
ord => ord,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for SystemTime {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
match self.unix_time.partial_cmp(&other.unix_time) {
|
||||
Some(Ordering::Equal) => self.ns_time.partial_cmp(&other.ns_time),
|
||||
ord => ord,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<SystemTime> for SystemTime {
|
||||
type Output = Result<Duration, SystemTimeError>;
|
||||
|
||||
fn sub(self, rhs: SystemTime) -> Self::Output {
|
||||
if self < rhs {
|
||||
let earl = (rhs - self).unwrap();
|
||||
Err(SystemTimeError(earl))
|
||||
} else {
|
||||
let usdiff = self.ns_time as isize - self.ns_time as isize;
|
||||
let usdiff = if usdiff >= 0 {
|
||||
Duration::from_nanos(usdiff as usize as u64)
|
||||
} else {
|
||||
Duration::from_nanos(0) - Duration::from_nanos((-usdiff) as usize as u64)
|
||||
};
|
||||
Ok(Duration::from_millis((self.unix_time - rhs.unix_time) as u64) + usdiff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub fn now() -> Self {
|
||||
unsafe {
|
||||
Self {
|
||||
unix_time: system_time_get(),
|
||||
ns_time: system_time_ns_get(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn duration_since(&self, earlier: &SystemTime) -> Result<Duration, SystemTimeError> {
|
||||
*self - *earlier
|
||||
}
|
||||
|
||||
pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
|
||||
SystemTime::now() - *self
|
||||
}
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
use alloc::string::ToString;
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use super::{
|
||||
clock::time::SystemTime,
|
||||
tty::tty::{Color, Message, MessageBuilder},
|
||||
};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum LoggerLevel {
|
||||
Fatal,
|
||||
Error,
|
||||
Warning,
|
||||
Info,
|
||||
Debug,
|
||||
Trace,
|
||||
}
|
||||
|
||||
pub struct KernelLogger {
|
||||
fatal_queue: Vec<(SystemTime, Message)>,
|
||||
error_queue: Vec<(SystemTime, Message)>,
|
||||
warning_queue: Vec<(SystemTime, Message)>,
|
||||
info_queue: Vec<(SystemTime, Message)>,
|
||||
debug_queue: Vec<(SystemTime, Message)>,
|
||||
trace_queue: Vec<(SystemTime, Message)>,
|
||||
}
|
||||
|
||||
impl KernelLogger {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
fatal_queue: vec![],
|
||||
error_queue: vec![],
|
||||
warning_queue: vec![],
|
||||
info_queue: vec![],
|
||||
debug_queue: vec![],
|
||||
trace_queue: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fatal(&mut self, msg: Message) {
|
||||
let msg = MessageBuilder::new()
|
||||
.message("Fatal: ")
|
||||
.foreground_color(Color::RED)
|
||||
.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: ")
|
||||
.foreground_color(Color::ORANGE)
|
||||
.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: ")
|
||||
.foreground_color(Color::PURPLE)
|
||||
.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: ")
|
||||
.foreground_color(Color::GREEN)
|
||||
.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: ")
|
||||
.foreground_color(Color::WHITE)
|
||||
.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: ")
|
||||
.foreground_color(Color::WHITE)
|
||||
.append(MessageBuilder::from_message(msg))
|
||||
.build();
|
||||
self.trace_queue.push((SystemTime::now(), msg));
|
||||
}
|
||||
|
||||
pub fn iter(&self, level: LoggerLevel) -> LogIterator {
|
||||
let mut logs = vec![];
|
||||
match level {
|
||||
LoggerLevel::Fatal => {
|
||||
logs.push(&self.fatal_queue);
|
||||
}
|
||||
LoggerLevel::Error => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
}
|
||||
LoggerLevel::Warning => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
logs.push(&self.warning_queue);
|
||||
}
|
||||
LoggerLevel::Info => {
|
||||
logs.push(&self.fatal_queue);
|
||||
logs.push(&self.error_queue);
|
||||
logs.push(&self.warning_queue);
|
||||
logs.push(&self.info_queue);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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![];
|
||||
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<'a> {
|
||||
logs: Vec<&'a (SystemTime, Message)>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for LogIterator<'a> {
|
||||
type Item = Message;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let res = if let Some((time, msg)) = self.logs.first() {
|
||||
Some(
|
||||
MessageBuilder::new()
|
||||
.message(&time.to_string())
|
||||
.append(MessageBuilder::from_message(msg.clone()))
|
||||
.build(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(_) = res {
|
||||
self.logs.remove(0);
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
|
@ -1,18 +1,23 @@
|
|||
use std::panic;
|
||||
use crate::message;
|
||||
|
||||
use crate::kernel::tty::tty::{Color, MessageBuilder, Tty};
|
||||
use super::{
|
||||
klog::{KernelLogger, LoggerLevel},
|
||||
tty::tty::{BuilderFunctions::*, Color, Tty},
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn kmain_rust() {
|
||||
extern "C" fn kmain_rust() -> ! {
|
||||
let tty = Tty::from_id(0).unwrap();
|
||||
// let ttyptr = unsafe { tty.get_c_tty_t() };
|
||||
|
||||
let hello = MessageBuilder::new()
|
||||
.message("Hello, ".to_string())
|
||||
.message("Metaverse".to_string())
|
||||
.foreground_color(Color(0xa, 0xee, 0xa))
|
||||
.message("!\n".to_string())
|
||||
.build();
|
||||
tty.print(hello);
|
||||
tty.enable();
|
||||
let mut logger = KernelLogger::new();
|
||||
logger.info(message!(
|
||||
Msg("Hello, "),
|
||||
Msg("Metaverse"),
|
||||
FgColor(Color::GREEN),
|
||||
Msg("!\n")
|
||||
));
|
||||
for msg in logger.iter(LoggerLevel::Info) {
|
||||
tty.print(msg);
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
|
|
|
@ -17,17 +17,19 @@ void *raw_allocator_allocate(raw_allocator_t *allocator, usize size, usize align
|
|||
{
|
||||
usize real_size = size;
|
||||
align_to(real_size, 16);
|
||||
raw_allocator_cell *cell = allocator->cells;
|
||||
while ((void *)raw_allocator_next_cell(cell) < (void *)allocator + allocator->size)
|
||||
raw_allocator_cell *cell = &allocator->cells;
|
||||
while ((void *)cell < raw_allocator_end(allocator))
|
||||
{
|
||||
while ( // 确保cell指向的内容还在这个allocator内
|
||||
(void *)raw_allocator_next_cell(cell) < raw_allocator_end(allocator) &&
|
||||
(void *)cell < raw_allocator_end(allocator) &&
|
||||
cell->length != 0)
|
||||
{
|
||||
cell = raw_allocator_next_cell(cell);
|
||||
}
|
||||
if (real_size <= cell->capacity)
|
||||
break;
|
||||
else
|
||||
cell = raw_allocator_next_cell(cell);
|
||||
}
|
||||
if ((void *)cell < raw_allocator_end(allocator))
|
||||
goto fitable_cell_finded;
|
||||
|
|
|
@ -192,7 +192,7 @@ void *memm_allocate(usize size, usize pid)
|
|||
MEMM_RAW_ALLOCATOR, pid);
|
||||
allocator = new_allocator;
|
||||
|
||||
allocator_iterator_t *allind = memm_allocate(sizeof(allocator_iterator_t), 0);
|
||||
allocator_iterator_t *allind = memm_kernel_allocate(sizeof(allocator_iterator_t));
|
||||
allind->allocator = new_allocator;
|
||||
allind->left = nullptr;
|
||||
allind->right = nullptr;
|
||||
|
@ -200,15 +200,23 @@ void *memm_allocate(usize size, usize pid)
|
|||
ptr = new_allocator->allocate(&new_allocator->allocator_instance, orgsize, 0);
|
||||
|
||||
after_allocation:
|
||||
if (ptr != nullptr)
|
||||
memm_addr_set_allocator(ptr, allocator);
|
||||
if (pid != 0)
|
||||
{ // TODO 进程管理中应该有一个用户地址-内核地址映射表
|
||||
// 在进程分配时将页映射到用户空间中,并将这个映射关系记录进这个表中
|
||||
// 需要返回的是用户空间的地址
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *memm_kernel_allocate(usize size)
|
||||
{
|
||||
return memm_allocate(size, 0);
|
||||
}
|
||||
|
||||
void *memm_user_allocate(usize size, usize pid)
|
||||
{
|
||||
void *res = memm_allocate(size, pid);
|
||||
// TODO 将内存空间映射到用户空间
|
||||
return res;
|
||||
}
|
||||
|
||||
void memm_free(void *mem)
|
||||
{
|
||||
allocator_t *allocator = memm_addr_get_allocator(mem);
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
extern crate core;
|
||||
|
||||
use core::alloc::{GlobalAlloc, Layout};
|
||||
use core::{
|
||||
alloc::{GlobalAlloc, Layout},
|
||||
ptr::null_mut,
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
pub fn memm_allocate(size: usize, pid: usize) -> *mut u8;
|
||||
pub fn memm_kernel_allocate(size: usize) -> *mut u8;
|
||||
// pub fn memm_user_allocate(size: usize, pid: usize);
|
||||
pub fn memm_free(mem: *mut u8);
|
||||
}
|
||||
|
||||
|
@ -11,7 +15,14 @@ pub struct KernelAllocator {}
|
|||
|
||||
unsafe impl GlobalAlloc for KernelAllocator {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
memm_allocate(layout.size(), 0)
|
||||
let res = memm_kernel_allocate(layout.size());
|
||||
if res == null_mut() {
|
||||
panic!(
|
||||
"Kernel allocator failed to allocate {} byte(s) memory.",
|
||||
layout.size()
|
||||
);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
pub mod clock;
|
||||
pub mod klog;
|
||||
pub mod main;
|
||||
pub mod memm;
|
||||
pub mod tty;
|
||||
pub mod main;
|
||||
pub mod sync;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
pub mod rwlock;
|
|
@ -0,0 +1,129 @@
|
|||
use core::{ops::{Deref, DerefMut}, ptr::null_mut};
|
||||
|
||||
use alloc::{vec, vec::Vec};
|
||||
|
||||
/// ## RwLock<T>
|
||||
/// 读写锁
|
||||
///
|
||||
/// * 对于写入操作:
|
||||
///
|
||||
/// 锁没有占用时,获取锁,并执行闭包。
|
||||
///
|
||||
/// 当锁已经被占用,将闭包悬挂。
|
||||
///
|
||||
/// 释放锁时,将所有悬挂的闭包都执行。
|
||||
///
|
||||
/// 正在释放锁时,`write`方法返回`Err(())`
|
||||
///
|
||||
/// ```
|
||||
/// let num = 6;
|
||||
/// let num = RwLock::new(num);
|
||||
/// if let Err(()) = num.write(
|
||||
/// |n| *n = 10
|
||||
/// ) {}
|
||||
/// let numstr = format!("{}", num.read());
|
||||
/// ````
|
||||
pub struct RwLock<'a, T> {
|
||||
obj: T,
|
||||
locked: bool,
|
||||
dealing_hanged: bool,
|
||||
ptr: *mut RwLockWriteGuard<'a, T>,
|
||||
hanging: Vec<&'a dyn Fn(&mut T)>,
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for RwLock<'_, T> {}
|
||||
unsafe impl<T> Sync for RwLock<'_, T> {}
|
||||
|
||||
impl<'a, T> RwLock<'a, T> {
|
||||
pub fn new(obj: T) -> Self {
|
||||
Self {
|
||||
obj,
|
||||
locked: false,
|
||||
dealing_hanged: false,
|
||||
ptr: null_mut(),
|
||||
hanging: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self) -> RwLockReadGuard<T> {
|
||||
RwLockReadGuard { obj: &self.obj }
|
||||
}
|
||||
|
||||
pub fn write(&'a mut self, f: &'a dyn Fn(&mut T)) -> Result<RwLockWriteGuard<T>, ()> {
|
||||
if self.dealing_hanged {
|
||||
Err(())
|
||||
} else if !self.locked {
|
||||
self.locked = true;
|
||||
f(&mut self.obj);
|
||||
let ptr = { self as *mut RwLock<'a, T> };
|
||||
let obj = &mut self.obj;
|
||||
let mut res = RwLockWriteGuard {
|
||||
obj,
|
||||
ptr,
|
||||
must_deal_hang: false,
|
||||
};
|
||||
self.ptr = &mut res as *mut RwLockWriteGuard<'_, T>;
|
||||
Ok(res)
|
||||
} else {
|
||||
self.hanging.push(f);
|
||||
let ptr = { self as *mut RwLock<'a, T> };
|
||||
let obj = &mut self.obj;
|
||||
Ok(RwLockWriteGuard {
|
||||
obj,
|
||||
ptr,
|
||||
must_deal_hang: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RwLockReadGuard<'a, T> {
|
||||
obj: &'a T,
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for RwLockReadGuard<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.obj
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Drop for RwLockReadGuard<'a, T> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
pub struct RwLockWriteGuard<'a, T> {
|
||||
obj: &'a mut T,
|
||||
ptr: *mut RwLock<'a, T>,
|
||||
must_deal_hang: bool,
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for RwLockWriteGuard<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.obj
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> DerefMut for RwLockWriteGuard<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.obj
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Drop for RwLockWriteGuard<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
if self.must_deal_hang {
|
||||
let p = unsafe { &mut *self.ptr };
|
||||
p.dealing_hanged = true;
|
||||
for f in p.hanging.iter() {
|
||||
f(self.obj);
|
||||
}
|
||||
p.hanging.clear();
|
||||
p.dealing_hanged = false;
|
||||
p.locked = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}};
|
||||
}
|
||||
|
|
|
@ -11,26 +11,29 @@ tty_controller_t *tty_controller_new()
|
|||
{
|
||||
memset(tty_ctrler.ttys, 0, sizeof(tty_ctrler.ttys));
|
||||
memset(tty_ctrler.map, 0, sizeof(tty_ctrler.map));
|
||||
memset(tty_ctrler.enabled, 0, sizeof(tty_ctrler.enabled));
|
||||
return &tty_ctrler;
|
||||
}
|
||||
|
||||
tty *tty_new(tty_type type, tty_mode mode)
|
||||
{
|
||||
tty *__tty = memm_allocate(sizeof(tty), 0);
|
||||
memset(__tty, 0, sizeof(tty));
|
||||
__tty->type = type;
|
||||
__tty->mode = mode;
|
||||
tty *res = nullptr;
|
||||
for (usize i = 0; i < TTY_MAX_NUM; ++i)
|
||||
{
|
||||
if (tty_ctrler.map[i] == false)
|
||||
{
|
||||
res = __tty;
|
||||
__tty->id = i;
|
||||
tty_ctrler.ttys[i] = __tty;
|
||||
res = memm_kernel_allocate(sizeof(tty));
|
||||
res->id = i;
|
||||
tty_ctrler.ttys[i] = res;
|
||||
tty_ctrler.map[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
res->type = type;
|
||||
res->mode = mode;
|
||||
res->enabled = false;
|
||||
res->width = 0;
|
||||
res->height = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -51,10 +54,14 @@ void tty_set_framebuffer(tty *ttyx, framebuffer *fb)
|
|||
if (ttyx->type != tty_type_raw_framebuffer)
|
||||
return;
|
||||
memcpy(&ttyx->typeinfo.raw_framebuffer, fb, sizeof(framebuffer));
|
||||
ttyx->width = ttyx->typeinfo.raw_framebuffer.width;
|
||||
ttyx->height = ttyx->typeinfo.raw_framebuffer.height;
|
||||
if (ttyx->mode == tty_mode_text)
|
||||
{
|
||||
ttyx->text.width = fb->width / tty_get_font()->char_width;
|
||||
ttyx->text.height = fb->height / tty_get_font()->char_height;
|
||||
ttyx->text.line = 0;
|
||||
ttyx->text.column = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +94,8 @@ inline static void putchar(
|
|||
{
|
||||
for (usize b = 0; b < TTY_FONT_SCALE; ++b)
|
||||
{
|
||||
put_pixel(ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
put_pixel(
|
||||
ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
ttyx->typeinfo.raw_framebuffer.width,
|
||||
ttyx->typeinfo.raw_framebuffer.pixsize,
|
||||
ttyx->text.column * font->char_width * TTY_FONT_SCALE + i * TTY_FONT_SCALE + a,
|
||||
|
@ -102,7 +110,8 @@ inline static void putchar(
|
|||
{
|
||||
for (usize b = 0; b < TTY_FONT_SCALE; ++b)
|
||||
{
|
||||
put_pixel(ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
put_pixel(
|
||||
ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
ttyx->typeinfo.raw_framebuffer.width,
|
||||
ttyx->typeinfo.raw_framebuffer.pixsize,
|
||||
ttyx->text.column * font->char_width * TTY_FONT_SCALE + i * TTY_FONT_SCALE + a,
|
||||
|
@ -121,7 +130,8 @@ inline static void newline(tty *ttyx)
|
|||
ttyx->text.line++;
|
||||
if (ttyx->text.line == ttyx->text.height)
|
||||
{
|
||||
scroll_buffer(ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
scroll_buffer(
|
||||
ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
ttyx->typeinfo.raw_framebuffer.width,
|
||||
ttyx->typeinfo.raw_framebuffer.height,
|
||||
ttyx->typeinfo.raw_framebuffer.pixsize,
|
||||
|
@ -132,6 +142,11 @@ inline static void newline(tty *ttyx)
|
|||
|
||||
void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor)
|
||||
{
|
||||
if (ttyx->enabled == false)
|
||||
return;
|
||||
// TODO 暂时只支持framebuffer
|
||||
if (ttyx->type != tty_type_raw_framebuffer)
|
||||
return;
|
||||
if (ttyx->mode != tty_mode_text)
|
||||
return;
|
||||
if (ttyx->typeinfo.raw_framebuffer.pixtype == bgr)
|
||||
|
@ -147,13 +162,14 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor)
|
|||
}
|
||||
}
|
||||
tty_font_t *font = tty_get_font();
|
||||
simple_lock_lock(ttyx->text.lock);
|
||||
usize len = strlen(string);
|
||||
simple_lock_lock(ttyx->text.lock);
|
||||
for (char *str = string; string - str < len; string++)
|
||||
{
|
||||
char c = *string;
|
||||
if (c == '\n')
|
||||
{ // 换行
|
||||
putchar(ttyx, ' ', 0, 0);
|
||||
newline(ttyx);
|
||||
continue;
|
||||
}
|
||||
|
@ -173,7 +189,8 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor)
|
|||
ttyx->text.line++;
|
||||
if (ttyx->text.line == ttyx->text.height)
|
||||
{
|
||||
scroll_buffer(ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
scroll_buffer(
|
||||
ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
ttyx->typeinfo.raw_framebuffer.width,
|
||||
ttyx->typeinfo.raw_framebuffer.height,
|
||||
ttyx->typeinfo.raw_framebuffer.pixsize,
|
||||
|
@ -192,7 +209,8 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor)
|
|||
}
|
||||
else if (c == '\f')
|
||||
{ // 滚动一行
|
||||
scroll_buffer(ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
scroll_buffer(
|
||||
ttyx->typeinfo.raw_framebuffer.pointer,
|
||||
ttyx->typeinfo.raw_framebuffer.width,
|
||||
ttyx->typeinfo.raw_framebuffer.height,
|
||||
ttyx->typeinfo.raw_framebuffer.pixsize,
|
||||
|
@ -213,3 +231,58 @@ void tty_text_print(tty *ttyx, char *string, u32 color, u32 bgcolor)
|
|||
putchar(ttyx, '\0', gen_color(0x88, 0x88, 0x88), 0);
|
||||
simple_lock_unlock(ttyx->text.lock);
|
||||
}
|
||||
|
||||
usize tty_get_width(tty *ttyx)
|
||||
{
|
||||
if (ttyx->mode == tty_mode_text)
|
||||
return ttyx->text.width;
|
||||
return ttyx->width;
|
||||
}
|
||||
|
||||
usize tty_get_height(tty *ttyx)
|
||||
{
|
||||
if (ttyx->mode == tty_mode_text)
|
||||
return ttyx->text.height;
|
||||
return ttyx->height;
|
||||
}
|
||||
|
||||
tty_type tty_get_type(tty *ttyx)
|
||||
{
|
||||
return ttyx->type;
|
||||
}
|
||||
|
||||
tty_mode tty_get_mode(tty *ttyx)
|
||||
{
|
||||
return ttyx->mode;
|
||||
}
|
||||
|
||||
bool tty_is_enabled(tty *ttyx)
|
||||
{
|
||||
return ttyx->enabled;
|
||||
}
|
||||
|
||||
bool tty_enable(tty *ttyx)
|
||||
{
|
||||
if (tty_ctrler.enabled[ttyx->id])
|
||||
return false;
|
||||
if (ttyx->type == tty_type_raw_framebuffer)
|
||||
{
|
||||
for (usize i = 0; i < TTY_MAX_NUM; ++i)
|
||||
{
|
||||
if (ttyx->id != i &&
|
||||
tty_ctrler.enabled[i] != nullptr &&
|
||||
tty_ctrler.ttys[i]->type == tty_type_raw_framebuffer)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ttyx->enabled = true;
|
||||
tty_ctrler.enabled[ttyx->id] = ttyx;
|
||||
return true;
|
||||
}
|
||||
|
||||
void tty_disable(tty *ttyx)
|
||||
{
|
||||
ttyx->enabled = false;
|
||||
tty_ctrler.enabled[ttyx->id] = false;
|
||||
}
|
||||
|
|
|
@ -1,25 +1,61 @@
|
|||
use std::{
|
||||
io::{BufWriter, Write},
|
||||
ptr::null_mut,
|
||||
use core::ptr::null_mut;
|
||||
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
vec,
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
fn tty_new(tty_type: u8, mode: u8) -> *mut u8;
|
||||
fn tty_get(id: usize) -> *mut *mut u8;
|
||||
pub fn tty_new(tty_type: u8, mode: u8) -> *mut u8;
|
||||
pub fn tty_get(id: usize) -> *mut *mut u8;
|
||||
pub fn tty_text_print(ttyx: *mut u8, string: *mut u8, color: u32, bgcolor: u32);
|
||||
fn tty_get_id(tty: *mut u8) -> usize;
|
||||
pub fn tty_get_id(tty: *mut u8) -> usize;
|
||||
|
||||
pub fn tty_get_width(tty: *mut u8) -> usize;
|
||||
pub fn tty_get_height(tty: *mut u8) -> usize;
|
||||
|
||||
pub fn tty_get_type(tty: *mut u8) -> u8;
|
||||
pub fn tty_get_mode(tty: *mut u8) -> u8;
|
||||
|
||||
pub fn tty_is_enabled(tty: *mut u8) -> bool;
|
||||
|
||||
pub fn tty_enable(tty: *mut u8) -> bool;
|
||||
pub fn tty_disable(tty: *mut u8);
|
||||
}
|
||||
|
||||
pub enum Type {
|
||||
Invalid = 0,
|
||||
RawFramebuffer = 1,
|
||||
Display = 2,
|
||||
VirtualTty = 3,
|
||||
VirtualTerm = 3,
|
||||
}
|
||||
|
||||
impl From<u8> for Type {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
1 => Type::RawFramebuffer,
|
||||
2 => Type::Display,
|
||||
3 => Type::VirtualTerm,
|
||||
_ => Type::Invalid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Mode {
|
||||
Text = 0,
|
||||
Graphics = 1,
|
||||
Invalid = 0,
|
||||
Text = 1,
|
||||
Graphics = 2,
|
||||
}
|
||||
|
||||
impl From<u8> for Mode {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
1 => Mode::Text,
|
||||
2 => Mode::Graphics,
|
||||
_ => Mode::Invalid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Tty {
|
||||
|
@ -50,12 +86,43 @@ impl Tty {
|
|||
unsafe { tty_get_id(self.tty_pointer) }
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Resolution {
|
||||
unsafe {
|
||||
Resolution {
|
||||
width: tty_get_width(self.tty_pointer),
|
||||
height: tty_get_height(self.tty_pointer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> Type {
|
||||
let tp = unsafe { tty_get_type(self.tty_pointer) };
|
||||
Type::from(tp)
|
||||
}
|
||||
|
||||
pub fn mode(&self) -> Mode {
|
||||
let mode = unsafe { tty_get_mode(self.tty_pointer) };
|
||||
Mode::from(mode)
|
||||
}
|
||||
|
||||
pub fn is_enabled(&self) -> bool {
|
||||
unsafe { tty_is_enabled(self.tty_pointer) }
|
||||
}
|
||||
|
||||
pub fn enable(&self) {
|
||||
unsafe { tty_enable(self.tty_pointer) };
|
||||
}
|
||||
|
||||
pub fn disable(&self) {
|
||||
unsafe { tty_disable(self.tty_pointer) };
|
||||
}
|
||||
|
||||
pub fn print(&self, msg: Message) {
|
||||
for MessageSection {
|
||||
mut msg,
|
||||
fgcolor,
|
||||
bgcolor,
|
||||
} in msg.into_iter()
|
||||
} in msg.0.into_iter()
|
||||
{
|
||||
unsafe {
|
||||
let string = msg.as_bytes_mut() as *mut [u8] as *mut u8;
|
||||
|
@ -74,8 +141,21 @@ impl Tty {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Color(pub u8, pub u8, pub u8);
|
||||
|
||||
impl Color {
|
||||
pub const WHITE: Color = Color(0xee, 0xee, 0xee);
|
||||
pub const BLACK: Color = Color(0, 0, 0);
|
||||
pub const RED: Color = Color(0xee, 0x22, 0x22);
|
||||
pub const GREEN: Color = Color(0x22, 0xee, 0x22);
|
||||
pub const BLUE: Color = Color(0x22, 0x22, 0xee);
|
||||
pub const YELLOW: Color = Color(0xee, 0x22, 0x22);
|
||||
pub const ORANGE: Color = Color(0xee, 0xee, 0x22);
|
||||
pub const PURPLE: Color = Color(0xee, 0, 0xee);
|
||||
pub const PINK: Color = Color(0xee, 0x44, 0x66);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -83,46 +163,117 @@ impl From<Color> for u32 {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Resolution {
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MessageSection {
|
||||
msg: String,
|
||||
fgcolor: Color,
|
||||
bgcolor: Color,
|
||||
}
|
||||
|
||||
type Message = Vec<MessageSection>;
|
||||
/// ## Message
|
||||
///
|
||||
/// 用`MessageBuilder`构造一个`Message`对象
|
||||
#[derive(Clone)]
|
||||
pub struct Message(Vec<MessageSection>);
|
||||
|
||||
/// ## 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 { msg: vec![] }
|
||||
Self {
|
||||
msg: Message(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn message(mut self, msg: String) -> Self {
|
||||
self.msg.push(MessageSection {
|
||||
msg,
|
||||
pub fn from_message(msg: Message) -> Self {
|
||||
Self { msg }
|
||||
}
|
||||
|
||||
pub fn message(mut self, msg: &str) -> Self {
|
||||
self.msg.0.push(MessageSection {
|
||||
msg: msg.to_string(),
|
||||
fgcolor: Color(0xee, 0xee, 0xee),
|
||||
bgcolor: Color(0, 0, 0),
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
pub fn message_mut(&mut self, msg: &str) {
|
||||
self.msg.0.push(MessageSection {
|
||||
msg: msg.to_string(),
|
||||
fgcolor: Color(0xee, 0xee, 0xee),
|
||||
bgcolor: Color(0, 0, 0),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn background_color(mut self, color: Color) -> Self {
|
||||
if let Some(msg) = self.msg.last_mut() {
|
||||
if let Some(msg) = self.msg.0.last_mut() {
|
||||
msg.bgcolor = color;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn background_color_mut(&mut self, color: Color) {
|
||||
if let Some(msg) = self.msg.0.last_mut() {
|
||||
msg.bgcolor = color;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn foreground_color(mut self, color: Color) -> Self {
|
||||
if let Some(msg) = self.msg.last_mut() {
|
||||
if let Some(msg) = self.msg.0.last_mut() {
|
||||
msg.fgcolor = color;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn foreground_color_mut(&mut self, color: Color) {
|
||||
if let Some(msg) = self.msg.0.last_mut() {
|
||||
msg.fgcolor = color;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn append(mut self, mut builder: Self) -> Self {
|
||||
self.msg.0.append(&mut builder.msg.0);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Message {
|
||||
self.msg
|
||||
}
|
||||
|
|
67
src/lib.rs
67
src/lib.rs
|
@ -1,4 +1,69 @@
|
|||
extern crate core;
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{panic::PanicInfo, ptr::null_mut};
|
||||
|
||||
use kernel::tty::tty::{self, tty_enable, tty_text_print, Color};
|
||||
|
||||
pub mod kernel;
|
||||
pub mod libk;
|
||||
|
||||
#[panic_handler]
|
||||
unsafe fn kernel_panic_handler(info: &PanicInfo) -> ! {
|
||||
let line_in_file = if let Some(loca) = info.location() {
|
||||
loca.line().to_string()
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let info = {
|
||||
let mut v = Vec::new();
|
||||
v.push(("Kernel Panic: ", (Color::RED, Color::BLACK)));
|
||||
v.push((
|
||||
if let Some(loca) = info.location() {
|
||||
loca.file()
|
||||
} else {
|
||||
"NoFile"
|
||||
},
|
||||
(Color::GREEN, Color::BLACK),
|
||||
));
|
||||
v.push((":", (Color::WHITE, Color::BLACK)));
|
||||
v.push((
|
||||
if let Some(_) = info.location() {
|
||||
line_in_file.as_str()
|
||||
} else {
|
||||
"NoLine"
|
||||
},
|
||||
(Color::WHITE, Color::BLACK),
|
||||
));
|
||||
v.push((": ", (Color::WHITE, Color::BLACK)));
|
||||
v.push((
|
||||
if let Some(&s) = info.payload().downcast_ref::<&str>() {
|
||||
s
|
||||
} else {
|
||||
"Unknown panic."
|
||||
},
|
||||
(Color::BLUE, Color::BLACK),
|
||||
));
|
||||
v.push(("\n", (Color::BLACK, Color::BLACK)));
|
||||
v
|
||||
};
|
||||
let tty = tty::tty_get(0);
|
||||
if tty != null_mut() {
|
||||
let tty = *tty;
|
||||
tty_enable(tty);
|
||||
for (msgo, (fgc, bgc)) in info.into_iter() {
|
||||
let msg = String::from(msgo).as_bytes_mut() as *mut [u8] as *mut u8;
|
||||
let p = msg.offset(msgo.len() as isize);
|
||||
let swp = *p;
|
||||
*p = 0;
|
||||
tty_text_print(tty, msg, u32::from(fgc), u32::from(bgc));
|
||||
*p = swp;
|
||||
}
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
lst_iterator_t *lst_new(usize start, usize end)
|
||||
{
|
||||
lst_iterator_t *lst = memm_allocate(sizeof(lst_iterator_t), 0);
|
||||
lst_iterator_t *lst = memm_kernel_allocate(sizeof(lst_iterator_t));
|
||||
lst->line.left = start;
|
||||
lst->line.right = end;
|
||||
lst->next = nullptr;
|
||||
|
@ -128,7 +128,7 @@ bool lst_add(lst_iterator_t *lst, usize left, usize right, bool force)
|
|||
lst->line.left = left;
|
||||
else
|
||||
{
|
||||
lst_iterator_t *new_node = memm_allocate(sizeof(lst_iterator_t), 0);
|
||||
lst_iterator_t *new_node = memm_kernel_allocate(sizeof(lst_iterator_t));
|
||||
new_node->line = line;
|
||||
new_node->next = lst;
|
||||
if (last != nullptr)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
pub mod string;
|
|
@ -17,12 +17,6 @@ SECTIONS {
|
|||
{
|
||||
*(.cpumeta)
|
||||
}
|
||||
. = 4M;
|
||||
..kstack :
|
||||
{
|
||||
kstack = .;
|
||||
*(.kstack)
|
||||
}
|
||||
. = 16M;
|
||||
.text :
|
||||
{
|
||||
|
@ -62,6 +56,50 @@ SECTIONS {
|
|||
{}
|
||||
.igot.plt :
|
||||
{}
|
||||
.tbss :
|
||||
{
|
||||
*(.tbss)
|
||||
}
|
||||
.tdata :
|
||||
{
|
||||
*(.tdata)
|
||||
}
|
||||
.debug_line :
|
||||
{
|
||||
*(.debug_line)
|
||||
}
|
||||
.debug_abbrev :
|
||||
{
|
||||
*(.debug_abbrev)
|
||||
}
|
||||
.debug_info :
|
||||
{
|
||||
*(.debug_info)
|
||||
}
|
||||
.debug_str :
|
||||
{
|
||||
*(.debug_str)
|
||||
}
|
||||
.debug_aranges :
|
||||
{
|
||||
*(.debug_aranges)
|
||||
}
|
||||
.debug_ranges :
|
||||
{
|
||||
*(.debug_ranges)
|
||||
}
|
||||
.debug_pubnames :
|
||||
{
|
||||
*(.debug_pubnames)
|
||||
}
|
||||
.debug_pubtypes :
|
||||
{
|
||||
*(.debug_pubtypes)
|
||||
}
|
||||
.debug_frame :
|
||||
{
|
||||
*(.debug_frame)
|
||||
}
|
||||
.kend :
|
||||
{
|
||||
*(.kend)
|
||||
|
|
Loading…
Reference in New Issue