This commit is contained in:
parent
c472ef1e27
commit
34e784ddf7
9 changed files with 98 additions and 37 deletions
|
@ -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) {
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue