diff --git a/src/arch/i686/instructions.rs b/src/arch/i686/instructions.rs index 43bf791..fb2b084 100644 --- a/src/arch/i686/instructions.rs +++ b/src/arch/i686/instructions.rs @@ -12,3 +12,9 @@ pub unsafe fn sti() { asm!("sti"); } + +#[inline(always)] +pub unsafe fn cli() +{ + asm!("cli"); +} diff --git a/src/arch/i686/interrupts/mod.rs b/src/arch/i686/interrupts/mod.rs index 8112032..97b62f6 100644 --- a/src/arch/i686/interrupts/mod.rs +++ b/src/arch/i686/interrupts/mod.rs @@ -19,6 +19,11 @@ pub unsafe fn enable() { instructions::sti(); } +#[inline(always)] +pub unsafe fn disable() +{ + instructions::cli(); +} #[derive(Copy, Clone, Debug)] #[repr(C, packed)] @@ -74,7 +79,7 @@ impl State } #[no_mangle] -pub unsafe extern "C" fn interrupt_handler(state: &State) +pub unsafe extern "C" fn interrupt_handler(state: &State) -> usize { let interrupt = state.interrupt; match interrupt @@ -82,18 +87,21 @@ pub unsafe extern "C" fn interrupt_handler(state: &State) 0x00..=0x1f => { exceptions::handler(state); + 0 }, 0x20..=0x2f => { irq::handler(state); + 0 } 0x30 | 0x80 => { - software::handler(state); + software::handler(state) } _ => { crate::serial_println!("Got unhandled interrupt {:02x}", interrupt); + 0 } - }; + } } diff --git a/src/arch/i686/interrupts/software.rs b/src/arch/i686/interrupts/software.rs index 72a58a5..de5f182 100644 --- a/src/arch/i686/interrupts/software.rs +++ b/src/arch/i686/interrupts/software.rs @@ -1,33 +1,35 @@ use super::State; +use crate::arch; + use core::slice; #[derive(Copy, Clone)] pub struct Syscall { name: &'static str, - pub handler: unsafe fn(u32, u32, u32) + pub handler: unsafe fn(u32, u32, u32) -> usize } pub static SYSCALLS: [Syscall; 2] = [ - Syscall {name: "read", handler: sys_dummy}, + Syscall {name: "read", handler: sys_read}, Syscall {name: "write", handler: sys_write} ]; -pub unsafe fn handler(state: &State) +pub unsafe fn handler(state: &State) -> usize { - syscall(state.eax, state.ebx, state.ecx, state.edx); + syscall(state.eax, state.ebx, state.ecx, state.edx) } -unsafe fn syscall(syscall_number: u32, arg1: u32, arg2: u32, arg3: u32) +unsafe fn syscall(syscall_number: u32, arg1: u32, arg2: u32, arg3: u32) -> usize { if (syscall_number as usize) < SYSCALLS.len() { let syscall = SYSCALLS[syscall_number as usize]; - crate::serial_println!("Called syscall {}({}, {}, {})", syscall.name, arg1, arg2, arg3); - (syscall.handler)(arg1, arg2, arg3); + //crate::serial_println!("Called syscall {}({}, {}, {})", syscall.name, arg1, arg2, arg3); + return (syscall.handler)(arg1, arg2, arg3); } else { @@ -35,12 +37,30 @@ unsafe fn syscall(syscall_number: u32, arg1: u32, arg2: u32, arg3: u32) } } -unsafe fn sys_dummy(_arg1: u32, _arg2: u32, _arg3: u32) +unsafe fn sys_dummy(_arg1: u32, _arg2: u32, _arg3: u32) -> usize { + 0 +} +unsafe fn sys_read(_file_descriptor: u32, buffer: u32, len: u32) -> usize +{ + let len = len as usize; + let buffer = slice::from_raw_parts_mut(buffer as *mut u8, len); + let buf = &mut crate::keyboard::BUFFER.assume_init_mut(); + while buf.len() < len + { + super::enable(); + arch::halt(); + super::disable(); + } + for i in 0..len + { + buffer[i] = buf.remove(0) as u8; + } + return len; } -unsafe fn sys_write(_file_descriptor: u32, buffer: u32, len: u32) +unsafe fn sys_write(_file_descriptor: u32, buffer: u32, len: u32) -> usize { let len = len as usize; let buffer = slice::from_raw_parts(buffer as *const u8, len); @@ -48,4 +68,5 @@ unsafe fn sys_write(_file_descriptor: u32, buffer: u32, len: u32) { crate::log!("{}", buffer[i] as char); } + 0 } diff --git a/src/arch/i686/isr.asm b/src/arch/i686/isr.asm index 9891348..0cdddb6 100644 --- a/src/arch/i686/isr.asm +++ b/src/arch/i686/isr.asm @@ -277,6 +277,9 @@ isr_no_error 253 isr_no_error 254 isr_no_error 255 +global retval +retval: dd 0 + isr_common: cli ; push eax, ecx, edx, ebx, esi, edi @@ -298,6 +301,7 @@ isr_common: push esp ; pass the saved args to the function via the old stack pointer extern interrupt_handler call interrupt_handler + mov [retval], eax add esp, 4 pop eax diff --git a/src/arch/i686/mod.rs b/src/arch/i686/mod.rs index 1ff2cf9..8e09ed4 100644 --- a/src/arch/i686/mod.rs +++ b/src/arch/i686/mod.rs @@ -4,6 +4,7 @@ pub mod gdt; pub mod instructions; pub mod interrupts; pub mod port; +pub mod syscall; pub fn init() { diff --git a/src/arch/i686/syscall.rs b/src/arch/i686/syscall.rs new file mode 100644 index 0000000..5ac96f4 --- /dev/null +++ b/src/arch/i686/syscall.rs @@ -0,0 +1,14 @@ +use core::arch::asm; + +pub unsafe fn syscall(syscall_number: u32, arg1: u32, arg2: u32, arg3: u32) -> usize +{ + let ret: usize; + asm!("int 0x80; mov eax, retval", + in("eax") syscall_number, + in("ebx") arg1, + in("ecx") arg2, + in("edx") arg3, + lateout("eax") ret); + ret +} + diff --git a/src/arch/mod.rs b/src/arch/mod.rs index 06c4467..6a4c727 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -8,5 +8,6 @@ pub use i686:: { halt, interrupts, - port + port, + syscall }; diff --git a/src/elsos.rs b/src/elsos.rs index a4d1803..662c20d 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -11,6 +11,8 @@ extern crate alloc; use core::panic::PanicInfo; use crate::multiboot::{MULTIBOOT_MMAP, MULTIBOOT_MMAP_ENTRIES}; +use alloc::string::String; + mod arch; mod ferramenta; mod vga; @@ -21,6 +23,7 @@ mod serial; mod memory; mod libc; mod time; +mod syscall; static VERSION: &str = env!("VERSION"); static PATCHLEVEL: &str = env!("PATCHLEVEL"); @@ -61,10 +64,11 @@ pub extern "C" fn kernel_main(magic: u32, address: u32) tty::prompt(); unsafe { + keyboard::BUFFER.as_mut_ptr().write(String::new()); arch::interrupts::init(); arch::interrupts::enable(); } - tests(); + //tests(); loop { arch::halt(); @@ -75,11 +79,17 @@ pub extern "C" fn kernel_main(magic: u32, address: u32) fn tests() { // put tests here + vga_println!("getting one line..."); + vga_println!("got line \"{}\"", ferramenta::get_line()); unsafe { - let text = [b'H', b'e', b'l', b'l', b'o', b'\n']; - let len = 6; - ferramenta::syscall(1, 0, &text as *const _ as u32, len); + let mut text = [b'H', b'e', b'l', b'l', b'o']; + let len = 5; + syscall::write(0, text.as_ptr() as u32, len); + vga_println!(); + syscall::read(0, text.as_mut_ptr() as u32, len); + syscall::write(0, text.as_ptr() as u32, len); + vga_println!(); } } diff --git a/src/ferramenta.rs b/src/ferramenta.rs index d446209..e32edf5 100644 --- a/src/ferramenta.rs +++ b/src/ferramenta.rs @@ -1,7 +1,9 @@ use crate::memory; +use crate::syscall; + +use alloc::string::String; use core::slice; -use core::arch::asm; pub fn shutdown_qemu() { @@ -95,16 +97,24 @@ pub unsafe fn print_memory_bin(ptr: *const u8, n: usize) crate::logln!(); } -pub unsafe fn syscall(syscall_number: u32, arg1: u32, arg2: u32, arg3: u32) -> u32 +pub fn get_line() -> String { - let ret: u32; - asm!("int 0x80", - in("eax") syscall_number, - in("ebx") arg1, - in("ecx") arg2, - in("edx") arg3, - lateout("eax") ret); - ret + let mut line = String::new(); + let mut buf = [b'\0']; + + while buf[0] != b'\n' + { + unsafe + { + while syscall::read(0, buf.as_mut_ptr() as u32, 1) == 0 {} + } + if buf[0] != b'\n' + { + line.push(buf[0] as char); + } + } + + line } #[macro_export] diff --git a/src/keyboard/azerty.rs b/src/keyboard/azerty.rs index 998133f..6fc75f8 100644 --- a/src/keyboard/azerty.rs +++ b/src/keyboard/azerty.rs @@ -58,6 +58,7 @@ pub fn char_from_input(keyboard_input: &KeyboardInput) -> Option 0x34 => Some('/'), 0x35 => Some('+'), 0x39 => Some(' '), + 0x1C => Some('\n'), _ => None, }; } @@ -113,6 +114,7 @@ pub fn char_from_input(keyboard_input: &KeyboardInput) -> Option 0x34 => Some(':'), 0x35 => Some('='), 0x39 => Some(' '), + 0x1C => Some('\n'), _ => None, }; } diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 06baf86..a2cb72e 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -1,6 +1,9 @@ use crate::arch; use crate::tty; +use core::mem::MaybeUninit; +use alloc::string::String; + mod azerty; mod qwerty; @@ -34,18 +37,27 @@ static mut KEYBOARD_STATE: KeyboardState = KeyboardState ctrl: false, }; + +pub static mut BUFFER: MaybeUninit = MaybeUninit::uninit(); + pub fn char_from_input(keyboard_input: &KeyboardInput) -> Option { unsafe { - if crate::SETTINGS.layout == 1 + let c = if crate::SETTINGS.layout == 1 { qwerty::char_from_input(keyboard_input) } else { azerty::char_from_input(keyboard_input) + }; + if let Some(key) = c + { + let buf = BUFFER.assume_init_mut(); + buf.push(key); } + c } } diff --git a/src/keyboard/qwerty.rs b/src/keyboard/qwerty.rs index af1e8db..ce1c0b6 100644 --- a/src/keyboard/qwerty.rs +++ b/src/keyboard/qwerty.rs @@ -58,6 +58,7 @@ pub fn char_from_input(keyboard_input: &KeyboardInput) -> Option 0x34 => Some('>'), 0x35 => Some('?'), 0x39 => Some(' '), + 0x1C => Some('\n'), _ => None, }; } @@ -113,6 +114,7 @@ pub fn char_from_input(keyboard_input: &KeyboardInput) -> Option 0x34 => Some('.'), 0x35 => Some('/'), 0x39 => Some(' '), + 0x1C => Some('\n'), _ => None, }; } diff --git a/src/memory/allocator.rs b/src/memory/allocator.rs index d4a74e5..848e7dd 100644 --- a/src/memory/allocator.rs +++ b/src/memory/allocator.rs @@ -8,9 +8,9 @@ unsafe impl GlobalAlloc for Allocator { unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { - crate::serial_println!("trying to allocate {} ({:#x}) bytes...", _layout.size(), _layout.size()); + //crate::serial_println!("trying to allocate {} ({:#x}) bytes...", _layout.size(), _layout.size()); let address = vmalloc(_layout.size()); - crate::serial_println!("allocated {} bytes at {:p}", _layout.size(), address); + //crate::serial_println!("allocated {} bytes at {:p}", _layout.size(), address); address as *mut u8 } @@ -21,7 +21,7 @@ unsafe impl GlobalAlloc for Allocator unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { - crate::serial_println!("deallocating {:p}", _ptr); + //crate::serial_println!("deallocating {:p}", _ptr); vfree(_ptr as *mut c_void); } } diff --git a/src/syscall.rs b/src/syscall.rs new file mode 100644 index 0000000..439b8b5 --- /dev/null +++ b/src/syscall.rs @@ -0,0 +1,19 @@ +use crate::arch; + +#[inline(always)] +pub unsafe fn syscall(syscall_number: u32, arg1: u32, arg2: u32, arg3: u32) -> usize +{ + arch::syscall::syscall(syscall_number, arg1, arg2, arg3) +} + +#[inline(always)] +pub unsafe fn read(file_descriptor: u32, buffer: u32, len: u32) -> usize +{ + syscall(0, file_descriptor, buffer, len) +} + +#[inline(always)] +pub unsafe fn write(file_descriptor: u32, buffer: u32, len: u32) -> usize +{ + syscall(1, file_descriptor, buffer, len) +} diff --git a/src/tty/mod.rs b/src/tty/mod.rs index 36a4c25..35b1c91 100644 --- a/src/tty/mod.rs +++ b/src/tty/mod.rs @@ -154,6 +154,11 @@ pub fn input(keyboard_input: &keyboard::KeyboardInput) { if let Some(key) = keyboard::char_from_input(keyboard_input) { + if key == '\n' + { + line_return(true); + return; + } if keyboard_input.state.ctrl { match key @@ -195,7 +200,6 @@ pub fn input(keyboard_input: &keyboard::KeyboardInput) match keyboard_input.scancode { 0x0e => backspace(), - 0x1C => line_return(true), 0x4B => cursor_left(), 0x4D => cursor_right(), 0x48 => cursor_up(),