mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 01:35:19 +08:00
init
This commit is contained in:
commit
4736cfcb4e
2
.cargo/config.toml
Normal file
2
.cargo/config.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[build]
|
||||
target = "riscv64imac-unknown-none-elf"
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
91
Cargo.lock
generated
Normal file
91
Cargo.lock
generated
Normal file
@ -0,0 +1,91 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "raw-cpuid"
|
||||
version = "10.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "sbi-rt"
|
||||
version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c113c53291db8ac141e01f43224ed488b8d6001ab66737b82e04695a43a42b7"
|
||||
dependencies = [
|
||||
"sbi-spec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sbi-spec"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d4027cf9bb591a9fd0fc0e283be6165c5abe96cb73e9f0e24738c227f425377"
|
||||
dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "tiny_os"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"sbi-rt",
|
||||
"uart_16550",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uart_16550"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dc00444796f6c71f47c85397a35e9c4dbf9901902ac02386940d178e2b78687"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"rustversion",
|
||||
"x86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x86"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
"raw-cpuid",
|
||||
]
|
26
Cargo.toml
Normal file
26
Cargo.toml
Normal file
@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "tiny_os"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
default = ["arch_riscv64", "board_virt"]
|
||||
arch_riscv64 = []
|
||||
arch_arm = []
|
||||
arch_x86 = []
|
||||
board_default = []
|
||||
board_virt = []
|
||||
board_thead = []
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
||||
[dependencies]
|
||||
sbi-rt = { version = "0.0.2", features = ["legacy"] }
|
||||
uart_16550 = "0.3"
|
||||
log = "0.4"
|
23
build.rs
Normal file
23
build.rs
Normal file
@ -0,0 +1,23 @@
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
struct TargetConfiguration {
|
||||
target: &'static str,
|
||||
lds: &'static str,
|
||||
}
|
||||
|
||||
const TARGET_CONFIGURATIONS: &[TargetConfiguration] = &[TargetConfiguration {
|
||||
target: "riscv64",
|
||||
lds: "src/arch/riscv/boot/linker64.ld",
|
||||
}];
|
||||
|
||||
let target = std::env::var("TARGET").unwrap();
|
||||
for cfg in TARGET_CONFIGURATIONS {
|
||||
if target.starts_with(cfg.target) {
|
||||
println!("cargo:rustc-link-arg=-T{}", cfg.lds);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
panic!("Unsupported target: {}", target);
|
||||
}
|
2
rust-toolchain.toml
Normal file
2
rust-toolchain.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
72
src/arch/io.rs
Normal file
72
src/arch/io.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use core::fmt::Write;
|
||||
|
||||
pub struct RawConsole;
|
||||
|
||||
pub trait Printer: Write {
|
||||
fn put_char(c: char);
|
||||
|
||||
#[inline]
|
||||
fn put_str(s: &str) {
|
||||
for c in s.chars() {
|
||||
Self::put_char(c);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn put_line(s: &str) {
|
||||
Self::put_str(s);
|
||||
Self::put_char('\n');
|
||||
}
|
||||
|
||||
fn put_num(mut num: usize) {
|
||||
if num == 0 {
|
||||
Self::put_char('0');
|
||||
return;
|
||||
}
|
||||
|
||||
let digits = "0123456789".as_bytes();
|
||||
let mut buf = [0u8; 10];
|
||||
let mut i = 0;
|
||||
|
||||
while num != 0 {
|
||||
buf[i] = digits[num % 10];
|
||||
num /= 10;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
buf[..i]
|
||||
.iter()
|
||||
.rev()
|
||||
.for_each(|c| Self::put_char(*c as char));
|
||||
}
|
||||
|
||||
fn put_hex(mut num: usize) {
|
||||
if num == 0 {
|
||||
Self::put_str("0x0");
|
||||
return;
|
||||
}
|
||||
|
||||
let alphabet = "0123456789abcdef".as_bytes();
|
||||
let mut buf = [0u8; 8];
|
||||
let mut i = 0;
|
||||
|
||||
while num != 0 {
|
||||
buf[i] = alphabet[num % 16];
|
||||
num /= 16;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Self::put_str("0x");
|
||||
buf[..i]
|
||||
.iter()
|
||||
.rev()
|
||||
.for_each(|c| Self::put_char(*c as char));
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for RawConsole {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
Self::put_str(s);
|
||||
Ok(())
|
||||
}
|
||||
}
|
18
src/arch/lowlevel.rs
Normal file
18
src/arch/lowlevel.rs
Normal file
@ -0,0 +1,18 @@
|
||||
pub struct Hardware;
|
||||
|
||||
pub trait LowLevel {
|
||||
fn halt() {}
|
||||
|
||||
fn shutdown(_failure: bool) -> ! {
|
||||
Self::halt();
|
||||
|
||||
#[allow(clippy::empty_loop)]
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn reset(_failure: bool) -> ! {
|
||||
panic!("Reset is not implemented for this architecture");
|
||||
}
|
||||
|
||||
fn disable_interrupt() {}
|
||||
}
|
10
src/arch/mod.rs
Normal file
10
src/arch/mod.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// Basic IO
|
||||
pub mod io;
|
||||
|
||||
// Low Level
|
||||
pub mod lowlevel;
|
||||
|
||||
// Arch Level
|
||||
#[cfg(feature = "arch_riscv64")]
|
||||
#[path = "riscv/mod.rs"]
|
||||
mod riscv;
|
3
src/arch/riscv/board/virt/mod.rs
Normal file
3
src/arch/riscv/board/virt/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub const UART0_BASE: usize = 0x1000_0000;
|
||||
|
||||
pub mod printer;
|
17
src/arch/riscv/board/virt/printer.rs
Normal file
17
src/arch/riscv/board/virt/printer.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use crate::arch::io::{Printer, RawConsole};
|
||||
|
||||
impl Printer for RawConsole {
|
||||
#[inline]
|
||||
fn put_char(c: char) {
|
||||
let uart = super::UART0_BASE as *mut char;
|
||||
unsafe { uart.write_volatile(c) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn put_str(s: &str) {
|
||||
let uart = super::UART0_BASE as *mut char;
|
||||
for c in s.chars() {
|
||||
unsafe { uart.write_volatile(c) }
|
||||
}
|
||||
}
|
||||
}
|
52
src/arch/riscv/boot/linker64.ld
Normal file
52
src/arch/riscv/boot/linker64.ld
Normal file
@ -0,0 +1,52 @@
|
||||
OUTPUT_ARCH(riscv)
|
||||
ENTRY(_start)
|
||||
|
||||
BASE_ADDRESS = 0x80200000;
|
||||
|
||||
MEMORY {
|
||||
DRAM : ORIGIN = BASE_ADDRESS, LENGTH = 16M
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
. = BASE_ADDRESS;
|
||||
|
||||
.text : {
|
||||
__text_start = .;
|
||||
*(.text.entry)
|
||||
*(.text .text.*)
|
||||
__text_end = .;
|
||||
} > DRAM
|
||||
|
||||
.rodata : {
|
||||
. = ALIGN(8);
|
||||
__rodata_start = .;
|
||||
*(.rodata .rodata.*)
|
||||
*(.srodata .srodata.*)
|
||||
__rodata_end = .;
|
||||
} > DRAM
|
||||
|
||||
.data : {
|
||||
. = ALIGN(8);
|
||||
__data_start = .;
|
||||
*(.data .data.*)
|
||||
*(.sdata .sdata.*)
|
||||
__data_end = .;
|
||||
} > DRAM
|
||||
|
||||
.stack : {
|
||||
. = ALIGN(8);
|
||||
*(.boot_stack)
|
||||
} > DRAM
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(8);
|
||||
__bss_start = .;
|
||||
*(.bss .bss.*)
|
||||
*(.sbss .sbss.*)
|
||||
__bss_end = .;
|
||||
} > DRAM
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
}
|
||||
}
|
43
src/arch/riscv/entry.rs
Normal file
43
src/arch/riscv/entry.rs
Normal file
@ -0,0 +1,43 @@
|
||||
#[naked]
|
||||
#[no_mangle]
|
||||
#[link_section = ".text.entry"]
|
||||
unsafe extern "C" fn _start(hart_id: usize, device_tree_addr: usize) -> ! {
|
||||
// simplest starter
|
||||
// no stack here
|
||||
|
||||
const STACK_SIZE: usize = 4096 * 16;
|
||||
#[link_section = ".boot_stack"]
|
||||
static mut STACK: [u8; STACK_SIZE] = [0u8; STACK_SIZE];
|
||||
|
||||
core::arch::asm!(
|
||||
"la sp, {stack} + {stack_size}",
|
||||
"j {main}",
|
||||
stack_size = const STACK_SIZE,
|
||||
stack = sym STACK,
|
||||
main = sym pre_main,
|
||||
options(noreturn),
|
||||
)
|
||||
}
|
||||
|
||||
extern "C" fn pre_main(hart_id: usize, device_tree_addr: usize) -> ! {
|
||||
unsafe { zero_bss() }
|
||||
|
||||
// TODO: initialize page table
|
||||
|
||||
crate::entry::rust_main(hart_id, device_tree_addr);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static mut __bss_start: u8;
|
||||
static mut __bss_end: u8;
|
||||
}
|
||||
|
||||
unsafe fn zero_bss() {
|
||||
let mut cur = &mut __bss_start as *mut u8;
|
||||
let end = &mut __bss_end as *mut u8;
|
||||
|
||||
while cur < end {
|
||||
cur.write_volatile(0);
|
||||
cur = cur.add(1);
|
||||
}
|
||||
}
|
10
src/arch/riscv/io.rs
Normal file
10
src/arch/riscv/io.rs
Normal file
@ -0,0 +1,10 @@
|
||||
#[allow(unused_imports)]
|
||||
use crate::arch::io::{Printer, RawConsole};
|
||||
|
||||
#[cfg(feature = "board_default")]
|
||||
impl Printer for RawConsole {
|
||||
fn put_char(c: char) {
|
||||
#[allow(deprecated)]
|
||||
sbi_rt::legacy::console_putchar(c as usize);
|
||||
}
|
||||
}
|
37
src/arch/riscv/lowlevel.rs
Normal file
37
src/arch/riscv/lowlevel.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use crate::arch::lowlevel::{Hardware, LowLevel};
|
||||
use log::error;
|
||||
|
||||
impl LowLevel for Hardware {
|
||||
#[inline]
|
||||
fn halt() {
|
||||
unsafe { core::arch::asm!("wfi") }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shutdown(failure: bool) -> ! {
|
||||
Self::disable_interrupt();
|
||||
|
||||
if failure {
|
||||
sbi_rt::system_reset(sbi_rt::Shutdown, sbi_rt::SystemFailure);
|
||||
} else {
|
||||
sbi_rt::system_reset(sbi_rt::Shutdown, sbi_rt::NoReason);
|
||||
}
|
||||
|
||||
loop {
|
||||
// in case system_reset failed
|
||||
Self::halt()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reset(failure: bool) -> ! {
|
||||
if failure {
|
||||
sbi_rt::system_reset(sbi_rt::ColdReboot, sbi_rt::SystemFailure);
|
||||
} else {
|
||||
sbi_rt::system_reset(sbi_rt::WarmReboot, sbi_rt::NoReason);
|
||||
}
|
||||
|
||||
error!("[riscv/lowlevel] system_reset failed, shutdown instead");
|
||||
Self::shutdown(true);
|
||||
}
|
||||
}
|
7
src/arch/riscv/mod.rs
Normal file
7
src/arch/riscv/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
#[cfg(feature = "board_virt")]
|
||||
#[path = "board/virt/mod.rs"]
|
||||
mod board;
|
||||
|
||||
pub mod entry;
|
||||
pub mod io;
|
||||
pub mod lowlevel;
|
30
src/entry.rs
Normal file
30
src/entry.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use crate::arch::lowlevel::{Hardware, LowLevel};
|
||||
use log::{error, info};
|
||||
|
||||
pub extern "C" fn rust_main(hart_id: usize, device_tree_addr: usize) -> ! {
|
||||
crate::logging::init();
|
||||
|
||||
info!("[rust_main] Kernel Started");
|
||||
|
||||
info!("Hello World!");
|
||||
info!("hart_id = {}", hart_id);
|
||||
info!("device_tree_addr = {:#x}", device_tree_addr);
|
||||
|
||||
// TODO: setup and start scheduler
|
||||
|
||||
error!("[rust_main] Should not reach here! Maybe scheduler is not working?");
|
||||
Hardware::shutdown(true);
|
||||
}
|
||||
|
||||
pub fn print_hello() {
|
||||
const SERIAL_PORT_BASE_ADDRESS: usize = 0x1000_0000;
|
||||
const HELLO: &[u8] = b"Hello World!\n";
|
||||
|
||||
use uart_16550::MmioSerialPort;
|
||||
let mut serial_port = unsafe { MmioSerialPort::new(SERIAL_PORT_BASE_ADDRESS) };
|
||||
serial_port.init();
|
||||
|
||||
for &byte in HELLO {
|
||||
serial_port.send(byte);
|
||||
}
|
||||
}
|
21
src/lang.rs
Normal file
21
src/lang.rs
Normal file
@ -0,0 +1,21 @@
|
||||
use crate::arch::lowlevel::{Hardware, LowLevel};
|
||||
use core::panic::PanicInfo;
|
||||
use log::error;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
error!("[lang] Kernel panic!");
|
||||
|
||||
if let Some(location) = info.location() {
|
||||
error!(
|
||||
"[lang] Panicked: [{}:{}] {}",
|
||||
location.file(),
|
||||
location.line(),
|
||||
info.message().unwrap(),
|
||||
);
|
||||
} else {
|
||||
error!("[lang] Panicked: {}", info.message().unwrap());
|
||||
}
|
||||
|
||||
Hardware::shutdown(true);
|
||||
}
|
17
src/lib.rs
Normal file
17
src/lib.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#![no_std]
|
||||
#![feature(asm_const)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(fmt_internals)]
|
||||
|
||||
// arch
|
||||
pub mod arch;
|
||||
|
||||
// rust language runtime
|
||||
pub mod lang;
|
||||
|
||||
// entrypoint
|
||||
pub mod entry;
|
||||
|
||||
// logging
|
||||
pub mod logging;
|
31
src/logging.rs
Normal file
31
src/logging.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use crate::arch::io::RawConsole;
|
||||
use core::fmt::Write;
|
||||
use log::{self, 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;
|
||||
}
|
||||
|
||||
RawConsole
|
||||
.write_fmt(format_args!("[{}] {}\n", record.level(), record.args()))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn flush(&self) {}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
static LOGGER: SimpleLogger = SimpleLogger;
|
||||
log::set_logger(&LOGGER).unwrap();
|
||||
|
||||
// TODO: get log level from boot env
|
||||
log::set_max_level(LevelFilter::Trace);
|
||||
}
|
6
src/main.rs
Normal file
6
src/main.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[allow(unused_imports)]
|
||||
#[allow(clippy::single_component_path_imports)]
|
||||
use tiny_os;
|
Loading…
Reference in New Issue
Block a user