Add display tty
All checks were successful
Build / build (push) Successful in 1m13s

This commit is contained in:
Mathieu Strypsteen 2024-11-15 22:20:42 +01:00
parent c472ef1e27
commit 34e784ddf7
9 changed files with 98 additions and 37 deletions

View file

@ -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); 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_offset = phys % 0x1000;
let phys_end = (phys + size + 0xfff) / 0x1000 * 0x1000; let phys_end = (phys + size + 0xfff) / 0x1000 * 0x1000;
let phys_start = phys - phys_offset; let phys_start = phys - phys_offset;
size = phys_end - phys_start; size = phys_end - phys_start;
let virt_start = find_free_virt_range(KERNEL_MAPPINGS_START, KERNEL_MAPPINGS_END, size); 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 virt_start + phys_offset
} }
pub unsafe fn unmap_physical(address: u64, size: u64) { pub unsafe fn unmap_physical(address: u64, size: u64) {

View file

@ -1,5 +1,6 @@
use core::convert::Infallible; use core::convert::Infallible;
use alloc::vec::Vec;
use embedded_graphics::{ use embedded_graphics::{
pixelcolor::Bgr888, pixelcolor::Bgr888,
prelude::{DrawTarget, OriginDimensions, RgbColor, Size}, prelude::{DrawTarget, OriginDimensions, RgbColor, Size},
@ -7,7 +8,7 @@ use embedded_graphics::{
}; };
pub struct FramebufferTarget { pub struct FramebufferTarget {
pub framebuffer: *mut u8, pub framebuffer: Vec<u8>,
pub width: usize, pub width: usize,
pub height: usize, pub height: usize,
pub stride: 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 { if i.0.x < 0 || i.0.x >= self.width as i32 || i.0.y < 0 || i.0.y >= self.height as i32 {
continue; continue;
} }
let offset = (i.0.y * self.stride as i32 + i.0.x) as isize * 4; let offset = (i.0.y * self.stride as i32 + i.0.x) as usize * 4;
unsafe { self.framebuffer[offset] = i.1.b();
self.framebuffer.offset(offset).write_volatile(i.1.b()); self.framebuffer[offset + 1] = i.1.g();
self.framebuffer.offset(offset + 1).write_volatile(i.1.g()); self.framebuffer[offset + 2] = i.1.r();
self.framebuffer.offset(offset + 2).write_volatile(i.1.r());
}
} }
Ok(()) Ok(())
} }
@ -41,5 +40,3 @@ impl OriginDimensions for FramebufferTarget {
Size::new(self.width as u32, self.height as u32) Size::new(self.width as u32, self.height as u32)
} }
} }
unsafe impl Send for FramebufferTarget {}
unsafe impl Sync for FramebufferTarget {}

View file

