ch2: Applications

user_lib
user apps
This commit is contained in:
Tateisi 2025-08-03 05:00:14 +08:00
parent f5c1eb99b3
commit 93d85e1d32
25 changed files with 357 additions and 2 deletions

7
os/.cargo/config.toml Normal file
View file

@ -0,0 +1,7 @@
[build]
target = "riscv64gc-unknown-none-elf"
[target.riscv64gc-unknown-none-elf]
rustflags = [
"-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes"
]

1
os/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

32
os/Cargo.lock generated Normal file
View file

@ -0,0 +1,32 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "os"
version = "0.1.0"
dependencies = [
"log",
"sbi-rt",
]
[[package]]
name = "sbi-rt"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbaa69be1eedc61c426e6d489b2260482e928b465360576900d52d496a58bd0"
dependencies = [
"sbi-spec",
]
[[package]]
name = "sbi-spec"
version = "0.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e36312fb5ddc10d08ecdc65187402baba4ac34585cb9d1b78522ae2358d890"

8
os/Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "os"
version = "0.1.0"
edition = "2021"
[dependencies]
log = "0.4.22"
sbi-rt = "0.0.3"

29
os/src/console.rs Normal file
View file

@ -0,0 +1,29 @@
use core::fmt::{self, Write};
use crate::sbi;
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
sbi::console_write(s.as_bytes());
Ok(())
}
}
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
#[macro_export]
macro_rules! print {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!($fmt $(, $($arg)+)?));
};
}
#[macro_export]
macro_rules! println {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
};
}

12
os/src/entry.asm Normal file
View file

@ -0,0 +1,12 @@
.section .text.entry
.globl _start
_start:
la sp, boot_start_top
call rust_main
.section .bss.stack
.globl boot_stack_lower_bound
boot_stack_lower_bound:
.space 4096 * 16
.globl boot_start_top
boot_start_top:

18
os/src/lang_items.rs Normal file
View file

@ -0,0 +1,18 @@
use core::panic::PanicInfo;
use crate::{sbi, println};
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
let err = info.message().as_str().unwrap();
if let Some(location) = info.location() {
println!(
"Panicked at {}:{} {}",
location.file(),
location.line(),
err
);
} else {
println!("Panicked: {}", err);
}
sbi::shutdown(true)
}

48
os/src/linker.ld Normal file
View file

@ -0,0 +1,48 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0x80200000;
SECTIONS
{
. = BASE_ADDRESS;
skernel = .;
stext = .;
.text : {
*(.text.entry)
*(.text .text.*)
}
. = ALIGN(4K);
etext = .;
srodata = .;
.rodata : {
*(.data .rodata.*)
*(.srodata .srodata.*)
}
. = ALIGN(4K);
erodata = .;
sdata = .;
.data : {
*(.data .data.*)
*(.sdata .sdata.*)
}
. = ALIGN(4K);
edata = .;
.bss : {
*(.bss.stack)
sbss = .;
*(.bss .bss.*)
*(.sbss .sbss.*)
}
. = ALIGN(4K);
ebss = .;
ekernel = .;
/DISCARD/ : {
*(.eh_frame)
}
}

42
os/src/logger.rs Normal file
View file

@ -0,0 +1,42 @@
use log::{Level, LevelFilter, Log};
use crate::println;
struct Logger;
impl Log for Logger {
fn enabled(&self, _metadata: &log::Metadata) -> bool {
true
}
fn log(&self, record: &log::Record) {
if !self.enabled(record.metadata()) {
return;
}
let (color, level) = match record.level() {
Level::Error => (31, "ERR"),
Level::Warn => (93, "WRN"),
Level::Info => (34, "INF"),
Level::Debug => (32, "DBG"),
Level::Trace => (90, "TRC"),
};
println!("\x1b[{}m{}\x1b[0m \x1b[1m{}\x1b[0m {}", color, level, record.target(), record.args());
}
fn flush(&self) {}
}
pub fn init() {
static LOGGER: Logger = Logger;
log::set_logger(&LOGGER).unwrap();
log::set_max_level(match option_env!("LOG") {
Some("ERROR") => LevelFilter::Error,
Some("WARN") => LevelFilter::Warn,
Some("INFO") => LevelFilter::Info,
Some("DEBUG") => LevelFilter::Debug,
Some("TRACE") => LevelFilter::Trace,
_ => LevelFilter::Off,
});
}

65
os/src/main.rs Normal file
View file

@ -0,0 +1,65 @@
#![no_std]
#![no_main]
mod lang_items;
mod sbi;
mod logger;
#[macro_use]
mod console;
use core::arch::global_asm;
use log::{debug, error, info, trace, warn};
global_asm!(include_str!("entry.asm"));
#[no_mangle]
pub fn rust_main() -> ! {
clear_bss();
logger::init();
print_system_info();
print_to_console();
panic!("Shutdown machine!");
}
fn clear_bss() {
extern "C" {
fn sbss();
fn ebss();
}
(sbss as usize..ebss as usize).for_each(|a| {
unsafe { (a as *mut u8).write_volatile(0) }
});
}
fn print_to_console() {
sbi::console_write_byte('O' as u8);
sbi::console_write_byte('K' as u8);
sbi::console_write_byte('\n' as u8);
trace!("Hello World.");
debug!("Hello World.");
info!("Hello World.");
warn!("Hello World.");
error!("Hello World.");
}
fn print_system_info() {
extern "C" {
fn stext();
fn etext();
fn sdata();
fn edata();
fn srodata();
fn erodata();
fn sbss();
fn ebss();
}
info!(".text [{:#x}, {:#x}]", stext as usize, etext as usize);
info!(".rodata [{:#x}, {:#x}]", srodata as usize, erodata as usize);
info!(".data [{:#x}, {:#x}]", sdata as usize, edata as usize);
info!(".bss [{:#x}, {:#x}]", sbss as usize, ebss as usize);
}

19
os/src/sbi.rs Normal file
View file

@ -0,0 +1,19 @@
pub fn console_write_byte(c: u8) {
sbi_rt::console_write_byte(c);
}
pub fn console_write(bytes: &[u8]) {
let range = bytes.as_ptr_range();
let bytes = sbi_rt::Physical::new(bytes.len(), range.start as usize, range.end as usize);
sbi_rt::console_write(bytes);
}
pub fn shutdown(failure: bool) -> ! {
use sbi_rt::{system_reset, NoReason, Shutdown, SystemFailure};
if !failure {
system_reset(Shutdown, NoReason);
} else {
system_reset(Shutdown, SystemFailure);
}
unreachable!()
}