From 5f4154bd24a98a52a2c32b88cb41a9e4699195a3 Mon Sep 17 00:00:00 2001 From: csd4ni3l <96988024+csd4ni3l@users.noreply.github.com> Date: Thu, 28 May 2026 18:51:03 +0200 Subject: [PATCH] Remove unused imports, merge ps2 and virtio to both use linux input events and move parsing code to libxunil, and add mouse support again by using them, remove unneeded graphics and console output code, merge build files to a rust app builder, make framebuffer a driver and remove the graphics folder, add shell as an app in VFS --- .gitmodules | 3 + assets/.gitignore | 1 + build_and_run.sh | 9 +- build_badapple.sh | 5 - build_doomgeneric.sh | 1 - build_helloworld.sh | 1 - build_init.sh | 5 - build_libxunil.sh | 2 - build_rust_app.sh | 13 ++ config.mk | 2 +- kernel/Cargo.lock | 7 - kernel/Cargo.toml | 1 - kernel/build.rs | 3 +- kernel/src/arch/syscall.rs | 32 ++- kernel/src/arch/x86_64/gdt.rs | 1 - kernel/src/arch/x86_64/init.rs | 23 +-- kernel/src/arch/x86_64/interrupts.rs | 12 +- kernel/src/arch/x86_64/paging.rs | 5 +- kernel/src/config.rs | 2 +- kernel/src/driver/elf/loader.rs | 7 +- .../src/driver/{graphics => }/framebuffer.rs | 37 +--- kernel/src/driver/graphics/font_render.rs | 69 ------- kernel/src/driver/graphics/mod.rs | 6 - kernel/src/driver/io/fs/assets.rs | 9 +- kernel/src/driver/io/fs/vfs.rs | 4 + kernel/src/driver/io/input.rs | 155 ++++++++++++++ kernel/src/driver/io/keyboard.rs | 192 ------------------ kernel/src/driver/io/mod.rs | 3 +- kernel/src/driver/io/mouse.rs | 45 ---- kernel/src/driver/io/ps2.rs | 141 ++++++------- kernel/src/driver/io/virtio/input.rs | 170 +--------------- kernel/src/driver/mod.rs | 3 +- kernel/src/driver/serial.rs | 115 ----------- kernel/src/main.rs | 68 +++---- kernel/src/task/process.rs | 8 +- user/apps/doomgeneric | 2 +- user/init | 2 +- user/libxunil | 2 +- 38 files changed, 336 insertions(+), 830 deletions(-) delete mode 100644 build_badapple.sh delete mode 100644 build_init.sh delete mode 100644 build_libxunil.sh create mode 100644 build_rust_app.sh rename kernel/src/driver/{graphics => }/framebuffer.rs (85%) delete mode 100644 kernel/src/driver/graphics/font_render.rs delete mode 100644 kernel/src/driver/graphics/mod.rs create mode 100644 kernel/src/driver/io/input.rs delete mode 100644 kernel/src/driver/io/keyboard.rs delete mode 100644 kernel/src/driver/io/mouse.rs delete mode 100644 kernel/src/driver/serial.rs diff --git a/.gitmodules b/.gitmodules index b12d272..f408cd3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "user/apps/badapple"] path = user/apps/badapple url = https://github.com/XunilGroup/xunil_badapple.git +[submodule "user/apps/shell"] + path = user/apps/shell + url = https://github.com/XunilGroup/xunil_shell.git diff --git a/assets/.gitignore b/assets/.gitignore index 9505710..597a985 100644 --- a/assets/.gitignore +++ b/assets/.gitignore @@ -2,3 +2,4 @@ doomgeneric* init helloworld* badapple* +shell* diff --git a/build_and_run.sh b/build_and_run.sh index 541493b..a63d609 100644 --- a/build_and_run.sh +++ b/build_and_run.sh @@ -1,7 +1,8 @@ -export KARCH=aarch64 -bash build_libxunil.sh -bash build_init.sh +export KARCH=x86_64 +bash build_rust_app.sh libxunil +bash build_rust_app.sh init bash build_doomgeneric.sh bash build_helloworld.sh -bash build_badapple.sh +bash build_rust_app.sh badapple +bash build_rust_app.sh shell make run diff --git a/build_badapple.sh b/build_badapple.sh deleted file mode 100644 index 2f9d32e..0000000 --- a/build_badapple.sh +++ /dev/null @@ -1,5 +0,0 @@ -bash build_libxunil.sh -cd user/apps/badapple -cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true -cp ./target/$KARCH-unknown-none/release/badapple ../../../assets/$KARCH/badapple -cd ../../.. diff --git a/build_doomgeneric.sh b/build_doomgeneric.sh index e79bd6a..34f98c4 100644 --- a/build_doomgeneric.sh +++ b/build_doomgeneric.sh @@ -1,4 +1,3 @@ -bash build_libxunil.sh cd user/apps/doomgeneric/doomgeneric rm -r ./build make -j16 -f Makefile.xunil diff --git a/build_helloworld.sh b/build_helloworld.sh index 4058150..3ddb36f 100644 --- a/build_helloworld.sh +++ b/build_helloworld.sh @@ -1,4 +1,3 @@ -bash build_libxunil.sh cd user/apps/helloworld bash compile.sh cd ../../../ diff --git a/build_init.sh b/build_init.sh deleted file mode 100644 index bc0d829..0000000 --- a/build_init.sh +++ /dev/null @@ -1,5 +0,0 @@ -bash build_libxunil.sh -cd user/init -cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true -cp ./target/$KARCH-unknown-none/release/init ../../assets/$KARCH/init -cd ../.. diff --git a/build_libxunil.sh b/build_libxunil.sh deleted file mode 100644 index b529599..0000000 --- a/build_libxunil.sh +++ /dev/null @@ -1,2 +0,0 @@ -cd user/libxunil -cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true diff --git a/build_rust_app.sh b/build_rust_app.sh new file mode 100644 index 0000000..e91e37c --- /dev/null +++ b/build_rust_app.sh @@ -0,0 +1,13 @@ +#!/bin/bash +if [[ "$1" = "init" || "$1" = "libxunil" ]]; then + cd user/$1 +else + cd user/apps/$1 +fi + +cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true +if [[ "$1" = "init" || "$1" = "libxunil" ]]; then + cp ./target/$KARCH-unknown-none/release/$1 ../../assets/$KARCH/$1 +else + cp ./target/$KARCH-unknown-none/release/$1 ../../../assets/$KARCH/$1 +fi diff --git a/config.mk b/config.mk index 152d679..11f68b9 100644 --- a/config.mk +++ b/config.mk @@ -1,4 +1,4 @@ -export KARCH ?= aarch64 +export KARCH ?= x86_64 export OUTPUT ?= kernel export MEMORY ?= 1G export TIMER_FREQUENCY_HZ ?= 1000 diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index d2de632..f0ba046 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -9,7 +9,6 @@ dependencies = [ "aarch64-cpu", "bitflags", "fdt", - "font8x8", "heapless", "lazy_static", "limine", @@ -59,12 +58,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67" -[[package]] -name = "font8x8" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875488b8711a968268c7cf5d139578713097ca4635a76044e8fe8eedf831d07e" - [[package]] name = "hash32" version = "0.3.1" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 9027837..cf395a2 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -10,7 +10,6 @@ bench = false [dependencies] bitflags = "2.11.1" -font8x8 = { version = "0.3.1", default-features = false } heapless = "0.9.2" lazy_static = { version = "1.5.0", features = ["spin_no_std"] } limine = "0.5" diff --git a/kernel/build.rs b/kernel/build.rs index f257f64..baa3e7f 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -34,7 +34,8 @@ fn main() { pub static DOOM_WAD: &[u8] = include_bytes!(\"../../../../../assets/doom1.wad\");\n\ pub static DOOM_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/doomgeneric\");\n\ pub static HELLOWORLD_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/helloworld.elf\");\n\ - pub static BADAPPLE_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/badapple\");" + pub static BADAPPLE_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/badapple\");\n\ + pub static SHELL_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/shell\");" ), ) .unwrap(); diff --git a/kernel/src/arch/syscall.rs b/kernel/src/arch/syscall.rs index a9170b0..f154cce 100644 --- a/kernel/src/arch/syscall.rs +++ b/kernel/src/arch/syscall.rs @@ -3,6 +3,9 @@ use core::sync::atomic::Ordering; #[cfg(target_arch = "x86_64")] use crate::arch::x86_64::paging::create_and_map_multiple_pages; +use crate::driver::io::input::{InputEvent, process_input}; +#[cfg(target_arch = "x86_64")] +use crate::driver::io::ps2::process_scancodes; use alloc::vec; use alloc::{string::String, vec::Vec}; #[cfg(target_arch = "x86_64")] @@ -16,20 +19,13 @@ use x86_64::{ #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::paging::AArchPageTable; -#[cfg(target_arch = "x86_64")] -use crate::driver::io::ps2::process_scancodes; -#[cfg(target_arch = "aarch64")] -use crate::driver::io::virtio::input::process_keycodes; use crate::{ arch::arch::{FRAME_ALLOCATOR, GLOBAL_TICK_COUNT, serial_print}, config::TIMER_FREQUENCY_HZ, driver::{ elf::loader::run_elf, - graphics::framebuffer::{FRAMEBUFFER, USER_FB_BASE, with_framebuffer}, - io::{ - fs::vfs::{vfs_close, vfs_lseek, vfs_open, vfs_read}, - keyboard::KeyboardEvent, - }, + framebuffer::{FRAMEBUFFER, USER_FB_BASE, with_framebuffer}, + io::fs::vfs::{vfs_close, vfs_lseek, vfs_open, vfs_read}, ipc::{Permissions, create_port, manage_port, read_port, write_port}, timer::TIMER, }, @@ -71,7 +67,7 @@ const UNLINK: usize = 87; const GETDENTS64: usize = 217; const CLOCK_GETTIME: usize = 228; const EXIT_GROUP: usize = 231; -const KBD_READ: usize = 666; +const INPUT_READ: usize = 666; const SLEEP: usize = 909090; // zzz haha const IPC_CREATE: usize = 500; const IPC_READ: usize = 501; @@ -211,11 +207,11 @@ fn close(fd: isize) -> isize { vfs_close(fd as i64) as isize } -fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize { +fn input_read(user_ptr: *mut InputEvent, max_events: isize) -> isize { #[cfg(target_arch = "x86_64")] process_scancodes(); - #[cfg(target_arch = "aarch64")] - process_keycodes(); + + process_input(); if max_events <= 0 || user_ptr.is_null() { return -1; @@ -229,15 +225,15 @@ fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize { return SCHEDULER .with_process(pid as u64, |process| { - let to_copy = (max_events as usize).min(process.kbd_buffer.len()); + let to_copy = (max_events as usize).min(process.input_buffer.len()); if let Some(address_space) = process.address_space.as_mut() { if let Ok(_) = copy_to_user( &mut address_space.mapper, user_ptr as *mut u8, - process.kbd_buffer.as_ptr() as *const u8, - to_copy * size_of::(), + process.input_buffer.as_ptr() as *const u8, + to_copy * size_of::(), ) { - process.kbd_buffer.drain(0..to_copy); + process.input_buffer.drain(0..to_copy); return to_copy as isize; } else { @@ -695,7 +691,7 @@ pub unsafe extern "C" fn syscall_dispatch( EXECVE => exec(arg0), CLOCK_GETTIME => ((TIMER.now().elapsed() as usize) * (TIMER_FREQUENCY_HZ / 1000)) as isize, MAP_FRAMEBUFFER => map_framebuffer(), - KBD_READ => kbd_read(arg0 as *mut KeyboardEvent, arg1), + INPUT_READ => input_read(arg0 as *mut InputEvent, arg1), GETPID => { let pid = current_pid().unwrap_or(0); diff --git a/kernel/src/arch/x86_64/gdt.rs b/kernel/src/arch/x86_64/gdt.rs index f7b321c..cba0834 100644 --- a/kernel/src/arch/x86_64/gdt.rs +++ b/kernel/src/arch/x86_64/gdt.rs @@ -1,6 +1,5 @@ use core::mem::MaybeUninit; -use alloc::boxed::Box; use lazy_static::lazy_static; use spin::mutex::Mutex; use x86_64::VirtAddr; diff --git a/kernel/src/arch/x86_64/init.rs b/kernel/src/arch/x86_64/init.rs index 92dbbcb..5ad80af 100644 --- a/kernel/src/arch/x86_64/init.rs +++ b/kernel/src/arch/x86_64/init.rs @@ -1,17 +1,14 @@ use crate::{ - arch::{ - arch::serial_print, - x86_64::{ - gdt::load_gdt_x86_64, - heap::init_heap, - interrupts::{PICS, init_idt_x86_64}, - kmi::setup_kmi, - paging::{FRAME_ALLOCATOR_X86_64, initialize_paging_x86_64}, - syscall::init_syscalls, - }, + arch::x86_64::{ + gdt::load_gdt_x86_64, + heap::init_heap, + interrupts::{PICS, init_idt_x86_64}, + kmi::setup_kmi, + paging::{FRAME_ALLOCATOR_X86_64, initialize_paging_x86_64}, + syscall::init_syscalls, }, config::TIMER_FREQUENCY_HZ, - driver::{io::mouse::MOUSE, ipc::init_ipc}, + driver::ipc::init_ipc, mm::shm::init_shm, }; @@ -82,7 +79,7 @@ pub fn init_x86_64<'a>( pics.write_masks(master_mask, slave_mask); } - let kmi_status = setup_kmi(); + setup_kmi(); set_pit_interval(); @@ -94,8 +91,6 @@ pub fn init_x86_64<'a>( interrupts::enable(); - MOUSE.set_status(kmi_status); - init_ipc(); init_shm(); diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index b14ef8b..ae50e39 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -1,15 +1,9 @@ -use core::{arch::naked_asm, sync::atomic::Ordering}; +use core::arch::naked_asm; use crate::{ - arch::{arch::serial_print, x86_64::gdt}, - driver::{ - graphics::framebuffer::with_framebuffer, - io::ps2::{keyboard_interrupt, mouse_interrupt, push_scancode}, - serial::with_serial_console, - timer::TIMER, - }, + arch::x86_64::gdt, + driver::io::ps2::{keyboard_interrupt, mouse_interrupt, push_scancode}, println, - util::U64Buf, }; use lazy_static::lazy_static; use pic8259::ChainedPics; diff --git a/kernel/src/arch/x86_64/paging.rs b/kernel/src/arch/x86_64/paging.rs index 695ed8a..18b358d 100644 --- a/kernel/src/arch/x86_64/paging.rs +++ b/kernel/src/arch/x86_64/paging.rs @@ -8,10 +8,7 @@ use x86_64::{ }, }; -use crate::{ - arch::arch::{HHDM_OFFSET, XunilFrameAllocator, serial_print}, - println, -}; +use crate::arch::arch::{HHDM_OFFSET, XunilFrameAllocator}; unsafe fn active_level_4_table(mem_offset: VirtAddr) -> &'static mut PageTable { let (level_4_table, _) = Cr3::read(); diff --git a/kernel/src/config.rs b/kernel/src/config.rs index 82f0fdc..1a3ed00 100644 --- a/kernel/src/config.rs +++ b/kernel/src/config.rs @@ -1,2 +1,2 @@ pub const TIMER_FREQUENCY_HZ: usize = 1000; -pub const KARCH: &str = "aarch64"; \ No newline at end of file +pub const KARCH: &str = "x86_64"; \ No newline at end of file diff --git a/kernel/src/driver/elf/loader.rs b/kernel/src/driver/elf/loader.rs index e3927a5..75ee9b8 100644 --- a/kernel/src/driver/elf/loader.rs +++ b/kernel/src/driver/elf/loader.rs @@ -4,7 +4,7 @@ use core::{ }; #[cfg(target_arch = "x86_64")] -use crate::arch::x86_64::{interrupts, paging::create_and_map_multiple_pages}; +use crate::arch::x86_64::paging::create_and_map_multiple_pages; #[allow(unused_imports)] use crate::driver::elf::{ header::{ @@ -19,10 +19,7 @@ use crate::arch::aarch64::paging::{ AArchPageTable, create_and_map_multiple_pages, kernel_data_flags, user_data_flags, }; use crate::{ - arch::arch::KERNEL_MAPPER, - mm::address_space::AddressSpace, - println, - task::{context::UserContext, scheduler::SCHEDULER}, + arch::arch::KERNEL_MAPPER, mm::address_space::AddressSpace, println, task::scheduler::SCHEDULER, }; #[cfg(target_arch = "x86_64")] use x86_64::{ diff --git a/kernel/src/driver/graphics/framebuffer.rs b/kernel/src/driver/framebuffer.rs similarity index 85% rename from kernel/src/driver/graphics/framebuffer.rs rename to kernel/src/driver/framebuffer.rs index 5dacebb..888fc28 100644 --- a/kernel/src/driver/graphics/framebuffer.rs +++ b/kernel/src/driver/framebuffer.rs @@ -1,10 +1,10 @@ +use crate::arch::arch::safe_lock; use limine::framebuffer::Framebuffer as LimineFramebuffer; use spin::Mutex; + #[cfg(target_arch = "x86_64")] use x86_64::structures::paging::OffsetPageTable; -use crate::arch::arch::safe_lock; - #[repr(C)] pub struct UserFrameBuffer { pub buf_virt: *mut u32, @@ -56,11 +56,7 @@ impl Framebuffer { #[cfg(target_arch = "x86_64")] pub fn setup_x86_64(&mut self, mapper: &mut OffsetPageTable) { - use crate::{ - arch::arch::{FRAME_ALLOCATOR, HHDM_OFFSET, serial_print}, - arch::x86_64::paging::initialize_paging_x86_64, - util::U64Buf, - }; + use crate::arch::arch::FRAME_ALLOCATOR; use x86_64::{ PhysAddr, VirtAddr, structures::paging::{ @@ -85,8 +81,6 @@ impl Framebuffer { fa.allocate_frame().expect("framebuffer pixel frame"); } - let hhdm_offset = HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed); - let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::NO_EXECUTE; let struct_page = Page::::containing_address(VirtAddr::new(KERNEL_FB_BASE)); @@ -167,31 +161,6 @@ impl Framebuffer { self.meta.struct_phys = struct_phys; } - #[inline(always)] - pub fn put_pixel(&mut self, x: usize, y: usize, color: u32) { - if x >= self.width || y >= self.height { - return; - } - let idx = y * self.pitch + x; - if idx >= self.meta.buf_len { - return; - } - unsafe { self.user_fb.buf_virt.add(idx).write(color) }; - } - - #[inline(always)] - pub fn fill_span(&mut self, x: usize, y: usize, len: usize, color: u32) { - if y >= self.height || x >= self.width || len == 0 { - return; - } - let len = core::cmp::min(len, self.width - x); - let start = y * self.pitch + x; - unsafe { - let slice = core::slice::from_raw_parts_mut(self.user_fb.buf_virt.add(start), len); - slice.fill(color); - } - } - pub fn present(&mut self) { unsafe { core::ptr::copy_nonoverlapping(self.user_fb.buf_virt, self.addr, self.meta.buf_len); diff --git a/kernel/src/driver/graphics/font_render.rs b/kernel/src/driver/graphics/font_render.rs deleted file mode 100644 index 2dd48a4..0000000 --- a/kernel/src/driver/graphics/font_render.rs +++ /dev/null @@ -1,69 +0,0 @@ -extern crate font8x8; - -use crate::driver::graphics::framebuffer::Framebuffer; -use font8x8::legacy::BASIC_LEGACY; - -pub fn rectangle_filled( - framebuffer: &mut Framebuffer, - x: usize, - y: usize, - width: usize, - height: usize, - color: u32, -) { - for yy in y..y + height { - framebuffer.fill_span(x, yy, width, color); - } -} - -pub fn render_char( - framebuffer: &mut Framebuffer, - start_x: usize, - start_y: usize, - char: usize, - font_size: usize, - color: u32, -) { - if let Some(glyph) = BASIC_LEGACY.get(char) { - for (row, row_bits) in glyph.iter().enumerate() { - for bit in 0..8 { - if (row_bits & (1 << bit)) != 0 { - rectangle_filled( - framebuffer, - start_x + bit * font_size, - start_y + row * font_size, - font_size, - font_size, - color, - ); - } - } - } - } -} - -pub fn render_text( - framebuffer: &mut Framebuffer, - start_x: usize, - start_y: usize, - text: &str, - font_size: usize, - color: u32, - margin_left: usize, -) -> (usize, usize) { - let mut x = start_x; - let mut y = start_y; - - for b in text.bytes() { - if b == b'\n' { - y += 12 * font_size; - x = margin_left; - continue; - } - - render_char(framebuffer, x, y, b as usize, font_size, color); - x += 8 * font_size; - } - - (x, y) -} diff --git a/kernel/src/driver/graphics/mod.rs b/kernel/src/driver/graphics/mod.rs deleted file mode 100644 index 66487e0..0000000 --- a/kernel/src/driver/graphics/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod font_render; -pub mod framebuffer; - -pub fn rgb(r: u8, g: u8, b: u8) -> u32 { - ((r as u32) << 16) | ((g as u32) << 8) | (b as u32) -} diff --git a/kernel/src/driver/io/fs/assets.rs b/kernel/src/driver/io/fs/assets.rs index 92d9f39..d070c71 100644 --- a/kernel/src/driver/io/fs/assets.rs +++ b/kernel/src/driver/io/fs/assets.rs @@ -1,5 +1,6 @@ -pub static INIT_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/init"); +pub static INIT_ELF: &[u8] = include_bytes!("../../../../../assets/x86_64/init"); pub static DOOM_WAD: &[u8] = include_bytes!("../../../../../assets/doom1.wad"); -pub static DOOM_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/doomgeneric"); -pub static HELLOWORLD_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/helloworld.elf"); -pub static BADAPPLE_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/badapple"); \ No newline at end of file +pub static DOOM_ELF: &[u8] = include_bytes!("../../../../../assets/x86_64/doomgeneric"); +pub static HELLOWORLD_ELF: &[u8] = include_bytes!("../../../../../assets/x86_64/helloworld.elf"); +pub static BADAPPLE_ELF: &[u8] = include_bytes!("../../../../../assets/x86_64/badapple"); +pub static SHELL_ELF: &[u8] = include_bytes!("../../../../../assets/x86_64/shell"); \ No newline at end of file diff --git a/kernel/src/driver/io/fs/vfs.rs b/kernel/src/driver/io/fs/vfs.rs index 9494e88..727ba7c 100644 --- a/kernel/src/driver/io/fs/vfs.rs +++ b/kernel/src/driver/io/fs/vfs.rs @@ -56,6 +56,10 @@ static FILES: &[FakeFileEntry] = &[ name: "doomgeneric", data: DOOM_ELF, }, + FakeFileEntry { + name: "shell", + data: SHELL_ELF, + }, FakeFileEntry { name: "doom1.wad", data: DOOM_WAD, diff --git a/kernel/src/driver/io/input.rs b/kernel/src/driver/io/input.rs new file mode 100644 index 0000000..37f4704 --- /dev/null +++ b/kernel/src/driver/io/input.rs @@ -0,0 +1,155 @@ +use heapless::spsc::{Consumer, Producer, Queue}; +use static_cell::StaticCell; + +use crate::task::scheduler::SCHEDULER; + +pub const KEY_RESERVED: u8 = 0; +pub const KEY_ESC: u8 = 1; +pub const KEY_1: u8 = 2; +pub const KEY_2: u8 = 3; +pub const KEY_3: u8 = 4; +pub const KEY_4: u8 = 5; +pub const KEY_5: u8 = 6; +pub const KEY_6: u8 = 7; +pub const KEY_7: u8 = 8; +pub const KEY_8: u8 = 9; +pub const KEY_9: u8 = 10; +pub const KEY_0: u8 = 11; +pub const KEY_MINUS: u8 = 12; +pub const KEY_EQUAL: u8 = 13; +pub const KEY_BACKSPACE: u8 = 14; +pub const KEY_TAB: u8 = 15; +pub const KEY_Q: u8 = 16; +pub const KEY_W: u8 = 17; +pub const KEY_E: u8 = 18; +pub const KEY_R: u8 = 19; +pub const KEY_T: u8 = 20; +pub const KEY_Y: u8 = 21; +pub const KEY_U: u8 = 22; +pub const KEY_I: u8 = 23; +pub const KEY_O: u8 = 24; +pub const KEY_P: u8 = 25; +pub const KEY_LEFTBRACE: u8 = 26; +pub const KEY_RIGHTBRACE: u8 = 27; +pub const KEY_ENTER: u8 = 28; +pub const KEY_LEFTCTRL: u8 = 29; +pub const KEY_A: u8 = 30; +pub const KEY_S: u8 = 31; +pub const KEY_D: u8 = 32; +pub const KEY_F: u8 = 33; +pub const KEY_G: u8 = 34; +pub const KEY_H: u8 = 35; +pub const KEY_J: u8 = 36; +pub const KEY_K: u8 = 37; +pub const KEY_L: u8 = 38; +pub const KEY_SEMICOLON: u8 = 39; +pub const KEY_APOSTROPHE: u8 = 40; +pub const KEY_GRAVE: u8 = 41; +pub const KEY_LEFTSHIFT: u8 = 42; +pub const KEY_BACKSLASH: u8 = 43; +pub const KEY_Z: u8 = 44; +pub const KEY_X: u8 = 45; +pub const KEY_C: u8 = 46; +pub const KEY_V: u8 = 47; +pub const KEY_B: u8 = 48; +pub const KEY_N: u8 = 49; +pub const KEY_M: u8 = 50; +pub const KEY_COMMA: u8 = 51; +pub const KEY_DOT: u8 = 52; +pub const KEY_SLASH: u8 = 53; +pub const KEY_RIGHTSHIFT: u8 = 54; +pub const KEY_KPASTERISK: u8 = 55; +pub const KEY_LEFTALT: u8 = 56; +pub const KEY_SPACE: u8 = 57; +pub const KEY_CAPSLOCK: u8 = 58; +pub const KEY_F1: u8 = 59; +pub const KEY_F2: u8 = 60; +pub const KEY_F3: u8 = 61; +pub const KEY_F4: u8 = 62; +pub const KEY_F5: u8 = 63; +pub const KEY_F6: u8 = 64; +pub const KEY_F7: u8 = 65; +pub const KEY_F8: u8 = 66; +pub const KEY_F9: u8 = 67; +pub const KEY_F10: u8 = 68; +pub const KEY_NUMLOCK: u8 = 69; +pub const KEY_SCROLLLOCK: u8 = 70; +pub const KEY_KP7: u8 = 71; +pub const KEY_KP8: u8 = 72; +pub const KEY_KP9: u8 = 73; +pub const KEY_KPMINUS: u8 = 74; +pub const KEY_KP4: u8 = 75; +pub const KEY_KP5: u8 = 76; +pub const KEY_KP6: u8 = 77; +pub const KEY_KPPLUS: u8 = 78; +pub const KEY_KP1: u8 = 79; +pub const KEY_KP2: u8 = 80; +pub const KEY_KP3: u8 = 81; +pub const KEY_KP0: u8 = 82; +pub const KEY_KPDOT: u8 = 83; +pub const KEY_RIGHTCTRL: u8 = 97; +pub const KEY_UP: u8 = 103; +pub const KEY_LEFT: u8 = 105; +pub const KEY_RIGHT: u8 = 106; +pub const KEY_DOWN: u8 = 108; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct InputEvent { + pub event_type: u16, + pub code: u16, + pub value: u32, +} + +pub const EVENT_KEY: u16 = 0x01; +pub const EVENT_REL: u16 = 0x02; + +pub const BTN_LEFT: u16 = 0x110; +pub const BTN_RIGHT: u16 = 0x111; +pub const BTN_MIDDLE: u16 = 0x112; + +pub const REL_X: u16 = 0x00; +pub const REL_Y: u16 = 0x01; +pub const REL_WHEEL: u16 = 0x08; + +pub static INPUT_QUEUE: StaticCell> = StaticCell::new(); +pub static mut INPUT_PROD: Option> = None; +pub static mut INPUT_CONS: Option> = None; + +pub fn init_input() { + let q = INPUT_QUEUE.init(Queue::new()); + let (p, c) = q.split(); + unsafe { + INPUT_PROD = Some(p); + INPUT_CONS = Some(c); + } +} + +pub fn process_input() { + loop { + let input_event = unsafe { + #[allow(static_mut_refs)] + match INPUT_CONS.as_mut() { + Some(cons) => match cons.dequeue() { + Some(b) => b, + None => break, + }, + None => break, + } + }; + + let mut scheduler = SCHEDULER.lock(); + for process in scheduler.processes.values_mut() { + process.input_buffer.push(input_event); + } + drop(scheduler); + } +} + +pub fn enqueue_input_event(input_event: InputEvent) { + #[allow(static_mut_refs)] + let _ = match unsafe { INPUT_PROD.as_mut() } { + Some(prod) => prod.enqueue(input_event).is_ok(), + _ => false, + }; +} diff --git a/kernel/src/driver/io/keyboard.rs b/kernel/src/driver/io/keyboard.rs deleted file mode 100644 index 6442ff8..0000000 --- a/kernel/src/driver/io/keyboard.rs +++ /dev/null @@ -1,192 +0,0 @@ -pub const KEY_RESERVED: u8 = 0; -pub const KEY_ESC: u8 = 1; -pub const KEY_1: u8 = 2; -pub const KEY_2: u8 = 3; -pub const KEY_3: u8 = 4; -pub const KEY_4: u8 = 5; -pub const KEY_5: u8 = 6; -pub const KEY_6: u8 = 7; -pub const KEY_7: u8 = 8; -pub const KEY_8: u8 = 9; -pub const KEY_9: u8 = 10; -pub const KEY_0: u8 = 11; -pub const KEY_MINUS: u8 = 12; -pub const KEY_EQUAL: u8 = 13; -pub const KEY_BACKSPACE: u8 = 14; -pub const KEY_TAB: u8 = 15; -pub const KEY_Q: u8 = 16; -pub const KEY_W: u8 = 17; -pub const KEY_E: u8 = 18; -pub const KEY_R: u8 = 19; -pub const KEY_T: u8 = 20; -pub const KEY_Y: u8 = 21; -pub const KEY_U: u8 = 22; -pub const KEY_I: u8 = 23; -pub const KEY_O: u8 = 24; -pub const KEY_P: u8 = 25; -pub const KEY_LEFTBRACE: u8 = 26; -pub const KEY_RIGHTBRACE: u8 = 27; -pub const KEY_ENTER: u8 = 28; -pub const KEY_LEFTCTRL: u8 = 29; -pub const KEY_A: u8 = 30; -pub const KEY_S: u8 = 31; -pub const KEY_D: u8 = 32; -pub const KEY_F: u8 = 33; -pub const KEY_G: u8 = 34; -pub const KEY_H: u8 = 35; -pub const KEY_J: u8 = 36; -pub const KEY_K: u8 = 37; -pub const KEY_L: u8 = 38; -pub const KEY_SEMICOLON: u8 = 39; -pub const KEY_APOSTROPHE: u8 = 40; -pub const KEY_GRAVE: u8 = 41; -pub const KEY_LEFTSHIFT: u8 = 42; -pub const KEY_BACKSLASH: u8 = 43; -pub const KEY_Z: u8 = 44; -pub const KEY_X: u8 = 45; -pub const KEY_C: u8 = 46; -pub const KEY_V: u8 = 47; -pub const KEY_B: u8 = 48; -pub const KEY_N: u8 = 49; -pub const KEY_M: u8 = 50; -pub const KEY_COMMA: u8 = 51; -pub const KEY_DOT: u8 = 52; -pub const KEY_SLASH: u8 = 53; -pub const KEY_RIGHTSHIFT: u8 = 54; -pub const KEY_KPASTERISK: u8 = 55; -pub const KEY_LEFTALT: u8 = 56; -pub const KEY_SPACE: u8 = 57; -pub const KEY_CAPSLOCK: u8 = 58; -pub const KEY_F1: u8 = 59; -pub const KEY_F2: u8 = 60; -pub const KEY_F3: u8 = 61; -pub const KEY_F4: u8 = 62; -pub const KEY_F5: u8 = 63; -pub const KEY_F6: u8 = 64; -pub const KEY_F7: u8 = 65; -pub const KEY_F8: u8 = 66; -pub const KEY_F9: u8 = 67; -pub const KEY_F10: u8 = 68; -pub const KEY_NUMLOCK: u8 = 69; -pub const KEY_SCROLLLOCK: u8 = 70; -pub const KEY_KP7: u8 = 71; -pub const KEY_KP8: u8 = 72; -pub const KEY_KP9: u8 = 73; -pub const KEY_KPMINUS: u8 = 74; -pub const KEY_KP4: u8 = 75; -pub const KEY_KP5: u8 = 76; -pub const KEY_KP6: u8 = 77; -pub const KEY_KPPLUS: u8 = 78; -pub const KEY_KP1: u8 = 79; -pub const KEY_KP2: u8 = 80; -pub const KEY_KP3: u8 = 81; -pub const KEY_KP0: u8 = 82; -pub const KEY_KPDOT: u8 = 83; -pub const KEY_RIGHTCTRL: u8 = 97; -pub const KEY_UP: u8 = 103; -pub const KEY_LEFT: u8 = 105; -pub const KEY_RIGHT: u8 = 106; -pub const KEY_DOWN: u8 = 108; - -pub const KEY_TO_CHAR: [Option<(char, char)>; 84] = [ - None, // 0 KEY_RESERVED - Some(('\x1b', '\x1b')), // 1 KEY_ESC - Some(('1', '!')), // 2 KEY_1 - Some(('2', '@')), // 3 KEY_2 - Some(('3', '#')), // 4 KEY_3 - Some(('4', '$')), // 5 KEY_4 - Some(('5', '%')), // 6 KEY_5 - Some(('6', '^')), // 7 KEY_6 - Some(('7', '&')), // 8 KEY_7 - Some(('8', '*')), // 9 KEY_8 - Some(('9', '(')), // 10 KEY_9 - Some(('0', ')')), // 11 KEY_0 - Some(('-', '_')), // 12 KEY_MINUS - Some(('=', '+')), // 13 KEY_EQUAL - Some(('\x08', '\x08')), // 14 KEY_BACKSPACE - Some(('\t', '\t')), // 15 KEY_TAB - Some(('q', 'Q')), // 16 KEY_Q - Some(('w', 'W')), // 17 KEY_W - Some(('e', 'E')), // 18 KEY_E - Some(('r', 'R')), // 19 KEY_R - Some(('t', 'T')), // 20 KEY_T - Some(('y', 'Y')), // 21 KEY_Y - Some(('u', 'U')), // 22 KEY_U - Some(('i', 'I')), // 23 KEY_I - Some(('o', 'O')), // 24 KEY_O - Some(('p', 'P')), // 25 KEY_P - Some(('[', '{')), // 26 KEY_LEFTBRACE - Some((']', '}')), // 27 KEY_RIGHTBRACE - Some(('\n', '\n')), // 28 KEY_ENTER - None, // 29 KEY_LEFTCTRL - Some(('a', 'A')), // 30 KEY_A - Some(('s', 'S')), // 31 KEY_S - Some(('d', 'D')), // 32 KEY_D - Some(('f', 'F')), // 33 KEY_F - Some(('g', 'G')), // 34 KEY_G - Some(('h', 'H')), // 35 KEY_H - Some(('j', 'J')), // 36 KEY_J - Some(('k', 'K')), // 37 KEY_K - Some(('l', 'L')), // 38 KEY_L - Some((';', ':')), // 39 KEY_SEMICOLON - Some(('\'', '"')), // 40 KEY_APOSTROPHE - Some(('`', '~')), // 41 KEY_GRAVE - None, // 42 KEY_LEFTSHIFT - Some(('\\', '|')), // 43 KEY_BACKSLASH - Some(('z', 'Z')), // 44 KEY_Z - Some(('x', 'X')), // 45 KEY_X - Some(('c', 'C')), // 46 KEY_C - Some(('v', 'V')), // 47 KEY_V - Some(('b', 'B')), // 48 KEY_B - Some(('n', 'N')), // 49 KEY_N - Some(('m', 'M')), // 50 KEY_M - Some((',', '<')), // 51 KEY_COMMA - Some(('.', '>')), // 52 KEY_DOT - Some(('/', '?')), // 53 KEY_SLASH - None, // 54 KEY_RIGHTSHIFT - Some(('*', '*')), // 55 KEY_KPASTERISK - None, // 56 KEY_LEFTALT - Some((' ', ' ')), // 57 KEY_SPACE - None, // 58 KEY_CAPSLOCK - None, // 59 KEY_F1 - None, // 60 KEY_F2 - None, // 61 KEY_F3 - None, // 62 KEY_F4 - None, // 63 KEY_F5 - None, // 64 KEY_F6 - None, // 65 KEY_F7 - None, // 66 KEY_F8 - None, // 67 KEY_F9 - None, // 68 KEY_F10 - None, // 69 KEY_NUMLOCK - None, // 70 KEY_SCROLLLOCK - Some(('7', '7')), // 71 KEY_KP7 - Some(('8', '8')), // 72 KEY_KP8 - Some(('9', '9')), // 73 KEY_KP9 - Some(('-', '-')), // 74 KEY_KPMINUS - Some(('4', '4')), // 75 KEY_KP4 - Some(('5', '5')), // 76 KEY_KP5 - Some(('6', '6')), // 77 KEY_KP6 - Some((('+'), '+')), // 78 KEY_KPPLUS - Some(('1', '1')), // 79 KEY_KP1 - Some(('2', '2')), // 80 KEY_KP2 - Some(('3', '3')), // 81 KEY_KP3 - Some(('0', '0')), // 82 KEY_KP0 - Some(('.', '.')), // 83 KEY_KPDOT -]; - -pub fn keycode_to_char(keycode: u8, shift: bool) -> Option { - let entry = KEY_TO_CHAR.get(keycode as usize)?.as_ref()?; - Some(if shift { entry.1 } else { entry.0 }) -} - -#[repr(C)] -#[derive(Clone, Debug, Copy, Default)] -pub struct KeyboardEvent { - pub state: u8, - pub _pad1: u8, - pub key: u16, - pub mods: u16, - pub _pad2: u16, - pub unicode: u32, -} diff --git a/kernel/src/driver/io/mod.rs b/kernel/src/driver/io/mod.rs index aab5f37..b8634d8 100644 --- a/kernel/src/driver/io/mod.rs +++ b/kernel/src/driver/io/mod.rs @@ -1,6 +1,5 @@ pub mod fs; -pub mod keyboard; -pub mod mouse; +pub mod input; #[cfg(target_arch = "x86_64")] pub mod ps2; pub mod virtio; diff --git a/kernel/src/driver/io/mouse.rs b/kernel/src/driver/io/mouse.rs deleted file mode 100644 index 610e46d..0000000 --- a/kernel/src/driver/io/mouse.rs +++ /dev/null @@ -1,45 +0,0 @@ -use core::sync::atomic::{AtomicBool, AtomicI16, AtomicU8, Ordering}; - -pub struct Mouse { - pub left_button_pressed: AtomicBool, - pub right_button_pressed: AtomicBool, - pub middle_button_pressed: AtomicBool, - pub x_delta: AtomicI16, - pub y_delta: AtomicI16, - pub status: AtomicU8, -} - -impl Mouse { - const fn new() -> Mouse { - Mouse { - left_button_pressed: AtomicBool::new(false), - right_button_pressed: AtomicBool::new(false), - middle_button_pressed: AtomicBool::new(false), - x_delta: AtomicI16::new(0), - y_delta: AtomicI16::new(0), - status: AtomicU8::new(0), - } - } - - pub fn button_state(&self) -> (bool, bool, bool) { - ( - self.left_button_pressed.load(Ordering::Relaxed), - self.right_button_pressed.load(Ordering::Relaxed), - self.middle_button_pressed.load(Ordering::Relaxed), - ) - } - pub fn take_motion(&self) -> (i16, i16) { - ( - self.x_delta.swap(0, Ordering::Relaxed), - self.y_delta.swap(0, Ordering::Relaxed), - ) - } - pub fn set_status(&self, status: u8) { - self.status.store(status, Ordering::Relaxed); - } - pub fn get_status(&self) -> u8 { - self.status.load(Ordering::Relaxed) - } -} - -pub static MOUSE: Mouse = Mouse::new(); diff --git a/kernel/src/driver/io/ps2.rs b/kernel/src/driver/io/ps2.rs index 8159af0..b147b29 100644 --- a/kernel/src/driver/io/ps2.rs +++ b/kernel/src/driver/io/ps2.rs @@ -1,23 +1,14 @@ -use core::sync::atomic::{AtomicU8, AtomicU64, Ordering}; +use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; use heapless::spsc::{Consumer, Producer, Queue}; -use pc_keyboard::{DecodedKey, HandleControl, KeyCode, KeyState, Keyboard, ScancodeSet2, layouts}; +use pc_keyboard::{HandleControl, KeyCode, KeyState, Keyboard, ScancodeSet2, layouts}; use static_cell::StaticCell; -#[cfg(target_arch = "aarch64")] -use crate::arch::aarch64::kmi::{ - read_keyboard_control, read_keyboard_data, read_mouse_control, read_mouse_data, -}; #[cfg(target_arch = "x86_64")] use crate::arch::x86_64::kmi::{ read_keyboard_control, read_keyboard_data, read_mouse_control, read_mouse_data, }; -use crate::{ - driver::io::{keyboard::*, mouse::MOUSE}, - println, - task::scheduler::SCHEDULER, - util::get_bit, -}; +use crate::{driver::io::input::*, util::get_bit}; pub fn keycode_to_linux(kc: KeyCode) -> Option { let code = match kc { @@ -118,7 +109,9 @@ static mut SCANCODE_PROD: Option> = None; static mut SCANCODE_CONS: Option> = None; static mut KEYBOARD: Option> = None; -static DROPPED_SCANCODES: AtomicU64 = AtomicU64::new(0); +static MOUSE_LEFT_BUTTON: AtomicBool = AtomicBool::new(false); +static MOUSE_RIGHT_BUTTON: AtomicBool = AtomicBool::new(false); +static MOUSE_MIDDLE_BUTTON: AtomicBool = AtomicBool::new(false); pub fn init_keyboard() { let q = SCANCODE_QUEUE.init(Queue::new()); @@ -136,17 +129,11 @@ pub fn init_keyboard() { } pub fn push_scancode(scancode: u8) { - let pushed = unsafe { - #[allow(static_mut_refs)] - match SCANCODE_PROD.as_mut() { - Some(prod) => prod.enqueue(scancode).is_ok(), - _ => false, - } + #[allow(static_mut_refs)] + match unsafe { SCANCODE_PROD.as_mut() } { + Some(prod) => prod.enqueue(scancode).is_ok(), + _ => false, }; - - if !pushed { - DROPPED_SCANCODES.fetch_add(1, Ordering::Relaxed); - } } pub fn process_scancodes() { @@ -162,45 +149,24 @@ pub fn process_scancodes() { } }; - if let Some(kbd_event) = process_scancode(scancode) { - let mut scheduler = SCHEDULER.lock(); - for process in scheduler.processes.values_mut() { - process.kbd_buffer.push(kbd_event); + #[allow(static_mut_refs)] + let kbd = unsafe { KEYBOARD.as_mut().unwrap() }; + if let Ok(Some(key_event)) = kbd.add_byte(scancode) { + if let Some(linux_keycode) = keycode_to_linux(key_event.code) { + enqueue_input_event(InputEvent { + event_type: EVENT_KEY, + code: linux_keycode as u16, + value: if key_event.state == KeyState::Down { + 1 + } else { + 0 + }, + }); } - drop(scheduler); } } } -pub fn process_scancode(scancode: u8) -> Option { - #[allow(static_mut_refs)] - let kbd = unsafe { KEYBOARD.as_mut().expect("keyboard not initialized") }; - if let Ok(Some(key_event)) = kbd.add_byte(scancode) { - let keycode = key_event.code; - let keystate = key_event.state; - let (unicode, state) = match (kbd.process_keyevent(key_event), keystate) { - (Some(DecodedKey::Unicode(ch)), st) => (ch as u32, st), - _ => (0, keystate), - }; - - if let Some(linux_keycode) = keycode_to_linux(keycode) { - let effective_shift = kbd.get_modifiers().is_shifted() & kbd.get_modifiers().capslock; - return Some(KeyboardEvent { - state: if state == KeyState::Down { 1 } else { 0 }, - _pad1: 0, - key: linux_keycode as u16, - mods: 0, - _pad2: 0, - unicode: keycode_to_char(linux_keycode, effective_shift).unwrap_or('\0') as u32, - }); - } else { - return None; - } - } else { - return None; - } -} - static CURRENTLY_RECEIVING_STATE: AtomicU8 = AtomicU8::new(0); static FLAGS_BYTE: AtomicU8 = AtomicU8::new(0); static X_DELTA_BYTE: AtomicU8 = AtomicU8::new(0); @@ -293,34 +259,53 @@ pub fn process_mouse_interrupt() -> Option<(bool, bool, bool, i16, i16)> { } pub fn mouse_interrupt() { - if let Some(interrupt_result) = process_mouse_interrupt() { - MOUSE - .left_button_pressed - .store(interrupt_result.0, Ordering::Relaxed); - MOUSE - .right_button_pressed - .store(interrupt_result.1, Ordering::Relaxed); - MOUSE - .middle_button_pressed - .store(interrupt_result.2, Ordering::Relaxed); - MOUSE - .x_delta - .fetch_add(interrupt_result.3, Ordering::Relaxed); - MOUSE - .y_delta - .fetch_add(interrupt_result.4, Ordering::Relaxed); + if let Some((left, right, middle, dx, dy)) = process_mouse_interrupt() { + if left != MOUSE_LEFT_BUTTON.swap(left, Ordering::Relaxed) { + enqueue_input_event(InputEvent { + event_type: EVENT_KEY, + code: BTN_LEFT, + value: left as u32, + }); + } + + if right != MOUSE_RIGHT_BUTTON.swap(right, Ordering::Relaxed) { + enqueue_input_event(InputEvent { + event_type: EVENT_KEY, + code: BTN_RIGHT, + value: right as u32, + }); + } + + if middle != MOUSE_MIDDLE_BUTTON.swap(middle, Ordering::Relaxed) { + enqueue_input_event(InputEvent { + event_type: EVENT_KEY, + code: BTN_MIDDLE, + value: middle as u32, + }); + } + + if dx != 0 { + enqueue_input_event(InputEvent { + event_type: EVENT_REL, + code: REL_X, + value: dx as i32 as u32, + }); + } + + if dy != 0 { + enqueue_input_event(InputEvent { + event_type: EVENT_REL, + code: REL_Y, + value: dy as i32 as u32, + }); + } } } pub fn keyboard_interrupt() -> Option { - #[cfg(target_arch = "x86_64")] if (unsafe { read_keyboard_control() } & 0x01) == 0 { return None; // OBF clear, no data } - #[cfg(target_arch = "aarch64")] - if (unsafe { read_keyboard_control() } & 0x10) == 0 { - return None; // RXFULL clear, no data - } let scancode = unsafe { read_keyboard_data() }; Some(scancode) diff --git a/kernel/src/driver/io/virtio/input.rs b/kernel/src/driver/io/virtio/input.rs index ff0d57e..261c6fc 100644 --- a/kernel/src/driver/io/virtio/input.rs +++ b/kernel/src/driver/io/virtio/input.rs @@ -1,34 +1,12 @@ -use heapless::spsc::{Consumer, Producer, Queue}; -use static_cell::StaticCell; - -use crate::{ - arch::arch::serial_print, - driver::io::{ - keyboard::{ - KEY_CAPSLOCK, KEY_LEFTALT, KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT, KeyboardEvent, - keycode_to_char, - }, - mouse::MOUSE, - virtio::{ - KEYBOARD_SLOT, MOUSE_SLOT, VIRTIO_MMIO_BASE, VIRTIO_MMIO_STRIDE, - queue::{QUEUE_SIZE, VirtqueueMem}, - transport::{VirtioMmio, VirtioMmioReg}, - }, +use crate::driver::io::{ + input::{InputEvent, enqueue_input_event}, + virtio::{ + KEYBOARD_SLOT, MOUSE_SLOT, VIRTIO_MMIO_BASE, VIRTIO_MMIO_STRIDE, + queue::{QUEUE_SIZE, VirtqueueMem}, + transport::{VirtioMmio, VirtioMmioReg}, }, - task::scheduler::SCHEDULER, }; -const BTN_LEFT: u16 = 0x110; -const BTN_RIGHT: u16 = 0x111; -const BTN_MIDDLE: u16 = 0x112; - -const REL_X: u16 = 0x00; -const REL_Y: u16 = 0x01; -const REL_WHEEL: u16 = 0x08; - -const EVENT_KEY: u16 = 0x01; -const EVENT_REL: u16 = 0x02; - #[repr(u8)] pub enum VirtioInputCfgSelect { Unset = 0x00, @@ -48,84 +26,8 @@ pub struct VirtioInputEvent { value: u32, } -pub struct ModState { - shift: bool, - caps_lock: bool, - ctrl: bool, - alt: bool, -} - -impl ModState { - pub const fn new() -> Self { - Self { - shift: false, - caps_lock: false, - ctrl: false, - alt: false, - } - } - pub fn update(&mut self, code: u8, value: u32) { - match code { - KEY_LEFTSHIFT | KEY_RIGHTSHIFT => self.shift = value != 0, - KEY_LEFTCTRL => self.ctrl = value != 0, - KEY_CAPSLOCK => self.caps_lock = value != 0, - KEY_LEFTALT => self.alt = value != 0, - _ => {} - } - } - - pub fn effective_shift(&self) -> bool { - self.shift ^ self.caps_lock - } -} - pub static mut VIRTIO_KEYBOARD_QUEUE: VirtqueueMem = unsafe { core::mem::zeroed() }; pub static mut VIRTIO_MOUSE_QUEUE: VirtqueueMem = unsafe { core::mem::zeroed() }; -pub static mut MODIFIERS: ModState = ModState::new(); - -static KEYCODE_QUEUE: StaticCell> = StaticCell::new(); -static mut KEYCODE_PROD: Option> = None; -static mut KEYCODE_CONS: Option> = None; - -pub fn init_keyboard() { - let q = KEYCODE_QUEUE.init(Queue::new()); - let (p, c) = q.split(); - - unsafe { - KEYCODE_PROD = Some(p); - KEYCODE_CONS = Some(c); - } -} - -pub fn process_keycodes() { - let mut scheduler = SCHEDULER.lock(); - - loop { - let keycode_data = unsafe { - #[allow(static_mut_refs)] - match KEYCODE_CONS.as_mut() { - Some(cons) => match cons.dequeue() { - Some(b) => b, - None => break, - }, - None => break, - } - }; - - for process in scheduler.processes.values_mut() { - process.kbd_buffer.push(KeyboardEvent { - state: keycode_data.1, - _pad1: 0, - key: keycode_data.0 as u16, - mods: 0, - _pad2: 0, - unicode: keycode_to_char(keycode_data.0, keycode_data.2).unwrap_or('\0') as u32, - }); - } - } - - drop(scheduler); -} pub fn read_device_name(device: &VirtioMmio) -> &str { return unsafe { @@ -214,59 +116,9 @@ pub fn handle_event(event: &VirtioInputEvent) { return; } - match event.event_type { - EVENT_KEY => { - unsafe { MODIFIERS.update(event.code as u8, event.value) }; - match event.code { - BTN_LEFT => { - MOUSE - .left_button_pressed - .store(event.value == 1, core::sync::atomic::Ordering::Relaxed); - } - BTN_RIGHT => { - MOUSE - .right_button_pressed - .store(event.value == 1, core::sync::atomic::Ordering::Relaxed); - } - BTN_MIDDLE => { - MOUSE - .middle_button_pressed - .store(event.value == 1, core::sync::atomic::Ordering::Relaxed); - } - _ => { - let state = match event.value { - 1 => 1, - 0 => 0, - _ => return, - }; - - let _ = match unsafe { KEYCODE_PROD.as_mut() } { - Some(prod) => prod - .enqueue(unsafe { - (event.code as u8, state, MODIFIERS.effective_shift()) - }) - .is_ok(), - _ => false, - }; - } - } - } - EVENT_REL => match event.code { - REL_X => { - MOUSE.x_delta.fetch_add( - event.value as i32 as i16, - core::sync::atomic::Ordering::Relaxed, - ); - } - REL_Y => { - MOUSE.y_delta.fetch_add( - event.value as i32 as i16, - core::sync::atomic::Ordering::Relaxed, - ); - } - REL_WHEEL => {} - _ => {} - }, - _ => serial_print("Could not recognize virtio input event from interrupt\n"), - }; + enqueue_input_event(InputEvent { + event_type: event.event_type, + code: event.code, + value: event.value, + }); } diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs index fe9b2c6..8415cd6 100644 --- a/kernel/src/driver/mod.rs +++ b/kernel/src/driver/mod.rs @@ -1,6 +1,5 @@ pub mod elf; -pub mod graphics; +pub mod framebuffer; pub mod io; pub mod ipc; -pub mod serial; pub mod timer; diff --git a/kernel/src/driver/serial.rs b/kernel/src/driver/serial.rs deleted file mode 100644 index be9c3ef..0000000 --- a/kernel/src/driver/serial.rs +++ /dev/null @@ -1,115 +0,0 @@ -use crate::alloc::string::ToString; -use crate::arch::arch::serial_print; -use crate::driver::graphics::font_render::render_text; -use crate::driver::graphics::framebuffer::Framebuffer; -use crate::{arch::arch::safe_lock, driver::graphics::rgb}; -use alloc::string::String; -use core::fmt::{self, Write}; -use spin::Mutex; - -pub struct ConsoleWriter<'a> { - pub fb: &'a mut Framebuffer, - pub console: &'a mut SerialConsole, - pub should_center: bool, -} - -impl Write for ConsoleWriter<'_> { - fn write_str(&mut self, s: &str) -> fmt::Result { - serial_print(s); - self.console.print(s, self.fb); - Ok(()) - } -} - -pub struct SerialConsole { - text: String, - pub font_size: usize, - dirty: bool, -} - -impl SerialConsole { - pub fn new() -> SerialConsole { - SerialConsole { - text: String::new(), - font_size: 1, - dirty: false, - } - } - - pub fn print(&mut self, text: &str, fb: &mut Framebuffer) { - if text == "\x1b[2J" { - self.text.clear(); - return; - } - - let max_height = fb.height / (12 * self.font_size); - let max_width = fb.width / (8 * self.font_size); - - for ch in text.chars() { - if ch == '\n' { - self.text.push('\n'); - continue; - } - - let line_len = self - .text - .rsplit('\n') - .next() - .map(|l| l.chars().count()) - .unwrap_or(0); - - if line_len >= max_width { - self.text.push('\n'); - } - - self.text.push(ch); - } - - let lines = self.text.lines().count(); - - if lines > max_height { - let remove = lines - max_height; - let mut split = 0; - - for (i, c) in self.text.char_indices() { - if c == '\n' { - split += 1; - if split == remove { - self.text = self.text[i + 1..].to_string(); - break; - } - } - } - } - - self.dirty = true; - } - - pub fn render(&mut self, fb: &mut Framebuffer) { - if self.dirty { - fb.clear(rgb(0, 0, 0)); - self.dirty = false; - render_text(fb, 0, 0, &self.text, self.font_size, rgb(255, 255, 255), 0); - } - } - - pub fn clear(&mut self) { - self.dirty = true; - self.text.clear(); - } -} - -pub static SERIAL_CONSOLE: Mutex> = Mutex::new(None); - -pub fn init_serial_console() { - *SERIAL_CONSOLE.lock() = Some(SerialConsole::new()); -} - -pub fn with_serial_console(f: F) { - safe_lock(|| { - let mut guard = SERIAL_CONSOLE.lock(); - if let Some(sc) = guard.as_mut() { - f(sc); - } - }); -} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 0caefba..e8c84de 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -5,7 +5,7 @@ extern crate alloc; -use core::fmt::Write; +use core::fmt::{self, Write}; use core::sync::atomic::{AtomicU64, Ordering}; use limine::{ @@ -20,10 +20,8 @@ use limine::{ use crate::arch::aarch64::paging::AArchPageTable; #[cfg(target_arch = "x86_64")] use crate::arch::arch::KERNEL_MAPPER; -#[cfg(target_arch = "aarch64")] -use crate::driver::io::virtio::input::init_keyboard; -#[cfg(target_arch = "aarch64")] -use crate::util::U64Buf; +use crate::driver::io::input::init_input; + #[cfg(target_arch = "aarch64")] use aarch64_cpu::registers::{DAIF, Writeable}; @@ -33,12 +31,9 @@ use crate::driver::io::ps2::init_keyboard; use crate::arch::arch::{HHDM_OFFSET, infinite_idle, init, kernel_crash, serial_print}; use crate::driver::{ elf::loader::run_elf, - graphics::{ - framebuffer::{init_framebuffer, with_framebuffer}, - rgb, - }, + framebuffer::{init_framebuffer, with_framebuffer}, io::fs::assets::INIT_ELF, - serial::{ConsoleWriter, init_serial_console, with_serial_console}, + // serial::{ConsoleWriter, init_serial_console, with_serial_console}, timer::TIMER, }; @@ -105,18 +100,19 @@ macro_rules! println { }; } +pub struct SerialWriter {} + +impl Write for SerialWriter { + fn write_str(&mut self, s: &str) -> fmt::Result { + serial_print(s); + Ok(()) + } +} + #[doc(hidden)] pub fn _print(args: core::fmt::Arguments) { - with_framebuffer(|fb| { - with_serial_console(|console| { - let mut writer = ConsoleWriter { - fb, - console, - should_center: false, - }; - let _ = writer.write_fmt(args); - }); - }); + let mut writer = SerialWriter {}; + let _ = writer.write_fmt(args); } #[unsafe(no_mangle)] @@ -189,9 +185,8 @@ pub unsafe extern "C" fn kernel_main_aarch64(mapper: &mut AArchPageTable) -> ! { } else { panic!("no framebuffers found"); } - init_serial_console(); - init_keyboard(); + init_input(); if let Some(date_at_boot_response) = DATE_AT_BOOT_REQUEST.get_response() { TIMER.set_date_at_boot(date_at_boot_response.timestamp().as_secs()); @@ -234,9 +229,8 @@ pub unsafe fn kernel_main_x86_64() -> ! { } } - init_serial_console(); - init_keyboard(); + init_input(); #[allow(static_mut_refs)] unsafe { @@ -294,22 +288,22 @@ fn rust_panic(_info: &core::panic::PanicInfo) -> ! { }; serial_print(msg); serial_print("\n"); - with_framebuffer(|mut fb| { - fb.clear(rgb(180, 0, 0)); + // with_framebuffer(|mut fb| { + // fb.clear(rgb(180, 0, 0)); - with_serial_console(|console| { - console.clear(); + // with_serial_console(|console| { + // console.clear(); - let mut writer = ConsoleWriter { - fb: &mut fb, - console, - should_center: true, - }; + // let mut writer = ConsoleWriter { + // fb: &mut fb, + // console, + // should_center: true, + // }; - let _ = writer.write_str("KERNEL PANIC\n\n"); - let _ = writer.write_fmt(core::format_args!("{}", _info)); - }); - }); + // let _ = writer.write_str("KERNEL PANIC\n\n"); + // let _ = writer.write_fmt(core::format_args!("{}", _info)); + // }); + // }); infinite_idle(); } diff --git a/kernel/src/task/process.rs b/kernel/src/task/process.rs index 1528185..322189f 100644 --- a/kernel/src/task/process.rs +++ b/kernel/src/task/process.rs @@ -3,8 +3,8 @@ use core::sync::atomic::Ordering; use alloc::vec::Vec; use crate::{ - arch::arch::GLOBAL_TICK_COUNT, driver::io::keyboard::KeyboardEvent, - mm::address_space::AddressSpace, task::context::UserContext, + arch::arch::GLOBAL_TICK_COUNT, driver::io::input::InputEvent, mm::address_space::AddressSpace, + task::context::UserContext, }; pub enum ProcessState { @@ -27,7 +27,7 @@ pub struct Process { pub kernel_stack_top: u64, pub heap_base: u64, pub heap_end: u64, - pub kbd_buffer: Vec, + pub input_buffer: Vec, pub address_space: Option, pub saved_ctx: Option, pub user_entry: u64, @@ -51,7 +51,7 @@ impl Process { heap_base, heap_end, last_switch_tick: GLOBAL_TICK_COUNT.load(Ordering::Relaxed), - kbd_buffer: Vec::new(), + input_buffer: Vec::new(), address_space: None, saved_ctx: None, user_entry, diff --git a/user/apps/doomgeneric b/user/apps/doomgeneric index c8cde8f..a04df50 160000 --- a/user/apps/doomgeneric +++ b/user/apps/doomgeneric @@ -1 +1 @@ -Subproject commit c8cde8fe456d3ef3b1d7ee1894952ea3119773d4 +Subproject commit a04df50195107be3f5c6f906505faf9adabff90e diff --git a/user/init b/user/init index 2c1ffa3..5ed48db 160000 --- a/user/init +++ b/user/init @@ -1 +1 @@ -Subproject commit 2c1ffa31d61358f68cd9d5a875df0c5332ca0114 +Subproject commit 5ed48dbd780a9c11de0dda933596a5bbb4a7e998 diff --git a/user/libxunil b/user/libxunil index a6448bc..7f9192f 160000 --- a/user/libxunil +++ b/user/libxunil @@ -1 +1 @@ -Subproject commit a6448bc1f25eebe051f4952ab0675ad7a7ecafb2 +Subproject commit 7f9192f4e8a57753da8c54829a9b6d36aa5851c9