From d2466a1293b24db63e24877345c78e878d2b8ceb Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 18 Jul 2024 18:18:12 +0200 Subject: [PATCH 01/27] interrrupts..... --- shell/Cargo.toml | 1 + shell/src/interrupts.rs | 18 ++++++++++++++++++ shell/src/lib.rs | 16 ++++++++++++++++ shell/src/main.rs | 8 ++++++-- 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 shell/src/interrupts.rs create mode 100644 shell/src/lib.rs diff --git a/shell/Cargo.toml b/shell/Cargo.toml index d1d9fd7..4ee1090 100644 --- a/shell/Cargo.toml +++ b/shell/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" bootloader = "0.9" volatile = "0.2.6" spin = "0.5.2" +x86_64 = "0.14.2" [dependencies.lazy_static] version = "1.0" diff --git a/shell/src/interrupts.rs b/shell/src/interrupts.rs new file mode 100644 index 0000000..82790ac --- /dev/null +++ b/shell/src/interrupts.rs @@ -0,0 +1,18 @@ +use crate::println; +use lazy_static::lazy_static; +use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; + +lazy_static! { + static ref IDT: InterruptDescriptorTable = { + let mut idt = InterruptDescriptorTable::new(); + idt.breakpoint.set_handler_fn(breakpoint_handler); + idt + }; +} +pub fn init_idt() { + IDT.load(); +} + +extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) { + println!("EX: BREAKPOINT\n{:#?}", stack_frame); +} diff --git a/shell/src/lib.rs b/shell/src/lib.rs new file mode 100644 index 0000000..ad841aa --- /dev/null +++ b/shell/src/lib.rs @@ -0,0 +1,16 @@ +#![no_std] +#![no_main] +#![feature(abi_x86_interrupt)] + +pub mod interrupts; +pub mod vga_buffer; + +pub fn init() { + interrupts::init_idt(); +} + +#[no_mangle] +pub extern "C" fn _start() -> ! { + init(); + loop {} +} diff --git a/shell/src/main.rs b/shell/src/main.rs index 27e99b1..219488a 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -1,10 +1,10 @@ -#![no_main] #![no_std] +#![no_main] #![allow(clippy::empty_loop)] use core::panic::PanicInfo; -mod vga_buffer; +use hlshell::println; #[panic_handler] fn panic(info: &PanicInfo) -> ! { @@ -16,5 +16,9 @@ fn panic(info: &PanicInfo) -> ! { pub extern "C" fn _start() -> ! { println!("HighlightOS Shell v0.3.0\n\nhls < "); + x86_64::instructions::interrupts::int3(); //invoke a new interruption + + println!("crash??"); + loop {} } From ce715f13781202251a7996c8dcde6a680aa239b3 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 18 Jul 2024 18:24:31 +0200 Subject: [PATCH 02/27] fixed --- shell/src/lib.rs | 6 ------ shell/src/main.rs | 4 +++- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/shell/src/lib.rs b/shell/src/lib.rs index ad841aa..4223f2e 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs @@ -8,9 +8,3 @@ pub mod vga_buffer; pub fn init() { interrupts::init_idt(); } - -#[no_mangle] -pub extern "C" fn _start() -> ! { - init(); - loop {} -} diff --git a/shell/src/main.rs b/shell/src/main.rs index 219488a..883fe3b 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -16,9 +16,11 @@ fn panic(info: &PanicInfo) -> ! { pub extern "C" fn _start() -> ! { println!("HighlightOS Shell v0.3.0\n\nhls < "); + hlshell::init(); + x86_64::instructions::interrupts::int3(); //invoke a new interruption - println!("crash??"); + println!("WORKS."); loop {} } From 507134eed60fcf82e950c17a7eb4ce2c29dd1b27 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 18 Jul 2024 18:48:07 +0200 Subject: [PATCH 03/27] double faults --- shell/src/gdt.rs | 53 +++++++++++++++++++++++++++++++++++++++++ shell/src/interrupts.rs | 15 +++++++++++- shell/src/lib.rs | 2 ++ shell/src/main.rs | 10 +++++++- 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 shell/src/gdt.rs diff --git a/shell/src/gdt.rs b/shell/src/gdt.rs new file mode 100644 index 0000000..47b8d0c --- /dev/null +++ b/shell/src/gdt.rs @@ -0,0 +1,53 @@ +use lazy_static::lazy_static; +use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector}; +use x86_64::structures::tss::TaskStateSegment; +use x86_64::VirtAddr; + +pub const DOUBLE_FAULT_IST_IDX: u16 = 0; + +lazy_static! { + static ref TSS: TaskStateSegment = { + let mut tss = TaskStateSegment::new(); + tss.interrupt_stack_table[DOUBLE_FAULT_IST_IDX as usize] = { + const STACK_SIZE: usize = 4096 * 5; + static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; + + let stack_start = VirtAddr::from_ptr(unsafe { &STACK }); + let stack_end = stack_start + STACK_SIZE; + stack_end + }; + tss + }; +} + +lazy_static! { + static ref GDT: (GlobalDescriptorTable, Selectors) = { + let mut gdt = GlobalDescriptorTable::new(); + let code_selector = gdt.add_entry(Descriptor::kernel_code_segment()); + let tss_selector = gdt.add_entry(Descriptor::tss_segment(&TSS)); + ( + gdt, + Selectors { + code_selector, + tss_selector, + }, + ) + }; +} + +pub fn init() { + use x86_64::instructions::segmentation::{Segment, CS}; + use x86_64::instructions::tables::load_tss; + + GDT.0.load(); + + unsafe { + CS::set_reg(GDT.1.code_selector); + load_tss(GDT.1.tss_selector); + } +} + +struct Selectors { + code_selector: SegmentSelector, + tss_selector: SegmentSelector, +} diff --git a/shell/src/interrupts.rs b/shell/src/interrupts.rs index 82790ac..5755748 100644 --- a/shell/src/interrupts.rs +++ b/shell/src/interrupts.rs @@ -1,3 +1,4 @@ +use crate::gdt; use crate::println; use lazy_static::lazy_static; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; @@ -6,6 +7,11 @@ lazy_static! { static ref IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); idt.breakpoint.set_handler_fn(breakpoint_handler); + unsafe { + idt.double_fault + .set_handler_fn(double_fault_handler) + .set_stack_index(gdt::DOUBLE_FAULT_IST_IDX); + } idt }; } @@ -14,5 +20,12 @@ pub fn init_idt() { } extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) { - println!("EX: BREAKPOINT\n{:#?}", stack_frame); + println!("\nEX: BREAKPOINT\n{:#?}\n", stack_frame); +} + +extern "x86-interrupt" fn double_fault_handler( + stack_frame: InterruptStackFrame, + _error_code: u64, +) -> ! { + panic!("\nEX: DOUBLE FAULT\n{:#?}\n", stack_frame); } diff --git a/shell/src/lib.rs b/shell/src/lib.rs index 4223f2e..28f3d67 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs @@ -2,9 +2,11 @@ #![no_main] #![feature(abi_x86_interrupt)] +pub mod gdt; pub mod interrupts; pub mod vga_buffer; pub fn init() { interrupts::init_idt(); + gdt::init(); } diff --git a/shell/src/main.rs b/shell/src/main.rs index 883fe3b..7063cca 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -18,7 +18,15 @@ pub extern "C" fn _start() -> ! { hlshell::init(); - x86_64::instructions::interrupts::int3(); //invoke a new interruption + fn stack_overflow() { + stack_overflow(); + } + + stack_overflow(); + + unsafe { + *(0xdeadbeef as *mut u8) = 42; // trigger a page fault + }; println!("WORKS."); From 8d5416ab42ff25b78c15bbca7929602760a6171e Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 18 Jul 2024 18:53:35 +0200 Subject: [PATCH 04/27] Implement serial --- shell/Cargo.toml | 1 + shell/src/serial.rs | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 shell/src/serial.rs diff --git a/shell/Cargo.toml b/shell/Cargo.toml index 4ee1090..31ec16d 100644 --- a/shell/Cargo.toml +++ b/shell/Cargo.toml @@ -8,6 +8,7 @@ bootloader = "0.9" volatile = "0.2.6" spin = "0.5.2" x86_64 = "0.14.2" +uart_16550 = "0.2.0" [dependencies.lazy_static] version = "1.0" diff --git a/shell/src/serial.rs b/shell/src/serial.rs new file mode 100644 index 0000000..e8807df --- /dev/null +++ b/shell/src/serial.rs @@ -0,0 +1,37 @@ +use lazy_static::lazy_static; +use spin::Mutex; +use uart_16550::SerialPort; + +lazy_static! { + pub static ref SERIAL1: Mutex = { + let mut serial_port = unsafe { SerialPort::new(0x3F8) }; + serial_port.init(); + Mutex::new(serial_port) + }; +} + +#[doc(hidden)] +pub fn _print(args: ::core::fmt::Arguments) { + use core::fmt::Write; + SERIAL1 + .lock() + .write_fmt(args) + .expect("Printing to serial failed"); +} + +/// Prints to the host through the serial interface. +#[macro_export] +macro_rules! serial_print { + ($($arg:tt)*) => { + $crate::serial::_print(format_args!($($arg)*)); + }; +} + +/// Prints to the host through the serial interface, appending a newline. +#[macro_export] +macro_rules! serial_println { + () => ($crate::serial_print!("\n")); + ($fmt:expr) => ($crate::serial_print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => ($crate::serial_print!( + concat!($fmt, "\n"), $($arg)*)); +} From a39e524c29265f9a2ca1d6e81ffde5b4b7e0d8f2 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 18 Jul 2024 18:56:30 +0200 Subject: [PATCH 05/27] cargo fixes --- shell/src/gdt.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/src/gdt.rs b/shell/src/gdt.rs index 47b8d0c..1b66300 100644 --- a/shell/src/gdt.rs +++ b/shell/src/gdt.rs @@ -1,3 +1,4 @@ +use core::ptr::addr_of; use lazy_static::lazy_static; use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector}; use x86_64::structures::tss::TaskStateSegment; @@ -12,9 +13,8 @@ lazy_static! { const STACK_SIZE: usize = 4096 * 5; static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; - let stack_start = VirtAddr::from_ptr(unsafe { &STACK }); - let stack_end = stack_start + STACK_SIZE; - stack_end + let stack_start = VirtAddr::from_ptr(unsafe { addr_of!(STACK) }); + stack_start + STACK_SIZE }; tss }; From c07fec82c27975d3b6482bad60d16ef3843f0b7a Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 18 Jul 2024 19:05:35 +0200 Subject: [PATCH 06/27] add author --- shell/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/Cargo.toml b/shell/Cargo.toml index 31ec16d..b918d28 100644 --- a/shell/Cargo.toml +++ b/shell/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "hlshell" version = "0.3.0" +authors = ["Adam Perkowski "] edition = "2021" [dependencies] From dccd57fda8c15c42b28e660420b3c1451899cfa3 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 18 Jul 2024 19:07:35 +0200 Subject: [PATCH 07/27] todo --- shell/Cargo.toml | 1 + shell/TODO | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 shell/TODO diff --git a/shell/Cargo.toml b/shell/Cargo.toml index b918d28..a3c716a 100644 --- a/shell/Cargo.toml +++ b/shell/Cargo.toml @@ -10,6 +10,7 @@ volatile = "0.2.6" spin = "0.5.2" x86_64 = "0.14.2" uart_16550 = "0.2.0" +pic8259 = "0.10.1" [dependencies.lazy_static] version = "1.0" diff --git a/shell/TODO b/shell/TODO new file mode 100644 index 0000000..2ca0fc2 --- /dev/null +++ b/shell/TODO @@ -0,0 +1,2 @@ +- RTC +- update dependencies From 465027562e733812c82edfb564fa1183c9f3f4e4 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 18 Jul 2024 19:14:58 +0200 Subject: [PATCH 08/27] CHECKPOINT --- shell/src/interrupts.rs | 9 +++++++++ shell/src/lib.rs | 4 +++- shell/src/main.rs | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/shell/src/interrupts.rs b/shell/src/interrupts.rs index 5755748..91e27a7 100644 --- a/shell/src/interrupts.rs +++ b/shell/src/interrupts.rs @@ -1,6 +1,8 @@ use crate::gdt; use crate::println; use lazy_static::lazy_static; +use pic8259::ChainedPics; +use spin; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; lazy_static! { @@ -15,6 +17,13 @@ lazy_static! { idt }; } + +pub const PIC_0_OFFSET: u8 = 32; +pub const PIC_1_OFFSET: u8 = PIC_0_OFFSET + 8; + +pub static PICS: spin::Mutex = + spin::Mutex::new(unsafe { ChainedPics::new(PIC_0_OFFSET, PIC_1_OFFSET) }); + pub fn init_idt() { IDT.load(); } diff --git a/shell/src/lib.rs b/shell/src/lib.rs index 28f3d67..dd28218 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs @@ -7,6 +7,8 @@ pub mod interrupts; pub mod vga_buffer; pub fn init() { - interrupts::init_idt(); gdt::init(); + interrupts::init_idt(); + unsafe { interrupts::PICS.lock().initialize() }; + x86_64::instructions::interrupts::enable(); } diff --git a/shell/src/main.rs b/shell/src/main.rs index 7063cca..2d34ea9 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -24,9 +24,9 @@ pub extern "C" fn _start() -> ! { stack_overflow(); - unsafe { + /* unsafe { *(0xdeadbeef as *mut u8) = 42; // trigger a page fault - }; + }; */ println!("WORKS."); From d9262541a64f4af9f89cee24d2884a72cec7ebd8 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 18 Jul 2024 19:42:05 +0200 Subject: [PATCH 09/27] Hardware Interrupts Implemented --- shell/src/interrupts.rs | 27 +++++++++++++++++++++++++++ shell/src/lib.rs | 6 ++++++ shell/src/main.rs | 15 +++++++-------- shell/src/serial.rs | 12 ++++++++---- shell/src/vga_buffer.rs | 6 +++++- 5 files changed, 53 insertions(+), 13 deletions(-) diff --git a/shell/src/interrupts.rs b/shell/src/interrupts.rs index 91e27a7..64042f9 100644 --- a/shell/src/interrupts.rs +++ b/shell/src/interrupts.rs @@ -1,4 +1,5 @@ use crate::gdt; +use crate::print; use crate::println; use lazy_static::lazy_static; use pic8259::ChainedPics; @@ -14,6 +15,7 @@ lazy_static! { .set_handler_fn(double_fault_handler) .set_stack_index(gdt::DOUBLE_FAULT_IST_IDX); } + idt[InterruptIndex::Timer.as_usize()].set_handler_fn(timer_interrupt_handler); idt }; } @@ -24,6 +26,22 @@ pub const PIC_1_OFFSET: u8 = PIC_0_OFFSET + 8; pub static PICS: spin::Mutex = spin::Mutex::new(unsafe { ChainedPics::new(PIC_0_OFFSET, PIC_1_OFFSET) }); +#[derive(Debug, Clone, Copy)] +#[repr(u8)] +pub enum InterruptIndex { + Timer = PIC_0_OFFSET, +} + +impl InterruptIndex { + fn as_u8(self) -> u8 { + self as u8 + } + + fn as_usize(self) -> usize { + usize::from(self.as_u8()) + } +} + pub fn init_idt() { IDT.load(); } @@ -38,3 +56,12 @@ extern "x86-interrupt" fn double_fault_handler( ) -> ! { panic!("\nEX: DOUBLE FAULT\n{:#?}\n", stack_frame); } + +extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) { + print!("."); + + unsafe { + PICS.lock() + .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); + } +} diff --git a/shell/src/lib.rs b/shell/src/lib.rs index dd28218..31e90ab 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs @@ -12,3 +12,9 @@ pub fn init() { unsafe { interrupts::PICS.lock().initialize() }; x86_64::instructions::interrupts::enable(); } + +pub fn hlt_loop() -> ! { + loop { + x86_64::instructions::hlt(); + } +} diff --git a/shell/src/main.rs b/shell/src/main.rs index 2d34ea9..38904ec 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -4,7 +4,7 @@ use core::panic::PanicInfo; -use hlshell::println; +use hlshell::{print, println}; #[panic_handler] fn panic(info: &PanicInfo) -> ! { @@ -14,21 +14,20 @@ fn panic(info: &PanicInfo) -> ! { #[no_mangle] pub extern "C" fn _start() -> ! { - println!("HighlightOS Shell v0.3.0\n\nhls < "); - hlshell::init(); - fn stack_overflow() { + print!("HighlightOS Shell v0.3.0\n\nhls < "); + + /* fn stack_overflow() { stack_overflow(); } - stack_overflow(); + stack_overflow(); */ /* unsafe { *(0xdeadbeef as *mut u8) = 42; // trigger a page fault }; */ - println!("WORKS."); - - loop {} + // loop {} + hlshell::hlt_loop(); } diff --git a/shell/src/serial.rs b/shell/src/serial.rs index e8807df..6fb62c8 100644 --- a/shell/src/serial.rs +++ b/shell/src/serial.rs @@ -13,10 +13,14 @@ lazy_static! { #[doc(hidden)] pub fn _print(args: ::core::fmt::Arguments) { use core::fmt::Write; - SERIAL1 - .lock() - .write_fmt(args) - .expect("Printing to serial failed"); + use x86_64::instructions::interrupts; + + interrupts::without_interrupts(|| { + SERIAL1 + .lock() + .write_fmt(args) + .expect("Printing to serial failed"); + }); } /// Prints to the host through the serial interface. diff --git a/shell/src/vga_buffer.rs b/shell/src/vga_buffer.rs index 0cb9f83..053d03d 100644 --- a/shell/src/vga_buffer.rs +++ b/shell/src/vga_buffer.rs @@ -138,5 +138,9 @@ macro_rules! println { #[doc(hidden)] pub fn _print(args: fmt::Arguments) { use core::fmt::Write; - WRITER.lock().write_fmt(args).unwrap(); + use x86_64::instructions::interrupts; + + interrupts::without_interrupts(|| { + WRITER.lock().write_fmt(args).unwrap(); + }); } From 30ad34db0bfcce3ea4b1d2870254094b2729a347 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 18 Jul 2024 19:58:07 +0200 Subject: [PATCH 10/27] Keyboard Input --- shell/Cargo.toml | 1 + shell/src/interrupts.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/shell/Cargo.toml b/shell/Cargo.toml index a3c716a..5b4791e 100644 --- a/shell/Cargo.toml +++ b/shell/Cargo.toml @@ -11,6 +11,7 @@ spin = "0.5.2" x86_64 = "0.14.2" uart_16550 = "0.2.0" pic8259 = "0.10.1" +pc-keyboard = "0.7.0" [dependencies.lazy_static] version = "1.0" diff --git a/shell/src/interrupts.rs b/shell/src/interrupts.rs index 64042f9..97c7ae1 100644 --- a/shell/src/interrupts.rs +++ b/shell/src/interrupts.rs @@ -16,6 +16,7 @@ lazy_static! { .set_stack_index(gdt::DOUBLE_FAULT_IST_IDX); } idt[InterruptIndex::Timer.as_usize()].set_handler_fn(timer_interrupt_handler); + idt[InterruptIndex::Keyboard.as_usize()].set_handler_fn(keyboard_interrupt_handler); idt }; } @@ -30,6 +31,7 @@ pub static PICS: spin::Mutex = #[repr(u8)] pub enum InterruptIndex { Timer = PIC_0_OFFSET, + Keyboard, } impl InterruptIndex { @@ -58,6 +60,7 @@ extern "x86-interrupt" fn double_fault_handler( } extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) { + #[cfg(debug_assertions)] print!("."); unsafe { @@ -65,3 +68,36 @@ extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFr .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); } } + +extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) { + use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1}; + use spin::Mutex; + use x86_64::instructions::port::Port; + + lazy_static! { + static ref KEYBOARD: Mutex> = + Mutex::new(Keyboard::new( + ScancodeSet1::new(), + layouts::Us104Key, + HandleControl::Ignore + )); + } + + let mut keyboard = KEYBOARD.lock(); + let mut port = Port::new(0x60); + + let scancode: u8 = unsafe { port.read() }; + if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { + if let Some(key) = keyboard.process_keyevent(key_event) { + match key { + DecodedKey::Unicode(character) => print!("{}", character), + DecodedKey::RawKey(key) => print!("{:?}", key), + } + } + } + + unsafe { + PICS.lock() + .notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8()); + } +} From 9ffe502a4003fef2b4e582c33495ab64ed4517a2 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 00:28:21 +0200 Subject: [PATCH 11/27] Add page fault handling --- shell/src/interrupts.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/shell/src/interrupts.rs b/shell/src/interrupts.rs index 97c7ae1..94d725e 100644 --- a/shell/src/interrupts.rs +++ b/shell/src/interrupts.rs @@ -1,22 +1,30 @@ use crate::gdt; +use crate::hlt_loop; use crate::print; use crate::println; use lazy_static::lazy_static; use pic8259::ChainedPics; use spin; +use x86_64::structures::idt::PageFaultErrorCode; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; lazy_static! { static ref IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); + idt.breakpoint.set_handler_fn(breakpoint_handler); + unsafe { idt.double_fault .set_handler_fn(double_fault_handler) .set_stack_index(gdt::DOUBLE_FAULT_IST_IDX); } + + idt.page_fault.set_handler_fn(page_fault_handler); + idt[InterruptIndex::Timer.as_usize()].set_handler_fn(timer_interrupt_handler); idt[InterruptIndex::Keyboard.as_usize()].set_handler_fn(keyboard_interrupt_handler); + idt }; } @@ -101,3 +109,19 @@ extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStac .notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8()); } } + +extern "x86-interrupt" fn page_fault_handler( + stack_frame: InterruptStackFrame, + error_code: PageFaultErrorCode, +) { + use x86_64::registers::control::Cr2; + + println!( + "\nEX: PAGE FAULT\nAccessed address: {:?}\nError code: {:?}\n\n{:#?}\n", + Cr2::read(), + error_code, + stack_frame + ); + + hlt_loop(); +} From e473225c5800eaee835af8fb35175ac65aa8518d Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 00:58:58 +0200 Subject: [PATCH 12/27] Accessing tables --- shell/Cargo.toml | 5 ++++- shell/src/interrupts.rs | 3 --- shell/src/lib.rs | 1 + shell/src/main.rs | 50 ++++++++++++++++++++++++++++------------- shell/src/mem.rs | 14 ++++++++++++ 5 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 shell/src/mem.rs diff --git a/shell/Cargo.toml b/shell/Cargo.toml index 5b4791e..f958f40 100644 --- a/shell/Cargo.toml +++ b/shell/Cargo.toml @@ -5,7 +5,6 @@ authors = ["Adam Perkowski "] edition = "2021" [dependencies] -bootloader = "0.9" volatile = "0.2.6" spin = "0.5.2" x86_64 = "0.14.2" @@ -13,6 +12,10 @@ uart_16550 = "0.2.0" pic8259 = "0.10.1" pc-keyboard = "0.7.0" +[dependencies.bootloader] +version = "0.9" +features = ["map_physical_memory"] + [dependencies.lazy_static] version = "1.0" features = ["spin_no_std"] diff --git a/shell/src/interrupts.rs b/shell/src/interrupts.rs index 94d725e..bcb4c25 100644 --- a/shell/src/interrupts.rs +++ b/shell/src/interrupts.rs @@ -68,9 +68,6 @@ extern "x86-interrupt" fn double_fault_handler( } extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) { - #[cfg(debug_assertions)] - print!("."); - unsafe { PICS.lock() .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); diff --git a/shell/src/lib.rs b/shell/src/lib.rs index 31e90ab..4f2265b 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs @@ -4,6 +4,7 @@ pub mod gdt; pub mod interrupts; +pub mod mem; pub mod vga_buffer; pub fn init() { diff --git a/shell/src/main.rs b/shell/src/main.rs index 38904ec..cada09e 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -2,32 +2,50 @@ #![no_main] #![allow(clippy::empty_loop)] +use bootloader::{entry_point, BootInfo}; use core::panic::PanicInfo; +use x86_64::structures::paging::PageTable; use hlshell::{print, println}; -#[panic_handler] -fn panic(info: &PanicInfo) -> ! { - println!("{}", info); - loop {} -} +entry_point!(kernel_main); + +fn kernel_main(boot_info: &'static BootInfo) -> ! { + use hlshell::mem::active_lvl_4_table; + use x86_64::VirtAddr; + + #[cfg(debug_assertions)] + println!("Initializing..."); -#[no_mangle] -pub extern "C" fn _start() -> ! { hlshell::init(); - print!("HighlightOS Shell v0.3.0\n\nhls < "); + let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); + let l4_table = unsafe { active_lvl_4_table(phys_mem_offset) }; - /* fn stack_overflow() { - stack_overflow(); - } + for (i, entry) in l4_table.iter().enumerate() { + if !entry.is_unused() { + println!("L4 entry | {} | {:?}", i, entry); - stack_overflow(); */ + let phys = entry.frame().unwrap().start_address(); + let virt = phys.as_u64() + boot_info.physical_memory_offset; + let ptr = VirtAddr::new(virt).as_mut_ptr(); + let l3_table: &PageTable = unsafe { &*ptr }; - /* unsafe { - *(0xdeadbeef as *mut u8) = 42; // trigger a page fault - }; */ + for (i, entry) in l3_table.iter().enumerate() { + if !entry.is_unused() { + println!(" | L3 entry| {} | {:?}", i, entry); + } + } + } + } + + print!("HighlightOS Shell v0.3.0\n\nhls < "); - // loop {} hlshell::hlt_loop(); } + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + println!("{}", info); + loop {} +} diff --git a/shell/src/mem.rs b/shell/src/mem.rs new file mode 100644 index 0000000..3355c7e --- /dev/null +++ b/shell/src/mem.rs @@ -0,0 +1,14 @@ +use x86_64::{structures::paging::PageTable, VirtAddr}; + +// Returns a mutable reference to the active level 4 table. +pub unsafe fn active_lvl_4_table(ph_memory_offset: VirtAddr) -> &'static mut PageTable { + use x86_64::registers::control::Cr3; + + let (lvl_4_table_frame, _) = Cr3::read(); + + let phys = lvl_4_table_frame.start_address(); + let virt = ph_memory_offset + phys.as_u64(); + let page_table_ptr: *mut PageTable = virt.as_mut_ptr(); + + &mut *page_table_ptr // unsafe return +} From f507d8761d9207c2431344e48040f4da0d74bbaf Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 01:00:04 +0200 Subject: [PATCH 13/27] move shell to res --- shell/src/{ => res}/commands.rs | 0 shell/src/{ => res}/shell.rs | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename shell/src/{ => res}/commands.rs (100%) rename shell/src/{ => res}/shell.rs (100%) diff --git a/shell/src/commands.rs b/shell/src/res/commands.rs similarity index 100% rename from shell/src/commands.rs rename to shell/src/res/commands.rs diff --git a/shell/src/shell.rs b/shell/src/res/shell.rs similarity index 100% rename from shell/src/shell.rs rename to shell/src/res/shell.rs From 8087d68b26f2d9b326cc9ee46bb04cbed95c66c0 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 01:35:18 +0200 Subject: [PATCH 14/27] Everything works --- shell/TODO | 1 + shell/src/main.rs | 36 +++++++++--------------- shell/src/mem.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 82 insertions(+), 25 deletions(-) diff --git a/shell/TODO b/shell/TODO index 2ca0fc2..0e6b37c 100644 --- a/shell/TODO +++ b/shell/TODO @@ -1,2 +1,3 @@ - RTC - update dependencies +- add debug commands that exist only in debug build diff --git a/shell/src/main.rs b/shell/src/main.rs index cada09e..a826743 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -11,35 +11,25 @@ use hlshell::{print, println}; entry_point!(kernel_main); fn kernel_main(boot_info: &'static BootInfo) -> ! { - use hlshell::mem::active_lvl_4_table; - use x86_64::VirtAddr; + use hlshell::mem; + use x86_64::{structures::paging::Page, VirtAddr}; #[cfg(debug_assertions)] - println!("Initializing..."); + println!("Initializing...\n"); hlshell::init(); let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); - let l4_table = unsafe { active_lvl_4_table(phys_mem_offset) }; - - for (i, entry) in l4_table.iter().enumerate() { - if !entry.is_unused() { - println!("L4 entry | {} | {:?}", i, entry); - - let phys = entry.frame().unwrap().start_address(); - let virt = phys.as_u64() + boot_info.physical_memory_offset; - let ptr = VirtAddr::new(virt).as_mut_ptr(); - let l3_table: &PageTable = unsafe { &*ptr }; - - for (i, entry) in l3_table.iter().enumerate() { - if !entry.is_unused() { - println!(" | L3 entry| {} | {:?}", i, entry); - } - } - } - } - - print!("HighlightOS Shell v0.3.0\n\nhls < "); + let mut mapper = unsafe { mem::init(phys_mem_offset) }; + let mut frame_allocator = mem::EmptyFrameAllocator; + + let page = Page::containing_address(VirtAddr::new(0)); + mem::create_example_mapping(page, &mut mapper, &mut frame_allocator); + + let page_ptr: *mut u64 = page.start_address().as_mut_ptr(); + unsafe { page_ptr.offset(400).write_volatile(0x_f021_f077_f065_f04e) }; + + print!("\nHighlightOS Shell v0.3.0\n\nhls < "); hlshell::hlt_loop(); } diff --git a/shell/src/mem.rs b/shell/src/mem.rs index 3355c7e..9119fe5 100644 --- a/shell/src/mem.rs +++ b/shell/src/mem.rs @@ -1,7 +1,18 @@ -use x86_64::{structures::paging::PageTable, VirtAddr}; +use bootloader::bootinfo::{MemoryMap, MemoryRegionType}; +use x86_64::{ + structures::paging::{ + FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB, + }, + PhysAddr, VirtAddr, +}; + +pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> { + let lvl_4_table = active_lvl_4_table(physical_memory_offset); + OffsetPageTable::new(lvl_4_table, physical_memory_offset) +} // Returns a mutable reference to the active level 4 table. -pub unsafe fn active_lvl_4_table(ph_memory_offset: VirtAddr) -> &'static mut PageTable { +unsafe fn active_lvl_4_table(ph_memory_offset: VirtAddr) -> &'static mut PageTable { use x86_64::registers::control::Cr3; let (lvl_4_table_frame, _) = Cr3::read(); @@ -12,3 +23,58 @@ pub unsafe fn active_lvl_4_table(ph_memory_offset: VirtAddr) -> &'static mut Pag &mut *page_table_ptr // unsafe return } + +pub fn create_example_mapping( + page: Page, + mapper: &mut OffsetPageTable, + frame_allocator: &mut impl FrameAllocator, +) { + use x86_64::structures::paging::PageTableFlags as Flags; + + let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); + let flags = Flags::PRESENT | Flags::WRITABLE; + + let map_to_result = unsafe { + // FIXME: this is not safe + mapper.map_to(page, frame, flags, frame_allocator) + }; + map_to_result.expect("map_to failed").flush(); +} + +pub struct EmptyFrameAllocator; + +unsafe impl FrameAllocator for EmptyFrameAllocator { + fn allocate_frame(&mut self) -> Option { + None + } +} + +pub struct BootInfoFrameAlloc { + memory_map: &'static MemoryMap, + next: usize, +} + +impl BootInfoFrameAlloc { + pub unsafe fn init(memory_map: &'static MemoryMap) -> Self { + BootInfoFrameAlloc { + memory_map, + next: 0, + } + } + fn usable_frames(&self) -> impl Iterator { + let regions = self.memory_map.iter(); + let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable); + let addr_ranges = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr()); + let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096)); + + frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))) + } +} + +unsafe impl FrameAllocator for BootInfoFrameAlloc { + fn allocate_frame(&mut self) -> Option { + let frame = self.usable_frames().nth(self.next); + self.next += 1; + frame + } +} From 7afff11c50e12da176fb361ac6316c228474e06c Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 02:42:45 +0200 Subject: [PATCH 15/27] Add correct version displaying --- shell/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/src/main.rs b/shell/src/main.rs index a826743..66ce8b8 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -29,7 +29,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { let page_ptr: *mut u64 = page.start_address().as_mut_ptr(); unsafe { page_ptr.offset(400).write_volatile(0x_f021_f077_f065_f04e) }; - print!("\nHighlightOS Shell v0.3.0\n\nhls < "); + print!("\nHighlightOS Shell v{}\n\nhls < ", env!("CARGO_PKG_VERSION")); hlshell::hlt_loop(); } From 99b5949e19a6a3aa30c9dd74fedf6491e93b2834 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 19:19:03 +0200 Subject: [PATCH 16/27] Heap allocation works --- shell/Cargo.toml | 1 + shell/src/allocator.rs | 44 ++++++++++++++++++++++++++++++++++++++++++ shell/src/lib.rs | 3 +++ shell/src/main.rs | 19 +++++++++++------- 4 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 shell/src/allocator.rs diff --git a/shell/Cargo.toml b/shell/Cargo.toml index f958f40..c54c4bb 100644 --- a/shell/Cargo.toml +++ b/shell/Cargo.toml @@ -11,6 +11,7 @@ x86_64 = "0.14.2" uart_16550 = "0.2.0" pic8259 = "0.10.1" pc-keyboard = "0.7.0" +linked_list_allocator = "0.9.0" [dependencies.bootloader] version = "0.9" diff --git a/shell/src/allocator.rs b/shell/src/allocator.rs new file mode 100644 index 0000000..5f3e70c --- /dev/null +++ b/shell/src/allocator.rs @@ -0,0 +1,44 @@ +use alloc::alloc::{GlobalAlloc, Layout}; +use core::ptr::null_mut; +use linked_list_allocator::LockedHeap; +use x86_64::{ + structures::paging::{ + mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB, + }, + VirtAddr, +}; + +pub const HEAP_START: usize = 0x_4444_4444_0000; +pub const HEAP_SIZE: usize = 100 * 1024; // 100KiB + +#[global_allocator] +static ALLOCATOR: LockedHeap = LockedHeap::empty(); + +pub fn init_heap( + mapper: &mut impl Mapper, + frame_allocator: &mut impl FrameAllocator, +) -> Result<(), MapToError> { + let page_range = { + let heap_start = VirtAddr::new(HEAP_START as u64); + let heap_end = heap_start + HEAP_SIZE - 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) + }; + + for page in page_range { + let frame = frame_allocator + .allocate_frame() + .ok_or(MapToError::FrameAllocationFailed)?; + let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; + + unsafe { mapper.map_to(page, frame, flags, frame_allocator)?.flush() }; + } + + unsafe { + ALLOCATOR.lock().init(HEAP_START, HEAP_SIZE); + } + + Ok(()) +} diff --git a/shell/src/lib.rs b/shell/src/lib.rs index 4f2265b..10f4a76 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs @@ -2,6 +2,9 @@ #![no_main] #![feature(abi_x86_interrupt)] +extern crate alloc; + +pub mod allocator; pub mod gdt; pub mod interrupts; pub mod mem; diff --git a/shell/src/main.rs b/shell/src/main.rs index 66ce8b8..709bec8 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -2,6 +2,9 @@ #![no_main] #![allow(clippy::empty_loop)] +extern crate alloc; + +use alloc::boxed::Box; use bootloader::{entry_point, BootInfo}; use core::panic::PanicInfo; use x86_64::structures::paging::PageTable; @@ -11,7 +14,8 @@ use hlshell::{print, println}; entry_point!(kernel_main); fn kernel_main(boot_info: &'static BootInfo) -> ! { - use hlshell::mem; + use hlshell::allocator; + use hlshell::mem::{self, BootInfoFrameAlloc}; use x86_64::{structures::paging::Page, VirtAddr}; #[cfg(debug_assertions)] @@ -21,15 +25,16 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); let mut mapper = unsafe { mem::init(phys_mem_offset) }; - let mut frame_allocator = mem::EmptyFrameAllocator; + let mut frame_allocator = unsafe { BootInfoFrameAlloc::init(&boot_info.memory_map) }; - let page = Page::containing_address(VirtAddr::new(0)); - mem::create_example_mapping(page, &mut mapper, &mut frame_allocator); + allocator::init_heap(&mut mapper, &mut frame_allocator).expect("Heap initialization failed"); - let page_ptr: *mut u64 = page.start_address().as_mut_ptr(); - unsafe { page_ptr.offset(400).write_volatile(0x_f021_f077_f065_f04e) }; + let x = Box::new(41); - print!("\nHighlightOS Shell v{}\n\nhls < ", env!("CARGO_PKG_VERSION")); + print!( + "\nHighlightOS Shell v{}\n\nhls < ", + env!("CARGO_PKG_VERSION") + ); hlshell::hlt_loop(); } From 338107b5aab93d64e63408399f17b160a5c7cb99 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 19:19:43 +0200 Subject: [PATCH 17/27] ... --- shell/.cargo/config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/.cargo/config.toml b/shell/.cargo/config.toml index 3818a03..1a7856a 100644 --- a/shell/.cargo/config.toml +++ b/shell/.cargo/config.toml @@ -1,5 +1,5 @@ [unstable] -build-std = ["core", "compiler_builtins"] +build-std = ["core", "compiler_builtins", "alloc"] build-std-features = ["compiler-builtins-mem"] [build] From c3a56202fc18258ac90967547e20d37f1dbc6762 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 19:25:44 +0200 Subject: [PATCH 18/27] Allocator from scratch --- shell/src/allocator.rs | 42 ++++++++- shell/src/allocator/bump.rs | 55 ++++++++++++ shell/src/allocator/fixed_size_block.rs | 86 ++++++++++++++++++ shell/src/allocator/linked_list.rs | 114 ++++++++++++++++++++++++ shell/src/lib.rs | 1 + 5 files changed, 295 insertions(+), 3 deletions(-) create mode 100644 shell/src/allocator/bump.rs create mode 100644 shell/src/allocator/fixed_size_block.rs create mode 100644 shell/src/allocator/linked_list.rs diff --git a/shell/src/allocator.rs b/shell/src/allocator.rs index 5f3e70c..853658f 100644 --- a/shell/src/allocator.rs +++ b/shell/src/allocator.rs @@ -1,6 +1,6 @@ use alloc::alloc::{GlobalAlloc, Layout}; use core::ptr::null_mut; -use linked_list_allocator::LockedHeap; +use fixed_size_block::FixedSizeBlockAllocator; use x86_64::{ structures::paging::{ mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB, @@ -8,11 +8,15 @@ use x86_64::{ VirtAddr, }; +pub mod bump; +pub mod fixed_size_block; +pub mod linked_list; + pub const HEAP_START: usize = 0x_4444_4444_0000; -pub const HEAP_SIZE: usize = 100 * 1024; // 100KiB +pub const HEAP_SIZE: usize = 100 * 1024; // 100 KiB #[global_allocator] -static ALLOCATOR: LockedHeap = LockedHeap::empty(); +static ALLOCATOR: Locked = Locked::new(FixedSizeBlockAllocator::new()); pub fn init_heap( mapper: &mut impl Mapper, @@ -42,3 +46,35 @@ pub fn init_heap( Ok(()) } + +pub struct Dummy; + +unsafe impl GlobalAlloc for Dummy { + unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { + null_mut() + } + + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { + panic!("dealloc should be never called") + } +} + +pub struct Locked { + inner: spin::Mutex, +} + +impl Locked { + pub const fn new(inner: A) -> Self { + Locked { + inner: spin::Mutex::new(inner), + } + } + + pub fn lock(&self) -> spin::MutexGuard { + self.inner.lock() + } +} + +fn align_up(addr: usize, align: usize) -> usize { + (addr + align - 1) & !(align - 1) +} diff --git a/shell/src/allocator/bump.rs b/shell/src/allocator/bump.rs new file mode 100644 index 0000000..f4fce42 --- /dev/null +++ b/shell/src/allocator/bump.rs @@ -0,0 +1,55 @@ +use super::{align_up, Locked}; +use alloc::alloc::{GlobalAlloc, Layout}; +use core::ptr; + +pub struct BumpAllocator { + heap_start: usize, + heap_end: usize, + next: usize, + allocations: usize, +} + +impl BumpAllocator { + pub const fn new() -> Self { + BumpAllocator { + heap_start: 0, + heap_end: 0, + next: 0, + allocations: 0, + } + } + + pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) { + self.heap_start = heap_start; + self.heap_end = heap_start.saturating_add(heap_size); + self.next = heap_start; + } +} + +unsafe impl GlobalAlloc for Locked { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let mut bump = self.lock(); + let alloc_start = align_up(bump.next, layout.align()); + let alloc_end = match alloc_start.checked_add(layout.size()) { + Some(end) => end, + None => return ptr::null_mut(), + }; + + if alloc_end > bump.heap_end { + ptr::null_mut() + } else { + bump.next = alloc_end; + bump.allocations += 1; + alloc_start as *mut u8 + } + } + + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { + let mut bump = self.lock(); + + bump.allocations -= 1; + if bump.allocations == 0 { + bump.next = bump.heap_start; + } + } +} diff --git a/shell/src/allocator/fixed_size_block.rs b/shell/src/allocator/fixed_size_block.rs new file mode 100644 index 0000000..0c4b4b2 --- /dev/null +++ b/shell/src/allocator/fixed_size_block.rs @@ -0,0 +1,86 @@ +use super::Locked; +use alloc::alloc::{GlobalAlloc, Layout}; +use core::{ + mem, + ptr::{self, NonNull}, +}; + +const BLOCK_SIZES: &[usize] = &[8, 16, 32, 64, 128, 256, 512, 1024, 2048]; + +fn list_index(layout: &Layout) -> Option { + let required_block_size = layout.size().max(layout.align()); + BLOCK_SIZES.iter().position(|&s| s >= required_block_size) +} + +struct ListNode { + next: Option<&'static mut ListNode>, +} + +pub struct FixedSizeBlockAllocator { + list_heads: [Option<&'static mut ListNode>; BLOCK_SIZES.len()], + fallback_allocator: linked_list_allocator::Heap, +} + +impl FixedSizeBlockAllocator { + pub const fn new() -> Self { + const EMPTY: Option<&'static mut ListNode> = None; + FixedSizeBlockAllocator { + list_heads: [EMPTY; BLOCK_SIZES.len()], + fallback_allocator: linked_list_allocator::Heap::empty(), + } + } + + pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) { + self.fallback_allocator.init(heap_start, heap_size); + } + + /// Allocates using the fallback allocator. + fn fallback_alloc(&mut self, layout: Layout) -> *mut u8 { + match self.fallback_allocator.allocate_first_fit(layout) { + Ok(ptr) => ptr.as_ptr(), + Err(_) => ptr::null_mut(), + } + } +} + +unsafe impl GlobalAlloc for Locked { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let mut allocator = self.lock(); + match list_index(&layout) { + Some(index) => match allocator.list_heads[index].take() { + Some(node) => { + allocator.list_heads[index] = node.next.take(); + node as *mut ListNode as *mut u8 + } + None => { + let block_size = BLOCK_SIZES[index]; + let block_align = block_size; + let layout = Layout::from_size_align(block_size, block_align).unwrap(); + allocator.fallback_alloc(layout) + } + }, + None => allocator.fallback_alloc(layout), + } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + let mut allocator = self.lock(); + match list_index(&layout) { + Some(index) => { + let new_node = ListNode { + next: allocator.list_heads[index].take(), + }; + + assert!(mem::size_of::() <= BLOCK_SIZES[index]); + assert!(mem::align_of::() <= BLOCK_SIZES[index]); + let new_node_ptr = ptr as *mut ListNode; + new_node_ptr.write(new_node); + allocator.list_heads[index] = Some(&mut *new_node_ptr); + } + None => { + let ptr = NonNull::new(ptr).unwrap(); + allocator.fallback_allocator.deallocate(ptr, layout); + } + } + } +} diff --git a/shell/src/allocator/linked_list.rs b/shell/src/allocator/linked_list.rs new file mode 100644 index 0000000..597704a --- /dev/null +++ b/shell/src/allocator/linked_list.rs @@ -0,0 +1,114 @@ +use super::{align_up, Locked}; +use alloc::alloc::{GlobalAlloc, Layout}; +use core::{mem, ptr}; + +struct ListNode { + size: usize, + next: Option<&'static mut ListNode>, +} + +impl ListNode { + const fn new(size: usize) -> Self { + ListNode { size, next: None } + } + + fn start_addr(&self) -> usize { + self as *const Self as usize + } + + fn end_addr(&self) -> usize { + self.start_addr() + self.size + } +} + +pub struct LinkedListAllocator { + head: ListNode, +} + +impl LinkedListAllocator { + pub const fn new() -> Self { + Self { + head: ListNode::new(0), + } + } + + pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) { + self.add_free_region(heap_start, heap_size); + } + + unsafe fn add_free_region(&mut self, addr: usize, size: usize) { + assert_eq!(align_up(addr, mem::align_of::()), addr); + assert!(size >= mem::size_of::()); + + let mut node = ListNode::new(size); + node.next = self.head.next.take(); + let node_ptr = addr as *mut ListNode; + node_ptr.write(node); + self.head.next = Some(&mut *node_ptr) + } + + fn find_region(&mut self, size: usize, align: usize) -> Option<(&'static mut ListNode, usize)> { + let mut current = &mut self.head; + while let Some(ref mut region) = current.next { + if let Ok(alloc_start) = Self::alloc_from_region(®ion, size, align) { + let next = region.next.take(); + let ret = Some((current.next.take().unwrap(), alloc_start)); + current.next = next; + return ret; + } else { + current = current.next.as_mut().unwrap(); + } + } + + None + } + + fn alloc_from_region(region: &ListNode, size: usize, align: usize) -> Result { + let alloc_start = align_up(region.start_addr(), align); + let alloc_end = alloc_start.checked_add(size).ok_or(())?; + + if alloc_end > region.end_addr() { + return Err(()); + } + + let excess_size = region.end_addr() - alloc_end; + if excess_size > 0 && excess_size < mem::size_of::() { + return Err(()); + } + + Ok(alloc_start) + } + + fn size_align(layout: Layout) -> (usize, usize) { + let layout = layout + .align_to(mem::align_of::()) + .expect("adjusting alignment failed") + .pad_to_align(); + let size = layout.size().max(mem::size_of::()); + (size, layout.align()) + } +} + +unsafe impl GlobalAlloc for Locked { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let (size, align) = LinkedListAllocator::size_align(layout); + let mut allocator = self.lock(); + + if let Some((region, alloc_start)) = allocator.find_region(size, align) { + let alloc_end = alloc_start.checked_add(size).expect("overflow"); + let excess_size = region.end_addr() - alloc_end; + if excess_size > 0 { + allocator.add_free_region(alloc_end, excess_size); + } + alloc_start as *mut u8 + } else { + ptr::null_mut() + } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + let (size, _) = LinkedListAllocator::size_align(layout); + + self.lock().add_free_region(ptr as usize, size) + } +} diff --git a/shell/src/lib.rs b/shell/src/lib.rs index 10f4a76..3a07547 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs @@ -1,6 +1,7 @@ #![no_std] #![no_main] #![feature(abi_x86_interrupt)] +#![feature(const_mut_refs)] extern crate alloc; From 2f58af5bc20a6a8c20f834191d352f89b5808cbb Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 19:36:05 +0200 Subject: [PATCH 19/27] Clippy calm down --- shell/src/main.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/shell/src/main.rs b/shell/src/main.rs index 709bec8..dc7c0c8 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -1,13 +1,11 @@ #![no_std] #![no_main] #![allow(clippy::empty_loop)] +#![warn(clippy::new_without_default)] +#![warn(clippy::missing_safety_doc)] -extern crate alloc; - -use alloc::boxed::Box; use bootloader::{entry_point, BootInfo}; use core::panic::PanicInfo; -use x86_64::structures::paging::PageTable; use hlshell::{print, println}; @@ -16,7 +14,7 @@ entry_point!(kernel_main); fn kernel_main(boot_info: &'static BootInfo) -> ! { use hlshell::allocator; use hlshell::mem::{self, BootInfoFrameAlloc}; - use x86_64::{structures::paging::Page, VirtAddr}; + use x86_64::VirtAddr; #[cfg(debug_assertions)] println!("Initializing...\n"); @@ -29,8 +27,6 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { allocator::init_heap(&mut mapper, &mut frame_allocator).expect("Heap initialization failed"); - let x = Box::new(41); - print!( "\nHighlightOS Shell v{}\n\nhls < ", env!("CARGO_PKG_VERSION") From 316550889c6fed865524a8a24b4225d57ed6b443 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 19:37:55 +0200 Subject: [PATCH 20/27] Move res to cmd --- shell/src/{res => cmd}/commands.rs | 0 shell/src/{res => cmd}/shell.rs | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename shell/src/{res => cmd}/commands.rs (100%) rename shell/src/{res => cmd}/shell.rs (100%) diff --git a/shell/src/res/commands.rs b/shell/src/cmd/commands.rs similarity index 100% rename from shell/src/res/commands.rs rename to shell/src/cmd/commands.rs diff --git a/shell/src/res/shell.rs b/shell/src/cmd/shell.rs similarity index 100% rename from shell/src/res/shell.rs rename to shell/src/cmd/shell.rs From 4edaa57eeae981e380860542b964933c23403afd Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 20:04:05 +0200 Subject: [PATCH 21/27] commands integrated --- shell/src/cmd/{commands.rs => mod.rs} | 51 +++++++++++---------- shell/src/main.rs | 66 +++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 27 deletions(-) rename shell/src/cmd/{commands.rs => mod.rs} (78%) diff --git a/shell/src/cmd/commands.rs b/shell/src/cmd/mod.rs similarity index 78% rename from shell/src/cmd/commands.rs rename to shell/src/cmd/mod.rs index a4cc8a8..e05bd73 100644 --- a/shell/src/cmd/commands.rs +++ b/shell/src/cmd/mod.rs @@ -1,8 +1,13 @@ // Copyleft 🄯 2024 Adam Perkowski -use std::io; -use std::io::Write; -use std::process; +// use std::io; +// use std::io::Write; +// use std::process; + +extern crate alloc; +use alloc::vec::Vec; + +use hlshell::{print, println}; pub struct Command { pub name: &'static str, @@ -56,23 +61,23 @@ fn cc(_args: Vec<&str>) -> i32 { 0 } -fn exit_hls(_args: Vec<&str>) -> i32 { - print!("are you sure you want to exit? [ y/N ] < "); +// fn exit_hls(_args: Vec<&str>) -> i32 { +// print!("are you sure you want to exit? [ y/N ] < "); - let mut inpt = String::new(); +// let mut inpt = String::new(); - io::stdout().flush().unwrap(); - io::stdin().read_line(&mut inpt).unwrap(); +// io::stdout().flush().unwrap(); +// io::stdin().read_line(&mut inpt).unwrap(); - if inpt.to_lowercase() == "y\n" { - println!(); - process::exit(0); - } - // return 0 - else { - 3 - } -} +// if inpt.to_lowercase() == "y\n" { +// println!(); +// process::exit(0); +// } +// // return 0 +// else { +// 3 +// } +// } fn document(_args: Vec<&str>) -> i32 { if !_args.is_empty() { @@ -114,12 +119,12 @@ pub const COMMAND_LIST: &[Command] = &[ doc: "display copyright info", fun: cc, }, - Command { - name: "exit", - args: "", - doc: "exit the shell :((", - fun: exit_hls, - }, + // Command { + // name: "exit", + // args: "", + // doc: "exit the shell :((", + // fun: exit_hls, + // }, Command { name: "getdoc", args: "[cmd]", diff --git a/shell/src/main.rs b/shell/src/main.rs index dc7c0c8..7aa824e 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -4,13 +4,24 @@ #![warn(clippy::new_without_default)] #![warn(clippy::missing_safety_doc)] +extern crate alloc; +use alloc::{string::String, vec}; + use bootloader::{entry_point, BootInfo}; use core::panic::PanicInfo; use hlshell::{print, println}; +mod cmd; +use cmd::COMMAND_LIST; + entry_point!(kernel_main); +struct RtrType { + code: &'static i32, + info: &'static str, +} + fn kernel_main(boot_info: &'static BootInfo) -> ! { use hlshell::allocator; use hlshell::mem::{self, BootInfoFrameAlloc}; @@ -27,14 +38,61 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { allocator::init_heap(&mut mapper, &mut frame_allocator).expect("Heap initialization failed"); - print!( - "\nHighlightOS Shell v{}\n\nhls < ", - env!("CARGO_PKG_VERSION") - ); + // let args: vec::Vec<&str> = vec![""]; + // (COMMAND_LIST[1].fun)(args); + + print!("\nHighlightOS Shell v{}\n\n", env!("CARGO_PKG_VERSION")); + + loop { + let mut input = String::new(); + print!("hls < "); + + // io::stdout().flush().unwrap(); + // io::stdin().read_line(&mut inpt).unwrap(); + + // input.pop(); + + let mut args: vec::Vec<&str> = input.split(' ').collect(); + + if let Some(command) = COMMAND_LIST.iter().find(|&com| com.name == args[0]) { + // args.remove(0); + + let rtr = (command.fun)(args); + + if rtr != 1 { + if let Some(return_code) = RTR_LIST.iter().find(|&rtr_t| rtr_t.code == &rtr) { + println!("\n > {}\n{}\n", input, return_code.info); + } else { + println!("\n > {}\nreturned : {}\n", input, rtr); + } + } + } else { + println!("\n > {}\ncommand not found\n", input); + } + } hlshell::hlt_loop(); } +const RTR_LIST: &[RtrType] = &[ + RtrType { + code: &0, + info: "executed successfully", + }, + RtrType { + code: &2, + info: "returned general error", + }, + RtrType { + code: &3, + info: "returned critical error", + }, + RtrType { + code: &4, + info: "returned user error", + }, +]; + #[panic_handler] fn panic(info: &PanicInfo) -> ! { println!("{}", info); From 3240986e7e3fae325a11e0b5913cc60287b4efd7 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 20:24:02 +0200 Subject: [PATCH 22/27] TODO --- shell/TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/TODO b/shell/TODO index 0e6b37c..b5e1103 100644 --- a/shell/TODO +++ b/shell/TODO @@ -1,3 +1,4 @@ - RTC - update dependencies - add debug commands that exist only in debug build +- add 'other' section to commands that lets you create commands and install them via 'patching' From 8068612dd9a0184ae2057cbcf7295b8a62f946cb Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 20:27:32 +0200 Subject: [PATCH 23/27] howing rawkeys only for debug --- shell/src/interrupts.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/shell/src/interrupts.rs b/shell/src/interrupts.rs index bcb4c25..632328f 100644 --- a/shell/src/interrupts.rs +++ b/shell/src/interrupts.rs @@ -96,7 +96,10 @@ extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStac if let Some(key) = keyboard.process_keyevent(key_event) { match key { DecodedKey::Unicode(character) => print!("{}", character), + #[cfg(debug_assertions)] DecodedKey::RawKey(key) => print!("{:?}", key), + #[cfg(not(debug_assertions))] + DecodedKey::RawKey(key) => (), } } } From 85afd88dd2efd0122d6cd7bbb978522c028137bd Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Fri, 19 Jul 2024 20:56:06 +0200 Subject: [PATCH 24/27] saving input --- shell/src/interrupts.rs | 40 +++++++++++++++++++++++----------- shell/src/keyboard_buffer.rs | 26 ++++++++++++++++++++++ shell/src/lib.rs | 1 + shell/src/main.rs | 42 ++++++++++++++++++------------------ 4 files changed, 76 insertions(+), 33 deletions(-) create mode 100644 shell/src/keyboard_buffer.rs diff --git a/shell/src/interrupts.rs b/shell/src/interrupts.rs index 632328f..5925c2e 100644 --- a/shell/src/interrupts.rs +++ b/shell/src/interrupts.rs @@ -1,5 +1,6 @@ use crate::gdt; use crate::hlt_loop; +use crate::keyboard_buffer::{clear_buffer, read_buffer, BUFFER, BUFFER_INDEX, BUFFER_SIZE}; use crate::print; use crate::println; use lazy_static::lazy_static; @@ -88,18 +89,33 @@ extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStac )); } - let mut keyboard = KEYBOARD.lock(); - let mut port = Port::new(0x60); - - let scancode: u8 = unsafe { port.read() }; - if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { - if let Some(key) = keyboard.process_keyevent(key_event) { - match key { - DecodedKey::Unicode(character) => print!("{}", character), - #[cfg(debug_assertions)] - DecodedKey::RawKey(key) => print!("{:?}", key), - #[cfg(not(debug_assertions))] - DecodedKey::RawKey(key) => (), + if unsafe { BUFFER_INDEX } < BUFFER_SIZE { + let mut keyboard = KEYBOARD.lock(); + let mut port = Port::new(0x60); + + let scancode: u8 = unsafe { port.read() }; + if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { + if let Some(key) = keyboard.process_keyevent(key_event) { + match key { + DecodedKey::Unicode(character) => { + unsafe { + if character != '\n' { + BUFFER[BUFFER_INDEX] = character; + BUFFER_INDEX += 1; + } else { + clear_buffer(); + } + } + print!("{}", character); + } + + #[cfg(debug_assertions)] + DecodedKey::RawKey(key) => print!("{:?}", key), + + #[cfg(not(debug_assertions))] + DecodedKey::RawKey(_) => (), + } + // print!("{}", read_buffer()); } } } diff --git a/shell/src/keyboard_buffer.rs b/shell/src/keyboard_buffer.rs new file mode 100644 index 0000000..a0a5158 --- /dev/null +++ b/shell/src/keyboard_buffer.rs @@ -0,0 +1,26 @@ +use alloc::string::String; + +pub const BUFFER_SIZE: usize = 256; +pub static mut BUFFER: [char; BUFFER_SIZE] = ['\0'; BUFFER_SIZE]; +pub static mut BUFFER_INDEX: usize = 0; + +pub fn read_buffer() -> String { + let mut buffer_content = String::new(); + + unsafe { + for i in 0..BUFFER_INDEX { + buffer_content.push(BUFFER[i]); + } + } + + buffer_content +} + +pub fn clear_buffer() { + unsafe { + for i in 0..BUFFER_SIZE { + BUFFER[i] = '\0'; + } + BUFFER_INDEX = 0; + } +} diff --git a/shell/src/lib.rs b/shell/src/lib.rs index 3a07547..da744e6 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs @@ -8,6 +8,7 @@ extern crate alloc; pub mod allocator; pub mod gdt; pub mod interrupts; +pub mod keyboard_buffer; pub mod mem; pub mod vga_buffer; diff --git a/shell/src/main.rs b/shell/src/main.rs index 7aa824e..43c0bf5 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -43,33 +43,33 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { print!("\nHighlightOS Shell v{}\n\n", env!("CARGO_PKG_VERSION")); - loop { - let mut input = String::new(); - print!("hls < "); + // loop { + // let mut input = String::new(); + // print!("hls < "); - // io::stdout().flush().unwrap(); - // io::stdin().read_line(&mut inpt).unwrap(); + // // io::stdout().flush().unwrap(); + // // io::stdin().read_line(&mut inpt).unwrap(); - // input.pop(); + // // input.pop(); - let mut args: vec::Vec<&str> = input.split(' ').collect(); + // let mut args: vec::Vec<&str> = input.split(' ').collect(); - if let Some(command) = COMMAND_LIST.iter().find(|&com| com.name == args[0]) { - // args.remove(0); + // if let Some(command) = COMMAND_LIST.iter().find(|&com| com.name == args[0]) { + // // args.remove(0); - let rtr = (command.fun)(args); + // let rtr = (command.fun)(args); - if rtr != 1 { - if let Some(return_code) = RTR_LIST.iter().find(|&rtr_t| rtr_t.code == &rtr) { - println!("\n > {}\n{}\n", input, return_code.info); - } else { - println!("\n > {}\nreturned : {}\n", input, rtr); - } - } - } else { - println!("\n > {}\ncommand not found\n", input); - } - } + // if rtr != 1 { + // if let Some(return_code) = RTR_LIST.iter().find(|&rtr_t| rtr_t.code == &rtr) { + // println!("\n > {}\n{}\n", input, return_code.info); + // } else { + // println!("\n > {}\nreturned : {}\n", input, rtr); + // } + // } + // } else { + // println!("\n > {}\ncommand not found\n", input); + // } + // } hlshell::hlt_loop(); } From 5d8378a2b7d2c1f4d05fdeaa35b7c2c9c53c3bed Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Sat, 20 Jul 2024 03:56:10 +0200 Subject: [PATCH 25/27] upate the panic handler loop --- shell/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/src/main.rs b/shell/src/main.rs index 43c0bf5..25b21cc 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -96,5 +96,5 @@ const RTR_LIST: &[RtrType] = &[ #[panic_handler] fn panic(info: &PanicInfo) -> ! { println!("{}", info); - loop {} + hlshell::hlt_loop(); } From 2a2b9975943a9ec07dc229c324e9d5ae9d1db327 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Sat, 20 Jul 2024 17:23:26 +0200 Subject: [PATCH 26/27] DONE --- shell/src/cmd/mod.rs | 3 +- shell/src/cmd/shell.rs | 67 ----------------------------------------- shell/src/interrupts.rs | 10 ++---- shell/src/main.rs | 58 ++++++++++++++++++++--------------- 4 files changed, 38 insertions(+), 100 deletions(-) delete mode 100644 shell/src/cmd/shell.rs diff --git a/shell/src/cmd/mod.rs b/shell/src/cmd/mod.rs index e05bd73..de2ef27 100644 --- a/shell/src/cmd/mod.rs +++ b/shell/src/cmd/mod.rs @@ -81,7 +81,8 @@ fn cc(_args: Vec<&str>) -> i32 { fn document(_args: Vec<&str>) -> i32 { if !_args.is_empty() { - if let Some(command) = COMMAND_LIST.iter().find(|&cmd| cmd.name == _args[0]) { + let req_com = &_args[0].replace("\n", ""); + if let Some(command) = COMMAND_LIST.iter().find(|&cmd| cmd.name == req_com) { println!("{} >> {}", command.name, command.doc); 0 } else { diff --git a/shell/src/cmd/shell.rs b/shell/src/cmd/shell.rs deleted file mode 100644 index 5c3937c..0000000 --- a/shell/src/cmd/shell.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyleft 🄯 2024 Adam Perkowski - -use std::io; -use std::io::Write; - -mod commands; - -use commands::COMMAND_LIST; - -struct RtrType { - code: &'static i32, - info: &'static str, -} - -fn main() { - // (COMMAND_LIST[0].fun)(); - - println!("HighlightOS Shell\nversion {}\n", env!("CARGO_PKG_VERSION")); - - loop { - let mut inpt = String::new(); - - print!("hls < "); - - io::stdout().flush().unwrap(); - io::stdin().read_line(&mut inpt).unwrap(); - - inpt.pop(); - - let mut args: Vec<&str> = inpt.split(' ').collect(); - - if let Some(command) = COMMAND_LIST.iter().find(|&cmd| cmd.name == args[0]) { - args.remove(0); - - let rtr = (command.fun)(args); - - if rtr != 1 { - if let Some(return_code) = RTR_LIST.iter().find(|&rtr_t| rtr_t.code == &rtr) { - println!("\n > {}\n{}\n", inpt, return_code.info); - } else { - println!("\n > {}\nreturned : {}\n", inpt, rtr) - } - } - } else { - println!("\n > {}\ncommand not found\n", inpt); - } - } -} - -const RTR_LIST: &[RtrType] = &[ - RtrType { - code: &0, - info: "executed successfully", - }, - RtrType { - code: &2, - info: "returned general error", - }, - RtrType { - code: &3, - info: "returned critical error", - }, - RtrType { - code: &4, - info: "returned user error", - }, -]; diff --git a/shell/src/interrupts.rs b/shell/src/interrupts.rs index 5925c2e..c41c010 100644 --- a/shell/src/interrupts.rs +++ b/shell/src/interrupts.rs @@ -1,6 +1,6 @@ use crate::gdt; use crate::hlt_loop; -use crate::keyboard_buffer::{clear_buffer, read_buffer, BUFFER, BUFFER_INDEX, BUFFER_SIZE}; +use crate::keyboard_buffer::{BUFFER, BUFFER_INDEX, BUFFER_SIZE}; use crate::print; use crate::println; use lazy_static::lazy_static; @@ -99,12 +99,8 @@ extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStac match key { DecodedKey::Unicode(character) => { unsafe { - if character != '\n' { - BUFFER[BUFFER_INDEX] = character; - BUFFER_INDEX += 1; - } else { - clear_buffer(); - } + BUFFER[BUFFER_INDEX] = character; + BUFFER_INDEX += 1; } print!("{}", character); } diff --git a/shell/src/main.rs b/shell/src/main.rs index 25b21cc..96c0cde 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -5,12 +5,12 @@ #![warn(clippy::missing_safety_doc)] extern crate alloc; -use alloc::{string::String, vec}; +use alloc::vec; use bootloader::{entry_point, BootInfo}; use core::panic::PanicInfo; -use hlshell::{print, println}; +use hlshell::{keyboard_buffer, print, println}; mod cmd; use cmd::COMMAND_LIST; @@ -41,37 +41,45 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { // let args: vec::Vec<&str> = vec![""]; // (COMMAND_LIST[1].fun)(args); - print!("\nHighlightOS Shell v{}\n\n", env!("CARGO_PKG_VERSION")); + print!( + "\nHighlightOS Shell v{}\n\nhls < ", + env!("CARGO_PKG_VERSION") + ); - // loop { - // let mut input = String::new(); - // print!("hls < "); + loop { + let input = keyboard_buffer::read_buffer(); - // // io::stdout().flush().unwrap(); - // // io::stdin().read_line(&mut inpt).unwrap(); + if input.ends_with("\n") { + keyboard_buffer::clear_buffer(); - // // input.pop(); + let mut args: vec::Vec<&str> = input.split(' ').collect(); - // let mut args: vec::Vec<&str> = input.split(' ').collect(); + if args[0] != "\n" { + let req_com = &args[0].replace("\n", ""); - // if let Some(command) = COMMAND_LIST.iter().find(|&com| com.name == args[0]) { - // // args.remove(0); + if let Some(command) = COMMAND_LIST.iter().find(|&com| com.name == req_com) { + args.remove(0); - // let rtr = (command.fun)(args); + let rtr = (command.fun)(args); - // if rtr != 1 { - // if let Some(return_code) = RTR_LIST.iter().find(|&rtr_t| rtr_t.code == &rtr) { - // println!("\n > {}\n{}\n", input, return_code.info); - // } else { - // println!("\n > {}\nreturned : {}\n", input, rtr); - // } - // } - // } else { - // println!("\n > {}\ncommand not found\n", input); - // } - // } + if rtr != 1 { + if let Some(return_code) = RTR_LIST.iter().find(|&rtr_t| rtr_t.code == &rtr) + { + println!("\n > {}\n{}\n", req_com, return_code.info); + } else { + println!("\n > {}\nreturned : {}\n", req_com, rtr); + } + } + } else { + println!("\n > {}\ncommand not found\n", input); + } + } - hlshell::hlt_loop(); + print!("hls < "); + } + } + + // hlshell::hlt_loop(); } const RTR_LIST: &[RtrType] = &[ From 0f5233a66970d5e70f9c9e0bdc5b8119b7ddbfbf Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Sat, 20 Jul 2024 17:41:17 +0200 Subject: [PATCH 27/27] better init system --- shell/src/cmd/mod.rs | 19 +++++++++++++++++++ shell/src/main.rs | 8 +++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/shell/src/cmd/mod.rs b/shell/src/cmd/mod.rs index de2ef27..1f5a445 100644 --- a/shell/src/cmd/mod.rs +++ b/shell/src/cmd/mod.rs @@ -95,6 +95,12 @@ fn document(_args: Vec<&str>) -> i32 { } } +#[cfg(debug_assertions)] +fn crasher(_args: Vec<&str>) -> i32 { + println!("CRASHING...\n\n"); + panic!("Invoked by crasher"); +} + pub const COMMAND_LIST: &[Command] = &[ Command { name: "clrs", @@ -132,4 +138,17 @@ pub const COMMAND_LIST: &[Command] = &[ doc: "display doc of selected command", fun: document, }, + // Command { + // name: "reinit", + // args: "", + // doc: "re-init the system", + // fun: crate::init_kernel, + // }, + #[cfg(debug_assertions)] + Command { + name: "crash_kernel", + args: "", + doc: "DEV | panic! the system", + fun: crasher, + }, ]; diff --git a/shell/src/main.rs b/shell/src/main.rs index 96c0cde..1fd6adf 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -22,7 +22,7 @@ struct RtrType { info: &'static str, } -fn kernel_main(boot_info: &'static BootInfo) -> ! { +pub fn init_kernel(boot_info: &'static BootInfo) { use hlshell::allocator; use hlshell::mem::{self, BootInfoFrameAlloc}; use x86_64::VirtAddr; @@ -46,6 +46,12 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { env!("CARGO_PKG_VERSION") ); + () +} + +fn kernel_main(boot_info: &'static BootInfo) -> ! { + init_kernel(boot_info); + loop { let input = keyboard_buffer::read_buffer();