@ -124,7 +124,7 @@ extern "C" fn AcpiOsInstallInterruptHandler(gsi: UINT32, handler: ACPI_OSD_HANDL
#[no_mangle] #[no_mangle]
extern "C" fn AcpiOsMapMemory(phys: ACPI_PHYSICAL_ADDRESS, size: ACPI_SIZE) -> *mut c_void { extern "C" fn AcpiOsMapMemory(phys: ACPI_PHYSICAL_ADDRESS, size: ACPI_SIZE) -> *mut c_void {
unsafe { unsafe {
return map_physical(phys, size) as *mut c_void; return map_physical(phys, size, false) as *mut c_void;
} }
} }
#[no_mangle] #[no_mangle]

View file

@ -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 kernel_common::loader_struct::FramebufferInfo;
use spin::Mutex; use spin::Mutex;
use crate::{cpu::paging::map_physical, misc::draw_target::FramebufferTarget}; use crate::{cpu::paging::map_physical, misc::draw_target::FramebufferTarget};
static FRAMEBUFFER: Mutex<FramebufferTarget> = Mutex::new(FramebufferTarget { static FRAMEBUFFER: Mutex<Option<FramebufferTarget>> = Mutex::new(None);
framebuffer: null_mut(), static FRAMEBUFFER_ADDR: AtomicPtr<u8> = AtomicPtr::new(null_mut());
width: 0, static WIDTH: AtomicUsize = AtomicUsize::new(0);
height: 0, static HEIGHT: AtomicUsize = AtomicUsize::new(0);
stride: 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) { pub fn setup_display(info: FramebufferInfo) {
let addr = unsafe { map_physical(info.address, info.height * info.stride * 4) }; let addr = unsafe { map_physical(info.address, info.height * info.stride * 4, true) };
*FRAMEBUFFER.lock() = FramebufferTarget { FRAMEBUFFER_ADDR.store(addr as *mut u8, Ordering::SeqCst);
framebuffer: addr as *mut u8, let fb = vec![0; info.height as usize * info.stride as usize * 4];
*FRAMEBUFFER.lock() = Some(FramebufferTarget {
framebuffer: fb,
width: info.width as usize, width: info.width as usize,
height: info.height as usize, height: info.height as usize,
stride: info.stride 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);
} }

View file

@ -10,7 +10,7 @@ pub struct EarlyACPIHandler {}
impl AcpiHandler for EarlyACPIHandler { impl AcpiHandler for EarlyACPIHandler {
unsafe fn map_physical_region<T>(&self, phys: usize, size: usize) -> PhysicalMapping<Self, T> { unsafe fn map_physical_region<T>(&self, phys: usize, size: usize) -> PhysicalMapping<Self, T> {
unsafe { 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); return PhysicalMapping::new(phys, NonNull::new(virt as *mut T).unwrap(), size, size, *self);
} }
} }

View file

@ -131,7 +131,7 @@ pub fn sleep_internal(task: Task) {
} }
pub fn setup_hpet(tables: &AcpiTables<EarlyACPIHandler>) { pub fn setup_hpet(tables: &AcpiTables<EarlyACPIHandler>) {
let hpet_info = HpetInfo::new(tables).unwrap(); 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); ADDRESS.store(address, Ordering::SeqCst);
let period = unsafe { address.add(REGISTER_CAPABILITIES).read_volatile() >> 32 } as usize; let period = unsafe { address.add(REGISTER_CAPABILITIES).read_volatile() >> 32 } as usize;
PERIOD.store(period, Ordering::SeqCst); PERIOD.store(period, Ordering::SeqCst);

View file

@ -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) { pub fn setup_ioapic(apic_i: u8, phys: u64, gsi_base: u32) {
let apic_i = apic_i as usize; 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].address.store(address, Ordering::SeqCst);
IOAPICS[apic_i].start_gsi.store(gsi_base, Ordering::SeqCst); IOAPICS[apic_i].start_gsi.store(gsi_base, Ordering::SeqCst);
let max_ints = (read_register(apic_i, REGISTER_VERSION) >> 16) & 0xff; let max_ints = (read_register(apic_i, REGISTER_VERSION) >> 16) & 0xff;

View file

@ -26,7 +26,7 @@ pub fn send_eoi() {
} }
} }
pub fn setup_lapic(phys: u64) { 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); ADDRESS.store(address, Ordering::SeqCst);
unsafe { unsafe {
BSP_LAPIC_ID.store(address.add(REGISTER_ID).read_volatile() as u8, Ordering::SeqCst); BSP_LAPIC_ID.store(address.add(REGISTER_ID).read_volatile() as u8, Ordering::SeqCst);

View file

@ -3,7 +3,7 @@ use core::{
sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering}, 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 kernel_common::instructions::hlt;
use spin::Mutex; use spin::Mutex;
@ -32,7 +32,7 @@ pub enum TaskState {
pub struct Task { pub struct Task {
pub id: usize, pub id: usize,
state: ISRState, state: ISRState,
_kernel_stack: Box<Stack>, _kernel_stack: Vec<u8>,
initial_func: fn(), initial_func: fn(),
pub task_state: TaskState, pub task_state: TaskState,
pub sleep_until_us: usize, pub sleep_until_us: usize,
@ -43,17 +43,14 @@ pub struct Task {
const STACK_SIZE: usize = 64 * 1024; const STACK_SIZE: usize = 64 * 1024;
static NEXT_TASK_ID: AtomicUsize = AtomicUsize::new(2); static NEXT_TASK_ID: AtomicUsize = AtomicUsize::new(2);
#[repr(align(16))]
#[repr(C)]
struct Stack([u8; STACK_SIZE]);
pub static CURRENT_TASK: Mutex<Option<Task>> = Mutex::new(None); pub static CURRENT_TASK: Mutex<Option<Task>> = Mutex::new(None);
pub static CURRENT_TASK_LOCK: Spinlock = Spinlock::new(); pub static CURRENT_TASK_LOCK: Spinlock = Spinlock::new();
static RFLAGS: AtomicU64 = AtomicU64::new(0); static RFLAGS: AtomicU64 = AtomicU64::new(0);
pub static MULTITASKING_ENABLED: AtomicBool = AtomicBool::new(false); pub static MULTITASKING_ENABLED: AtomicBool = AtomicBool::new(false);
pub fn allocate_stack() -> u64 { 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<u8> = 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) { pub fn switch_task(current_state: &mut ISRState, new_task: Task) {
assert!(CURRENT_TASK_LOCK.is_locked()); assert!(CURRENT_TASK_LOCK.is_locked());
@ -77,8 +74,7 @@ pub fn switch_task(current_state: &mut ISRState, new_task: Task) {
schedule_timer_interrupt(); schedule_timer_interrupt();
} }
pub fn create_task(func: fn()) -> Task { pub fn create_task(func: fn()) -> Task {
let stack = Box::new(Stack([0; STACK_SIZE])); let stack = vec![0; STACK_SIZE];
let stack_address: *const Stack = &*stack;
let task = Task { let task = Task {
id: NEXT_TASK_ID.fetch_add(1, Ordering::SeqCst), id: NEXT_TASK_ID.fetch_add(1, Ordering::SeqCst),
state: ISRState { state: ISRState {
@ -102,7 +98,7 @@ pub fn create_task(func: fn()) -> Task {
rip: task_entry as u64, rip: task_entry as u64,
cs: 8, cs: 8,
rflags: RFLAGS.load(Ordering::SeqCst), 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, ss: 16,
}, },
_kernel_stack: stack, _kernel_stack: stack,