mirror of
https://github.com/LearningOS/rust-based-os-comp2022.git
synced 2026-05-05 11:20:06 +08:00
add os[1-8]-ref for os refereces, add guide, add README
This commit is contained in:
7
os1-ref/.cargo/config
Normal file
7
os1-ref/.cargo/config
Normal 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"
|
||||
]
|
||||
10
os1-ref/Cargo.toml
Normal file
10
os1-ref/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "os"
|
||||
version = "0.1.0"
|
||||
authors = ["Yifan Wu <shinbokuow@163.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
49
os1-ref/Makefile
Normal file
49
os1-ref/Makefile
Normal file
@@ -0,0 +1,49 @@
|
||||
# Building
|
||||
TARGET := riscv64gc-unknown-none-elf
|
||||
MODE := release
|
||||
KERNEL_ELF := target/$(TARGET)/$(MODE)/os
|
||||
KERNEL_BIN := $(KERNEL_ELF).bin
|
||||
|
||||
# BOARD
|
||||
BOARD ?= qemu
|
||||
SBI ?= rustsbi
|
||||
BOOTLOADER := ../bootloader/$(SBI)-$(BOARD).bin
|
||||
|
||||
# KERNEL ENTRY
|
||||
KERNEL_ENTRY_PA := 0x80200000
|
||||
|
||||
# Binutils
|
||||
OBJDUMP := rust-objdump --arch-name=riscv64
|
||||
OBJCOPY := rust-objcopy --binary-architecture=riscv64
|
||||
|
||||
build: env $(KERNEL_BIN)
|
||||
|
||||
$(KERNEL_BIN): kernel
|
||||
@$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@
|
||||
|
||||
env:
|
||||
(rustup target list | grep "riscv64gc-unknown-none-elf (installed)") || rustup target add $(TARGET)
|
||||
cargo install cargo-binutils --vers ~0.3
|
||||
rustup component add rust-src
|
||||
rustup component add llvm-tools-preview
|
||||
|
||||
kernel:
|
||||
@cargo build --release
|
||||
|
||||
clean:
|
||||
@cargo clean
|
||||
|
||||
run: build
|
||||
@qemu-system-riscv64 \
|
||||
-machine virt \
|
||||
-nographic \
|
||||
-bios $(BOOTLOADER) \
|
||||
-device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA)
|
||||
|
||||
debug: build
|
||||
@tmux new-session -d \
|
||||
"qemu-system-riscv64 -machine virt -nographic -bios $(BOOTLOADER) -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) -s -S" && \
|
||||
tmux split-window -h "riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'" && \
|
||||
tmux -2 attach-session -d
|
||||
|
||||
.PHONY: build env kernel clean run-inner
|
||||
37
os1-ref/src/console.rs
Normal file
37
os1-ref/src/console.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
/*!
|
||||
|
||||
本模块实现了 print 和 println 宏。
|
||||
|
||||
*/
|
||||
|
||||
use crate::sbi::console_putchar;
|
||||
use core::fmt::{self, Write};
|
||||
|
||||
struct Stdout;
|
||||
|
||||
impl Write for Stdout {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for c in s.chars() {
|
||||
console_putchar(c as usize);
|
||||
}
|
||||
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
os1-ref/src/entry.asm
Normal file
12
os1-ref/src/entry.asm
Normal file
@@ -0,0 +1,12 @@
|
||||
.section .text.entry
|
||||
.globl _start
|
||||
_start:
|
||||
la sp, boot_stack_top
|
||||
call rust_main
|
||||
|
||||
.section .bss.stack
|
||||
.globl boot_stack
|
||||
boot_stack:
|
||||
.space 4096 * 16
|
||||
.globl boot_stack_top
|
||||
boot_stack_top:
|
||||
17
os1-ref/src/lang_items.rs
Normal file
17
os1-ref/src/lang_items.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use crate::sbi::shutdown;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
if let Some(location) = info.location() {
|
||||
println!(
|
||||
"Panicked at {}:{} {}",
|
||||
location.file(),
|
||||
location.line(),
|
||||
info.message().unwrap()
|
||||
);
|
||||
} else {
|
||||
println!("Panicked: {}", info.message().unwrap());
|
||||
}
|
||||
shutdown()
|
||||
}
|
||||
48
os1-ref/src/linker.ld
Normal file
48
os1-ref/src/linker.ld
Normal 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 : {
|
||||
*(.rodata .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)
|
||||
}
|
||||
}
|
||||
47
os1-ref/src/logging.rs
Normal file
47
os1-ref/src/logging.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
/*!
|
||||
|
||||
本模块利用 log crate 为你提供了日志功能,使用方式见 main.rs.
|
||||
|
||||
*/
|
||||
|
||||
use log::{self, Level, LevelFilter, Log, Metadata, Record};
|
||||
|
||||
struct SimpleLogger;
|
||||
|
||||
impl Log for SimpleLogger {
|
||||
fn enabled(&self, _metadata: &Metadata) -> bool {
|
||||
true
|
||||
}
|
||||
fn log(&self, record: &Record) {
|
||||
if !self.enabled(record.metadata()) {
|
||||
return;
|
||||
}
|
||||
let color = match record.level() {
|
||||
Level::Error => 31, // Red
|
||||
Level::Warn => 93, // BrightYellow
|
||||
Level::Info => 34, // Blue
|
||||
Level::Debug => 32, // Green
|
||||
Level::Trace => 90, // BrightBlack
|
||||
};
|
||||
println!(
|
||||
"\u{1B}[{}m[{:>5}] {}\u{1B}[0m",
|
||||
color,
|
||||
record.level(),
|
||||
record.args(),
|
||||
);
|
||||
}
|
||||
fn flush(&self) {}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
static LOGGER: SimpleLogger = SimpleLogger;
|
||||
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,
|
||||
});
|
||||
}
|
||||
49
os1-ref/src/main.rs
Normal file
49
os1-ref/src/main.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(panic_info_message)]
|
||||
|
||||
use log::*;
|
||||
|
||||
#[macro_use]
|
||||
mod console;
|
||||
mod lang_items;
|
||||
mod logging;
|
||||
mod sbi;
|
||||
|
||||
core::arch::global_asm!(include_str!("entry.asm"));
|
||||
|
||||
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) });
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn rust_main() -> ! {
|
||||
extern "C" {
|
||||
fn stext();
|
||||
fn etext();
|
||||
fn srodata();
|
||||
fn erodata();
|
||||
fn sdata();
|
||||
fn edata();
|
||||
fn sbss();
|
||||
fn ebss();
|
||||
fn boot_stack();
|
||||
fn boot_stack_top();
|
||||
}
|
||||
clear_bss();
|
||||
logging::init();
|
||||
println!("Hello, world!");
|
||||
trace!(".text [{:#x}, {:#x})", stext as usize, etext as usize);
|
||||
debug!(".rodata [{:#x}, {:#x})", srodata as usize, erodata as usize);
|
||||
info!(".data [{:#x}, {:#x})", sdata as usize, edata as usize);
|
||||
warn!(
|
||||
"boot_stack [{:#x}, {:#x})",
|
||||
boot_stack as usize, boot_stack_top as usize
|
||||
);
|
||||
error!(".bss [{:#x}, {:#x})", sbss as usize, ebss as usize);
|
||||
panic!("Shutdown machine!");
|
||||
}
|
||||
34
os1-ref/src/sbi.rs
Normal file
34
os1-ref/src/sbi.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
#![allow(unused)]
|
||||
|
||||
const SBI_SET_TIMER: usize = 0;
|
||||
const SBI_CONSOLE_PUTCHAR: usize = 1;
|
||||
const SBI_CONSOLE_GETCHAR: usize = 2;
|
||||
const SBI_SHUTDOWN: usize = 8;
|
||||
|
||||
#[inline(always)]
|
||||
fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
|
||||
let mut ret;
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("x10") arg0 => ret,
|
||||
in("x11") arg1,
|
||||
in("x12") arg2,
|
||||
in("x17") which,
|
||||
);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn console_putchar(c: usize) {
|
||||
sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0);
|
||||
}
|
||||
|
||||
pub fn console_getchar() -> usize {
|
||||
sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0)
|
||||
}
|
||||
|
||||
pub fn shutdown() -> ! {
|
||||
sbi_call(SBI_SHUTDOWN, 0, 0, 0);
|
||||
panic!("It should shutdown!");
|
||||
}
|
||||
Reference in New Issue
Block a user