From 34e784ddf798d4ca63eda1015d12f476f2f088fb Mon Sep 17 00:00:00 2001 From: Mathieu Strypsteen Date: Fri, 15 Nov 2024 22:20:42 +0100 Subject: [PATCH] Add display tty --- kernel/src/cpu/paging.rs | 6 ++- kernel/src/misc/draw_target.rs | 15 +++--- kernel/src/sys/acpica_osl.rs | 2 +- kernel/src/sys/display.rs | 88 +++++++++++++++++++++++++++++----- kernel/src/sys/early_acpi.rs | 2 +- kernel/src/sys/hpet.rs | 2 +- kernel/src/sys/ioapic.rs | 2 +- kernel/src/sys/lapic.rs | 2 +- kernel/src/sys/task.rs | 16 +++---- 9 files changed, 98 insertions(+), 37 deletions(-) diff --git a/kernel/src/cpu/paging.rs b/kernel/src/cpu/paging.rs index b7f7747..1136a78 100644 --- a/kernel/src/cpu/paging.rs +++ b/kernel/src/cpu/paging.rs @@ -158,13 +158,15 @@ fn map_range(virt_start: u64, phys_start: u64, size: u64, user: bool, write: boo map(current_pml4.as_mut().unwrap(), virt_start + i * 0x1000, phys_start + i * 0x1000, user, write, exec, cache_disable); } } -pub unsafe fn map_physical(phys: u64, mut size: u64) -> u64 { +pub unsafe fn map_physical(phys: u64, mut size: u64, write_combining: bool) -> u64 { + // TODO: Implement WC let phys_offset = phys % 0x1000; let phys_end = (phys + size + 0xfff) / 0x1000 * 0x1000; let phys_start = phys - phys_offset; size = phys_end - phys_start; let virt_start = find_free_virt_range(KERNEL_MAPPINGS_START, KERNEL_MAPPINGS_END, size); - map_range(virt_start, phys_start, size, false, true, false, true); + let cache_disable = !write_combining; + map_range(virt_start, phys_start, size, false, true, false, cache_disable); virt_start + phys_offset } pub unsafe fn unmap_physical(address: u64, size: u64) { diff --git a/kernel/src/misc/draw_target.rs b/kernel/src/misc/draw_target.rs index 9def6b3..69305b4 100644 --- a/kernel/src/misc/draw_target.rs +++ b/kernel/src/misc/draw_target.rs @@ -1,5 +1,6 @@ use core::convert::Infallible; +use alloc::vec::Vec; use embedded_graphics::{ pixelcolor::Bgr888, prelude::{DrawTarget, OriginDimensions, RgbColor, Size}, @@ -7,7 +8,7 @@ use embedded_graphics::{ }; pub struct FramebufferTarget { - pub framebuffer: *mut u8, + pub framebuffer: Vec, pub width: usize, pub height: usize, pub stride: usize, @@ -26,12 +27,10 @@ impl DrawTarget for FramebufferTarget { if i.0.x < 0 || i.0.x >= self.width as i32 || i.0.y < 0 || i.0.y >= self.height as i32 { continue; } - let offset = (i.0.y * self.stride as i32 + i.0.x) as isize * 4; - unsafe { - self.framebuffer.offset(offset).write_volatile(i.1.b()); - self.framebuffer.offset(offset + 1).write_volatile(i.1.g()); - self.framebuffer.offset(offset + 2).write_volatile(i.1.r()); - } + let offset = (i.0.y * self.stride as i32 + i.0.x) as usize * 4; + self.framebuffer[offset] = i.1.b(); + self.framebuffer[offset + 1] = i.1.g(); + self.framebuffer[offset + 2] = i.1.r(); } Ok(()) } @@ -41,5 +40,3 @@ impl OriginDimensions for FramebufferTarget { Size::new(self.width as u32, self.height as u32) } } -unsafe impl Send for FramebufferTarget {} -unsafe impl Sync for FramebufferTarget {} diff --git a/kernel/src/sys/acpica_osl.rs b/kernel/src/sys/acpica_osl.rs index f041055..2690a38 100644 --- a/kernel/src/sys/acpica_osl.rs +++ b/kernel/src/sys/acpica_osl.rs @@ -124,7 +124,7 @@ extern "C" fn AcpiOsInstallInterruptHandler(gsi: UINT32, handler: ACPI_OSD_HANDL #[no_mangle] extern "C" fn AcpiOsMapMemory(phys: ACPI_PHYSICAL_ADDRESS, size: ACPI_SIZE) -> *mut c_void { unsafe { - return map_physical(phys, size) as *mut c_void; + return map_physical(phys, size, false) as *mut c_void; } } #[no_mangle] diff --git a/kernel/src/sys/display.rs b/kernel/src/sys/display.rs index 8b73c8e..9017aa6 100644 --- a/kernel/src/sys/display.rs +++ b/kernel/src/sys/display.rs @@ -1,23 +1,89 @@ -use core::ptr::null_mut; +use core::{ + ptr::null_mut, + sync::atomic::{AtomicPtr, AtomicUsize, Ordering}, +}; +use alloc::{string::ToString, vec}; +use embedded_graphics::{ + mono_font::{iso_8859_13::FONT_10X20, MonoTextStyle}, + pixelcolor::Bgr888, + prelude::*, + text::Text, +}; use kernel_common::loader_struct::FramebufferInfo; use spin::Mutex; use crate::{cpu::paging::map_physical, misc::draw_target::FramebufferTarget}; -static FRAMEBUFFER: Mutex = Mutex::new(FramebufferTarget { - framebuffer: null_mut(), - width: 0, - height: 0, - stride: 0, -}); +static FRAMEBUFFER: Mutex> = Mutex::new(None); +static FRAMEBUFFER_ADDR: AtomicPtr = AtomicPtr::new(null_mut()); +static WIDTH: AtomicUsize = AtomicUsize::new(0); +static HEIGHT: AtomicUsize = AtomicUsize::new(0); +static CURRENT_X: AtomicUsize = AtomicUsize::new(0); +static CURRENT_Y: AtomicUsize = AtomicUsize::new(0); +fn write_char(x: usize, y: usize, c: char) { + let fb = &mut *FRAMEBUFFER.lock(); + let str = c.to_string(); + let pos = Point::new(x as i32 * 10 + 9, y as i32 * 20 + 19); + let style = MonoTextStyle::new(&FONT_10X20, Bgr888::WHITE); + let text = Text::new(&str, pos, style); + text.draw(fb.as_mut().unwrap()).unwrap(); +} +fn scroll() { + let fb = &mut *FRAMEBUFFER.lock(); + let fb = fb.as_mut().unwrap(); + let height = HEIGHT.load(Ordering::SeqCst); + let line_size = fb.stride * 20 * 4; + fb.framebuffer.copy_within(line_size..line_size * height, 0); + fb.framebuffer[line_size * (height - 1)..].fill(0); + CURRENT_Y.store(CURRENT_Y.load(Ordering::SeqCst) - 1, Ordering::SeqCst); +} +fn copy_to_fb() { + let fb = &mut *FRAMEBUFFER.lock(); + let fb = fb.as_mut().unwrap(); + let addr = FRAMEBUFFER_ADDR.load(Ordering::SeqCst); + let size = fb.stride * fb.height * 4; + unsafe { + addr.copy_from_nonoverlapping(fb.framebuffer.as_ptr(), size); + } +} +pub fn display_print(str: &str) { + let mut current_x = CURRENT_X.load(Ordering::SeqCst); + let mut current_y = CURRENT_Y.load(Ordering::SeqCst); + let width = WIDTH.load(Ordering::SeqCst); + let height = HEIGHT.load(Ordering::SeqCst); + for c in str.chars() { + if c == '\n' { + current_x = 0; + current_y += 1; + continue; + } + if current_x == width { + current_x = 0; + current_y += 1; + } + if current_y == height { + scroll(); + current_y -= 1; + } + write_char(current_x, current_y, c); + current_x += 1; + } + CURRENT_X.store(current_x, Ordering::SeqCst); + CURRENT_Y.store(current_y, Ordering::SeqCst); + copy_to_fb(); +} pub fn setup_display(info: FramebufferInfo) { - let addr = unsafe { map_physical(info.address, info.height * info.stride * 4) }; - *FRAMEBUFFER.lock() = FramebufferTarget { - framebuffer: addr as *mut u8, + let addr = unsafe { map_physical(info.address, info.height * info.stride * 4, true) }; + FRAMEBUFFER_ADDR.store(addr as *mut u8, Ordering::SeqCst); + let fb = vec![0; info.height as usize * info.stride as usize * 4]; + *FRAMEBUFFER.lock() = Some(FramebufferTarget { + framebuffer: fb, width: info.width as usize, height: info.height as usize, stride: info.stride as usize, - }; + }); + WIDTH.store(info.width as usize / 10 - 1, Ordering::SeqCst); + HEIGHT.store(info.height as usize / 20 - 1, Ordering::SeqCst); } diff --git a/kernel/src/sys/early_acpi.rs b/kernel/src/sys/early_acpi.rs index df230a5..64e5c66 100644 --- a/kernel/src/sys/early_acpi.rs +++ b/kernel/src/sys/early_acpi.rs @@ -10,7 +10,7 @@ pub struct EarlyACPIHandler {} impl AcpiHandler for EarlyACPIHandler { unsafe fn map_physical_region(&self, phys: usize, size: usize) -> PhysicalMapping { unsafe { - let virt = map_physical(phys as u64, size as u64); + let virt = map_physical(phys as u64, size as u64, false); return PhysicalMapping::new(phys, NonNull::new(virt as *mut T).unwrap(), size, size, *self); } } diff --git a/kernel/src/sys/hpet.rs b/kernel/src/sys/hpet.rs index b6fd3bf..e3c0979 100644 --- a/kernel/src/sys/hpet.rs +++ b/kernel/src/sys/hpet.rs @@ -131,7 +131,7 @@ pub fn sleep_internal(task: Task) { } pub fn setup_hpet(tables: &AcpiTables) { let hpet_info = HpetInfo::new(tables).unwrap(); - let address = unsafe { map_physical(hpet_info.base_address as u64, 0x200) } as *mut u64; + let address = unsafe { map_physical(hpet_info.base_address as u64, 0x200, false) } as *mut u64; ADDRESS.store(address, Ordering::SeqCst); let period = unsafe { address.add(REGISTER_CAPABILITIES).read_volatile() >> 32 } as usize; PERIOD.store(period, Ordering::SeqCst); diff --git a/kernel/src/sys/ioapic.rs b/kernel/src/sys/ioapic.rs index 54e1e46..10133ec 100644 --- a/kernel/src/sys/ioapic.rs +++ b/kernel/src/sys/ioapic.rs @@ -94,7 +94,7 @@ pub fn register_irq_handler(vector: usize, handler: fn()) { } pub fn setup_ioapic(apic_i: u8, phys: u64, gsi_base: u32) { let apic_i = apic_i as usize; - let address = unsafe { map_physical(phys, 0x14) as *mut u32 }; + let address = unsafe { map_physical(phys, 0x14, false) as *mut u32 }; IOAPICS[apic_i].address.store(address, Ordering::SeqCst); IOAPICS[apic_i].start_gsi.store(gsi_base, Ordering::SeqCst); let max_ints = (read_register(apic_i, REGISTER_VERSION) >> 16) & 0xff; diff --git a/kernel/src/sys/lapic.rs b/kernel/src/sys/lapic.rs index 67effb3..83e078e 100644 --- a/kernel/src/sys/lapic.rs +++ b/kernel/src/sys/lapic.rs @@ -26,7 +26,7 @@ pub fn send_eoi() { } } pub fn setup_lapic(phys: u64) { - let address = unsafe { map_physical(phys, 0x400) as *mut u32 }; + let address = unsafe { map_physical(phys, 0x400, false) as *mut u32 }; ADDRESS.store(address, Ordering::SeqCst); unsafe { BSP_LAPIC_ID.store(address.add(REGISTER_ID).read_volatile() as u8, Ordering::SeqCst); diff --git a/kernel/src/sys/task.rs b/kernel/src/sys/task.rs index b82b092..d3b5a99 100644 --- a/kernel/src/sys/task.rs +++ b/kernel/src/sys/task.rs @@ -3,7 +3,7 @@ use core::{ sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering}, }; -use alloc::{boxed::Box, sync::Arc}; +use alloc::{sync::Arc, vec, vec::Vec}; use kernel_common::instructions::hlt; use spin::Mutex; @@ -32,7 +32,7 @@ pub enum TaskState { pub struct Task { pub id: usize, state: ISRState, - _kernel_stack: Box, + _kernel_stack: Vec, initial_func: fn(), pub task_state: TaskState, pub sleep_until_us: usize, @@ -43,17 +43,14 @@ pub struct Task { const STACK_SIZE: usize = 64 * 1024; static NEXT_TASK_ID: AtomicUsize = AtomicUsize::new(2); -#[repr(align(16))] -#[repr(C)] -struct Stack([u8; STACK_SIZE]); - pub static CURRENT_TASK: Mutex> = Mutex::new(None); pub static CURRENT_TASK_LOCK: Spinlock = Spinlock::new(); static RFLAGS: AtomicU64 = AtomicU64::new(0); pub static MULTITASKING_ENABLED: AtomicBool = AtomicBool::new(false); pub fn allocate_stack() -> u64 { - Box::leak(Box::new(Stack([0; STACK_SIZE]))) as *mut Stack as u64 + STACK_SIZE as u64 + let stack: Vec = vec![0; STACK_SIZE]; + stack.leak().as_mut_ptr() as u64 + STACK_SIZE as u64 } pub fn switch_task(current_state: &mut ISRState, new_task: Task) { assert!(CURRENT_TASK_LOCK.is_locked()); @@ -77,8 +74,7 @@ pub fn switch_task(current_state: &mut ISRState, new_task: Task) { schedule_timer_interrupt(); } pub fn create_task(func: fn()) -> Task { - let stack = Box::new(Stack([0; STACK_SIZE])); - let stack_address: *const Stack = &*stack; + let stack = vec![0; STACK_SIZE]; let task = Task { id: NEXT_TASK_ID.fetch_add(1, Ordering::SeqCst), state: ISRState { @@ -102,7 +98,7 @@ pub fn create_task(func: fn()) -> Task { rip: task_entry as u64, cs: 8, rflags: RFLAGS.load(Ordering::SeqCst), - rsp: stack_address as u64 + STACK_SIZE as u64, + rsp: stack.as_ptr() as u64 + STACK_SIZE as u64, ss: 16, }, _kernel_stack: stack,