diff --git a/.cargo/config.toml b/.cargo/config.toml index 0f4b13b..daa85e1 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,5 @@ [build] -target = "x86_64-kernel" +target = "x86_64-kernel.json" target-dir = "build/target" [unstable] diff --git a/.idea/FoundryOS.iml b/.idea/FoundryOS.iml index 158aa3e..4c628e5 100644 --- a/.idea/FoundryOS.iml +++ b/.idea/FoundryOS.iml @@ -4,6 +4,8 @@ + + diff --git a/docs/.obsidian/appearance.json b/docs/.obsidian/appearance.json index 9e26dfe..4eaf459 100644 --- a/docs/.obsidian/appearance.json +++ b/docs/.obsidian/appearance.json @@ -1 +1,3 @@ -{} \ No newline at end of file +{ + "cssTheme": "Dark Moss" +} \ No newline at end of file diff --git a/docs/.obsidian/workspace.json b/docs/.obsidian/workspace.json index bf6bc64..689237d 100644 --- a/docs/.obsidian/workspace.json +++ b/docs/.obsidian/workspace.json @@ -3,26 +3,6 @@ "id": "20da7b1c0adc4114", "type": "split", "children": [ - { - "id": "6bf1f87bf81a3031", - "type": "tabs", - "children": [ - { - "id": "add883d295e04659", - "type": "leaf", - "state": { - "type": "markdown", - "state": { - "file": "Planning & To-Dos.md", - "mode": "source", - "source": false - }, - "icon": "lucide-file", - "title": "Planning & To-Dos" - } - } - ] - }, { "id": "c178a2dff57ae0aa", "type": "tabs", @@ -34,7 +14,7 @@ "type": "markdown", "state": { "file": "Planning & To-Dos.md", - "mode": "preview", + "mode": "source", "source": false }, "icon": "lucide-file", @@ -73,7 +53,7 @@ "state": { "type": "search", "state": { - "query": "tag:#Threading", + "query": "", "matchingCase": false, "explainSearch": false, "collapseAll": false, @@ -94,12 +74,11 @@ "title": "Bookmarks" } } - ], - "currentTab": 1 + ] } ], "direction": "horizontal", - "width": 200 + "width": 307.5 }, "right": { "id": "baa2a8e61b737fa6", @@ -177,7 +156,8 @@ } ], "direction": "horizontal", - "width": 300 + "width": 300, + "collapsed": true }, "left-ribbon": { "hiddenItems": { @@ -185,11 +165,11 @@ "graph:Open graph view": false, "canvas:Create new canvas": false, "daily-notes:Open today's daily note": false, - "templates:Insert template": false, - "command-palette:Open command palette": false + "command-palette:Open command palette": false, + "templates:Insert template": false } }, - "active": "add883d295e04659", + "active": "6d395e6a4c72e1c8", "lastOpenFiles": [ "Usage/Building The Kernel.md", "Planning & To-Dos.md", diff --git a/docs/Planning & To-Dos.md b/docs/Planning & To-Dos.md index 2758021..ab30a64 100644 --- a/docs/Planning & To-Dos.md +++ b/docs/Planning & To-Dos.md @@ -1,3 +1,24 @@ +> [!todo] Testing +> - [ ] setup custom test frameworks (Use CrystalOS-V2 as a reference) +> - [ ] write a sub-crate for tests +> - [ ] implement several unit tests on things that we are likely to break often +> - [ ] setup Git CI/CD pipeline with testing +> - [ ] figure out how to run QEMU in the test environment +> - [ ] write a script to run tests +> - [ ] a release should only be published if all tests pass + +> [!todo] Allocator +> - [ ] learn about several allocator designs and decide on the optimal one +> - [ ] implementation +> - [ ] implement an allocate method +> - [ ] implement a deallocate method +> - [ ] set the global allocator +> - [ ] testing +> - [ ] write unit tests +> - [ ] many allocations +> - [ ] large allocations +> - [ ] allocating more memory than is available +> - [ ] pass unit tests > [!todo] Threading > - [ ] implement thread switching functionality diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index 7476eb6..31c4190 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -8,7 +8,6 @@ use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, S use spin::{Lazy, Mutex}; -use super::apic::enable_apic; use super::gdt; static IDT: Lazy = Lazy::new(|| { @@ -92,7 +91,7 @@ extern "x86-interrupt" fn double_fault_handler( } extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) { - use pc_keyboard::{HandleControl, Keyboard, ScancodeSet1, layouts}; + use pc_keyboard::{layouts, HandleControl, Keyboard, ScancodeSet1}; // use pc_keyboard::DecodedKey; use spin::Mutex; use x86_64::instructions::port::Port; @@ -125,13 +124,13 @@ extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFr } extern "x86-interrupt" fn page_fault_handler( - stack_frame: InterruptStackFrame, - error_code: PageFaultErrorCode, + _stack_frame: InterruptStackFrame, + _error_code: PageFaultErrorCode, ) { // serial_println!("Exception: Page Fault"); // serial_println!("Accessed Address: {:?}", Cr2::read()); // serial_println!("Error Code: {:?}", error_code); - // serial_println!("{:#?}", stack_frame); + // serial_println!("{:#?}", _stack_frame); if let Some(frame_allocator) = FRAME_ALLOCATOR.get() { let mut f = frame_allocator.lock(); diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 48d4c75..3a08569 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -79,7 +79,7 @@ pub fn boot() -> Result<(), &'static str> { print_log!(" Initialising Memory Subsystem... "); let physical_memory_offset = VirtAddr::new(*memmap::PHYSICAL_MEMORY_OFFSET); - let mut l4_table = memory::init_page_table(physical_memory_offset); + memory::init_page_table(physical_memory_offset); println_log!("[Success]"); print_log!(" Setting Up Page Table... "); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 7348d45..d5839dc 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -28,23 +28,9 @@ extern "C" fn kmain() -> ! { println!("Dimensions: {}x{} (px)", dimensions2.0, dimensions2.1); println!("Dimensions: {}x{} (chars)", dimensions.0, dimensions.1); - let vector = vec![0; 100]; - println!("vec 100 works"); - let vector2 = vec![0; 1000]; - println!("vec 1000 works"); - let vector3 = vec![0; 10000]; - println!("vec 10000 works"); - let vector4 = vec![vec![Colour::Black; 1000]; 1000]; - println!("vec 100000 works"); - let mut executor = Executor::new(); - - let mut v = Vec::with_capacity(1000 * 1000); - for i in 0..1000 * 1000 { - v.push(i); - } - println!("v.len(): {}", v.len()); - executor.spawn(Task::new(shell())); executor.run(); + + loop {} } diff --git a/libk/Cargo.toml b/libk/Cargo.toml index 9b9f99c..3809bb8 100644 --- a/libk/Cargo.toml +++ b/libk/Cargo.toml @@ -18,5 +18,5 @@ spin = "0.9.8" futures-util = { version = "0.3.31", default-features = false, features = [ "alloc", ] } -linked_list_allocator = "0.10.5" +linked_list_allocator = { version = "0.10.5", features = ["use_spin"] } libm = { path = "../libm" } diff --git a/libk/src/drivers/kalloc/allocator.rs b/libk/src/drivers/kalloc/allocator.rs index 5f8949b..086a8c0 100644 --- a/libk/src/drivers/kalloc/allocator.rs +++ b/libk/src/drivers/kalloc/allocator.rs @@ -1,15 +1,7 @@ use linked_list_allocator::LockedHeap; -use x86_64::{ - VirtAddr, - structures::paging::{ - FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB, - mapper::{MapToError, MapperFlushAll}, - }, -}; - -use crate::{ - drivers::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE}, - serial_print, serial_println, +use x86_64::structures::paging::{ + mapper::MapToError, + Size4KiB, }; /// We are currently using a linked list heap allocator which uses our underlying page allocator. @@ -24,46 +16,7 @@ pub const HEAP_SIZE: usize = 1024 * 1024 * 1024; /// Sets up the heap using the backing page frame allocator. pub fn init_heap() -> Result<(), MapToError> { - // let mut frame_allocator = if let Some(f) = FRAME_ALLOCATOR.get() { - // f.lock() - // } else { - // return Err(MapToError::FrameAllocationFailed); - // }; - - // let mut mapper = if let Some(m) = OFFSET_PAGE_TABLE.get() { - // m.lock() - // } else { - // return Err(MapToError::FrameAllocationFailed); - // }; - - // let range = { - // let heap_start = VirtAddr::new(HEAP_START as u64); - // let heap_end = heap_start + HEAP_SIZE as u64 - 1u64; - // let heap_start_page = Page::::containing_address(heap_start); - // let heap_end_page = Page::::containing_address(heap_end); - // Page::range_inclusive(heap_start_page, heap_end_page) - // }; - - // let usable_frames = frame_allocator.count_usable_frames(); - // serial_println!("usable frames: {}", usable_frames); - - // let mut i = 0; - // for page in range { - // i += 1; - // if i % 128 == 0 { - // serial_println!("allocated {} pages", i); - // } - // let frame = frame_allocator - // .allocate_frame() - // .ok_or(MapToError::FrameAllocationFailed)?; - // let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; - // unsafe { - // // IMPORTANT: make sure to flush the mapper!!!! - // let _ = mapper.map_to(page, frame, flags, &mut *frame_allocator)?; - // } - // } - - // MapperFlushAll::new().flush_all(); + // code to allocate frames is now done in the page fault interrupt handler! unsafe { ALLOCATOR.lock().init(HEAP_START as *mut u8, HEAP_SIZE); diff --git a/libk/src/drivers/memory.rs b/libk/src/drivers/memory.rs index 2e53a01..7a1e4ba 100644 --- a/libk/src/drivers/memory.rs +++ b/libk/src/drivers/memory.rs @@ -2,12 +2,12 @@ use limine::{memory_map::EntryType, response::MemoryMapResponse}; use spin::{Mutex, Once}; use x86_64::{ - PhysAddr, VirtAddr, - registers::control::Cr3, - structures::paging::{ - FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB, - page_table::FrameError, + registers::control::Cr3, structures::paging::{ + FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB + , }, + PhysAddr, + VirtAddr, }; pub static FRAME_ALLOCATOR: Once> = Once::new(); diff --git a/libk/src/std/ascii.rs b/libk/src/std/ascii.rs index c59deb8..1c17f34 100644 --- a/libk/src/std/ascii.rs +++ b/libk/src/std/ascii.rs @@ -1,5 +1,3 @@ -use alloc::vec::Vec; - use crate::{drivers::io::framebuffer::colour::Colour, resources::font::Font}; use super::{ diff --git a/libk/src/util/editor.rs b/libk/src/util/editor.rs index b172f47..065d4dc 100644 --- a/libk/src/util/editor.rs +++ b/libk/src/util/editor.rs @@ -44,53 +44,110 @@ impl<'a> Editor { let (width, height) = writer.font_size().into(); - let mut col = Self::PADDING; - let mut line = Self::PADDING; + let mut col = 0; + let mut line = 0; let mut scale = 1; for ch in self.buffer.chars() { if ch == '\n' { - line += scale * height; - col = Self::PADDING; + line += scale; + col = 0; scale = 1; continue; } - if width * scale + col > frame.dimensions().x() { - line += scale * height; - col = Self::PADDING; + if width * (col + 1) > frame.dimensions().x() - 2 * Self::PADDING { + line += scale; + col = 0; } - writer.render_glyph(&mut frame, Vec2::new(col, line), ch as u8, scale)?; - col += scale * width; + writer.render_glyph( + &mut frame, + Vec2::new(col * width + Self::PADDING, line * height + Self::PADDING), + ch as u8, + scale, + )?; + col += scale; } + writer.render_glyph( + &mut frame, + Vec2::new( + self.cursor_col * width + Self::PADDING, + self.cursor_line * height + Self::PADDING, + ), + b'_', + scale, + ); + Ok(frame) } + #[allow(unused_variables, dead_code, clippy::needless_pass_by_ref_mut)] fn get_lines(&self) -> Vec<&str> { - self.buffer.split('\n').collect::>(); - todo!() + self.buffer.split('\n').collect::>() } #[allow(unused_variables, dead_code, clippy::needless_pass_by_ref_mut)] fn move_cursor(&mut self, x: i32, y: i32) { - todo!() + self.cursor_line = self + .cursor_line + .checked_add_signed(y as isize) + .unwrap_or(self.cursor_line); + self.cursor_col = self + .cursor_col + .checked_add_signed(x as isize) + .unwrap_or(self.cursor_col); } #[allow(unused_variables, dead_code, clippy::needless_pass_by_ref_mut)] fn delete_char(&mut self) { - todo!() + let i = self.get_char_idx(); + self.buffer.remove(i); } #[allow(unused_variables, dead_code, clippy::needless_pass_by_ref_mut)] fn insert_char(&mut self, c: char) { - todo!() + let i = self.get_char_idx(); + self.buffer.insert(i, c); } #[allow(unused_variables, dead_code, clippy::needless_pass_by_ref_mut)] fn splitline(&mut self) { - todo!() + let i = self.get_char_idx(); + self.buffer.insert(i, '\n'); + } + + fn get_char_idx(&self) -> usize { + let frame = Frame::new(&self.window); + let writer = Writer::new(Font::default()); + let (width, _height) = writer.font_size().into(); + + let mut col = 0; + let mut line = 0; + let mut scale = 1; + + for (i, ch) in self.buffer.chars().enumerate() { + if ch == '\n' { + line += scale; + col = 0; + scale = 1; + continue; + } + + if width * (col + 1) > frame.dimensions().x() - 2 * Self::PADDING { + line += scale; + col = 0; + } + + if col == self.cursor_col && line == self.cursor_line { + return i; + } + + col += scale; + } + + 0 } } @@ -139,15 +196,19 @@ impl Application for Editor { } } KeyStroke::Left => { + serial_println!("Left\n"); self.move_cursor(-1, 0); } KeyStroke::Right => { + serial_println!("Right\n"); self.move_cursor(1, 0); } KeyStroke::Up => { + serial_println!("Up\n"); self.move_cursor(0, -1); } KeyStroke::Down => { + serial_println!("Down\n"); self.move_cursor(0, 1); } KeyStroke::None => {} diff --git a/libm/rust-toolchain.toml b/libm/rust-toolchain.toml new file mode 100644 index 0000000..77f6ca9 --- /dev/null +++ b/libm/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly" +targets = ["x86_64-linux-gnu"] \ No newline at end of file diff --git a/kernel/x86_64-kernel.json b/x86_64-kernel.json similarity index 100% rename from kernel/x86_64-kernel.json rename to x86_64-kernel.json