Add display support
All checks were successful
Build / build (push) Successful in 3m0s

This commit is contained in:
Mathieu Strypsteen 2024-11-13 16:15:41 +01:00
parent 7a47fbaea8
commit c472ef1e27
13 changed files with 199 additions and 8 deletions

64
Cargo.lock generated
View file

@ -41,6 +41,12 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "az"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
[[package]] [[package]]
name = "bindgen" name = "bindgen"
version = "0.70.1" version = "0.70.1"
@ -100,6 +106,12 @@ dependencies = [
"spin", "spin",
] ]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "cexpr" name = "cexpr"
version = "0.6.0" version = "0.6.0"
@ -138,6 +150,38 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b"
[[package]]
name = "embedded-graphics"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0649998afacf6d575d126d83e68b78c0ab0e00ca2ac7e9b3db11b4cbe8274ef0"
dependencies = [
"az",
"byteorder",
"embedded-graphics-core",
"float-cmp",
"micromath",
]
[[package]]
name = "embedded-graphics-core"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba9ecd261f991856250d2207f6d8376946cd9f412a2165d3b75bc87a0bc7a044"
dependencies = [
"az",
"byteorder",
]
[[package]]
name = "float-cmp"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
dependencies = [
"num-traits",
]
[[package]] [[package]]
name = "funty" name = "funty"
version = "2.0.0" version = "2.0.0"
@ -168,6 +212,7 @@ dependencies = [
"bitfield", "bitfield",
"bitvec", "bitvec",
"buddy_system_allocator", "buddy_system_allocator",
"embedded-graphics",
"kernel-common", "kernel-common",
"log", "log",
"spin", "spin",
@ -231,6 +276,12 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "micromath"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815"
[[package]] [[package]]
name = "minimal-lexical" name = "minimal-lexical"
version = "0.2.1" version = "0.2.1"
@ -247,6 +298,15 @@ dependencies = [
"minimal-lexical", "minimal-lexical",
] ]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "prettyplease" name = "prettyplease"
version = "0.2.25" version = "0.2.25"
@ -324,9 +384,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.4.8" version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",

View file

@ -1,2 +1,6 @@
[licenses] [licenses]
allow = ["Apache-2.0", "BSD-3-Clause", "BSD-3-Clause-acpica", "ISC", "MIT", "MPL-2.0", "Unicode-DFS-2016", "Unlicense"] allow = ["Apache-2.0", "BSD-3-Clause", "ISC", "MIT", "MPL-2.0", "Unlicense"]
exceptions = [
{allow = ["BSD-3-Clause-acpica"], crate = "acpica-rs"},
{allow = ["Unicode-DFS-2016"], crate = "unicode-ident"}
]

View file

@ -10,6 +10,7 @@ acpica-rs = {path = "../lib/acpica-rs"}
bitfield = "0.17.0" bitfield = "0.17.0"
bitvec = {version = "1.0.1", default-features = false, features = ["alloc", "atomic"]} bitvec = {version = "1.0.1", default-features = false, features = ["alloc", "atomic"]}
buddy_system_allocator = "0.11.0" buddy_system_allocator = "0.11.0"
embedded-graphics = "0.8.1"
kernel-common = {path = "../lib/kernel-common"} kernel-common = {path = "../lib/kernel-common"}
log = "0.4.22" log = "0.4.22"
spin = "0.9.8" spin = "0.9.8"

View file

