mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-04-25 11:49:03 +02:00
Move to single arch, add serial console, font rendering, panic handling, move graphics to multiple files, use a global mutex framebuffer & serialconsole
This commit is contained in:
32
kernel/Cargo.lock
generated
32
kernel/Cargo.lock
generated
@@ -8,6 +8,12 @@ version = "2.9.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "font8x8"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "875488b8711a968268c7cf5d139578713097ca4635a76044e8fe8eedf831d07e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "limine"
|
name = "limine"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -21,8 +27,19 @@ dependencies = [
|
|||||||
name = "limine-rust-template"
|
name = "limine-rust-template"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"font8x8",
|
||||||
"limine",
|
"limine",
|
||||||
"micromath",
|
"micromath",
|
||||||
|
"spin",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -30,3 +47,18 @@ name = "micromath"
|
|||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815"
|
checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
font8x8 = { version="0.3.1", default-features = false }
|
||||||
limine = "0.5"
|
limine = "0.5"
|
||||||
micromath = "2.1.0"
|
micromath = "2.1.0"
|
||||||
|
spin = "0.10.0"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|||||||
5
kernel/src/arch/mod.rs
Normal file
5
kernel/src/arch/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
pub mod serial;
|
||||||
|
pub mod gdt;
|
||||||
|
pub mod idt;
|
||||||
|
pub mod interrupts;
|
||||||
|
pub mod paging;
|
||||||
42
kernel/src/arch/serial.rs
Normal file
42
kernel/src/arch/serial.rs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
use crate::driver::graphics::framebuffer::{with_framebuffer, Framebuffer};
|
||||||
|
use crate::driver::graphics::font_render::render_text;
|
||||||
|
use crate::driver::graphics::base::rgb;
|
||||||
|
use spin::Mutex;
|
||||||
|
|
||||||
|
const DEFAULT_FONT_SIZE: usize = 3;
|
||||||
|
|
||||||
|
pub struct SerialConsole {
|
||||||
|
start_x: usize,
|
||||||
|
current_y: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerialConsole {
|
||||||
|
pub fn new(start_x: usize, start_y: usize) -> SerialConsole {
|
||||||
|
SerialConsole {
|
||||||
|
start_x,
|
||||||
|
current_y: start_y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_text(&mut self, fb: &mut Framebuffer, text: &str) {
|
||||||
|
self.current_y = render_text(fb, self.start_x - ((text.len() - text.matches('\n').count()) * DEFAULT_FONT_SIZE * 4), self.current_y, text, DEFAULT_FONT_SIZE, rgb(0, 0, 0));
|
||||||
|
self.current_y = render_text(fb, self.start_x - ((text.len() - text.matches('\n').count()) * DEFAULT_FONT_SIZE * 4), self.current_y, "\n", DEFAULT_FONT_SIZE, rgb(0, 0, 0)); // add a newline
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self, start_y: usize) {
|
||||||
|
self.current_y = start_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static SERIAL_CONSOLE: Mutex<Option<SerialConsole>> = Mutex::new(None);
|
||||||
|
|
||||||
|
pub fn init_serial_console(start_x: usize, start_y: usize) {
|
||||||
|
*SERIAL_CONSOLE.lock() = Some(SerialConsole::new(start_x, start_y));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_serial_console<F: FnOnce(&mut SerialConsole)>(f: F) {
|
||||||
|
let mut guard = SERIAL_CONSOLE.lock();
|
||||||
|
if let Some(fb) = guard.as_mut() {
|
||||||
|
f(fb);
|
||||||
|
}
|
||||||
|
}
|
||||||
5
kernel/src/driver/graphics/base.rs
Normal file
5
kernel/src/driver/graphics/base.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
pub const PI: f32 = 3.1415926535897;
|
||||||
|
|
||||||
|
pub fn rgb(r: u8, g: u8, b: u8) -> u32 {
|
||||||
|
((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
|
||||||
|
}
|
||||||
36
kernel/src/driver/graphics/font_render.rs
Normal file
36
kernel/src/driver/graphics/font_render.rs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
extern crate font8x8;
|
||||||
|
|
||||||
|
use crate::driver::graphics::framebuffer::Framebuffer;
|
||||||
|
use crate::driver::graphics::primitives::rectangle_filled;
|
||||||
|
use font8x8::legacy::BASIC_LEGACY;
|
||||||
|
|
||||||
|
pub fn render_char(framebuffer: &mut Framebuffer, start_x: usize, start_y: usize, char: usize, font_size: usize, color: u32) {
|
||||||
|
if let Some(glyph) = BASIC_LEGACY.get(char) {
|
||||||
|
for (row, row_bits) in glyph.iter().enumerate() {
|
||||||
|
for bit in 0..8 {
|
||||||
|
if (row_bits & (1 << bit)) != 0 {
|
||||||
|
rectangle_filled(framebuffer, start_x + bit * font_size, start_y + row * font_size, font_size, font_size, color, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_text(framebuffer: &mut Framebuffer, start_x: usize, start_y: usize, text: &str, font_size: usize, color: u32) -> usize {
|
||||||
|
let mut x = start_x;
|
||||||
|
let mut y = start_y;
|
||||||
|
|
||||||
|
for b in text.bytes() {
|
||||||
|
if b == b'\n' {
|
||||||
|
y += 12 * font_size;
|
||||||
|
x = start_x;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
render_char(framebuffer, x, y, b as usize, font_size, color);
|
||||||
|
x += 8 * font_size;
|
||||||
|
}
|
||||||
|
framebuffer.swap();
|
||||||
|
|
||||||
|
y
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
use limine::framebuffer::Framebuffer as LimineFramebuffer;
|
use limine::framebuffer::Framebuffer as LimineFramebuffer;
|
||||||
|
use spin::Mutex;
|
||||||
|
|
||||||
const MAX_BACKBUFFER_PIXELS: usize = 1920 * 1080;
|
const MAX_BACKBUFFER_PIXELS: usize = 1920 * 1080;
|
||||||
static mut BACK_BUFFER: [u32; MAX_BACKBUFFER_PIXELS] = [0; MAX_BACKBUFFER_PIXELS];
|
static mut BACK_BUFFER: [u32; MAX_BACKBUFFER_PIXELS] = [0; MAX_BACKBUFFER_PIXELS];
|
||||||
@@ -6,8 +7,8 @@ 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: *mut u32,
|
||||||
width: usize,
|
pub width: usize,
|
||||||
height: usize,
|
pub height: usize,
|
||||||
pitch: usize,
|
pitch: usize,
|
||||||
back_buffer_len: usize,
|
back_buffer_len: usize,
|
||||||
}
|
}
|
||||||
@@ -51,3 +52,18 @@ impl Framebuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for Framebuffer {}
|
||||||
|
|
||||||
|
pub static FRAMEBUFFER: Mutex<Option<Framebuffer>> = Mutex::new(None);
|
||||||
|
|
||||||
|
pub fn init_framebuffer(raw: &LimineFramebuffer) {
|
||||||
|
*FRAMEBUFFER.lock() = Some(Framebuffer::new(raw));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_framebuffer<F: FnOnce(&mut Framebuffer)>(f: F) {
|
||||||
|
let mut guard = FRAMEBUFFER.lock();
|
||||||
|
if let Some(fb) = guard.as_mut() {
|
||||||
|
f(fb);
|
||||||
|
}
|
||||||
|
}
|
||||||
4
kernel/src/driver/graphics/mod.rs
Normal file
4
kernel/src/driver/graphics/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
pub mod base;
|
||||||
|
pub mod framebuffer;
|
||||||
|
pub mod font_render;
|
||||||
|
pub mod primitives;
|
||||||
@@ -1,11 +1,6 @@
|
|||||||
use micromath::F32Ext;
|
use micromath::F32Ext;
|
||||||
use crate::driver::framebuffer::Framebuffer;
|
use crate::driver::graphics::framebuffer::Framebuffer;
|
||||||
|
use crate::driver::graphics::base::{rgb, PI};
|
||||||
const PI: f32 = 3.1415926535897;
|
|
||||||
|
|
||||||
pub fn rgb(r: u8, g: u8, b: u8) -> u32 {
|
|
||||||
((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn line(framebuffer: &mut Framebuffer, mut x0: i64, mut y0: i64, x1: i64, y1: i64, color: u32) {
|
pub fn line(framebuffer: &mut Framebuffer, mut x0: i64, mut y0: i64, x1: i64, y1: i64, color: u32) {
|
||||||
let mut dx = x1 - x0;
|
let mut dx = x1 - x0;
|
||||||
@@ -106,14 +101,16 @@ pub fn circle_filled(framebuffer: &mut Framebuffer, x0: usize, y0: usize, radius
|
|||||||
framebuffer.swap();
|
framebuffer.swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rectangle_filled(framebuffer: &mut Framebuffer, x: usize, y: usize, width: usize, height: usize, color: u32) {
|
pub fn rectangle_filled(framebuffer: &mut Framebuffer, x: usize, y: usize, width: usize, height: usize, 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();
|
framebuffer.swap();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rectangle_outline(framebuffer: &mut Framebuffer, x: i64, y: i64, width: i64, height: i64, color: u32) {
|
pub fn rectangle_outline(framebuffer: &mut Framebuffer, x: i64, y: i64, width: i64, height: i64, color: u32) {
|
||||||
line(framebuffer, x, y, x + width, y, color); // bottomleft -> bottomright
|
line(framebuffer, x, y, x + width, y, color); // bottomleft -> bottomright
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
pub mod framebuffer;
|
|
||||||
pub mod graphics;
|
pub mod graphics;
|
||||||
pub mod font_render;
|
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
@@ -7,9 +7,14 @@ use limine::BaseRevision;
|
|||||||
use limine::request::{FramebufferRequest, RequestsEndMarker, RequestsStartMarker};
|
use limine::request::{FramebufferRequest, RequestsEndMarker, RequestsStartMarker};
|
||||||
|
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
|
pub mod arch;
|
||||||
|
|
||||||
use crate::driver::graphics::{circle_filled, circle_outline, rectangle_filled, rectangle_outline, rgb, triangle_outline};
|
use spin::Mutex;
|
||||||
use crate::driver::framebuffer::Framebuffer;
|
use crate::arch::serial::{SerialConsole, init_serial_console, with_serial_console};
|
||||||
|
use crate::driver::graphics::font_render::render_text;
|
||||||
|
use crate::driver::graphics::primitives::{circle_filled, circle_outline, rectangle_filled, rectangle_outline, triangle_outline};
|
||||||
|
use crate::driver::graphics::base::rgb;
|
||||||
|
use crate::driver::graphics::framebuffer::{Framebuffer, init_framebuffer, with_framebuffer};
|
||||||
|
|
||||||
/// 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.
|
||||||
@@ -31,6 +36,27 @@ static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new();
|
|||||||
#[unsafe(link_section = ".requests_end_marker")]
|
#[unsafe(link_section = ".requests_end_marker")]
|
||||||
static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
|
static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
|
||||||
|
|
||||||
|
// #[macro_export]
|
||||||
|
// macro_rules! print {
|
||||||
|
// ($($arg:tt)*) => (with_framebuffer(|mut fb|{
|
||||||
|
// with_serial_console(|serial_console| {
|
||||||
|
// serial_console.render_text(&mut fb, format_args!($($arg)*));
|
||||||
|
// });
|
||||||
|
// }));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[macro_export]
|
||||||
|
// macro_rules! println {
|
||||||
|
// () => ($crate::print!("\n"));
|
||||||
|
// ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[doc(hidden)]
|
||||||
|
// pub fn _print(args: fmt::Arguments) {
|
||||||
|
// use core::fmt::Write;
|
||||||
|
// WRITER.lock().write_fmt(args).unwrap();
|
||||||
|
// }
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
unsafe extern "C" fn kmain() -> ! {
|
unsafe extern "C" fn kmain() -> ! {
|
||||||
// All limine requests must also be referenced in a called function, otherwise they may be
|
// All limine requests must also be referenced in a called function, otherwise they may be
|
||||||
@@ -39,13 +65,18 @@ unsafe extern "C" fn kmain() -> ! {
|
|||||||
|
|
||||||
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() {
|
||||||
let mut fb = Framebuffer::new(&limine_framebuffer);
|
init_framebuffer(&limine_framebuffer);
|
||||||
rectangle_filled(&mut fb, 0, 0, limine_framebuffer.width() as usize, limine_framebuffer.height() as usize, rgb(253, 129, 0));
|
with_framebuffer(|mut fb| {
|
||||||
rectangle_filled(&mut fb, 700, 400, 200, 200, rgb(0, 0, 0));
|
let (width, height) = (fb.width.clone(), fb.height.clone());
|
||||||
|
init_serial_console(width / 2, height / 3);
|
||||||
|
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));
|
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_filled(&mut fb, 200, 200, 100.0, rgb(0, 0, 0));
|
||||||
circle_outline(&mut fb, 400, 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));
|
triangle_outline(&mut fb, 100, 400, 200, 400, 150, 600, rgb(0, 0, 0));
|
||||||
|
});
|
||||||
|
panic!("idk, test");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +85,19 @@ unsafe extern "C" fn kmain() -> ! {
|
|||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
|
with_framebuffer(|mut fb|{
|
||||||
|
let (width, height) = (fb.width.clone(), fb.height.clone());
|
||||||
|
rectangle_filled(&mut fb, 0, 0, width, height, rgb(180, 0, 0), true);
|
||||||
|
with_serial_console(|serial_console| {
|
||||||
|
serial_console.clear(height / 3);
|
||||||
|
serial_console.render_text(&mut fb, "Kernel Panic! :C\n\n\n");
|
||||||
|
if let Some(message) = _info.message().as_str() {
|
||||||
|
serial_console.render_text(&mut fb, "Message:");
|
||||||
|
serial_console.render_text(&mut fb, message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
idle();
|
idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user