mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-04-25 11:49:03 +02:00
Add a kernel crash function, add a timer using the timer interrupt and
set PIT interval to 1000hz, use a vector inside Framebuffer, remove without_interrupts from the framebuffer and serial console, move to usize on primitives, add date at boot and turn on multithreading, add a boot animation and add a test_performance function with the new timer
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::driver::timer::TIMER;
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
use limine::response::{HhdmResponse, MemoryMapResponse};
|
use limine::response::{HhdmResponse, MemoryMapResponse};
|
||||||
|
|
||||||
@@ -14,8 +15,7 @@ pub fn init<'a>(
|
|||||||
return init_x86_64(hhdm_response, memory_map_response);
|
return init_x86_64(hhdm_response, memory_map_response);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn idle() -> ! {
|
pub fn idle() {
|
||||||
loop {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
asm!("hlt");
|
asm!("hlt");
|
||||||
@@ -25,4 +25,36 @@ pub fn idle() -> ! {
|
|||||||
asm!("idle 0");
|
asm!("idle 0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sleep(ticks: u64) {
|
||||||
|
let start = TIMER.now();
|
||||||
|
while (TIMER.now() - start).elapsed() <= ticks {
|
||||||
|
idle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn infinite_idle() -> ! {
|
||||||
|
loop {
|
||||||
|
idle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn kernel_crash() -> ! {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm!("ud2")
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm!("udf #0")
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm!("unimp")
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {} // satisfies -> ! on unknown archs
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
use crate::arch::x86_64::gdt::load_gdt_x86_64;
|
use crate::arch::x86_64::gdt::load_gdt_x86_64;
|
||||||
use crate::arch::x86_64::interrupts::{PICS, init_idt_x86_64};
|
use crate::arch::x86_64::interrupts::{InterruptIndex, PICS, init_idt_x86_64};
|
||||||
use limine::response::{HhdmResponse, MemoryMapResponse};
|
use limine::response::{HhdmResponse, MemoryMapResponse};
|
||||||
use x86_64::instructions::interrupts;
|
use x86_64::instructions::interrupts::without_interrupts;
|
||||||
|
use x86_64::instructions::{interrupts, port::Port};
|
||||||
|
|
||||||
|
const TIMER_PRECISION_HZ: u32 = 1000;
|
||||||
|
const PIT_DIVISOR: u16 = (1_193_182_u32 / TIMER_PRECISION_HZ) as u16;
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::arch::x86_64::{
|
use crate::arch::x86_64::{
|
||||||
@@ -22,6 +26,19 @@ pub fn memory_management_init<'a>(
|
|||||||
(mapper, frame_allocator)
|
(mapper, frame_allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_pit_interval() {
|
||||||
|
without_interrupts(|| {
|
||||||
|
let mut command_port: Port<u8> = Port::new(0x43);
|
||||||
|
let mut data_port: Port<u8> = Port::new(0x40);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
command_port.write(0b00_11_011_0);
|
||||||
|
data_port.write((PIT_DIVISOR & 0xFF) as u8); // low byte
|
||||||
|
data_port.write(((PIT_DIVISOR >> 8) & 0xFF) as u8); // high byte
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init_x86_64<'a>(
|
pub fn init_x86_64<'a>(
|
||||||
hhdm_response: &HhdmResponse,
|
hhdm_response: &HhdmResponse,
|
||||||
memory_map_response: &'a MemoryMapResponse,
|
memory_map_response: &'a MemoryMapResponse,
|
||||||
@@ -35,6 +52,8 @@ pub fn init_x86_64<'a>(
|
|||||||
pics.write_masks(0xFC, 0xFF);
|
pics.write_masks(0xFC, 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_pit_interval();
|
||||||
|
|
||||||
interrupts::enable();
|
interrupts::enable();
|
||||||
|
|
||||||
let (mut mapper, mut frame_allocator) =
|
let (mut mapper, mut frame_allocator) =
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::driver::timer::TIMER;
|
||||||
use crate::{arch::x86_64::gdt, driver::keyboard::keyboard_interrupt_handler, println};
|
use crate::{arch::x86_64::gdt, driver::keyboard::keyboard_interrupt_handler, println};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use pic8259::ChainedPics;
|
use pic8259::ChainedPics;
|
||||||
@@ -18,7 +19,7 @@ pub static PICS: Mutex<ChainedPics> =
|
|||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum InterruptIndex {
|
pub enum InterruptIndex {
|
||||||
Timer = PIC_1_OFFSET,
|
Timer = PIC_1_OFFSET,
|
||||||
Keyboard, // putting it below increments it by 1, so its offset + 1
|
Keyboard = PIC_1_OFFSET + 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InterruptIndex {
|
impl InterruptIndex {
|
||||||
@@ -83,6 +84,8 @@ pub extern "x86-interrupt" fn gpf_handler(stack_frame: InterruptStackFrame, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||||
|
TIMER.interrupt();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
PICS.lock()
|
PICS.lock()
|
||||||
.notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
.notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ pub fn render_char(
|
|||||||
font_size,
|
font_size,
|
||||||
font_size,
|
font_size,
|
||||||
color,
|
color,
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
|
use alloc::vec;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use limine::framebuffer::Framebuffer as LimineFramebuffer;
|
use limine::framebuffer::Framebuffer as LimineFramebuffer;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::arch::x86_64::interrupts::without_interrupts;
|
use crate::arch::x86_64::interrupts::without_interrupts;
|
||||||
|
|
||||||
const MAX_BACKBUFFER_PIXELS: usize = 1920 * 1080;
|
|
||||||
static mut BACK_BUFFER: [u32; MAX_BACKBUFFER_PIXELS] = [0; MAX_BACKBUFFER_PIXELS];
|
|
||||||
|
|
||||||
pub struct Framebuffer {
|
pub struct Framebuffer {
|
||||||
addr: *mut u32,
|
addr: *mut u32,
|
||||||
back_buffer: *mut u32,
|
back_buffer: Vec<u32>,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
pitch: usize,
|
pitch: usize,
|
||||||
@@ -21,12 +20,11 @@ impl Framebuffer {
|
|||||||
let width = limine_fb.width() as usize;
|
let width = limine_fb.width() as usize;
|
||||||
let height = limine_fb.height() as usize;
|
let height = limine_fb.height() as usize;
|
||||||
let pitch = limine_fb.pitch() as usize / 4;
|
let pitch = limine_fb.pitch() as usize / 4;
|
||||||
let needed = pitch.saturating_mul(height);
|
let back_buffer_len = width * height;
|
||||||
let back_buffer_len = core::cmp::min(needed, MAX_BACKBUFFER_PIXELS);
|
|
||||||
|
|
||||||
Framebuffer {
|
Framebuffer {
|
||||||
addr: limine_fb.addr().cast::<u32>(),
|
addr: limine_fb.addr().cast::<u32>(),
|
||||||
back_buffer: core::ptr::addr_of_mut!(BACK_BUFFER).cast::<u32>(),
|
back_buffer: vec![0u32; width * height],
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
pitch,
|
pitch,
|
||||||
@@ -44,16 +42,22 @@ impl Framebuffer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
self.back_buffer[idx] = color;
|
||||||
*self.back_buffer.add(idx) = color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn swap(&mut self) {
|
pub fn swap(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::copy_nonoverlapping(self.back_buffer, self.addr, self.back_buffer_len);
|
core::ptr::copy_nonoverlapping(
|
||||||
|
self.back_buffer.as_ptr(),
|
||||||
|
self.addr,
|
||||||
|
self.back_buffer_len,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self, color: u32) {
|
||||||
|
self.back_buffer.fill(color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Framebuffer {}
|
unsafe impl Send for Framebuffer {}
|
||||||
@@ -65,10 +69,8 @@ pub fn init_framebuffer(raw: &LimineFramebuffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_framebuffer<F: FnOnce(&mut Framebuffer)>(f: F) {
|
pub fn with_framebuffer<F: FnOnce(&mut Framebuffer)>(f: F) {
|
||||||
without_interrupts(|| {
|
|
||||||
let mut guard = FRAMEBUFFER.lock();
|
let mut guard = FRAMEBUFFER.lock();
|
||||||
if let Some(fb) = guard.as_mut() {
|
if let Some(fb) = guard.as_mut() {
|
||||||
f(fb);
|
f(fb);
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,45 @@
|
|||||||
use crate::driver::graphics::framebuffer::Framebuffer;
|
use crate::driver::graphics::{base::rgb, font_render::render_text, framebuffer::Framebuffer};
|
||||||
|
use alloc::{format, string::ToString};
|
||||||
use core::f32::consts::PI;
|
use core::f32::consts::PI;
|
||||||
use micromath::F32Ext;
|
use micromath::F32Ext;
|
||||||
|
|
||||||
pub fn line(framebuffer: &mut Framebuffer, mut x0: i64, mut y0: i64, x1: i64, y1: i64, color: u32) {
|
pub fn line(framebuffer: &mut Framebuffer, x0: usize, y0: usize, x1: usize, y1: usize, color: u32) {
|
||||||
let mut dx = x1 - x0;
|
let mut x0 = x0 as isize;
|
||||||
let mut dy = y1 - y0;
|
let mut y0 = y0 as isize;
|
||||||
|
let x1 = x1 as isize;
|
||||||
|
let y1 = y1 as isize;
|
||||||
|
|
||||||
|
let mut dx: isize = x1 - x0;
|
||||||
|
let mut dy: isize = y1 - y0;
|
||||||
|
|
||||||
if dx < 0 {
|
if dx < 0 {
|
||||||
dx = -dx;
|
dx = -dx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if dy < 0 {
|
if dy < 0 {
|
||||||
dy = -dy;
|
dy = -dy;
|
||||||
}
|
}
|
||||||
|
|
||||||
let step_x = if x0 < x1 { 1 } else { -1 };
|
let step_x: isize = if x0 < x1 { 1 } else { -1 };
|
||||||
let step_y = if y0 < y1 { 1 } else { -1 };
|
let step_y: isize = if y0 < y1 { 1 } else { -1 };
|
||||||
|
|
||||||
let mut error = dx - dy;
|
let mut error: isize = dx - dy;
|
||||||
let mut e2: i64;
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
framebuffer.put_pixel(x0 as usize, y0 as usize, color);
|
framebuffer.put_pixel(x0 as usize, y0 as usize, color);
|
||||||
|
|
||||||
if x0 == x1 && y0 == y1 {
|
let e2: isize = 2 * error;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
e2 = 2 * error;
|
|
||||||
|
|
||||||
if e2 > -dy {
|
if e2 > -dy {
|
||||||
error -= dy;
|
error -= dy;
|
||||||
x0 += step_x;
|
x0 += step_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if e2 < dx {
|
if e2 < dx {
|
||||||
error += dx;
|
error += dx;
|
||||||
y0 += step_y;
|
y0 += step_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if x0 == x1 && y0 == y1 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,31 +53,9 @@ pub fn triangle_outline(
|
|||||||
y3: usize,
|
y3: usize,
|
||||||
color: u32,
|
color: u32,
|
||||||
) {
|
) {
|
||||||
line(
|
line(framebuffer, x1, y1, x2, y2, color);
|
||||||
framebuffer,
|
line(framebuffer, x1, y1, x3, y3, color);
|
||||||
x1 as i64,
|
line(framebuffer, x2, y2, x3, y3, color);
|
||||||
y1 as i64,
|
|
||||||
x2 as i64,
|
|
||||||
y2 as i64,
|
|
||||||
color,
|
|
||||||
);
|
|
||||||
line(
|
|
||||||
framebuffer,
|
|
||||||
x1 as i64,
|
|
||||||
y1 as i64,
|
|
||||||
x3 as i64,
|
|
||||||
y3 as i64,
|
|
||||||
color,
|
|
||||||
);
|
|
||||||
line(
|
|
||||||
framebuffer,
|
|
||||||
x2 as i64,
|
|
||||||
y2 as i64,
|
|
||||||
x3 as i64,
|
|
||||||
y3 as i64,
|
|
||||||
color,
|
|
||||||
);
|
|
||||||
framebuffer.swap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn circle_outline(framebuffer: &mut Framebuffer, x: usize, y: usize, radius: f32, color: u32) {
|
pub fn circle_outline(framebuffer: &mut Framebuffer, x: usize, y: usize, radius: f32, color: u32) {
|
||||||
@@ -92,42 +72,37 @@ pub fn circle_outline(framebuffer: &mut Framebuffer, x: usize, y: usize, radius:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
framebuffer.swap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn circle_filled(framebuffer: &mut Framebuffer, x0: usize, y0: usize, radius: f32, color: u32) {
|
pub fn circle_filled(framebuffer: &mut Framebuffer, x0: usize, y0: usize, radius: f32, color: u32) {
|
||||||
let mut x = radius as i64;
|
let mut x = radius as isize;
|
||||||
let mut y: i64 = 0;
|
let mut y: isize = 0;
|
||||||
let mut x_change: i64 = 1 - (radius as i64 * 2);
|
let mut x_change: isize = 1 - (radius as isize * 2);
|
||||||
let mut y_change: i64 = 0;
|
let mut y_change: isize = 0;
|
||||||
let mut radius_error: i64 = 0;
|
let mut radius_error: isize = 0;
|
||||||
|
|
||||||
while x >= y {
|
while x >= y {
|
||||||
let mut i = x0 as i64 - x;
|
let mut i = x0 as isize - x;
|
||||||
while i <= x0 as i64 + x {
|
while i <= x0 as isize + x {
|
||||||
framebuffer.put_pixel(i as usize, (y0 as i64 + y) as usize, color);
|
framebuffer.put_pixel(i as usize, (y0 as isize + y) as usize, color);
|
||||||
framebuffer.put_pixel(i as usize, (y0 as i64 - y) as usize, color);
|
framebuffer.put_pixel(i as usize, (y0 as isize - y) as usize, color);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
let mut i = x0 as isize - y;
|
||||||
let mut i = x0 as i64 - y;
|
while i <= x0 as isize + y {
|
||||||
while i <= x0 as i64 + y {
|
framebuffer.put_pixel(i as usize, (y0 as isize + x) as usize, color);
|
||||||
framebuffer.put_pixel(i as usize, (y0 as i64 + x) as usize, color);
|
framebuffer.put_pixel(i as usize, (y0 as isize - x) as usize, color);
|
||||||
framebuffer.put_pixel(i as usize, (y0 as i64 - x) as usize, color);
|
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
y += 1;
|
y += 1;
|
||||||
radius_error += y_change;
|
radius_error += y_change;
|
||||||
y_change += 2;
|
y_change += 2;
|
||||||
|
|
||||||
if (radius_error * 2) + x_change > 0 {
|
if (radius_error * 2) + x_change > 0 {
|
||||||
x -= 1;
|
x -= 1;
|
||||||
radius_error += x_change;
|
radius_error += x_change;
|
||||||
x_change += 2;
|
x_change += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
framebuffer.swap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rectangle_filled(
|
pub fn rectangle_filled(
|
||||||
@@ -137,29 +112,24 @@ pub fn rectangle_filled(
|
|||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
color: u32,
|
color: u32,
|
||||||
swap: bool,
|
|
||||||
) {
|
) {
|
||||||
for fb_x in x..x + width {
|
for fb_x in x..x + width {
|
||||||
for fb_y in y..y + height {
|
for fb_y in y..y + height {
|
||||||
framebuffer.put_pixel(fb_x, fb_y, color);
|
framebuffer.put_pixel(fb_x, fb_y, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if swap {
|
|
||||||
framebuffer.swap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rectangle_outline(
|
pub fn rectangle_outline(
|
||||||
framebuffer: &mut Framebuffer,
|
framebuffer: &mut Framebuffer,
|
||||||
x: i64,
|
x: usize,
|
||||||
y: i64,
|
y: usize,
|
||||||
width: i64,
|
width: usize,
|
||||||
height: i64,
|
height: usize,
|
||||||
color: u32,
|
color: u32,
|
||||||
) {
|
) {
|
||||||
line(framebuffer, x, y, x + width, y, color); // bottomleft -> bottomright
|
line(framebuffer, x, y, x + width, y, color); // bottomleft -> bottomright
|
||||||
line(framebuffer, x, y + height, x + width, y + height, color); // topleft -> topright
|
line(framebuffer, x, y + height, x + width, y + height, color); // topleft -> topright
|
||||||
line(framebuffer, x, y, x, y + height, color); // bottomleft -> topleft
|
line(framebuffer, x, y, x, y + height, color); // bottomleft -> topleft
|
||||||
line(framebuffer, x + width, y, x + width, y + height, color); // bottomright -> topright
|
line(framebuffer, x + width, y, x + width, y + height, color); // bottomright -> topright
|
||||||
framebuffer.swap();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,10 +73,8 @@ pub fn init_serial_console(start_x: usize, start_y: usize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_serial_console<F: FnOnce(&mut SerialConsole)>(f: F) {
|
pub fn with_serial_console<F: FnOnce(&mut SerialConsole)>(f: F) {
|
||||||
without_interrupts(|| {
|
|
||||||
let mut guard = SERIAL_CONSOLE.lock();
|
let mut guard = SERIAL_CONSOLE.lock();
|
||||||
if let Some(fb) = guard.as_mut() {
|
if let Some(fb) = guard.as_mut() {
|
||||||
f(fb);
|
f(fb);
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,67 @@
|
|||||||
|
use core::{
|
||||||
|
ops::{Add, Sub},
|
||||||
|
sync::atomic::{AtomicU64, Ordering},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static TIMER: Timer = Timer::new();
|
||||||
|
|
||||||
|
pub struct Timer {
|
||||||
|
pub interrupt_count: AtomicU64,
|
||||||
|
pub date_at_boot: AtomicU64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Timer {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
interrupt_count: AtomicU64::new(0),
|
||||||
|
date_at_boot: AtomicU64::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_date_at_boot(&self, date_at_boot: u64) {
|
||||||
|
self.date_at_boot.store(date_at_boot, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_date_at_boot(&self) -> u64 {
|
||||||
|
self.date_at_boot.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn interrupt(&self) {
|
||||||
|
self.interrupt_count.fetch_add(1, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn now(&self) -> Time {
|
||||||
|
Time {
|
||||||
|
interrupt_count: self.interrupt_count.load(Ordering::Relaxed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||||
|
pub struct Time {
|
||||||
|
pub interrupt_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Time {
|
||||||
|
pub fn new(interrupt_count: u64) -> Self {
|
||||||
|
Self { interrupt_count }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn elapsed(&self) -> u64 {
|
||||||
|
self.interrupt_count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for Time {
|
||||||
|
type Output = Time;
|
||||||
|
fn add(self, other: Time) -> Time {
|
||||||
|
Time::new(self.interrupt_count + other.interrupt_count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub for Time {
|
||||||
|
type Output = Time;
|
||||||
|
fn sub(self, other: Time) -> Time {
|
||||||
|
Time::new(self.interrupt_count - other.interrupt_count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,20 +7,23 @@ use core::fmt::Write;
|
|||||||
|
|
||||||
use limine::BaseRevision;
|
use limine::BaseRevision;
|
||||||
use limine::request::{
|
use limine::request::{
|
||||||
FramebufferRequest, HhdmRequest, MemoryMapRequest, RequestsEndMarker, RequestsStartMarker,
|
DateAtBootRequest, FramebufferRequest, HhdmRequest, MemoryMapRequest, MpRequest,
|
||||||
|
RequestsEndMarker, RequestsStartMarker,
|
||||||
};
|
};
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
use crate::arch::arch::{idle, init};
|
use crate::arch::arch::{infinite_idle, init, kernel_crash, sleep};
|
||||||
use crate::driver::graphics::base::rgb;
|
use crate::driver::graphics::base::rgb;
|
||||||
use crate::driver::graphics::framebuffer::{init_framebuffer, with_framebuffer};
|
use crate::driver::graphics::framebuffer::{init_framebuffer, with_framebuffer};
|
||||||
use crate::driver::graphics::primitives::{
|
use crate::driver::graphics::primitives::{
|
||||||
circle_filled, circle_outline, rectangle_filled, rectangle_outline, triangle_outline,
|
circle_filled, circle_outline, rectangle_filled, rectangle_outline, triangle_outline,
|
||||||
};
|
};
|
||||||
use crate::driver::serial::{ConsoleWriter, init_serial_console, with_serial_console};
|
use crate::driver::serial::{ConsoleWriter, init_serial_console, with_serial_console};
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use crate::driver::timer::TIMER;
|
||||||
|
use crate::util::test_performance;
|
||||||
|
use alloc::{boxed::Box, string::ToString, vec::Vec};
|
||||||
|
|
||||||
/// Sets the base revision to the latest revision supported by the crate.
|
/// Sets the base revision to the latest revision supported by the crate.
|
||||||
/// See specification for further info.
|
/// See specification for further info.
|
||||||
@@ -42,6 +45,14 @@ static HHDM_REQUEST: HhdmRequest = HhdmRequest::new();
|
|||||||
#[unsafe(link_section = ".requests")]
|
#[unsafe(link_section = ".requests")]
|
||||||
static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new();
|
static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new();
|
||||||
|
|
||||||
|
#[used]
|
||||||
|
#[unsafe(link_section = ".requests")]
|
||||||
|
static DATE_AT_BOOT_REQUEST: DateAtBootRequest = DateAtBootRequest::new();
|
||||||
|
|
||||||
|
#[used]
|
||||||
|
#[unsafe(link_section = ".requests")]
|
||||||
|
static MP_REQUEST: MpRequest = MpRequest::new();
|
||||||
|
|
||||||
/// Define the stand and end markers for Limine requests.
|
/// Define the stand and end markers for Limine requests.
|
||||||
#[used]
|
#[used]
|
||||||
#[unsafe(link_section = ".requests_start_marker")]
|
#[unsafe(link_section = ".requests_start_marker")]
|
||||||
@@ -88,6 +99,16 @@ unsafe extern "C" fn kmain() -> ! {
|
|||||||
// removed by the linker.
|
// removed by the linker.
|
||||||
assert!(BASE_REVISION.is_supported());
|
assert!(BASE_REVISION.is_supported());
|
||||||
|
|
||||||
|
if let Some(hhdm_response) = HHDM_REQUEST.get_response() {
|
||||||
|
if let Some(memory_map_response) = MEMORY_MAP_REQUEST.get_response() {
|
||||||
|
let (mapper, frame_allocator) = init(hhdm_response, memory_map_response);
|
||||||
|
} else {
|
||||||
|
kernel_crash(); // Could not get required info from Limine's memory map.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
kernel_crash(); // Could not get required info from the Limine's higher-half direct mapping.
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.get_response() {
|
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.get_response() {
|
||||||
if let Some(limine_framebuffer) = framebuffer_response.framebuffers().next() {
|
if let Some(limine_framebuffer) = framebuffer_response.framebuffers().next() {
|
||||||
init_framebuffer(&limine_framebuffer);
|
init_framebuffer(&limine_framebuffer);
|
||||||
@@ -96,26 +117,13 @@ unsafe extern "C" fn kmain() -> ! {
|
|||||||
|
|
||||||
init_serial_console(0, 0);
|
init_serial_console(0, 0);
|
||||||
|
|
||||||
if let Some(hhdm_response) = HHDM_REQUEST.get_response() {
|
if let Some(date_at_boot_response) = DATE_AT_BOOT_REQUEST.get_response() {
|
||||||
if let Some(memory_map_response) = MEMORY_MAP_REQUEST.get_response() {
|
TIMER.set_date_at_boot(date_at_boot_response.timestamp().as_secs());
|
||||||
let (mapper, frame_allocator) = init(hhdm_response, memory_map_response);
|
|
||||||
} else {
|
} else {
|
||||||
panic!("Could not get required info from Limine's memory map. ")
|
println!("Could not get date at boot. Will default to 0.")
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!("Could not get required info from the Limine's higher-half direct mapping. ")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
with_framebuffer(|mut fb| {
|
boot_animation();
|
||||||
let (width, height) = (fb.width.clone(), fb.height.clone());
|
|
||||||
init_serial_console(0, 0);
|
|
||||||
rectangle_filled(&mut fb, 0, 0, width, height, rgb(253, 129, 0), true);
|
|
||||||
rectangle_filled(&mut fb, 700, 400, 200, 200, rgb(0, 0, 0), true);
|
|
||||||
rectangle_outline(&mut fb, 400, 400, 100, 100, rgb(0, 0, 0));
|
|
||||||
circle_filled(&mut fb, 200, 200, 100.0, rgb(0, 0, 0));
|
|
||||||
circle_outline(&mut fb, 400, 200, 100.0, rgb(0, 0, 0));
|
|
||||||
triangle_outline(&mut fb, 100, 400, 200, 400, 150, 600, rgb(0, 0, 0));
|
|
||||||
});
|
|
||||||
|
|
||||||
let x = Box::new(41);
|
let x = Box::new(41);
|
||||||
let mut test_vec: Vec<u16> = Vec::new();
|
let mut test_vec: Vec<u16> = Vec::new();
|
||||||
@@ -124,14 +132,82 @@ unsafe extern "C" fn kmain() -> ! {
|
|||||||
test_vec.push(9);
|
test_vec.push(9);
|
||||||
println!("After: {:?}", test_vec);
|
println!("After: {:?}", test_vec);
|
||||||
|
|
||||||
idle();
|
sleep(500);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
with_serial_console(|serial_console| serial_console.clear(0, 0));
|
||||||
|
|
||||||
|
with_framebuffer(|mut fb| {
|
||||||
|
fb.clear(rgb(253, 129, 0));
|
||||||
|
|
||||||
|
// rectangle_filled(&mut fb, 700, 400, 200, 200, rgb(0, 0, 0));
|
||||||
|
// rectangle_outline(&mut fb, 400, 400, 100, 100, rgb(0, 0, 0));
|
||||||
|
// circle_filled(&mut fb, 200, 200, 100.0, rgb(0, 0, 0));
|
||||||
|
|
||||||
|
circle_outline(&mut fb, 400, 200, 100.0, rgb(0, 0, 0));
|
||||||
|
triangle_outline(&mut fb, 100, 400, 200, 400, 150, 600, rgb(0, 0, 0));
|
||||||
|
});
|
||||||
|
|
||||||
|
let (hours, minutes, seconds) =
|
||||||
|
unix_to_hms(TIMER.get_date_at_boot() + (TIMER.now().elapsed()) / 1000);
|
||||||
|
|
||||||
|
print!("{:?}:{:?}:{:?}", hours, minutes, seconds);
|
||||||
|
|
||||||
|
sleep(16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn boot_animation() {
|
||||||
|
let mut i = 1;
|
||||||
|
|
||||||
|
while i < 10 {
|
||||||
|
let mut width = 0;
|
||||||
|
let mut height = 0;
|
||||||
|
|
||||||
|
with_framebuffer(|fb| {
|
||||||
|
fb.clear(rgb(253, 129, 0));
|
||||||
|
width = fb.width;
|
||||||
|
height = fb.height;
|
||||||
|
});
|
||||||
|
|
||||||
|
let text_width = ("XunilOS Loading".len() + ".".repeat(i).len()) * 4 * 2;
|
||||||
|
|
||||||
|
with_serial_console(|serial_console| {
|
||||||
|
serial_console.clear(width / 2 - text_width / 2, height / 2)
|
||||||
|
});
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
"XunilOS Loading".to_string() + &".".repeat(i).as_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
|
||||||
|
sleep(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
with_serial_console(|serial_console| {
|
||||||
|
serial_console.clear(0, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
with_framebuffer(|fb| {
|
||||||
|
fb.clear(rgb(253, 129, 0));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unix_to_hms(timestamp: u64) -> (u64, u64, u64) {
|
||||||
|
let seconds = timestamp % 86400;
|
||||||
|
let h = seconds / 3600;
|
||||||
|
let m = (seconds % 3600) / 60;
|
||||||
|
let s = seconds % 60;
|
||||||
|
(h, m, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
with_framebuffer(|mut fb| {
|
with_framebuffer(|mut fb| {
|
||||||
let (width, height) = (fb.width.clone(), fb.height.clone());
|
let (width, height) = (fb.width.clone(), fb.height.clone());
|
||||||
rectangle_filled(&mut fb, 0, 0, width, height, rgb(180, 0, 0), true);
|
rectangle_filled(&mut fb, 0, 0, width, height, rgb(180, 0, 0));
|
||||||
|
|
||||||
with_serial_console(|console| {
|
with_serial_console(|console| {
|
||||||
console.clear(5, 5);
|
console.clear(5, 5);
|
||||||
@@ -148,5 +224,5 @@ fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
idle();
|
infinite_idle();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::{driver::timer::TIMER, println};
|
||||||
use spin::{Mutex, MutexGuard};
|
use spin::{Mutex, MutexGuard};
|
||||||
|
|
||||||
pub struct LinkedNode {
|
pub struct LinkedNode {
|
||||||
@@ -34,3 +35,10 @@ impl<A> Locked<A> {
|
|||||||
self.inner.lock()
|
self.inner.lock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn test_performance<F: FnOnce()>(function: F) {
|
||||||
|
let start = TIMER.now();
|
||||||
|
let ret = function();
|
||||||
|
println!("took {} ms", (TIMER.now() - start).elapsed());
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user