Add the rust std as a custom sysroot
This commit is contained in:
@@ -3,10 +3,9 @@ target = "riscv64.json"
|
|||||||
|
|
||||||
[unstable]
|
[unstable]
|
||||||
json-target-spec = true
|
json-target-spec = true
|
||||||
build-std = ["core", "compiler_builtins", "alloc"]
|
|
||||||
build-std-features = ["compiler-builtins-mem"]
|
|
||||||
|
|
||||||
[target.riscv64]
|
[target.riscv64]
|
||||||
rustflags = [
|
rustflags = [
|
||||||
"-C", "link-arg=-Tilm.ld",
|
"-C", "link-arg=-Tilm.ld",
|
||||||
|
"--sysroot", "sysroot"
|
||||||
]
|
]
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,3 +7,6 @@
|
|||||||
disk.img
|
disk.img
|
||||||
**/*.mem
|
**/*.mem
|
||||||
mnt
|
mnt
|
||||||
|
|
||||||
|
sysroot/lib/rustlib/riscv64
|
||||||
|
library/alloc
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["crates/bytes-struct","crates/io","crates/os-std", "crates/shared", "user/*"]
|
members = [ "user/*"]
|
||||||
|
exclude = ["library"]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "kernel-rust"
|
name = "kernel-rust"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#![feature(iterator_try_collect, iter_order_by)]
|
#![feature(iterator_try_collect, iter_order_by)]
|
||||||
|
#![allow(unused_features)]
|
||||||
#![cfg_attr(any(not(feature = "std"), target_arch = "riscv64"), no_std)]
|
#![cfg_attr(any(not(feature = "std"), target_arch = "riscv64"), no_std)]
|
||||||
|
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ edition = "2024"
|
|||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
image = "0.25"
|
image = { version = "0.25", default-features = false, features = ["png"] }
|
||||||
syn = { version = "2", features = ["full"] }
|
syn = { version = "2", features = ["full"] }
|
||||||
zyn = "0.5"
|
zyn = "0.5"
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "os-std-macros"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
proc-macro = true
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
proc-macro2 = "1"
|
|
||||||
quote = "1"
|
|
||||||
syn = { version = "2", features = ["full"] }
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "os-std"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
os-std-macros = { path = "../os-std-macros" }
|
|
||||||
shared = { path = "../shared", features = ["user"] }
|
|
||||||
io = { path = "../io", features = ["alloc"] }
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
pub use io::SeekFrom;
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
|
|
||||||
extern crate alloc;
|
|
||||||
|
|
||||||
pub mod io;
|
|
||||||
pub mod prelude;
|
|
||||||
|
|
||||||
pub use shared::fs;
|
|
||||||
pub use shared::syscall;
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! custom_std_setup {
|
|
||||||
() => {
|
|
||||||
use $crate::prelude::*;
|
|
||||||
|
|
||||||
extern crate alloc;
|
|
||||||
|
|
||||||
struct GlobalAllocator;
|
|
||||||
|
|
||||||
#[global_allocator]
|
|
||||||
static GLOBAL_ALLOCATOR: GlobalAllocator = GlobalAllocator;
|
|
||||||
|
|
||||||
unsafe impl core::alloc::GlobalAlloc for GlobalAllocator {
|
|
||||||
unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
|
|
||||||
$crate::syscall::alloc(layout)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
|
|
||||||
$crate::syscall::dealloc(ptr, layout)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(_panic_info: &core::panic::PanicInfo) -> ! {
|
|
||||||
// TODO print
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
pub extern "C" fn _start() {
|
|
||||||
main()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! print {
|
|
||||||
($($args:expr),*) => {
|
|
||||||
$crate::syscall::write_string_temp(&format!($($args),*))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! println {
|
|
||||||
() => {
|
|
||||||
$crate::print!("");
|
|
||||||
// $crate::print!("\n\r");
|
|
||||||
};
|
|
||||||
($($args:expr),*) => {
|
|
||||||
$crate::print!($($args),*);
|
|
||||||
// $crate::println!();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
pub use crate::print;
|
|
||||||
pub use crate::println;
|
|
||||||
pub use alloc::format;
|
|
||||||
pub use alloc::string::String;
|
|
||||||
pub use alloc::vec;
|
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
use io::{IoBase, Read, Write};
|
||||||
|
|
||||||
|
use crate::syscall;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct File {
|
pub struct File {
|
||||||
fd: u64,
|
fd: u64,
|
||||||
@@ -6,7 +10,7 @@ pub struct File {
|
|||||||
impl File {
|
impl File {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// The file descriptor must be valid
|
/// The file descriptor must be valid
|
||||||
pub unsafe fn new(fd: u64) -> Self {
|
pub unsafe fn from_raw_fd(fd: u64) -> Self {
|
||||||
Self { fd }
|
Self { fd }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,3 +18,23 @@ impl File {
|
|||||||
self.fd
|
self.fd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IoBase for File {
|
||||||
|
type Error = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Read for File {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||||
|
Ok(syscall::read(self.as_fd(), buf) as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for File {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||||
|
Ok(syscall::write(self.as_fd(), buf) as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,9 +10,12 @@ pub enum SysCall {
|
|||||||
Read = 0,
|
Read = 0,
|
||||||
Write = 1,
|
Write = 1,
|
||||||
Open = 2,
|
Open = 2,
|
||||||
|
Close = 3,
|
||||||
Seek = 8,
|
Seek = 8,
|
||||||
Alloc = 40,
|
Alloc = 40,
|
||||||
Dealloc = 41,
|
Dealloc = 41,
|
||||||
|
Spawn = 58,
|
||||||
|
ExecVE = 59,
|
||||||
Exit = 60,
|
Exit = 60,
|
||||||
NanoSleep = 101,
|
NanoSleep = 101,
|
||||||
WriteIntTemp = 998,
|
WriteIntTemp = 998,
|
||||||
@@ -26,9 +29,12 @@ impl From<u64> for SysCall {
|
|||||||
0 => SysCall::Read,
|
0 => SysCall::Read,
|
||||||
1 => SysCall::Write,
|
1 => SysCall::Write,
|
||||||
2 => SysCall::Open,
|
2 => SysCall::Open,
|
||||||
|
3 => SysCall::Close,
|
||||||
8 => SysCall::Seek,
|
8 => SysCall::Seek,
|
||||||
40 => SysCall::Alloc,
|
40 => SysCall::Alloc,
|
||||||
41 => SysCall::Dealloc,
|
41 => SysCall::Dealloc,
|
||||||
|
58 => SysCall::Spawn,
|
||||||
|
59 => SysCall::ExecVE,
|
||||||
60 => SysCall::Exit,
|
60 => SysCall::Exit,
|
||||||
101 => SysCall::NanoSleep,
|
101 => SysCall::NanoSleep,
|
||||||
998 => SysCall::WriteIntTemp,
|
998 => SysCall::WriteIntTemp,
|
||||||
@@ -143,30 +149,53 @@ pub fn open<P: AsRef<Path>>(path: P) -> File {
|
|||||||
let ptr = path_str.as_ptr();
|
let ptr = path_str.as_ptr();
|
||||||
let size = path_str.len();
|
let size = path_str.len();
|
||||||
let (fd, ..) = syscall!(SysCall::Open, ptr as u64, size as u64);
|
let (fd, ..) = syscall!(SysCall::Open, ptr as u64, size as u64);
|
||||||
File::new(fd)
|
File::from_raw_fd(fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn write(file: &mut File, buf: &[u8]) {
|
pub fn close(file_descriptor: u64) {
|
||||||
|
unsafe {
|
||||||
|
syscall!(SysCall::Close, file_descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn write(file_descriptor: u64, buf: &[u8]) -> u64 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = buf.as_ptr();
|
let ptr = buf.as_ptr();
|
||||||
let size = buf.len();
|
let size = buf.len();
|
||||||
syscall!(SysCall::Write, file.as_fd(), ptr as u64, size as u64);
|
let (len, ..) = syscall!(SysCall::Write, file_descriptor, ptr as u64, size as u64);
|
||||||
|
len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn read(file: &mut File, buf: &mut [u8]) {
|
pub fn read(file_descriptor: u64, buf: &mut [u8]) -> u64 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = buf.as_ptr();
|
let ptr = buf.as_ptr();
|
||||||
let size = buf.len();
|
let size = buf.len();
|
||||||
syscall!(SysCall::Read, file.as_fd(), ptr as u64, size as u64);
|
let (len, ..) = syscall!(SysCall::Read, file_descriptor, ptr as u64, size as u64);
|
||||||
|
len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn seek(file: &mut File, seek: SeekFrom) {
|
pub fn seek(file_descriptor: u64, seek: SeekFrom) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (discriminant, value) = match seek {
|
let (discriminant, value) = match seek {
|
||||||
SeekFrom::Start(v) => (0, v),
|
SeekFrom::Start(v) => (0, v),
|
||||||
SeekFrom::End(v) => (1, v as u64),
|
SeekFrom::End(v) => (1, v as u64),
|
||||||
SeekFrom::Current(v) => (2, v as u64),
|
SeekFrom::Current(v) => (2, v as u64),
|
||||||
};
|
};
|
||||||
syscall!(SysCall::Seek, file.as_fd(), discriminant, value);
|
syscall!(SysCall::Seek, file_descriptor, discriminant, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn spawn<P: AsRef<Path>>(path: P) {
|
||||||
|
unsafe {
|
||||||
|
let path_str = path.as_ref().as_str();
|
||||||
|
let ptr = path_str.as_ptr();
|
||||||
|
let size = path_str.len();
|
||||||
|
syscall!(SysCall::Spawn, ptr as u64, size as u64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn execve<P: AsRef<Path>>(path: P) {
|
||||||
|
unsafe {
|
||||||
|
let path_str = path.as_ref().as_str();
|
||||||
|
let ptr = path_str.as_ptr();
|
||||||
|
let size = path_str.len();
|
||||||
|
syscall!(SysCall::ExecVE, ptr as u64, size as u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
ilm.ld
2
ilm.ld
@@ -5,7 +5,7 @@ OUTPUT_ARCH(riscv)
|
|||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
MEMORY {
|
MEMORY {
|
||||||
RAM (wxa) : ORIGIN = 0x80000000, LENGTH = 128M
|
RAM (wxa) : ORIGIN = 0x80000000, LENGTH = 512M
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
|
|||||||
15
justfile
15
justfile
@@ -12,13 +12,19 @@ mount_filesystem:
|
|||||||
sync_filesystem:
|
sync_filesystem:
|
||||||
sync
|
sync
|
||||||
|
|
||||||
|
update-std:
|
||||||
|
@cd library/std && just update-std
|
||||||
|
|
||||||
|
build-sysroot:
|
||||||
|
@cd library/std && just build-sysroot
|
||||||
|
|
||||||
build_user_prog prog:
|
build_user_prog prog:
|
||||||
RUSTFLAGS="-C relocation-model=pic -C link-arg=-Tuser.ld -C link-arg=-pie" cargo b {{ cargo_flags }} --package {{ prog }}
|
RUSTFLAGS="-C relocation-model=pic -C link-arg=-pie --sysroot {{ justfile_directory() / "sysroot" }}" cargo b {{ cargo_flags }} --package {{ prog }}
|
||||||
riscv64-elf-strip {{ bin_path / prog }}
|
riscv64-elf-strip {{ bin_path / prog }}
|
||||||
cp {{ bin_path / prog }} {{ "mnt/usr/bin" / prog }}
|
cp {{ bin_path / prog }} {{ "mnt/usr/bin" / prog }}
|
||||||
|
|
||||||
build: mount_filesystem (map_dir "user" f"just release=\"{{release}}\" cargo_flags=\"{{cargo_flags}}\" build_user_prog")
|
build: mount_filesystem (map_dir "user" f"just release=\"{{release}}\" cargo_flags=\"{{cargo_flags}}\" build_user_prog")
|
||||||
cargo b {{ cargo_flags }}
|
RUSTFLAGS="-Clink-arg=-Tilm.ld --sysroot {{ justfile_directory() / "sysroot" }}" cargo b {{ cargo_flags }}
|
||||||
just sync_filesystem
|
just sync_filesystem
|
||||||
|
|
||||||
run: build (runner f"{{bin_path / "kernel-rust"}}")
|
run: build (runner f"{{bin_path / "kernel-rust"}}")
|
||||||
@@ -34,8 +40,8 @@ qemu := f"qemu-system-riscv64 \
|
|||||||
-device bochs-display \
|
-device bochs-display \
|
||||||
-device virtio-keyboard-pci \
|
-device virtio-keyboard-pci \
|
||||||
-device virtio-mouse-pci \
|
-device virtio-mouse-pci \
|
||||||
-device loader,file=disk.img,addr=0x90000000 \
|
-device loader,file=disk.img,addr=0xA0000000 \
|
||||||
-bios none -m 512M {{qemu_flags}}"
|
-bios none -m 1024M {{qemu_flags}}"
|
||||||
|
|
||||||
# -trace \"virtio*\"
|
# -trace \"virtio*\"
|
||||||
# -d guest_errors,unimp,int"
|
# -d guest_errors,unimp,int"
|
||||||
@@ -53,4 +59,5 @@ runner args:
|
|||||||
{{ qemu }} -kernel {{ args }}
|
{{ qemu }} -kernel {{ args }}
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
cd library && just clean
|
||||||
cargo clean
|
cargo clean
|
||||||
|
|||||||
22
library/.gitignore
vendored
Normal file
22
library/.gitignore
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Cargo.lock
|
||||||
|
Cargo.toml
|
||||||
|
alloctests
|
||||||
|
backtrace
|
||||||
|
compiler-builtins
|
||||||
|
core
|
||||||
|
coretests
|
||||||
|
panic_abort
|
||||||
|
panic_unwind
|
||||||
|
portable-simd
|
||||||
|
proc_macro
|
||||||
|
profiler_builtins
|
||||||
|
rustc-std-workspace-alloc
|
||||||
|
rustc-std-workspace-core
|
||||||
|
rustc-std-workspace-std
|
||||||
|
std_detect
|
||||||
|
stdarch
|
||||||
|
sysroot
|
||||||
|
target
|
||||||
|
test
|
||||||
|
unwind
|
||||||
|
windows_link
|
||||||
108
library/justfile
Normal file
108
library/justfile
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
SRC_DIR := "std/src"
|
||||||
|
PATCH_DIR := "std/patches"
|
||||||
|
RUST_SRC := `rustc --print sysroot` / "lib/rustlib/src/rust/library"
|
||||||
|
ROOT_LINKS := "\
|
||||||
|
Cargo.toml backtrace std_detect panic_abort panic_unwind \
|
||||||
|
windows_link unwind alloc rustc-std-workspace-alloc \
|
||||||
|
rustc-std-workspace-core rustc-std-workspace-std \
|
||||||
|
compiler-builtins core stdarch portable-simd proc_macro \
|
||||||
|
profiler_builtins test coretests alloctests sysroot"
|
||||||
|
REAL_CP_FILES := "\
|
||||||
|
sys/args/mod.rs \
|
||||||
|
sys/io/error/mod.rs \
|
||||||
|
sys/pal/mod.rs \
|
||||||
|
sys/random/mod.rs \
|
||||||
|
sys/thread_local/mod.rs"
|
||||||
|
STD_FILES := "\
|
||||||
|
alloc.rs ascii.rs backtrace.rs bstr.rs env.rs error.rs fs.rs \
|
||||||
|
keyword_docs.rs lib.rs macros.rs panic.rs panicking.rs pat.rs \
|
||||||
|
path.rs process.rs random.rs rt.rs tests_helpers.rs time.rs \
|
||||||
|
backtrace collections ffi fs hash io net num os/raw/mod.rs \
|
||||||
|
os/raw/tests.rs os/mod.rs prelude process sync sys/alloc/mod.rs \
|
||||||
|
sys/args/unsupported.rs sys/env/mod.rs sys/env/common.rs \
|
||||||
|
sys/env/unsupported.rs sys/fd/mod.rs sys/fs/mod.rs \
|
||||||
|
sys/fs/common.rs sys/fs/unsupported.rs sys/helpers/mod.rs \
|
||||||
|
sys/helpers/small_c_string.rs sys/helpers/tests.rs sys/helpers/wstr.rs \
|
||||||
|
sys/io/error/generic.rs sys/io/io_slice/unsupported.rs \
|
||||||
|
sys/io/is_terminal/unsupported.rs sys/io/kernel_copy/mod.rs \
|
||||||
|
sys/io/mod.rs sys/net/connection/mod.rs sys/net/connection/unsupported.rs \
|
||||||
|
sys/net/hostname/mod.rs sys/net/hostname/unsupported.rs sys/net/mod.rs \
|
||||||
|
sys/os_str/bytes/tests.rs sys/os_str/bytes.rs sys/os_str/mod.rs \
|
||||||
|
sys/pal/unsupported/mod.rs sys/pal/unsupported/common.rs \
|
||||||
|
sys/pal/unsupported/os.rs sys/path/mod.rs sys/path/unix.rs \
|
||||||
|
sys/personality/dwarf/eh.rs sys/personality/dwarf/mod.rs \
|
||||||
|
sys/personality/dwarf/tests.rs sys/personality/mod.rs sys/pipe/mod.rs \
|
||||||
|
sys/pipe/unsupported.rs sys/platform_version/mod.rs sys/process/mod.rs \
|
||||||
|
sys/process/env.rs sys/process/unsupported.rs sys/random/unsupported.rs \
|
||||||
|
sys/stdio/mod.rs sys/stdio/unsupported.rs sys/sync/condvar/mod.rs \
|
||||||
|
sys/sync/condvar/no_threads.rs sys/sync/mutex/mod.rs \
|
||||||
|
sys/sync/mutex/no_threads.rs sys/sync/once/mod.rs \
|
||||||
|
sys/sync/once/no_threads.rs sys/sync/rwlock/mod.rs \
|
||||||
|
sys/sync/rwlock/no_threads.rs sys/sync/thread_parking/mod.rs \
|
||||||
|
sys/sync/thread_parking/unsupported.rs sys/sync/mod.rs \
|
||||||
|
sys/sync/once_box.rs sys/thread/mod.rs sys/thread/unsupported.rs \
|
||||||
|
sys/thread_local/no_threads.rs sys/thread_local/os.rs sys/time/mod.rs \
|
||||||
|
sys/time/unsupported.rs sys/backtrace.rs sys/cmath.rs \
|
||||||
|
sys/configure_builtins.rs sys/env_consts.rs sys/exit.rs sys/mod.rs thread"
|
||||||
|
KEEP_FILES := "sys sys/pal sys/pal/survos.rs sys/alloc sys/alloc/survos.rs"
|
||||||
|
|
||||||
|
setup-std:
|
||||||
|
@echo "🔗 Linking root directories..."
|
||||||
|
@for dir in {{ ROOT_LINKS }}; do ln -fs {{ RUST_SRC }}/$dir "."; done
|
||||||
|
|
||||||
|
@echo "📂 Processing std/src files..."
|
||||||
|
@for f in {{ STD_FILES }}; do {{ just_executable() }} cp_std $f; done
|
||||||
|
@for f in {{ REAL_CP_FILES }}; do {{ just_executable() }} real_cp_std $f; done
|
||||||
|
|
||||||
|
@{{ just_executable() }} cp_std "../build.rs"
|
||||||
|
@{{ just_executable() }} cp_std "../Cargo.toml"
|
||||||
|
@sed -i '59a\ || target_os == "survos"' std/src/../build.rs
|
||||||
|
|
||||||
|
update-std: setup-std patch-std
|
||||||
|
|
||||||
|
patch-std:
|
||||||
|
@echo "🛠️ Patching the std..."
|
||||||
|
@find {{ PATCH_DIR }} -type f -name "*.sed" | while read -r patch_file; do \
|
||||||
|
rel="${patch_file#{{ PATCH_DIR }}/}"; \
|
||||||
|
target="{{ SRC_DIR }}/${rel%.sed}.rs"; \
|
||||||
|
if [ -f "$target" ]; then \
|
||||||
|
echo " [SED] ${rel%.sed}.rs"; \
|
||||||
|
sed -i -f "$patch_file" "$target"; \
|
||||||
|
else \
|
||||||
|
echo "⚠ [WARN] target missing: $target"; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
|
||||||
|
build-sysroot:
|
||||||
|
RUSTFLAGS="-Zforce-unstable-if-unmarked -C relocation-model=pic -C link-arg=-pie" \
|
||||||
|
cargo build --package std --target ../riscv64.json --features compiler-builtins-mem
|
||||||
|
mkdir -p ../sysroot/lib/rustlib/riscv64/lib
|
||||||
|
rm -rf ../sysroot/lib/rustlib/riscv64/lib/*
|
||||||
|
cp target/riscv64/debug/deps/*.rlib ../sysroot/lib/rustlib/riscv64/lib
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cargo clean
|
||||||
|
rm -rf ../sysroot/lib/rustlib/riscv64/lib/*
|
||||||
|
@for item in $(find library/std/src); do \
|
||||||
|
basename_item=$(basename "$item"); \
|
||||||
|
keep=0; \
|
||||||
|
for protected in {{ KEEP_FILES }}; do \
|
||||||
|
echo $basename_item = $protected; \
|
||||||
|
if [ "$basename_item" = "$protected" ]; then keep=1; break; fi; \
|
||||||
|
done; \
|
||||||
|
if [ "$keep" -eq 0 ]; then \
|
||||||
|
rm -rf "$item"; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
rm -f std/build.rs std/Cargo.toml Cargo.toml
|
||||||
|
@for item in {{ ROOT_LINKS }}; do rm -rf $item; done
|
||||||
|
|
||||||
|
# --- Helpers ---
|
||||||
|
|
||||||
|
cp_std path:
|
||||||
|
@mkdir -p {{ SRC_DIR / parent_directory(path) }}
|
||||||
|
@ln -fs {{ RUST_SRC / "std/src" / path }} {{ parent_directory(SRC_DIR / path) }}
|
||||||
|
|
||||||
|
real_cp_std path:
|
||||||
|
@mkdir -p {{ SRC_DIR / parent_directory(path) }}
|
||||||
|
@cp -r {{ RUST_SRC / "std/src" / path }} {{ SRC_DIR / path }}
|
||||||
146
library/std/.gitignore
vendored
Normal file
146
library/std/.gitignore
vendored
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
Cargo.lock
|
||||||
|
Cargo.toml
|
||||||
|
build.rs
|
||||||
|
target
|
||||||
|
src/random.rs
|
||||||
|
src/num
|
||||||
|
src/prelude
|
||||||
|
src/sync
|
||||||
|
src/fs.rs
|
||||||
|
src/alloc.rs
|
||||||
|
src/process
|
||||||
|
src/backtrace.rs
|
||||||
|
src/ascii.rs
|
||||||
|
src/bstr.rs
|
||||||
|
src/thread
|
||||||
|
src/keyword_docs.rs
|
||||||
|
src/tests_helpers.rs
|
||||||
|
src/error.rs
|
||||||
|
src/net
|
||||||
|
src/rt.rs
|
||||||
|
src/sys/args
|
||||||
|
src/sys/args/mod.rs
|
||||||
|
src/sys/args/unsupported.rs
|
||||||
|
src/sys/thread_local
|
||||||
|
src/sys/thread_local/os.rs
|
||||||
|
src/sys/thread_local/no_threads.rs
|
||||||
|
src/sys/thread_local/mod.rs
|
||||||
|
src/sys/platform_version
|
||||||
|
src/sys/platform_version/mod.rs
|
||||||
|
src/sys/personality
|
||||||
|
src/sys/personality/dwarf
|
||||||
|
src/sys/personality/dwarf/eh.rs
|
||||||
|
src/sys/personality/dwarf/mod.rs
|
||||||
|
src/sys/personality/dwarf/tests.rs
|
||||||
|
src/sys/personality/mod.rs
|
||||||
|
src/sys/pal/mod.rs
|
||||||
|
src/sys/pal/unsupported
|
||||||
|
src/sys/pal/unsupported/os.rs
|
||||||
|
src/sys/pal/unsupported/mod.rs
|
||||||
|
src/sys/pal/unsupported/common.rs
|
||||||
|
src/sys/sync
|
||||||
|
src/sys/sync/condvar
|
||||||
|
src/sys/sync/condvar/no_threads.rs
|
||||||
|
src/sys/sync/condvar/mod.rs
|
||||||
|
src/sys/sync/mutex
|
||||||
|
src/sys/sync/mutex/no_threads.rs
|
||||||
|
src/sys/sync/mutex/mod.rs
|
||||||
|
src/sys/sync/once_box.rs
|
||||||
|
src/sys/sync/rwlock
|
||||||
|
src/sys/sync/rwlock/no_threads.rs
|
||||||
|
src/sys/sync/rwlock/mod.rs
|
||||||
|
src/sys/sync/mod.rs
|
||||||
|
src/sys/sync/thread_parking
|
||||||
|
src/sys/sync/thread_parking/mod.rs
|
||||||
|
src/sys/sync/thread_parking/unsupported.rs
|
||||||
|
src/sys/sync/once
|
||||||
|
src/sys/sync/once/no_threads.rs
|
||||||
|
src/sys/sync/once/mod.rs
|
||||||
|
src/sys/fd
|
||||||
|
src/sys/fd/mod.rs
|
||||||
|
src/sys/process
|
||||||
|
src/sys/process/mod.rs
|
||||||
|
src/sys/process/env.rs
|
||||||
|
src/sys/process/unsupported.rs
|
||||||
|
src/sys/pipe
|
||||||
|
src/sys/pipe/mod.rs
|
||||||
|
src/sys/pipe/unsupported.rs
|
||||||
|
src/sys/env_consts.rs
|
||||||
|
src/sys/backtrace.rs
|
||||||
|
src/sys/exit.rs
|
||||||
|
src/sys/thread
|
||||||
|
src/sys/thread/mod.rs
|
||||||
|
src/sys/thread/unsupported.rs
|
||||||
|
src/sys/env
|
||||||
|
src/sys/env/mod.rs
|
||||||
|
src/sys/env/common.rs
|
||||||
|
src/sys/env/unsupported.rs
|
||||||
|
src/sys/net
|
||||||
|
src/sys/net/hostname
|
||||||
|
src/sys/net/hostname/mod.rs
|
||||||
|
src/sys/net/hostname/unsupported.rs
|
||||||
|
src/sys/net/mod.rs
|
||||||
|
src/sys/net/connection
|
||||||
|
src/sys/net/connection/mod.rs
|
||||||
|
src/sys/net/connection/unsupported.rs
|
||||||
|
src/sys/path
|
||||||
|
src/sys/path/mod.rs
|
||||||
|
src/sys/path/unix.rs
|
||||||
|
src/sys/configure_builtins.rs
|
||||||
|
src/sys/mod.rs
|
||||||
|
src/sys/time
|
||||||
|
src/sys/time/mod.rs
|
||||||
|
src/sys/time/unsupported.rs
|
||||||
|
src/sys/stdio
|
||||||
|
src/sys/stdio/mod.rs
|
||||||
|
src/sys/stdio/unsupported.rs
|
||||||
|
src/sys/cmath.rs
|
||||||
|
src/sys/alloc/mod.rs
|
||||||
|
src/sys/helpers
|
||||||
|
src/sys/helpers/mod.rs
|
||||||
|
src/sys/helpers/wstr.rs
|
||||||
|
src/sys/helpers/tests.rs
|
||||||
|
src/sys/helpers/small_c_string.rs
|
||||||
|
src/sys/fs
|
||||||
|
src/sys/fs/mod.rs
|
||||||
|
src/sys/fs/common.rs
|
||||||
|
src/sys/fs/unsupported.rs
|
||||||
|
src/sys/random
|
||||||
|
src/sys/random/mod.rs
|
||||||
|
src/sys/random/unsupported.rs
|
||||||
|
src/sys/io
|
||||||
|
src/sys/io/is_terminal
|
||||||
|
src/sys/io/is_terminal/unsupported.rs
|
||||||
|
src/sys/io/mod.rs
|
||||||
|
src/sys/io/io_slice
|
||||||
|
src/sys/io/io_slice/unsupported.rs
|
||||||
|
src/sys/io/error
|
||||||
|
src/sys/io/error/mod.rs
|
||||||
|
src/sys/io/error/generic.rs
|
||||||
|
src/sys/io/kernel_copy
|
||||||
|
src/sys/io/kernel_copy/mod.rs
|
||||||
|
src/sys/os_str
|
||||||
|
src/sys/os_str/mod.rs
|
||||||
|
src/sys/os_str/bytes
|
||||||
|
src/sys/os_str/bytes/tests.rs
|
||||||
|
src/sys/os_str/bytes.rs
|
||||||
|
src/macros.rs
|
||||||
|
src/os
|
||||||
|
src/os/mod.rs
|
||||||
|
src/os/raw
|
||||||
|
src/os/raw/mod.rs
|
||||||
|
src/os/raw/tests.rs
|
||||||
|
src/backtrace
|
||||||
|
src/path.rs
|
||||||
|
src/lib.rs
|
||||||
|
src/process.rs
|
||||||
|
src/ffi
|
||||||
|
src/env.rs
|
||||||
|
src/pat.rs
|
||||||
|
src/fs
|
||||||
|
src/panic.rs
|
||||||
|
src/collections
|
||||||
|
src/panicking.rs
|
||||||
|
src/time.rs
|
||||||
|
src/io
|
||||||
|
src/hash
|
||||||
3
library/std/patches/sys/alloc/mod.sed
Normal file
3
library/std/patches/sys/alloc/mod.sed
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
109a \ target_os = "survos" => { \
|
||||||
|
mod survos; \
|
||||||
|
}
|
||||||
4
library/std/patches/sys/args/mod.sed
Normal file
4
library/std/patches/sys/args/mod.sed
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# 55a \ target_os = "survos" => { \
|
||||||
|
# mod survos; \
|
||||||
|
# pub use survos::*; \
|
||||||
|
# }
|
||||||
1
library/std/patches/sys/io/error/mod.sed
Normal file
1
library/std/patches/sys/io/error/mod.sed
Normal file
@@ -0,0 +1 @@
|
|||||||
|
45a \ target_os = "survos",
|
||||||
6
library/std/patches/sys/pal/mod.sed
Normal file
6
library/std/patches/sys/pal/mod.sed
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
62a \ target_os = "survos" => { \
|
||||||
|
mod unsupported; \
|
||||||
|
pub use self::unsupported::*; \
|
||||||
|
mod survos; \
|
||||||
|
pub use self::survos::*; \
|
||||||
|
}
|
||||||
2
library/std/patches/sys/random/mod.sed
Normal file
2
library/std/patches/sys/random/mod.sed
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
108a \target_os = "survos",
|
||||||
|
124a \target_os = "survos",
|
||||||
6
library/std/patches/sys/thread_local/mod.sed
Normal file
6
library/std/patches/sys/thread_local/mod.sed
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
32a \ target_os = "survos",
|
||||||
|
|
||||||
|
129a \ target_os = "survos" => { \
|
||||||
|
// todo \
|
||||||
|
pub(crate) fn enable() {} \
|
||||||
|
}
|
||||||
104
library/std/src/sys/alloc/survos.rs
Normal file
104
library/std/src/sys/alloc/survos.rs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#![allow(fuzzy_provenance_casts)]
|
||||||
|
|
||||||
|
use crate::alloc::{GlobalAlloc, Layout, System};
|
||||||
|
|
||||||
|
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
||||||
|
unsafe impl GlobalAlloc for System {
|
||||||
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
|
alloc(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||||
|
dealloc(ptr, layout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u64)]
|
||||||
|
enum SysCall {
|
||||||
|
Read = 0,
|
||||||
|
Write = 1,
|
||||||
|
Open = 2,
|
||||||
|
Close = 3,
|
||||||
|
Seek = 8,
|
||||||
|
Alloc = 40,
|
||||||
|
Dealloc = 41,
|
||||||
|
Spawn = 58,
|
||||||
|
ExecVE = 59,
|
||||||
|
Exit = 60,
|
||||||
|
NanoSleep = 101,
|
||||||
|
WriteIntTemp = 998,
|
||||||
|
WriteTemp = 999,
|
||||||
|
Unimplemented = 1 << 31,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
unsafe fn _syscall(
|
||||||
|
syscall: SysCall,
|
||||||
|
mut a1: u64,
|
||||||
|
mut a2: u64,
|
||||||
|
mut a3: u64,
|
||||||
|
mut a4: u64,
|
||||||
|
mut a5: u64,
|
||||||
|
mut a6: u64,
|
||||||
|
mut a7: u64,
|
||||||
|
) -> (u64, u64, u64, u64, u64, u64, u64, u64) {
|
||||||
|
let mut a0 = syscall as u64;
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm!(
|
||||||
|
"ecall",
|
||||||
|
inlateout("a0") a0,
|
||||||
|
inlateout("a1") a1,
|
||||||
|
inlateout("a2") a2,
|
||||||
|
inlateout("a3") a3,
|
||||||
|
inlateout("a4") a4,
|
||||||
|
inlateout("a5") a5,
|
||||||
|
inlateout("a6") a6,
|
||||||
|
inlateout("a7") a7,
|
||||||
|
clobber_abi("system")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
(a0, a1, a2, a3, a4, a5, a6, a7)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! syscall {
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr) => {
|
||||||
|
_syscall($syscall, $a1, $a2, $a3, $a4, $a5, $a6, $a7)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
|
||||||
|
syscall!($syscall, $a1, $a2, $a3, $a4, $a5, $a6, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
|
||||||
|
syscall!($syscall, $a1, $a2, $a3, $a4, $a5, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
|
||||||
|
syscall!($syscall, $a1, $a2, $a3, $a4, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr, $a3:expr) => {
|
||||||
|
syscall!($syscall, $a1, $a2, $a3, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr, $a2:expr) => {
|
||||||
|
syscall!($syscall, $a1, $a2, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr, $a1:expr) => {
|
||||||
|
syscall!($syscall, $a1, 0)
|
||||||
|
};
|
||||||
|
($syscall:expr) => {
|
||||||
|
syscall!($syscall, 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alloc(layout: Layout) -> *mut u8 {
|
||||||
|
unsafe {
|
||||||
|
let size = layout.size();
|
||||||
|
let align = layout.align();
|
||||||
|
let (ptr, ..) = syscall!(SysCall::Alloc, size as u64, align as u64);
|
||||||
|
ptr as *mut u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn dealloc(ptr: *mut u8, layout: core::alloc::Layout) {
|
||||||
|
unsafe {
|
||||||
|
let size = layout.size();
|
||||||
|
let align = layout.align();
|
||||||
|
syscall!(SysCall::Dealloc, ptr as u64, size as u64, align as u64);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
library/std/src/sys/pal/survos.rs
Normal file
11
library/std/src/sys/pal/survos.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/// # Safety
|
||||||
|
/// `argc` and `argv` are passed by the kernel
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub unsafe extern "C" fn _start(argc: isize, argv: *const *const u8) -> isize {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn main(argc: isize, argv: *const *const u8) -> isize;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { main(argc, argv) }
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
"target-endian": "little",
|
"target-endian": "little",
|
||||||
"target-pointer-width": 64,
|
"target-pointer-width": 64,
|
||||||
"arch": "riscv64",
|
"arch": "riscv64",
|
||||||
"os": "none",
|
"os": "survos",
|
||||||
"vendor": "unknown",
|
"vendor": "unknown",
|
||||||
"env": "",
|
"env": "",
|
||||||
"features": "+i,+m,+a,+zicsr",
|
"features": "+i,+m,+a,+zicsr",
|
||||||
|
|||||||
2
src/drivers.rs
Normal file
2
src/drivers.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod keyboard;
|
||||||
|
pub mod mouse;
|
||||||
67
src/drivers/keyboard.rs
Normal file
67
src/drivers/keyboard.rs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
use crate::{
|
||||||
|
keymap::{KeyType, ModifierType, map_keycode},
|
||||||
|
tty::TTY0,
|
||||||
|
virtio::{
|
||||||
|
Virtqueue,
|
||||||
|
input::{EventCodeValue, VirtioInputEvent, VirtioPciDriver},
|
||||||
|
},
|
||||||
|
virtual_fs::{FILE_SYSTEM, VirtualFileSystem},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct KeyboardState {
|
||||||
|
// ctrl_modifier: bool,
|
||||||
|
pub shift_modifier: bool,
|
||||||
|
pub alt_gr_modifier: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyboardState {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
// ctrl_modifier: false,
|
||||||
|
shift_modifier: false,
|
||||||
|
alt_gr_modifier: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static mut KBD_QUEUE: Virtqueue = unsafe { core::mem::zeroed() };
|
||||||
|
pub static mut KBD_DRIVER: VirtioPciDriver<KeyboardState> = unsafe {
|
||||||
|
VirtioPciDriver::new(
|
||||||
|
|state, event| {
|
||||||
|
let mut kbd_buffer = FILE_SYSTEM.open("/dev/input/keyboard".as_ref()).unwrap();
|
||||||
|
kbd_buffer
|
||||||
|
.write(core::mem::transmute::<
|
||||||
|
&VirtioInputEvent,
|
||||||
|
&[u8; size_of::<VirtioInputEvent>()],
|
||||||
|
>(event))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if event.is_key() {
|
||||||
|
let event = event.as_key_event();
|
||||||
|
#[allow(clippy::single_match)]
|
||||||
|
match map_keycode(event.code, state) {
|
||||||
|
KeyType::Ascii(c) if event.value == EventCodeValue::Pressed => {
|
||||||
|
let mut buf = [0; 4];
|
||||||
|
let to_send = c.encode_utf8(&mut buf);
|
||||||
|
for c in to_send.as_bytes() {
|
||||||
|
TTY0.buffer.borrow_mut().push(*c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyType::Modifier(ModifierType::Shift) => {
|
||||||
|
state.shift_modifier = !state.shift_modifier;
|
||||||
|
}
|
||||||
|
KeyType::Modifier(ModifierType::AltGr) => {
|
||||||
|
state.alt_gr_modifier = !state.alt_gr_modifier;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
// println!("event: {:#?}", event);
|
||||||
|
} else {
|
||||||
|
// println!("key pressed, {:#?}", event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
KeyboardState::new(),
|
||||||
|
&mut KBD_QUEUE,
|
||||||
|
)
|
||||||
|
};
|
||||||
38
src/drivers/mouse.rs
Normal file
38
src/drivers/mouse.rs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
use crate::{
|
||||||
|
cursor::{clear_cursor, draw_cursor},
|
||||||
|
vga::Vga,
|
||||||
|
virtio::{self, Virtqueue, input::VirtioPciDriver},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static mut MOUSE_POSITION: (u16, u16) = (0, 0);
|
||||||
|
|
||||||
|
static mut MOUSE_QUEUE: Virtqueue = unsafe { core::mem::zeroed() };
|
||||||
|
pub static mut MOUSE_DRIVER: VirtioPciDriver<()> = unsafe {
|
||||||
|
VirtioPciDriver::new(
|
||||||
|
|_, event| {
|
||||||
|
if event.is_relative() {
|
||||||
|
let event = event.as_relative_event();
|
||||||
|
|
||||||
|
clear_cursor(&mut Vga, MOUSE_POSITION.0, MOUSE_POSITION.1);
|
||||||
|
|
||||||
|
match event.code {
|
||||||
|
virtio::input::EventCodeRelative::X => {
|
||||||
|
MOUSE_POSITION.0 = (MOUSE_POSITION.0 as i32 + event.value) as u16
|
||||||
|
}
|
||||||
|
virtio::input::EventCodeRelative::Y => {
|
||||||
|
MOUSE_POSITION.1 = (MOUSE_POSITION.1 as i32 + event.value) as u16
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_cursor(&mut Vga, MOUSE_POSITION.0, MOUSE_POSITION.1);
|
||||||
|
|
||||||
|
// println!("mouse moved relatively, {:#?}", event);
|
||||||
|
} else {
|
||||||
|
// println!("mouse moved, {:#?}", event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
&mut MOUSE_QUEUE,
|
||||||
|
)
|
||||||
|
};
|
||||||
@@ -12,7 +12,7 @@ use io::{IoBase, Read, Seek, Write};
|
|||||||
|
|
||||||
use crate::virtual_fs::{VirtualFileSystem, VirtualNode};
|
use crate::virtual_fs::{VirtualFileSystem, VirtualNode};
|
||||||
|
|
||||||
const DISK_ADDR: *const u8 = 0x9000_0000 as *const _;
|
const DISK_ADDR: *const u8 = 0xA000_0000 as *const _;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Simple disk backend that reads from a fixed memory region.
|
/// Simple disk backend that reads from a fixed memory region.
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ use log::info;
|
|||||||
use shared::syscall::SysCall;
|
use shared::syscall::SysCall;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
KBD_DRIVER, MOUSE_DRIVER,
|
|
||||||
boot::sbi::{ExtensionID, TimerFunctionID},
|
boot::sbi::{ExtensionID, TimerFunctionID},
|
||||||
clear_csr,
|
clear_csr,
|
||||||
|
drivers::{keyboard::KBD_DRIVER, mouse::MOUSE_DRIVER},
|
||||||
process::{ExecutionContext, exit_process, sleep},
|
process::{ExecutionContext, exit_process, sleep},
|
||||||
read_csr,
|
read_csr,
|
||||||
riscv::{disable_interrupt, dump_cpu},
|
riscv::{disable_interrupt, dump_cpu},
|
||||||
@@ -160,6 +160,15 @@ unsafe extern "C" fn supervisor_trap_handler(
|
|||||||
|
|
||||||
unsafe { (*interrupt_state).a[0] = fd as u64 };
|
unsafe { (*interrupt_state).a[0] = fd as u64 };
|
||||||
}
|
}
|
||||||
|
SysCall::Close => {
|
||||||
|
let fd = a1;
|
||||||
|
|
||||||
|
let mut scheduler = SCHEDULER.lock();
|
||||||
|
let current_process = scheduler.get_current_process();
|
||||||
|
let mut vnode = current_process.fd_table[fd as usize].take().unwrap();
|
||||||
|
|
||||||
|
vnode.close();
|
||||||
|
}
|
||||||
SysCall::Write => {
|
SysCall::Write => {
|
||||||
let fd = a1;
|
let fd = a1;
|
||||||
let buf =
|
let buf =
|
||||||
@@ -168,7 +177,8 @@ unsafe extern "C" fn supervisor_trap_handler(
|
|||||||
let mut scheduler = SCHEDULER.lock();
|
let mut scheduler = SCHEDULER.lock();
|
||||||
let current_process = scheduler.get_current_process();
|
let current_process = scheduler.get_current_process();
|
||||||
let vnode = current_process.fd_table[fd as usize].as_mut().unwrap();
|
let vnode = current_process.fd_table[fd as usize].as_mut().unwrap();
|
||||||
vnode.write(buf).unwrap();
|
let res = vnode.write(buf).unwrap();
|
||||||
|
unsafe { (*interrupt_state).a[0] = res as u64 };
|
||||||
}
|
}
|
||||||
SysCall::Read => {
|
SysCall::Read => {
|
||||||
let fd = a1;
|
let fd = a1;
|
||||||
@@ -182,6 +192,8 @@ unsafe extern "C" fn supervisor_trap_handler(
|
|||||||
if res == 0 && !buf.is_empty() {
|
if res == 0 && !buf.is_empty() {
|
||||||
loop_syscall(interrupt_state);
|
loop_syscall(interrupt_state);
|
||||||
scheduler.schedule(&mut interrupt_state);
|
scheduler.schedule(&mut interrupt_state);
|
||||||
|
} else {
|
||||||
|
unsafe { (*interrupt_state).a[0] = res as u64 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SysCall::Seek => {
|
SysCall::Seek => {
|
||||||
@@ -197,6 +209,17 @@ unsafe extern "C" fn supervisor_trap_handler(
|
|||||||
let vnode = current_process.fd_table[fd as usize].as_mut().unwrap();
|
let vnode = current_process.fd_table[fd as usize].as_mut().unwrap();
|
||||||
vnode.seek(seek).unwrap();
|
vnode.seek(seek).unwrap();
|
||||||
}
|
}
|
||||||
|
SysCall::Spawn => {
|
||||||
|
let path = unsafe { str::from_raw_parts(a1 as *const u8, a2 as usize) };
|
||||||
|
let mut scheduler = SCHEDULER.lock();
|
||||||
|
scheduler.create_process_from_file(path, 0, core::ptr::null());
|
||||||
|
}
|
||||||
|
SysCall::ExecVE => {
|
||||||
|
// let path = unsafe { str::from_raw_parts(a1 as *const u8, a2 as usize) };
|
||||||
|
// let mut scheduler = SCHEDULER.lock();
|
||||||
|
// scheduler.create_process_from_file(path, &[]);
|
||||||
|
unimplemented!("ExecVE is not implemented")
|
||||||
|
}
|
||||||
SysCall::Alloc => {
|
SysCall::Alloc => {
|
||||||
let layout = Layout::from_size_align(a1 as usize, a2 as usize).unwrap();
|
let layout = Layout::from_size_align(a1 as usize, a2 as usize).unwrap();
|
||||||
// Allocate memory and put the pointer in a0
|
// Allocate memory and put the pointer in a0
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::KeyboardState;
|
use crate::drivers::keyboard::KeyboardState;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
#[derive_const(PartialEq, Eq)]
|
#[derive_const(PartialEq, Eq)]
|
||||||
|
|||||||
125
src/main.rs
125
src/main.rs
@@ -12,7 +12,8 @@
|
|||||||
arbitrary_self_types_pointers,
|
arbitrary_self_types_pointers,
|
||||||
derive_const,
|
derive_const,
|
||||||
const_cmp,
|
const_cmp,
|
||||||
const_trait_impl
|
const_trait_impl,
|
||||||
|
trait_alias
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use core::sync::atomic::AtomicBool;
|
use core::sync::atomic::AtomicBool;
|
||||||
@@ -22,20 +23,15 @@ use embedded_alloc::LlffHeap as Heap;
|
|||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cursor::{clear_cursor, draw_cursor},
|
drivers::{keyboard::KBD_DRIVER, mouse::MOUSE_DRIVER},
|
||||||
io::init_log,
|
io::init_log,
|
||||||
keymap::{KeyType, ModifierType, map_keycode},
|
pci::scan_virtio_devices,
|
||||||
pci::{PciDeviceIterator, scan_virtio_devices},
|
|
||||||
riscv::enable_supervisor_interrupt,
|
riscv::enable_supervisor_interrupt,
|
||||||
scheduler::{SCHEDULER, idle},
|
scheduler::{SCHEDULER, idle},
|
||||||
tty::TTY0,
|
|
||||||
user::{proc2, test},
|
user::{proc2, test},
|
||||||
vga::Vga,
|
vga::Vga,
|
||||||
virtio::{
|
virtio::input::init_plic_pci,
|
||||||
Virtqueue,
|
virtual_fs::init_file_system,
|
||||||
input::{EventCodeValue, VirtioInputEvent, VirtioPciDriver, init_plic_pci},
|
|
||||||
},
|
|
||||||
virtual_fs::{FILE_SYSTEM, VirtualFileSystem, init_file_system},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
@@ -44,6 +40,7 @@ mod critical_section;
|
|||||||
mod cursor;
|
mod cursor;
|
||||||
mod data_structures;
|
mod data_structures;
|
||||||
mod draw;
|
mod draw;
|
||||||
|
mod drivers;
|
||||||
mod fs;
|
mod fs;
|
||||||
mod interrupt;
|
mod interrupt;
|
||||||
mod io;
|
mod io;
|
||||||
@@ -75,97 +72,6 @@ const _: () = assert!(core::mem::size_of::<usize>() == core::mem::size_of::<u64>
|
|||||||
#[cfg(not(target_endian = "little"))]
|
#[cfg(not(target_endian = "little"))]
|
||||||
compile_error! {"This kernel implementation assume endianness is little-endian. Some memory access like PCI could not work in big-endian."}
|
compile_error! {"This kernel implementation assume endianness is little-endian. Some memory access like PCI could not work in big-endian."}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
|
||||||
pub struct KeyboardState {
|
|
||||||
// ctrl_modifier: bool,
|
|
||||||
pub shift_modifier: bool,
|
|
||||||
pub alt_gr_modifier: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KeyboardState {
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
// ctrl_modifier: false,
|
|
||||||
shift_modifier: false,
|
|
||||||
alt_gr_modifier: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static mut KBD_QUEUE: Virtqueue = unsafe { core::mem::zeroed() };
|
|
||||||
pub static mut KBD_DRIVER: VirtioPciDriver<KeyboardState> = unsafe {
|
|
||||||
VirtioPciDriver::new(
|
|
||||||
|state, event| {
|
|
||||||
let mut kbd_buffer = FILE_SYSTEM.open("/dev/input/keyboard".as_ref()).unwrap();
|
|
||||||
kbd_buffer
|
|
||||||
.write(core::mem::transmute::<
|
|
||||||
&VirtioInputEvent,
|
|
||||||
&[u8; size_of::<VirtioInputEvent>()],
|
|
||||||
>(event))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if event.is_key() {
|
|
||||||
let event = event.as_key_event();
|
|
||||||
#[allow(clippy::single_match)]
|
|
||||||
match map_keycode(event.code, state) {
|
|
||||||
KeyType::Ascii(c) if event.value == EventCodeValue::Pressed => {
|
|
||||||
let mut buf = [0; 4];
|
|
||||||
let to_send = c.encode_utf8(&mut buf);
|
|
||||||
for c in to_send.as_bytes() {
|
|
||||||
TTY0.buffer.borrow_mut().push(*c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
KeyType::Modifier(ModifierType::Shift) => {
|
|
||||||
state.shift_modifier = !state.shift_modifier;
|
|
||||||
}
|
|
||||||
KeyType::Modifier(ModifierType::AltGr) => {
|
|
||||||
state.alt_gr_modifier = !state.alt_gr_modifier;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
println!("event: {:#?}", event);
|
|
||||||
} else {
|
|
||||||
// println!("key pressed, {:#?}", event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
KeyboardState::new(),
|
|
||||||
&mut KBD_QUEUE,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
pub static mut MOUSE_POSITION: (u16, u16) = (0, 0);
|
|
||||||
|
|
||||||
static mut MOUSE_QUEUE: Virtqueue = unsafe { core::mem::zeroed() };
|
|
||||||
pub static mut MOUSE_DRIVER: VirtioPciDriver<()> = unsafe {
|
|
||||||
VirtioPciDriver::new(
|
|
||||||
|_, event| {
|
|
||||||
if event.is_relative() {
|
|
||||||
let event = event.as_relative_event();
|
|
||||||
|
|
||||||
clear_cursor(&mut Vga, MOUSE_POSITION.0, MOUSE_POSITION.1);
|
|
||||||
|
|
||||||
match event.code {
|
|
||||||
virtio::input::EventCodeRelative::X => {
|
|
||||||
MOUSE_POSITION.0 = (MOUSE_POSITION.0 as i32 + event.value) as u16
|
|
||||||
}
|
|
||||||
virtio::input::EventCodeRelative::Y => {
|
|
||||||
MOUSE_POSITION.1 = (MOUSE_POSITION.1 as i32 + event.value) as u16
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_cursor(&mut Vga, MOUSE_POSITION.0, MOUSE_POSITION.1);
|
|
||||||
|
|
||||||
// println!("mouse moved relatively, {:#?}", event);
|
|
||||||
} else {
|
|
||||||
// println!("mouse moved, {:#?}", event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(),
|
|
||||||
&mut MOUSE_QUEUE,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn supervisor_mode_entry() {
|
pub extern "C" fn supervisor_mode_entry() {
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -180,19 +86,20 @@ pub extern "C" fn supervisor_mode_entry() {
|
|||||||
info!("Hello World !");
|
info!("Hello World !");
|
||||||
// unsafe { Vga.draw_string(10, 10, "Hello World !", Color::WHITE, Color::BLACK) };
|
// unsafe { Vga.draw_string(10, 10, "Hello World !", Color::WHITE, Color::BLACK) };
|
||||||
|
|
||||||
SCHEDULER.lock().create_process(Box::new(test), "proc1");
|
// let binding = Box::leak(Box::new(["coucou".as_bytes()]));
|
||||||
SCHEDULER.lock().create_process(Box::new(proc2), "proc2");
|
SCHEDULER
|
||||||
|
.lock()
|
||||||
|
.create_process(Box::new(test), "proc1", 0, core::ptr::null());
|
||||||
|
SCHEDULER
|
||||||
|
.lock()
|
||||||
|
.create_process(Box::new(proc2), "proc2", 0, core::ptr::null());
|
||||||
|
|
||||||
SCHEDULER
|
SCHEDULER
|
||||||
.lock()
|
.lock()
|
||||||
.create_process_from_file("/usr/bin/test_pic");
|
.create_process_from_file("/usr/bin/test_pic", 0, core::ptr::null());
|
||||||
|
|
||||||
enable_supervisor_interrupt();
|
enable_supervisor_interrupt();
|
||||||
|
|
||||||
for pci in PciDeviceIterator::new() {
|
|
||||||
println!("{:x?}", pci.vendor_and_device_id())
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let (pci_keyboard, pci_mouse) = scan_virtio_devices();
|
let (pci_keyboard, pci_mouse) = scan_virtio_devices();
|
||||||
let (pci_keyboard, pci_mouse) = (pci_keyboard.unwrap(), pci_mouse.unwrap());
|
let (pci_keyboard, pci_mouse) = (pci_keyboard.unwrap(), pci_mouse.unwrap());
|
||||||
@@ -214,5 +121,5 @@ pub extern "C" fn supervisor_mode_entry() {
|
|||||||
init_plic_pci(pci_keyboard.irq);
|
init_plic_pci(pci_keyboard.irq);
|
||||||
init_plic_pci(pci_mouse.irq);
|
init_plic_pci(pci_mouse.irq);
|
||||||
}
|
}
|
||||||
idle();
|
idle(0, core::ptr::null());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ use crate::{
|
|||||||
riscv::SStatus,
|
riscv::SStatus,
|
||||||
scheduler::{ACTIVE_PID, SCHEDULER, Scheduler},
|
scheduler::{ACTIVE_PID, SCHEDULER, Scheduler},
|
||||||
time::elapsed_time_since_startup,
|
time::elapsed_time_since_startup,
|
||||||
tty::TTY0,
|
|
||||||
virtual_fs::{FILE_SYSTEM, VirtualFileSystem, VirtualNode},
|
virtual_fs::{FILE_SYSTEM, VirtualFileSystem, VirtualNode},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,6 +65,9 @@ pub struct ExecutionContext {
|
|||||||
pub mstatus: u64,
|
pub mstatus: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ProcessEntryTrait = Fn(isize, *const *const u8);
|
||||||
|
pub type ProcessEntry = dyn ProcessEntryTrait;
|
||||||
|
|
||||||
/// Represents a process in the system.
|
/// Represents a process in the system.
|
||||||
///
|
///
|
||||||
/// Each process has its own execution context, stack,
|
/// Each process has its own execution context, stack,
|
||||||
@@ -78,13 +80,13 @@ pub struct Process {
|
|||||||
/// Current state of the process.
|
/// Current state of the process.
|
||||||
pub state: ProcessState,
|
pub state: ProcessState,
|
||||||
/// Optional entry point for the process code.
|
/// Optional entry point for the process code.
|
||||||
pub entry: Option<Box<dyn Fn()>>,
|
pub entry: Option<Box<ProcessEntry>>,
|
||||||
/// Wake time for sleeping processes.
|
/// Wake time for sleeping processes.
|
||||||
pub wake_time: Duration,
|
pub wake_time: Duration,
|
||||||
/// Saved execution context.
|
/// Saved execution context.
|
||||||
pub ctx: ExecutionContext,
|
pub ctx: ExecutionContext,
|
||||||
/// Process stack.
|
/// Process stack.
|
||||||
pub stack: [u64; STACK_SIZE],
|
pub stack: Box<[u64; STACK_SIZE]>,
|
||||||
/// File descriptor table.
|
/// File descriptor table.
|
||||||
pub fd_table: Vec<Option<Box<dyn VirtualNode>>>,
|
pub fd_table: Vec<Option<Box<dyn VirtualNode>>>,
|
||||||
}
|
}
|
||||||
@@ -109,7 +111,7 @@ impl Default for Process {
|
|||||||
mepc: core::ptr::null(),
|
mepc: core::ptr::null(),
|
||||||
mstatus: 0,
|
mstatus: 0,
|
||||||
},
|
},
|
||||||
stack: [0; _],
|
stack: unsafe { Box::new_zeroed().assume_init() },
|
||||||
entry: None,
|
entry: None,
|
||||||
fd_table: Vec::new(),
|
fd_table: Vec::new(),
|
||||||
}
|
}
|
||||||
@@ -150,7 +152,12 @@ impl Scheduler {
|
|||||||
/// Attempts to open `path`, load its contents into memory and create a new
|
/// Attempts to open `path`, load its contents into memory and create a new
|
||||||
/// kernel process that will execute the loaded binary. Returns the PID of the
|
/// kernel process that will execute the loaded binary. Returns the PID of the
|
||||||
/// created process, or -1 on failure.
|
/// created process, or -1 on failure.
|
||||||
pub fn create_process_from_file<T: AsRef<Path>>(&mut self, path: T) -> i64 {
|
pub fn create_process_from_file<T: AsRef<Path>>(
|
||||||
|
&mut self,
|
||||||
|
path: T,
|
||||||
|
argc: isize,
|
||||||
|
argv: *const *const u8,
|
||||||
|
) -> i64 {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
let name = path.as_str();
|
let name = path.as_str();
|
||||||
|
|
||||||
@@ -231,25 +238,30 @@ impl Scheduler {
|
|||||||
// Entry point
|
// Entry point
|
||||||
let entry_va = gelf.entry;
|
let entry_va = gelf.entry;
|
||||||
let entry_addr = unsafe { base.add((entry_va - min_vaddr) as usize) } as *const u8;
|
let entry_addr = unsafe { base.add((entry_va - min_vaddr) as usize) } as *const u8;
|
||||||
let entry_fn =
|
let entry_fn = unsafe {
|
||||||
unsafe { core::mem::transmute::<*const u8, extern "C" fn()>(entry_addr) };
|
core::mem::transmute::<*const u8, extern "C" fn(isize, *const *const u8)>(
|
||||||
let wrapper = Box::new(move || {
|
entry_addr,
|
||||||
entry_fn();
|
)
|
||||||
});
|
};
|
||||||
|
let wrapper = move |argc, argv| {
|
||||||
|
entry_fn(argc, argv);
|
||||||
|
};
|
||||||
println!("Program loaded at : {:x?}", entry_addr);
|
println!("Program loaded at : {:x?}", entry_addr);
|
||||||
return self.create_process(wrapper, name);
|
return self.create_process(wrapper, name, argc, argv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: treat the file as a raw binary blob and execute in-place
|
// Fallback: treat the file as a raw binary blob and execute in-place
|
||||||
let entry_point = unsafe {
|
let entry_point = unsafe {
|
||||||
core::mem::transmute::<*const u8, extern "C" fn()>(Vec::leak(content).as_ptr())
|
core::mem::transmute::<*const u8, extern "C" fn(isize, *const *const u8)>(
|
||||||
|
Vec::leak(content).as_ptr(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let wrapper = move |argc, argv| {
|
||||||
|
entry_point(argc, argv);
|
||||||
};
|
};
|
||||||
let wrapper = Box::new(move || {
|
|
||||||
entry_point();
|
|
||||||
});
|
|
||||||
|
|
||||||
self.create_process(wrapper, name)
|
self.create_process(wrapper, name, argc, argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new process with the specified code and name.
|
/// Creates a new process with the specified code and name.
|
||||||
@@ -271,39 +283,48 @@ impl Scheduler {
|
|||||||
///
|
///
|
||||||
/// The provided `code` function will be executed when the process is first
|
/// The provided `code` function will be executed when the process is first
|
||||||
/// scheduled. Returns the new PID, or -1 if the process table is full.
|
/// scheduled. Returns the new PID, or -1 if the process table is full.
|
||||||
pub fn create_process<T: Into<String>, F: Fn() + 'static + Send>(
|
pub fn create_process<T: Into<String>, F: ProcessEntryTrait + 'static + Send>(
|
||||||
&mut self,
|
&mut self,
|
||||||
code: Box<F>,
|
code: F,
|
||||||
name: T,
|
name: T,
|
||||||
|
argc: isize,
|
||||||
|
argv: *const *const u8,
|
||||||
) -> i64 {
|
) -> i64 {
|
||||||
// SAFETY: Initializing process in the global table.
|
// SAFETY: Initializing process in the global table.
|
||||||
// Access is safe because we verified bounds and found a Dead slot.
|
// Access is safe because we verified bounds and found a Dead slot.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.process_table
|
self.process_table.insert(self.next_pid, Process::default());
|
||||||
.insert(self.next_pid, Box::new(Process::default()));
|
|
||||||
let process = self.process_table.get_mut(&self.next_pid).unwrap();
|
let process = self.process_table.get_mut(&self.next_pid).unwrap();
|
||||||
|
|
||||||
// Configure process metadata
|
// Configure process metadata
|
||||||
process.pid = self.next_pid as i64;
|
process.pid = self.next_pid as i64;
|
||||||
process.name = name.into();
|
process.name = name.into();
|
||||||
process.state = ProcessState::Activable;
|
process.state = ProcessState::Activable;
|
||||||
process.entry = Some(code);
|
process.entry = Some(Box::new(code));
|
||||||
|
|
||||||
process.fd_table = Vec::new();
|
process.fd_table = Vec::new();
|
||||||
FILE_SYSTEM.mount(
|
// FILE_SYSTEM.mount(
|
||||||
format!("/proc/{}/0", process.pid).into(),
|
// format!("/proc/{}/0", process.pid).into(),
|
||||||
Box::new(TTY0.clone()),
|
// Box::new(TTY0.clone()),
|
||||||
);
|
// );
|
||||||
// FD 0
|
// FD 0
|
||||||
process.fd_table.push(Some(
|
process
|
||||||
FILE_SYSTEM
|
.fd_table
|
||||||
.open(format!("/proc/{}/0", process.pid).as_ref())
|
.push(Some(FILE_SYSTEM.open("/dev/null".as_ref()).unwrap()));
|
||||||
.unwrap(),
|
// FD 1
|
||||||
));
|
process
|
||||||
|
.fd_table
|
||||||
|
.push(Some(FILE_SYSTEM.open("/dev/null".as_ref()).unwrap()));
|
||||||
|
// FD 2
|
||||||
|
process
|
||||||
|
.fd_table
|
||||||
|
.push(Some(FILE_SYSTEM.open("/dev/null".as_ref()).unwrap()));
|
||||||
|
|
||||||
// Configure execution context
|
// Configure execution context
|
||||||
// a0 contains the pointer to the function to execute
|
// a0 contains the pointer to the function to execute
|
||||||
process.ctx.a[0] = &raw const *process.entry.as_ref().unwrap_unchecked() as u64;
|
process.ctx.a[0] = &raw const *process.entry.as_ref().unwrap_unchecked() as u64;
|
||||||
|
process.ctx.a[1] = argc as u64;
|
||||||
|
process.ctx.a[2] = argv as u64;
|
||||||
|
|
||||||
// mepc points to process_launcher which will call the function
|
// mepc points to process_launcher which will call the function
|
||||||
process.ctx.mepc = process_launcher as *const _;
|
process.ctx.mepc = process_launcher as *const _;
|
||||||
@@ -338,10 +359,15 @@ impl Scheduler {
|
|||||||
/// This function is installed into the process `mepc` so that when the new
|
/// This function is installed into the process `mepc` so that when the new
|
||||||
/// process is scheduled it will run this launcher which calls the user
|
/// process is scheduled it will run this launcher which calls the user
|
||||||
/// function and ensures the process exits cleanly.
|
/// function and ensures the process exits cleanly.
|
||||||
extern "C" fn process_launcher(code: *const Box<dyn Fn()>) {
|
#[allow(improper_ctypes_definitions)]
|
||||||
|
extern "C" fn process_launcher(
|
||||||
|
code: *const Box<ProcessEntry>,
|
||||||
|
argc: isize,
|
||||||
|
argv: *const *const u8,
|
||||||
|
) {
|
||||||
// SAFETY: The code pointer was initialized in create_process
|
// SAFETY: The code pointer was initialized in create_process
|
||||||
// and points to a valid function.
|
// and points to a valid function.
|
||||||
unsafe { (*code)() };
|
unsafe { (*code)(argc, argv) };
|
||||||
|
|
||||||
// If user code didn't exit explicitly, call exit() to clean up the process
|
// If user code didn't exit explicitly, call exit() to clean up the process
|
||||||
exit();
|
exit();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use crate::{
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Scheduler {
|
pub struct Scheduler {
|
||||||
pub next_pid: u64,
|
pub next_pid: u64,
|
||||||
pub process_table: BTreeMap<u64, Box<Process>>,
|
pub process_table: BTreeMap<u64, Process>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static ACTIVE_PID: AtomicU64 = AtomicU64::new(0);
|
pub static ACTIVE_PID: AtomicU64 = AtomicU64::new(0);
|
||||||
@@ -30,7 +30,7 @@ pub static SCHEDULER: Mutex<LazyCell<Scheduler>> = Mutex::new(LazyCell::new(|| S
|
|||||||
/// Idle loop executed when there is no runnable process.
|
/// Idle loop executed when there is no runnable process.
|
||||||
///
|
///
|
||||||
/// Uses the `wfi` instruction to yield the CPU while waiting for interrupts.
|
/// Uses the `wfi` instruction to yield the CPU while waiting for interrupts.
|
||||||
pub fn idle() {
|
pub fn idle(_argc: isize, _argv: *const *const u8) {
|
||||||
loop {
|
loop {
|
||||||
// write_string_temp("idle");
|
// write_string_temp("idle");
|
||||||
// info!("idle");
|
// info!("idle");
|
||||||
@@ -47,7 +47,7 @@ impl Scheduler {
|
|||||||
/// it as the active process.
|
/// it as the active process.
|
||||||
pub fn init(&mut self) {
|
pub fn init(&mut self) {
|
||||||
info!("scheduler init");
|
info!("scheduler init");
|
||||||
self.create_process(Box::new(idle), "idle");
|
self.create_process(Box::new(idle), "idle", 0, core::ptr::null());
|
||||||
self.process_table.get_mut(&0).unwrap().state = ProcessState::Active;
|
self.process_table.get_mut(&0).unwrap().state = ProcessState::Active;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,9 +69,7 @@ impl Scheduler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut current_process_iter = self
|
let mut current_process_iter = self.process_table.range_mut(prev_pid + 1..);
|
||||||
.process_table
|
|
||||||
.range_mut((Bound::Excluded(prev_pid), Bound::Unbounded));
|
|
||||||
|
|
||||||
ACTIVE_PID.store(
|
ACTIVE_PID.store(
|
||||||
loop {
|
loop {
|
||||||
|
|||||||
@@ -6,14 +6,15 @@ use core::time::Duration;
|
|||||||
|
|
||||||
use shared::syscall::{sleep, write_string_temp};
|
use shared::syscall::{sleep, write_string_temp};
|
||||||
|
|
||||||
pub fn test() {
|
pub fn test(_argc: isize, _argv: *const *const u8) {
|
||||||
loop {
|
loop {
|
||||||
|
// write_string_temp(str::from_utf8(_args[0]).unwrap());
|
||||||
write_string_temp("test");
|
write_string_temp("test");
|
||||||
sleep(Duration::new(2, 0));
|
sleep(Duration::new(2, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn proc2() {
|
pub fn proc2(_argc: isize, _argv: *const *const u8) {
|
||||||
loop {
|
loop {
|
||||||
write_string_temp("proc2");
|
write_string_temp("proc2");
|
||||||
sleep(Duration::new(3, 0));
|
sleep(Duration::new(3, 0));
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ pub struct VirtioPciDriver<S, F: Fn(&mut S, &VirtioInputEvent) = fn(&mut S, &Vir
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
|
#[allow(unused)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum EventType {
|
pub enum EventType {
|
||||||
Sync = 0,
|
Sync = 0,
|
||||||
@@ -31,6 +32,7 @@ pub enum EventType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
|
#[allow(unused)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum EventCodeRelative {
|
pub enum EventCodeRelative {
|
||||||
X = 0,
|
X = 0,
|
||||||
@@ -39,6 +41,7 @@ pub enum EventCodeRelative {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
|
#[allow(unused)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum EventCodeValue {
|
pub enum EventCodeValue {
|
||||||
Released = 0,
|
Released = 0,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ use io::SeekFrom;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
draw::{Color, Draw, FONT_HEIGHT, FONT_WIDTH},
|
draw::{Color, Draw, FONT_HEIGHT, FONT_WIDTH},
|
||||||
println,
|
|
||||||
vga::{self, Vga},
|
vga::{self, Vga},
|
||||||
virtual_fs::{self, FILE_SYSTEM, VirtualFileSystem},
|
virtual_fs::{self, FILE_SYSTEM, VirtualFileSystem},
|
||||||
};
|
};
|
||||||
@@ -41,7 +40,6 @@ impl VirtualConsole {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_char(&mut self, c: char) {
|
pub fn write_char(&mut self, c: char) {
|
||||||
println!("char_console: {:?}", c as u64);
|
|
||||||
let mut last_cursor = self.cursor;
|
let mut last_cursor = self.cursor;
|
||||||
match c {
|
match c {
|
||||||
'\n' => {
|
'\n' => {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use hashbrown::HashMap;
|
|||||||
use io::{IoBase, Read, Seek, Write};
|
use io::{IoBase, Read, Seek, Write};
|
||||||
|
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
|
pub mod null;
|
||||||
pub mod stdin;
|
pub mod stdin;
|
||||||
pub mod virtual_stdin;
|
pub mod virtual_stdin;
|
||||||
|
|
||||||
@@ -16,10 +17,12 @@ use crate::{
|
|||||||
fs::Disk,
|
fs::Disk,
|
||||||
tty::TTY0,
|
tty::TTY0,
|
||||||
vga::Vga,
|
vga::Vga,
|
||||||
virtual_fs::{keyboard::KeyboardBuffer, virtual_stdin::VirtualStdin},
|
virtual_fs::{keyboard::KeyboardBuffer, null::Null, virtual_stdin::VirtualStdin},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait VirtualNode: IoBase<Error = ()> + Read + Write + Seek + Debug {}
|
pub trait VirtualNode: IoBase<Error = ()> + Read + Write + Seek + Debug {
|
||||||
|
fn close(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait VirtualFileSystem: Debug {
|
pub trait VirtualFileSystem: Debug {
|
||||||
fn open(&mut self, path: &Path) -> Result<Box<dyn VirtualNode + '_>, ()>;
|
fn open(&mut self, path: &Path) -> Result<Box<dyn VirtualNode + '_>, ()>;
|
||||||
@@ -62,6 +65,7 @@ pub unsafe fn init_file_system() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
FILE_SYSTEM.mount("/dev/fb0".into(), Box::new(VGAFileSystem));
|
FILE_SYSTEM.mount("/dev/fb0".into(), Box::new(VGAFileSystem));
|
||||||
FILE_SYSTEM.mount("/dev/tty0".into(), Box::new(TTY0.clone()));
|
FILE_SYSTEM.mount("/dev/tty0".into(), Box::new(TTY0.clone()));
|
||||||
|
FILE_SYSTEM.mount("/dev/null".into(), Box::new(Null));
|
||||||
FILE_SYSTEM.mount(
|
FILE_SYSTEM.mount(
|
||||||
"/dev/input/keyboard".into(),
|
"/dev/input/keyboard".into(),
|
||||||
Box::new(KeyboardBuffer::new()),
|
Box::new(KeyboardBuffer::new()),
|
||||||
|
|||||||
51
src/virtual_fs/null.rs
Normal file
51
src/virtual_fs/null.rs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
use alloc::boxed::Box;
|
||||||
|
use io::{IoBase, Read, Seek, Write};
|
||||||
|
|
||||||
|
use crate::virtual_fs::{VirtualFileSystem, VirtualNode};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Null;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NullNode;
|
||||||
|
|
||||||
|
impl VirtualFileSystem for Null {
|
||||||
|
fn open(
|
||||||
|
&mut self,
|
||||||
|
path: &bffs::path::Path,
|
||||||
|
) -> Result<alloc::boxed::Box<dyn crate::virtual_fs::VirtualNode + '_>, ()> {
|
||||||
|
if !path.is_empty() {
|
||||||
|
Err(())
|
||||||
|
} else {
|
||||||
|
Ok(Box::new(NullNode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IoBase for NullNode {
|
||||||
|
type Error = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Read for NullNode {
|
||||||
|
fn read(&mut self, _buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Seek for NullNode {
|
||||||
|
fn seek(&mut self, _pos: io::SeekFrom) -> Result<u64, Self::Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for NullNode {
|
||||||
|
fn write(&mut self, _buf: &[u8]) -> Result<usize, Self::Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VirtualNode for NullNode {}
|
||||||
1
sysroot/lib/rustlib/src/rust/library/library
Symbolic link
1
sysroot/lib/rustlib/src/rust/library/library
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../../../../../library
|
||||||
35
user.ld
35
user.ld
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* ld directives the for barmetal RISCV
|
|
||||||
*/
|
|
||||||
OUTPUT_ARCH(riscv)
|
|
||||||
ENTRY(_start)
|
|
||||||
|
|
||||||
MEMORY {
|
|
||||||
RAM (wxa) : ORIGIN = 0x0, LENGTH = 128M
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTIONS {
|
|
||||||
. = 0x0;
|
|
||||||
.text : {
|
|
||||||
KEEP(*(.text._start))
|
|
||||||
|
|
||||||
*(.text .text.*)
|
|
||||||
} > RAM
|
|
||||||
|
|
||||||
.rodata : {
|
|
||||||
*(.rodata .rodata.*)
|
|
||||||
} > RAM
|
|
||||||
|
|
||||||
.data : {
|
|
||||||
*(.data .data.*)
|
|
||||||
} > RAM
|
|
||||||
|
|
||||||
.bss : ALIGN(8) {
|
|
||||||
__bss_start = .;
|
|
||||||
*(.bss .bss.*)
|
|
||||||
__bss_end = .;
|
|
||||||
} > RAM
|
|
||||||
|
|
||||||
_heap_start = ALIGN(8);
|
|
||||||
_heap_end = ORIGIN(RAM) + LENGTH(RAM);
|
|
||||||
}
|
|
||||||
9
user/shell/Cargo.toml
Normal file
9
user/shell/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "shell"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# std = { path = "../../crates/std" }
|
||||||
|
# shared = { path = "../../crates/shared", features = ["user"] }
|
||||||
|
# core = { path = "../../crates/std/crates/core" }
|
||||||
9
user/shell/src/main.rs
Normal file
9
user/shell/src/main.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
fn main() {
|
||||||
|
let a = std::env::args();
|
||||||
|
for a in a {
|
||||||
|
println!("Argument: {}", a);
|
||||||
|
}
|
||||||
|
println!(
|
||||||
|
"Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls ! "
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -4,4 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
os-std = { path = "../../crates/os-std" }
|
# std = { path = "../../crates/std" }
|
||||||
|
shared = { path = "../../crates/shared", features = ["user"] }
|
||||||
|
io = { path = "../../crates/io" }
|
||||||
|
bffs = { path = "../../crates/bffs" }
|
||||||
|
|||||||
@@ -1,30 +1,24 @@
|
|||||||
#![no_std]
|
#![allow(unused)]
|
||||||
#![no_main]
|
|
||||||
|
|
||||||
// use core::time::Duration;
|
use io::{Read, Write};
|
||||||
|
use std::io::{Stdin, stdin};
|
||||||
use os_std::syscall;
|
use shared::syscall;
|
||||||
os_std::custom_std_setup! {}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// let mut input = String::new();
|
let mut input = String::new();
|
||||||
|
input.push('a');
|
||||||
// let mut file = syscall::open("/dev/fb0");
|
// let mut file = syscall::open("/dev/fb0");
|
||||||
// syscall::seek(&mut file, SeekFrom::End(-3));
|
// syscall::seek(&mut file, SeekFrom::End(-3));
|
||||||
// syscall::write(&mut file, &[255; 6400 * 50]);
|
// syscall::write(&mut file, &[255; 6400 * 50]);
|
||||||
// syscall::sleep(Duration::from_secs_f64(2.0));
|
// syscall::sleep(Duration::from_secs_f64(2.0));
|
||||||
let mut stdin = syscall::open("/dev/tty0");
|
syscall::close(0);
|
||||||
let mut file = syscall::open("/dev/tty0");
|
let mut tty = syscall::open("/dev/tty0");
|
||||||
|
tty.write(input.as_bytes()).unwrap();
|
||||||
|
syscall::spawn("/usr/bin/shell");
|
||||||
loop {
|
loop {
|
||||||
let mut test = [0; 2];
|
let mut test = [0; 2];
|
||||||
syscall::read(&mut stdin, &mut test);
|
let len = tty.read(&mut test).unwrap();
|
||||||
let len = *test.iter().find(|x| **x == 0).unwrap_or(&1) + 1;
|
tty.write(str::from_utf8(&test[..len as usize]).unwrap().as_bytes())
|
||||||
syscall::write(
|
.unwrap();
|
||||||
&mut file,
|
|
||||||
str::from_utf8(&test[..len as usize]).unwrap().as_bytes(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// println!(
|
|
||||||
// "Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls ! {:?}",
|
|
||||||
// str::from_utf8(&test)
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user