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