diff --git a/kernel/src/arch/riscv32/io.rs b/kernel/src/arch/riscv32/io.rs index f6d35bf..aa9129d 100644 --- a/kernel/src/arch/riscv32/io.rs +++ b/kernel/src/arch/riscv32/io.rs @@ -6,14 +6,24 @@ struct SerialPort; impl Write for SerialPort { fn write_str(&mut self, s: &str) -> Result { for c in s.bytes() { - sbi::console_putchar(c as usize); + if c == 8 { + sbi::console_putchar(8); + sbi::console_putchar(' ' as usize); + sbi::console_putchar(8); + } else { + sbi::console_putchar(c as usize); + } } Ok(()) } } pub fn getchar() -> char { - sbi::console_getchar() as u8 as char + match sbi::console_getchar() as u8 { + 255 => 0, // null + 127 => 8, // back + c => c, + } as char } pub fn putfmt(fmt: Arguments) { diff --git a/kernel/src/arch/x86_64/interrupt/handler.rs b/kernel/src/arch/x86_64/interrupt/handler.rs index 7ae856b..ee02605 100644 --- a/kernel/src/arch/x86_64/interrupt/handler.rs +++ b/kernel/src/arch/x86_64/interrupt/handler.rs @@ -131,13 +131,12 @@ fn keyboard() { fn com1() { use arch::driver::serial::*; - info!("\nInterupt: COM1"); - COM1.lock().receive(); + trace!("\nInterupt: COM1"); } fn com2() { use arch::driver::serial::*; - info!("\nInterupt: COM2"); + trace!("\nInterupt: COM2"); COM2.lock().receive(); } diff --git a/kernel/src/console.rs b/kernel/src/console.rs new file mode 100644 index 0000000..284e3b0 --- /dev/null +++ b/kernel/src/console.rs @@ -0,0 +1,64 @@ +use core::ops::Deref; + +pub struct LineBuf { + buf: [u8; BUF_SIZE], + len: usize, +} + +pub struct LineBufGuard<'a>(&'a str); + +const BUF_SIZE: usize = 256; + +impl LineBuf { + pub const fn new() -> Self { + LineBuf { + buf: [0; BUF_SIZE], + len: 0, + } + } + + /// Put a char received from serial. Return str if get a line. + pub fn push_u8<'a>(&'a mut self, c: u8) -> Option> { + use alloc::str; + match c { + b' '...128 if self.len != BUF_SIZE => { + self.buf[self.len] = c; + self.len += 1; + } + 8 /* '\b' */ if self.len != 0 => { + self.len -= 1; + } + b'\n' | b'\r' => { + let s = str::from_utf8(&self.buf[..self.len]).unwrap(); + self.len = 0; + return Some(LineBufGuard(s)); + } + _ => {} + } + None + } +} + +impl<'a> Deref for LineBufGuard<'a> { + type Target = str; + fn deref(&self) -> &str { + self.0 + } +} + +use alloc::string::String; +use arch::io::getchar; + +pub fn get_line() -> String { + let mut buf = LineBuf::new(); + loop { + let mut c = 0; + while c == 0 { + c = getchar() as u8; + } + print!("{}", c as char); + if let Some(line) = buf.push_u8(c) { + return String::from(&*line); + } + } +} \ No newline at end of file diff --git a/kernel/src/fs.rs b/kernel/src/fs.rs index 361d308..dd652f2 100644 --- a/kernel/src/fs.rs +++ b/kernel/src/fs.rs @@ -5,7 +5,7 @@ use arch::driver::ide; use spin::Mutex; use process; -pub fn load_sfs() { +pub fn shell() { #[cfg(target_arch = "riscv")] let device = { extern { @@ -19,17 +19,23 @@ pub fn load_sfs() { let sfs = SimpleFileSystem::open(device).unwrap(); let root = sfs.root_inode(); let files = root.borrow().list().unwrap(); - trace!("Loading programs: {:?}", files); + println!("Available programs: {:?}", files); -// for name in files.iter().filter(|&f| f != "." && f != "..") { - for name in files.iter().filter(|&f| f == "hello") { - static mut BUF: [u8; 64 << 12] = [0; 64 << 12]; - let file = root.borrow().lookup(name.as_str()).unwrap(); - let len = file.borrow().read_at(0, unsafe { &mut BUF }).unwrap(); - process::add_user_process(name, unsafe { &BUF[..len] }); + let mut buf = Box::new([0; 64 << 12]); + loop { + use console::get_line; + let name = get_line(); + if name == "" { + continue; + } + if let Ok(file) = root.borrow().lookup(name.as_str()) { + println!("Running: {}", name); + let len = file.borrow().read_at(0, &mut *buf).unwrap(); + process::add_user_process(name, &buf[..len]); + } else { + println!("Program not exist"); + } } - - process::print(); } struct MemBuf(&'static [u8]); diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index d48eb1a..3a132a3 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -66,6 +66,7 @@ mod fs; mod thread; mod sync; mod trap; +mod console; #[allow(dead_code)] #[cfg(target_arch = "x86_64")] @@ -85,9 +86,10 @@ pub extern "C" fn rust_main() -> ! { logging::init(); arch::init(); process::init(); - fs::load_sfs(); unsafe { arch::interrupt::enable(); } + fs::shell(); + // thread::test::local_key(); // thread::test::unpack(); // sync::test::philosopher_using_mutex();