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);
}
}
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) {

View file

@ -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<u8>,
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 {}

View file

@ -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]

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 spin::Mutex;
use crate::{cpu::paging::map_physical, misc::draw_target::FramebufferTarget};
static FRAMEBUFFER: Mutex<FramebufferTarget> = Mutex::new(FramebufferTarget {
framebuffer: null_mut(),
width: 0,
height: 0,
stride: 0,
});
static FRAMEBUFFER: Mutex<Option<FramebufferTarget>> = Mutex::new(None);
static FRAMEBUFFER_ADDR: AtomicPtr<u8> = 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);
}

View file

@ -10,7 +10,7 @@ pub struct EarlyACPIHandler {}
impl AcpiHandler for EarlyACPIHandler {
unsafe fn map_physical_region<T>(&self, phys: usize, size: usize) -> PhysicalMapping<Self, T> {
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);
}
}

View file

@ -131,7 +131,7 @@ pub fn sleep_internal(task: Task) {
}
pub fn setup_hpet(tables: &AcpiTables<EarlyACPIHandler>) {
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);

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) {
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;

View file

@ -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);

View file

@ -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<Stack>,
_kernel_stack: Vec<u8>,
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<Option<Task>> = 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<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) {
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,