From ae9eecf97b496ce04d418e8ed10c040c7090ca58 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Sun, 20 Dec 2020 00:52:14 +0800 Subject: [PATCH] Load app from sdcard on K210, but panicked on qemu. --- easy-fs/Cargo.toml | 5 +- easy-fs/src/bin/main.rs | 4 +- os/Makefile | 16 ++++- os/build.rs | 52 +-------------- os/src/config.rs | 2 +- os/src/drivers/block/mod.rs | 6 +- os/src/drivers/block/sdcard.rs | 2 +- os/src/drivers/block/virtio_blk.rs | 4 ++ os/src/fs/inode.rs | 104 +++++++++++++++++++++++++++++ os/src/fs/mod.rs | 6 +- os/src/fs/pipe.rs | 6 +- os/src/fs/stdio.rs | 4 ++ os/src/loader.rs | 62 ----------------- os/src/main.rs | 16 +++-- os/src/syscall/fs.rs | 6 ++ os/src/syscall/process.rs | 11 ++- os/src/task/mod.rs | 12 ++-- os/src/task/processor.rs | 1 + 18 files changed, 177 insertions(+), 142 deletions(-) create mode 100644 os/src/fs/inode.rs delete mode 100644 os/src/loader.rs diff --git a/easy-fs/Cargo.toml b/easy-fs/Cargo.toml index 8fd21501..f32c49f7 100644 --- a/easy-fs/Cargo.toml +++ b/easy-fs/Cargo.toml @@ -8,6 +8,5 @@ edition = "2018" [dependencies] spin = "0.7.0" -#lazy_static = { version = "1.4.0", features = ["spin_no_std"] } -lazy_static = "1.4.0" -rand = "0.8.0" \ No newline at end of file +lazy_static = { version = "1.4.0", features = ["spin_no_std"] } +#rand = "0.8.0" \ No newline at end of file diff --git a/easy-fs/src/bin/main.rs b/easy-fs/src/bin/main.rs index 51c08248..af972ddf 100644 --- a/easy-fs/src/bin/main.rs +++ b/easy-fs/src/bin/main.rs @@ -79,6 +79,7 @@ fn easy_fs_pack() -> std::io::Result<()> { Ok(()) } +/* #[test] fn efs_test() -> std::io::Result<()> { let block_file = Arc::new(BlockFile(Mutex::new( @@ -145,4 +146,5 @@ fn efs_test() -> std::io::Result<()> { random_str_test((12 + 128) * BLOCK_SZ); Ok(()) -} \ No newline at end of file +} + */ \ No newline at end of file diff --git a/os/Makefile b/os/Makefile index 0d48329c..ee507f84 100644 --- a/os/Makefile +++ b/os/Makefile @@ -5,6 +5,8 @@ KERNEL_ELF := target/$(TARGET)/$(MODE)/os KERNEL_BIN := $(KERNEL_ELF).bin KERNEL_ENTRY_PA := 0x80020000 DISASM_TMP := target/$(TARGET)/$(MODE)/asm +FS_IMG := ../user/target/$(TARGET)/$(MODE)/fs.img +SDCARD := /dev/sdb # BOARD BOARD ?= qemu @@ -22,11 +24,19 @@ OBJCOPY := rust-objcopy --binary-architecture=riscv64 # Disassembly DISASM ?= -x -build: $(KERNEL_BIN) +build: $(KERNEL_BIN) $(FS_IMG) + +sdcard: $(FS_IMG) + @sudo dd if=/dev/zero of=$(SDCARD) bs=1M count=16 + @sudo dd if=$(FS_IMG) of=$(SDCARD) $(KERNEL_BIN): kernel @$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@ +$(FS_IMG): + @echo "hello, world!" + @cd ../easy-fs && cargo run --release + kernel: @cd ../user && make build @cargo build --release --features "board_$(BOARD)" @@ -51,8 +61,8 @@ ifeq ($(BOARD),qemu) -nographic \ -bios $(BOOTLOADER) \ -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) \ - -drive file=fs.img,if=none,format=raw,id=x0 \ - -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 + -drive file=$(FS_IMG),if=none,format=raw,id=x0 \ + -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 else @cp $(BOOTLOADER) $(BOOTLOADER).copy @dd if=$(KERNEL_BIN) of=$(BOOTLOADER).copy bs=128K seek=1 diff --git a/os/build.rs b/os/build.rs index 2c006876..5529b4fe 100644 --- a/os/build.rs +++ b/os/build.rs @@ -1,56 +1,6 @@ -use std::io::{Result, Write}; -use std::fs::{File, read_dir}; +static TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/"; fn main() { println!("cargo:rerun-if-changed=../user/src/"); println!("cargo:rerun-if-changed={}", TARGET_PATH); - insert_app_data().unwrap(); } - -static TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/"; - -fn insert_app_data() -> Result<()> { - let mut f = File::create("src/link_app.S").unwrap(); - let mut apps: Vec<_> = read_dir("../user/src/bin") - .unwrap() - .into_iter() - .map(|dir_entry| { - let mut name_with_ext = dir_entry.unwrap().file_name().into_string().unwrap(); - name_with_ext.drain(name_with_ext.find('.').unwrap()..name_with_ext.len()); - name_with_ext - }) - .collect(); - apps.sort(); - - writeln!(f, r#" - .align 4 - .section .data - .global _num_app -_num_app: - .quad {}"#, apps.len())?; - - for i in 0..apps.len() { - writeln!(f, r#" .quad app_{}_start"#, i)?; - } - writeln!(f, r#" .quad app_{}_end"#, apps.len() - 1)?; - - writeln!(f, r#" - .global _app_names -_app_names:"#)?; - for app in apps.iter() { - writeln!(f, r#" .string "{}\n""#, app)?; - } - - for (idx, app) in apps.iter().enumerate() { - println!("app_{}: {}", idx, app); - writeln!(f, r#" - .section .data - .global app_{0}_start - .global app_{0}_end - .align 12 -app_{0}_start: - .incbin "{2}{1}" -app_{0}_end:"#, idx, app, TARGET_PATH)?; - } - Ok(()) -} \ No newline at end of file diff --git a/os/src/config.rs b/os/src/config.rs index 78c45d82..9a015bdc 100644 --- a/os/src/config.rs +++ b/os/src/config.rs @@ -16,7 +16,7 @@ pub const CLOCK_FREQ: usize = 12500000; #[cfg(feature = "board_qemu")] pub const MMIO: &[(usize, usize)] = &[ - (0x10001000, 0x10000), + (0x10000000, 0x10000), ]; #[cfg(feature = "board_k210")] diff --git a/os/src/drivers/block/mod.rs b/os/src/drivers/block/mod.rs index 3e7741d7..abf20b61 100644 --- a/os/src/drivers/block/mod.rs +++ b/os/src/drivers/block/mod.rs @@ -4,11 +4,7 @@ mod sdcard; use lazy_static::*; use alloc::sync::Arc; use core::any::Any; - -pub trait BlockDevice : Send + Sync + Any { - fn read_block(&self, block_id: usize, buf: &mut [u8]); - fn write_block(&self, block_id: usize, buf: &[u8]); -} +use easy_fs::BlockDevice; #[cfg(feature = "board_qemu")] type BlockDeviceImpl = virtio_blk::VirtIOBlock; diff --git a/os/src/drivers/block/sdcard.rs b/os/src/drivers/block/sdcard.rs index 9b743033..efc377b1 100644 --- a/os/src/drivers/block/sdcard.rs +++ b/os/src/drivers/block/sdcard.rs @@ -717,7 +717,7 @@ lazy_static! { fn init_sdcard() -> SDCard> { // wait previous output usleep(100000); - let peripherals = Peripherals::take().unwrap(); + let peripherals = unsafe { Peripherals::steal() }; sysctl::pll_set_freq(sysctl::pll::PLL0, 800_000_000).unwrap(); sysctl::pll_set_freq(sysctl::pll::PLL1, 300_000_000).unwrap(); sysctl::pll_set_freq(sysctl::pll::PLL2, 45_158_400).unwrap(); diff --git a/os/src/drivers/block/virtio_blk.rs b/os/src/drivers/block/virtio_blk.rs index 1c7a1fe8..7d09e22f 100644 --- a/os/src/drivers/block/virtio_blk.rs +++ b/os/src/drivers/block/virtio_blk.rs @@ -23,9 +23,12 @@ lazy_static! { impl BlockDevice for VirtIOBlock { fn read_block(&self, block_id: usize, buf: &mut [u8]) { + //println!("read block {}", block_id); self.0.lock().read_block(block_id, buf).expect("Error when reading VirtIOBlk"); + //println!("read block OK!"); } fn write_block(&self, block_id: usize, buf: &[u8]) { + //println!("write block {}", block_id); self.0.lock().write_block(block_id, buf).expect("Error when writing VirtIOBlk"); } } @@ -44,6 +47,7 @@ pub extern "C" fn virtio_dma_alloc(pages: usize) -> PhysAddr { for i in 0..pages { let frame = frame_alloc().unwrap(); if i == 0 { ppn_base = frame.ppn; } + println!("virtio_dma_alloc {:?}", frame.ppn); assert_eq!(frame.ppn.0, ppn_base.0 + i); QUEUE_FRAMES.lock().push(frame); } diff --git a/os/src/fs/inode.rs b/os/src/fs/inode.rs new file mode 100644 index 00000000..5b61ea49 --- /dev/null +++ b/os/src/fs/inode.rs @@ -0,0 +1,104 @@ +use easy_fs::{ + EasyFileSystem, + Inode, +}; +use crate::drivers::BLOCK_DEVICE; +use alloc::sync::Arc; +use lazy_static::*; +use bitflags::*; +use alloc::vec::Vec; +use spin::Mutex; + +pub struct OSInode { + readable: bool, + writable: bool, + inner: Mutex, +} + +pub struct OSInodeInner { + offset: usize, + inode: Arc, +} + +impl OSInode { + pub fn new( + readable: bool, + writable: bool, + inode: Arc, + ) -> Self { + Self { + readable, + writable, + inner: Mutex::new(OSInodeInner { + offset: 0, + inode, + }), + } + } + pub fn read_all(&self) -> Vec { + let mut inner = self.inner.lock(); + let mut buffer = [0u8; 512]; + let mut v: Vec = Vec::new(); + loop { + let len = inner.inode.read_at(inner.offset, &mut buffer); + if len == 0 { + break; + } + inner.offset += len; + v.extend_from_slice(&buffer[..len]); + } + v + } +} + +lazy_static! { + pub static ref ROOT_INODE: Arc = { + let efs = EasyFileSystem::open(BLOCK_DEVICE.clone()); + Arc::new(EasyFileSystem::root_inode(&efs)) + }; +} + +pub fn list_apps() { + println!("/**** APPS ****"); + for app in ROOT_INODE.ls() { + println!("{}", app); + } + println!("**************/") +} + +bitflags! { + pub struct OpenFlags: u32 { + const RDONLY = 0; + const WRONLY = 1 << 0; + const RDWR = 1 << 1; + const CREATE = 1 << 9; + const TRUNC = 1 << 10; + } +} + +impl OpenFlags { + /// Do not check validity for simplicity + /// Return (readable, writable) + pub fn read_write(&self) -> (bool, bool) { + if self.is_empty() { + (true, false) + } else if self.contains(Self::WRONLY) { + (false, true) + } else { + (true, true) + } + } +} + +pub fn open_file(name: &str, flags: OpenFlags) -> Option> { + let (readable, writable) = flags.read_write(); + // TODO: do not support CREATE or TRUNC flags now + ROOT_INODE.find(name) + .map(|inode| { + Arc::new(OSInode::new( + readable, + writable, + inode + )) + }) +} diff --git a/os/src/fs/mod.rs b/os/src/fs/mod.rs index 853ef41a..5f1f7aa6 100644 --- a/os/src/fs/mod.rs +++ b/os/src/fs/mod.rs @@ -1,10 +1,13 @@ mod pipe; mod stdio; +mod inode; use crate::mm::UserBuffer; use core::any::Any; pub trait File : Any + Send + Sync { + fn readable(&self) -> bool; + fn writable(&self) -> bool; fn read(&self, buf: UserBuffer) -> usize; fn write(&self, buf: UserBuffer) -> usize; fn as_any_ref(&self) -> &dyn Any; @@ -18,4 +21,5 @@ impl dyn File { } pub use pipe::{Pipe, make_pipe}; -pub use stdio::{Stdin, Stdout}; \ No newline at end of file +pub use stdio::{Stdin, Stdout}; +pub use inode::{OSInode, open_file, OpenFlags, list_apps}; \ No newline at end of file diff --git a/os/src/fs/pipe.rs b/os/src/fs/pipe.rs index ccbc53e0..ce3dd2ad 100644 --- a/os/src/fs/pipe.rs +++ b/os/src/fs/pipe.rs @@ -114,8 +114,10 @@ pub fn make_pipe() -> (Arc, Arc) { } impl File for Pipe { + fn readable(&self) -> bool { self.readable } + fn writable(&self) -> bool { self.writable } fn read(&self, buf: UserBuffer) -> usize { - assert_eq!(self.readable, true); + assert_eq!(self.readable(), true); let mut buf_iter = buf.into_iter(); let mut read_size = 0usize; loop { @@ -141,7 +143,7 @@ impl File for Pipe { } } fn write(&self, buf: UserBuffer) -> usize { - assert_eq!(self.writable, true); + assert_eq!(self.writable(), true); let mut buf_iter = buf.into_iter(); let mut write_size = 0usize; loop { diff --git a/os/src/fs/stdio.rs b/os/src/fs/stdio.rs index 841849ef..3af40cc0 100644 --- a/os/src/fs/stdio.rs +++ b/os/src/fs/stdio.rs @@ -9,6 +9,8 @@ pub struct Stdin; pub struct Stdout; impl File for Stdin { + fn readable(&self) -> bool { true } + fn writable(&self) -> bool { false } fn read(&self, mut user_buf: UserBuffer) -> usize { assert_eq!(user_buf.len(), 1); // busy loop @@ -33,6 +35,8 @@ impl File for Stdin { } impl File for Stdout { + fn readable(&self) -> bool { false } + fn writable(&self) -> bool { true } fn read(&self, _user_buf: UserBuffer) -> usize{ panic!("Cannot read from stdout!"); } diff --git a/os/src/loader.rs b/os/src/loader.rs deleted file mode 100644 index d49cf694..00000000 --- a/os/src/loader.rs +++ /dev/null @@ -1,62 +0,0 @@ -use alloc::vec::Vec; - -pub fn get_num_app() -> usize { - extern "C" { fn _num_app(); } - unsafe { (_num_app as usize as *const usize).read_volatile() } -} - -pub fn get_app_data(app_id: usize) -> &'static [u8] { - extern "C" { fn _num_app(); } - let num_app_ptr = _num_app as usize as *const usize; - let num_app = get_num_app(); - let app_start = unsafe { - core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1) - }; - assert!(app_id < num_app); - unsafe { - core::slice::from_raw_parts( - app_start[app_id] as *const u8, - app_start[app_id + 1] - app_start[app_id] - ) - } -} - -#[allow(unused)] -pub fn get_app_data_by_name(name: &str) -> Option<&'static [u8]> { - let num_app = get_num_app(); - let app_names = app_names(); - (0..num_app) - .find(|&i| app_names[i] == name) - .map(|i| get_app_data(i)) -} - -#[allow(unused)] -fn app_names() -> Vec<&'static str> { - let num_app = get_num_app(); - extern "C" { fn _app_names(); } - let mut start = _app_names as usize as *const u8; - let mut v = Vec::new(); - unsafe { - for _ in 0..num_app { - let mut end = start; - while end.read_volatile() != '\n' as u8 { - end = end.add(1); - } - let slice = core::slice::from_raw_parts(start, end as usize - start as usize); - let str = core::str::from_utf8(slice).unwrap(); - v.push(str); - // Mention that there is a extra char between names - start = end.add(2); - } - } - v -} - -pub fn list_apps() { - let apps = app_names(); - println!("/**** APPS ****"); - for app in apps { - println!("{}", app); - } - println!("**************/") -} \ No newline at end of file diff --git a/os/src/main.rs b/os/src/main.rs index ebe4a44e..464657b0 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -17,7 +17,6 @@ mod lang_items; mod sbi; mod syscall; mod trap; -mod loader; mod config; mod task; mod timer; @@ -26,7 +25,6 @@ mod fs; mod drivers; global_asm!(include_str!("entry.asm")); -global_asm!(include_str!("link_app.S")); fn clear_bss() { extern "C" { @@ -44,11 +42,21 @@ pub fn rust_main() -> ! { println!("[kernel] Hello, world!"); mm::init(); mm::remap_test(); - task::add_initproc(); trap::init(); trap::enable_timer_interrupt(); timer::set_next_trigger(); - loader::list_apps(); + fs::list_apps(); + //println!("after listing apps"); + task::add_initproc(); + /* + println!("after adding initproc!"); + println!("list apps again!"); + fs::list_apps(); + println!("test user_shell now!"); + let user_shell = fs::open_file("user_shell", fs::OpenFlags::RDONLY).unwrap(); + println!("user_shell size = {}", user_shell.read_all().len()); + println!("before running tasks!"); + */ task::run_tasks(); panic!("Unreachable in rust_main!"); } \ No newline at end of file diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index e4800fa9..cdaa3449 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -10,6 +10,9 @@ pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize { return -1; } if let Some(file) = &inner.fd_table[fd] { + if !file.writable() { + return -1; + } let file = file.clone(); // release Task lock manually to avoid deadlock drop(inner); @@ -30,6 +33,9 @@ pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize { } if let Some(file) = &inner.fd_table[fd] { let file = file.clone(); + if !file.readable() { + return -1; + } // release Task lock manually to avoid deadlock drop(inner); file.read( diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index 7ace0ffe..ca4482b2 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -10,7 +10,11 @@ use crate::mm::{ translated_str, translated_refmut, }; -use crate::loader::get_app_data_by_name; +use crate::fs::{ + OSInode, + open_file, + OpenFlags, +}; use alloc::sync::Arc; pub fn sys_exit(exit_code: i32) -> ! { @@ -48,9 +52,10 @@ pub fn sys_fork() -> isize { pub fn sys_exec(path: *const u8) -> isize { let token = current_user_token(); let path = translated_str(token, path); - if let Some(data) = get_app_data_by_name(path.as_str()) { + if let Some(app_inode) = open_file(path.as_str(), OpenFlags::RDONLY) { + let all_data = app_inode.read_all(); let task = current_task().unwrap(); - task.exec(data); + task.exec(all_data.as_slice()); 0 } else { -1 diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 1a74b4f1..0b856fd8 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -5,14 +5,14 @@ mod manager; mod processor; mod pid; -use crate::loader::{get_app_data_by_name}; +use crate::fs::{open_file, OpenFlags}; use switch::__switch; use task::{TaskControlBlock, TaskStatus}; use alloc::sync::Arc; use manager::fetch_task; use lazy_static::*; - pub use context::TaskContext; + pub use processor::{ run_tasks, current_task, @@ -76,9 +76,11 @@ pub fn exit_current_and_run_next(exit_code: i32) { } lazy_static! { - pub static ref INITPROC: Arc = Arc::new( - TaskControlBlock::new(get_app_data_by_name("initproc").unwrap()) - ); + pub static ref INITPROC: Arc = Arc::new({ + let inode = open_file("initproc", OpenFlags::RDONLY).unwrap(); + let v = inode.read_all(); + TaskControlBlock::new(v.as_slice()) + }); } pub fn add_initproc() { diff --git a/os/src/task/processor.rs b/os/src/task/processor.rs index 677d8792..c53ea507 100644 --- a/os/src/task/processor.rs +++ b/os/src/task/processor.rs @@ -61,6 +61,7 @@ lazy_static! { } pub fn run_tasks() { + println!("into Processor::run_tasks!"); PROCESSOR.run(); }