@ -113,6 +113,7 @@ pub fn find_free_virt_range(mut start: u64, end: u64, size: u64) -> u64 {
} }
fn map(pml4: &mut PageTable, virt: u64, phys: u64, user: bool, write: bool, exec: bool, cache_disable: bool) { fn map(pml4: &mut PageTable, virt: u64, phys: u64, user: bool, write: bool, exec: bool, cache_disable: bool) {
assert!(virt >= 0x1000, "First page shouldn't be mapped"); assert!(virt >= 0x1000, "First page shouldn't be mapped");
assert!(!write || !exec);
{ {
let mut frames_vec = PHYSICAL_FRAMES.lock(); let mut frames_vec = PHYSICAL_FRAMES.lock();
let frame = phys as usize / 0x1000; let frame = phys as usize / 0x1000;

View file

@ -17,13 +17,13 @@ use buddy_system_allocator::LockedHeap;
use cpu::{gdt::setup_gdt, idt::setup_idt, paging::setup_paging}; use cpu::{gdt::setup_gdt, idt::setup_idt, paging::setup_paging};
use kernel_common::{ use kernel_common::{
instructions::{cli, hlt}, instructions::{cli, hlt},
loader_struct::{LoaderStruct, LoaderStructMemoryRegion, LOADER_STRUCT_MAGIC}, loader_struct::{FramebufferInfo, LoaderStruct, LoaderStructMemoryRegion, LOADER_STRUCT_MAGIC},
log::init_logger, log::init_logger,
paging::{KERNEL_HEAP_INITIAL_SIZE, KERNEL_HEAP_START}, paging::{KERNEL_HEAP_INITIAL_SIZE, KERNEL_HEAP_START},
}; };
use log::{error, info}; use log::{error, info};
use spin::Mutex; use spin::Mutex;
use sys::{acpica_osl::AE_OK, early_acpi::EarlyACPIHandler, hpet::setup_hpet, lapic::setup_lapic_timer, madt::parse_madt, pic::disable_pic, task::setup_multitasking}; use sys::{acpica_osl::AE_OK, display::setup_display, early_acpi::EarlyACPIHandler, hpet::setup_hpet, lapic::setup_lapic_timer, madt::parse_madt, pic::disable_pic, task::setup_multitasking};
mod cpu; mod cpu;
mod misc; mod misc;
@ -39,6 +39,12 @@ static LOADER_STRUCT: Mutex<LoaderStruct> = Mutex::new(LoaderStruct {
rsdp_address: 0, rsdp_address: 0,
available_memory: [LoaderStructMemoryRegion { initial_page: 0, page_count: 0 }; 1024], available_memory: [LoaderStructMemoryRegion { initial_page: 0, page_count: 0 }; 1024],
vm: 0, vm: 0,
framebuffer: FramebufferInfo {
address: 0,
width: 0,
height: 0,
stride: 0,
},
}); });
global_asm!(include_str!("cpu/boot.s"), options(att_syntax)); global_asm!(include_str!("cpu/boot.s"), options(att_syntax));
@ -58,6 +64,7 @@ extern "C" fn early_main(temp_loader_struct: *const LoaderStruct) -> ! {
setup_gdt(); setup_gdt();
setup_idt(); setup_idt();
setup_paging(&loader_struct, loader_struct.phys_kernel_start, loader_struct.phys_heap_start); setup_paging(&loader_struct, loader_struct.phys_kernel_start, loader_struct.phys_heap_start);
setup_display(loader_struct.framebuffer);
disable_pic(); disable_pic();
RSDP_ADDRESS.store(loader_struct.rsdp_address, Ordering::SeqCst); RSDP_ADDRESS.store(loader_struct.rsdp_address, Ordering::SeqCst);
let early_acpi_tables; let early_acpi_tables;

View file

@ -0,0 +1,45 @@
use core::convert::Infallible;
use embedded_graphics::{
pixelcolor::Bgr888,
prelude::{DrawTarget, OriginDimensions, RgbColor, Size},
Pixel,
};
pub struct FramebufferTarget {
pub framebuffer: *mut u8,
pub width: usize,
pub height: usize,
pub stride: usize,
}
impl DrawTarget for FramebufferTarget {
type Color = Bgr888;
type Error = Infallible;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
for i in pixels {
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());
}
}
Ok(())
}
}
impl OriginDimensions for FramebufferTarget {
fn size(&self) -> Size {
Size::new(self.width as u32, self.height as u32)
}
}
unsafe impl Send for FramebufferTarget {}
unsafe impl Sync for FramebufferTarget {}

View file

@ -1 +1,2 @@
pub mod draw_target;
pub mod wrapped_alloc; pub mod wrapped_alloc;

23
kernel/src/sys/display.rs Normal file
View file

@ -0,0 +1,23 @@
use core::ptr::null_mut;
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,
});
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,
width: info.width as usize,
height: info.height as usize,
stride: info.stride as usize,
};
}

View file

@ -1,4 +1,5 @@
pub mod acpica_osl; pub mod acpica_osl;
pub mod display;
pub mod early_acpi; pub mod early_acpi;
pub mod hpet; pub mod hpet;
mod ioapic; mod ioapic;

View file

