mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-22 01:16:26 +04:00
Load app from sdcard on K210, but panicked on qemu.
This commit is contained in:
parent
ea515323d3
commit
ae9eecf97b
@ -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"
|
||||
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
|
||||
#rand = "0.8.0"
|
@ -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(())
|
||||
}
|
||||
}
|
||||
*/
|
16
os/Makefile
16
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
|
||||
|
52
os/build.rs
52
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(())
|
||||
}
|
@ -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")]
|
||||
|
@ -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;
|
||||
|
@ -717,7 +717,7 @@ lazy_static! {
|
||||
fn init_sdcard() -> SDCard<SPIImpl<SPI0>> {
|
||||
// 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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
104
os/src/fs/inode.rs
Normal file
104
os/src/fs/inode.rs
Normal file
@ -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<OSInodeInner>,
|
||||
}
|
||||
|
||||
pub struct OSInodeInner {
|
||||
offset: usize,
|
||||
inode: Arc<Inode>,
|
||||
}
|
||||
|
||||
impl OSInode {
|
||||
pub fn new(
|
||||
readable: bool,
|
||||
writable: bool,
|
||||
inode: Arc<Inode>,
|
||||
) -> Self {
|
||||
Self {
|
||||
readable,
|
||||
writable,
|
||||
inner: Mutex::new(OSInodeInner {
|
||||
offset: 0,
|
||||
inode,
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn read_all(&self) -> Vec<u8> {
|
||||
let mut inner = self.inner.lock();
|
||||
let mut buffer = [0u8; 512];
|
||||
let mut v: Vec<u8> = 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<Inode> = {
|
||||
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<Arc<OSInode>> {
|
||||
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
|
||||
))
|
||||
})
|
||||
}
|
@ -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};
|
||||
pub use stdio::{Stdin, Stdout};
|
||||
pub use inode::{OSInode, open_file, OpenFlags, list_apps};
|
@ -114,8 +114,10 @@ pub fn make_pipe() -> (Arc<Pipe>, Arc<Pipe>) {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -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!");
|
||||
}
|
||||
|
@ -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!("**************/")
|
||||
}
|
@ -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!");
|
||||
}
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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<TaskControlBlock> = Arc::new(
|
||||
TaskControlBlock::new(get_app_data_by_name("initproc").unwrap())
|
||||
);
|
||||
pub static ref INITPROC: Arc<TaskControlBlock> = Arc::new({
|
||||
let inode = open_file("initproc", OpenFlags::RDONLY).unwrap();
|
||||
let v = inode.read_all();
|
||||
TaskControlBlock::new(v.as_slice())
|
||||
});
|
||||
}
|
||||
|
||||
pub fn add_initproc() {
|
||||
|
@ -61,6 +61,7 @@ lazy_static! {
|
||||
}
|
||||
|
||||
pub fn run_tasks() {
|
||||
println!("into Processor::run_tasks!");
|
||||
PROCESSOR.run();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user