Merge pull request '增加内核日志功能' (#3) from pointer-to-bios/metaverse-dev:main into main

Reviewed-on: http://git.suthby.org:2024/metaverse/kernel-dev/pulls/3
This commit is contained in:
pointer-to-bios 2024-02-05 22:10:26 +08:00
commit 1f195f350d
30 changed files with 1079 additions and 118 deletions

2
.gitmodules vendored
View File

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

View File

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

View File

@ -56,7 +56,7 @@ make debug
* [x] 内存分配器
* [x] raw_allocator
* [x] tty
* [ ] 内核日志
* [x] 内核日志
* [ ] 文件系统
* [ ] vfs
* [ ] fat32驱动移植

View File

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

View File

@ -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);
/*

View File

@ -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类型的ttyframebuffer已被其它raw_framebuffer
* tty占用
*/
bool tty_enable(tty *ttyx);
void tty_disable(tty *ttyx);
#define TTY_FONT_SCALE 2
typedef struct __tty_font_t

@ -1 +1 @@
Subproject commit f8d0d53a23b5a91848d8f6491122b69f79994537
Subproject commit 087c4795bbc23cd0baee060bda8c1159a971a542

View File

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

View File

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

View File

@ -39,10 +39,6 @@ multiboot2_header:
dd 8
multiboot2_header_end:
section .kstack
kstack:
resb 0x1000000 - 0x400000
section .kend
global kend
kend:

1
src/kernel/clock/mod.rs Normal file
View File

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

20
src/kernel/clock/time.c Normal file
View File

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

166
src/kernel/clock/time.rs Normal file
View File

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

196
src/kernel/klog.rs Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

1
src/kernel/sync/mod.rs Normal file
View File

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

129
src/kernel/sync/rwlock.rs Normal file
View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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