@ -6,6 +6,14 @@ pub struct LoaderStructMemoryRegion {
} }
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct FramebufferInfo {
pub address: u64,
pub width: u64,
pub height: u64,
pub stride: u64,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct LoaderStruct { pub struct LoaderStruct {
pub magic: u64, pub magic: u64,
pub phys_kernel_start: u64, pub phys_kernel_start: u64,
@ -13,6 +21,7 @@ pub struct LoaderStruct {
pub rsdp_address: u64, pub rsdp_address: u64,
pub available_memory: [LoaderStructMemoryRegion; 1024], pub available_memory: [LoaderStructMemoryRegion; 1024],
pub vm: u8, pub vm: u8,
pub framebuffer: FramebufferInfo,
} }
pub const LOADER_STRUCT_MAGIC: u64 = 0x123456789abcdef0; pub const LOADER_STRUCT_MAGIC: u64 = 0x123456789abcdef0;

35
loader/src/display.rs Normal file
View file

@ -0,0 +1,35 @@
use kernel_common::loader_struct::FramebufferInfo;
use uefi::{
boot::{get_handle_for_protocol, open_protocol_exclusive, ScopedProtocol},
proto::console::gop::{GraphicsOutput, PixelFormat},
};
pub fn setup_display() -> FramebufferInfo {
let gop_handle = get_handle_for_protocol::<GraphicsOutput>().unwrap();
let mut gop: ScopedProtocol<GraphicsOutput> = open_protocol_exclusive(gop_handle).unwrap();
let modes = gop.modes();
let mut best_mode = None;
let mut best_width = 0;
let mut best_height = 0;
for i in modes {
let info = i.info();
if info.pixel_format() != PixelFormat::Bgr {
continue;
}
if info.resolution().0 > 1280 || info.resolution().1 > 720 {
continue;
}
if info.resolution().0 > best_width || info.resolution().1 > best_height {
best_width = info.resolution().0;
best_height = info.resolution().1;
best_mode = Some(i);
}
}
gop.set_mode(&best_mode.unwrap()).unwrap();
FramebufferInfo {
address: gop.frame_buffer().as_mut_ptr() as u64,
width: best_width as u64,
height: best_height as u64,
stride: best_mode.unwrap().info().stride() as u64,
}
}

View file

@ -1,10 +1,10 @@
use kernel_common::loader_struct::{LoaderStruct, LoaderStructMemoryRegion, LOADER_STRUCT_MAGIC}; use kernel_common::loader_struct::{FramebufferInfo, LoaderStruct, LoaderStructMemoryRegion, LOADER_STRUCT_MAGIC};
use uefi::{ use uefi::{
boot::MemoryType, boot::MemoryType,
mem::memory_map::{MemoryMap, MemoryMapOwned}, mem::memory_map::{MemoryMap, MemoryMapOwned},
}; };
pub fn generate_loader_struct(memory_map: &MemoryMapOwned, phys_start: u64, heap_start: u64, rsdp_address: u64, vm: bool) -> LoaderStruct { pub fn generate_loader_struct(memory_map: &MemoryMapOwned, phys_start: u64, heap_start: u64, rsdp_address: u64, vm: bool, framebuffer: FramebufferInfo) -> LoaderStruct {
let mut loader_struct = LoaderStruct { let mut loader_struct = LoaderStruct {
magic: LOADER_STRUCT_MAGIC, magic: LOADER_STRUCT_MAGIC,
phys_kernel_start: phys_start, phys_kernel_start: phys_start,
@ -12,6 +12,7 @@ pub fn generate_loader_struct(memory_map: &MemoryMapOwned, phys_start: u64, heap
rsdp_address, rsdp_address,
available_memory: [LoaderStructMemoryRegion { initial_page: 0, page_count: 0 }; 1024], available_memory: [LoaderStructMemoryRegion { initial_page: 0, page_count: 0 }; 1024],
vm: vm as u8, vm: vm as u8,
framebuffer,
}; };
let mut next_entry = 0; let mut next_entry = 0;
for i in memory_map.entries() { for i in memory_map.entries() {

View file

@ -10,6 +10,7 @@ use core::{
sync::atomic::{AtomicU64, Ordering}, sync::atomic::{AtomicU64, Ordering},
}; };
use display::setup_display;
use elf::{load_kernel, map_kernel}; use elf::{load_kernel, map_kernel};
use kernel_common::{ use kernel_common::{
instructions::{cli, hlt}, instructions::{cli, hlt},
@ -30,6 +31,7 @@ use uefi::{
Status, Status,
}; };
mod display;
mod elf; mod elf;
mod loader_struct; mod loader_struct;
mod paging; mod paging;
@ -63,10 +65,11 @@ fn main() -> Status {
} }
}); });
assert_ne!(rsdp.load(Ordering::SeqCst), 0, "RSDP not found"); assert_ne!(rsdp.load(Ordering::SeqCst), 0, "RSDP not found");
let framebuffer_info = setup_display();
let memory_map = unsafe { exit_boot_services(MemoryType::LOADER_DATA) }; let memory_map = unsafe { exit_boot_services(MemoryType::LOADER_DATA) };
let pml4 = setup_paging(&memory_map, heap_start); let pml4 = setup_paging(&memory_map, heap_start);
map_kernel(KERNEL, pml4, kernel_start); map_kernel(KERNEL, pml4, kernel_start);
let loader_struct = generate_loader_struct(&memory_map, kernel_start, heap_start, rsdp.load(Ordering::SeqCst), features.has_hypervisor()); let loader_struct = generate_loader_struct(&memory_map, kernel_start, heap_start, rsdp.load(Ordering::SeqCst), features.has_hypervisor(), framebuffer_info);
info!("Jumping to kernel..."); info!("Jumping to kernel...");
unsafe { unsafe {
(mem::transmute::<_, extern "C" fn(&LoaderStruct) -> !>(kernel_entry))(&loader_struct); (mem::transmute::<_, extern "C" fn(&LoaderStruct) -> !>(kernel_entry))(&loader_struct);