Compare commits
No commits in common. "08b2d22662fdae9d29325635aa121bfb66a2549e" and "2dfd253f34ec3d8901355d8129d751afa49a4d2e" have entirely different histories.
08b2d22662
...
2dfd253f34
86
Cargo.lock
generated
86
Cargo.lock
generated
|
@ -20,15 +20,6 @@ version = "0.2.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "approx"
|
|
||||||
version = "0.5.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
@ -120,13 +111,11 @@ name = "kernel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"cfg-if",
|
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"multiboot2",
|
"multiboot2",
|
||||||
"nalgebra",
|
|
||||||
"once",
|
"once",
|
||||||
"pc-keyboard",
|
"pc-keyboard",
|
||||||
"pic8259",
|
"pic8259",
|
||||||
|
@ -175,57 +164,6 @@ dependencies = [
|
||||||
"uefi-raw",
|
"uefi-raw",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nalgebra"
|
|
||||||
version = "0.33.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3c4b5f057b303842cf3262c27e465f4c303572e7f6b0648f60e16248ac3397f4"
|
|
||||||
dependencies = [
|
|
||||||
"approx",
|
|
||||||
"num-complex",
|
|
||||||
"num-rational",
|
|
||||||
"num-traits",
|
|
||||||
"simba",
|
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-complex"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-integer"
|
|
||||||
version = "0.1.46"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-rational"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
|
||||||
dependencies = [
|
|
||||||
"num-integer",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[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 = "once"
|
name = "once"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
@ -238,12 +176,6 @@ version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "paste"
|
|
||||||
version = "1.0.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pc-keyboard"
|
name = "pc-keyboard"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -318,18 +250,6 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "simba"
|
|
||||||
version = "0.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa"
|
|
||||||
dependencies = [
|
|
||||||
"approx",
|
|
||||||
"num-complex",
|
|
||||||
"num-traits",
|
|
||||||
"paste",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
@ -376,12 +296,6 @@ dependencies = [
|
||||||
"lock_api",
|
"lock_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typenum"
|
|
||||||
version = "1.17.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uart_16550"
|
name = "uart_16550"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
|
@ -5,8 +5,3 @@ members = [
|
||||||
|
|
||||||
exclude = ["boot"]
|
exclude = ["boot"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
strip = false
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,3 @@
|
||||||
%define VIDEO_MODE 1
|
|
||||||
|
|
||||||
section .data
|
|
||||||
global __VIDEO_MODE
|
|
||||||
__VIDEO_MODE: db VIDEO_MODE
|
|
||||||
|
|
||||||
|
|
||||||
section .multiboot_header
|
section .multiboot_header
|
||||||
header_start:
|
header_start:
|
||||||
dd 0xe85250d6 ; magic number (multiboot 2)
|
dd 0xe85250d6 ; magic number (multiboot 2)
|
||||||
|
@ -15,17 +8,7 @@ header_start:
|
||||||
|
|
||||||
; insert optional multiboot tags here
|
; insert optional multiboot tags here
|
||||||
|
|
||||||
%if VIDEO_MODE
|
; required end tag
|
||||||
dw 5 ; type
|
|
||||||
dw 1 ; flags
|
|
||||||
dd 20 ; size
|
|
||||||
dd 0 ; width
|
|
||||||
dd 0 ; height
|
|
||||||
dd 24 ; depth
|
|
||||||
; grub 2 expects 8 byte alignment
|
|
||||||
dw 0 ; padding
|
|
||||||
dw 0 ; padding
|
|
||||||
%endif
|
|
||||||
dw 0 ; type
|
dw 0 ; type
|
||||||
dw 0 ; flags
|
dw 0 ; flags
|
||||||
dd 8 ; size
|
dd 8 ; size
|
||||||
|
|
3
build.sh
3
build.sh
|
@ -2,9 +2,6 @@ BUILD_DIR="./target"
|
||||||
BIN="$BUILD_DIR/poppin.bin"
|
BIN="$BUILD_DIR/poppin.bin"
|
||||||
ISO="$BUILD_DIR/poppin.iso"
|
ISO="$BUILD_DIR/poppin.iso"
|
||||||
|
|
||||||
# config
|
|
||||||
VIDEO_MODE=true;
|
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
function cmd_exists() {
|
function cmd_exists() {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
name = "kernel"
|
name = "kernel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
test=false
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name="kernel"
|
name="kernel"
|
||||||
|
@ -9,15 +10,16 @@ test=false
|
||||||
crate-type=["staticlib"]
|
crate-type=["staticlib"]
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "2.5.0"
|
bitflags = "2.5.0"
|
||||||
cfg-if = "1.0.0"
|
|
||||||
crossbeam = { version = "0.8.4", default-features = false, features = ["alloc"] }
|
crossbeam = { version = "0.8.4", default-features = false, features = ["alloc"] }
|
||||||
hashbrown = "0.14.5"
|
hashbrown = "0.14.5"
|
||||||
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
|
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
multiboot2 = "0.20.2"
|
multiboot2 = "0.20.2"
|
||||||
nalgebra = { version = "0.33.0", default-features = false }
|
|
||||||
once = "0.3.4"
|
once = "0.3.4"
|
||||||
pc-keyboard = "0.7.0"
|
pc-keyboard = "0.7.0"
|
||||||
pic8259 = "0.11.0"
|
pic8259 = "0.11.0"
|
||||||
|
|
|
@ -37,10 +37,12 @@ impl EventManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispatch(&self, ev: &Event){
|
pub fn dispatch(&self, ev: &Event){
|
||||||
for listener in self.listeners.iter().flatten() {
|
for listener in &self.listeners {
|
||||||
if discriminant(ev) == discriminant(&listener.typ) {
|
if let Some(l) = listener {
|
||||||
// TODO: Do something with the result
|
if discriminant(ev) == discriminant(&l.typ) {
|
||||||
let _ = (listener.func)(ev);
|
// TODO: Do something with the result
|
||||||
|
let _ = (l.func)(ev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,14 @@ lazy_static! {
|
||||||
|
|
||||||
#[allow(unused_unsafe)]
|
#[allow(unused_unsafe)]
|
||||||
let stack_start = VirtAddr::from_ptr(unsafe { addr_of!(STACK) });
|
let stack_start = VirtAddr::from_ptr(unsafe { addr_of!(STACK) });
|
||||||
stack_start + STACK_SIZE as u64
|
let stack_end = stack_start + STACK_SIZE as u64;
|
||||||
|
stack_end
|
||||||
};
|
};
|
||||||
tss.privilege_stack_table[0] = {
|
tss.privilege_stack_table[0] = {
|
||||||
#[allow(unused_unsafe)]
|
#[allow(unused_unsafe)]
|
||||||
let stack_start = VirtAddr::from_ptr(unsafe { addr_of!(PRIV_TSS_STACK) });
|
let stack_start = VirtAddr::from_ptr(unsafe { addr_of!(PRIV_TSS_STACK) });
|
||||||
stack_start + STACK_SIZE as u64
|
let stack_end = stack_start + STACK_SIZE as u64;
|
||||||
|
stack_end
|
||||||
};
|
};
|
||||||
tss
|
tss
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode};
|
use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode};
|
||||||
use crate::interrupts::InterruptIndex;
|
use crate::{events::EVENTMAN, interrupts::InterruptIndex};
|
||||||
|
|
||||||
mod ps2_keyboard;
|
mod ps2_keyboard;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
|
use hashbrown::HashSet;
|
||||||
|
use pc_keyboard::{DecodedKey, KeyState};
|
||||||
|
use spin::Mutex;
|
||||||
use x86_64::structures::idt::InterruptStackFrame;
|
use x86_64::structures::idt::InterruptStackFrame;
|
||||||
|
|
||||||
use crate::{events::EVENTMAN, interrupts::PICS};
|
use crate::{events::EVENTMAN, interrupts::PICS};
|
||||||
|
|
||||||
|
pub struct Ps2KbPressEvent(DecodedKey);
|
||||||
|
|
||||||
pub extern "x86-interrupt" fn ps2_kb_int(_sf: InterruptStackFrame){
|
pub extern "x86-interrupt" fn ps2_kb_int(_sf: InterruptStackFrame){
|
||||||
use pc_keyboard::{layouts, HandleControl, Keyboard, ScancodeSet1};
|
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use x86_64::instructions::port::Port;
|
use x86_64::instructions::port::Port;
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
#![feature(ptr_internals)]
|
#![feature(ptr_internals)]
|
||||||
#![feature(allocator_api)]
|
#![feature(allocator_api)]
|
||||||
|
|
||||||
use std::vga::video::Color;
|
use core::ptr::addr_of;
|
||||||
|
|
||||||
use mem::paging::ActivePageTable;
|
use alloc::vec::Vec;
|
||||||
use multiboot2::{BootInformation, BootInformationHeader};
|
use pc_keyboard::{DecodedKey, KeyCode};
|
||||||
use pc_keyboard::KeyCode;
|
use x86_64::instructions::nop;
|
||||||
|
|
||||||
|
use crate::{gdt::PRIV_TSS_STACK, scheduler::{executor::Executor, Task}, utils::jmp_to_usermode};
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
@ -26,24 +27,50 @@ mod mem;
|
||||||
mod scheduler;
|
mod scheduler;
|
||||||
mod std;
|
mod std;
|
||||||
|
|
||||||
fn init(mb2p: *const BootInformationHeader) -> ActivePageTable {
|
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn kmain(mb2_info_addr: usize) -> ! {
|
||||||
|
// Init
|
||||||
logger::init(log::LevelFilter::Trace).unwrap();
|
logger::init(log::LevelFilter::Trace).unwrap();
|
||||||
gdt::init();
|
gdt::init();
|
||||||
interrupts::init_idt();
|
interrupts::init_idt();
|
||||||
utils::enable_nxe_bit();
|
utils::enable_nxe_bit();
|
||||||
utils::enable_write_protect_bit();
|
utils::enable_write_protect_bit();
|
||||||
std::init();
|
std::init();
|
||||||
mem::init(mb2p)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn kmain(mb2p: *const BootInformationHeader) -> ! {
|
|
||||||
let _ = init(mb2p); // active table
|
|
||||||
|
|
||||||
let vc = std::vga::video::VideoControler::new(mb2p);
|
let active_table = mem::init(mb2_info_addr);
|
||||||
// vc.set_px(0, 0, Color::new(0xFF, 0xFF, 0x0));
|
|
||||||
// vc.fill_screen(Color::new(0xFF, 0x0, 0x0));
|
//unsafe {
|
||||||
|
// jmp_to_usermode(active_table, usermode_code as *const () as usize, addr_of!(PRIV_TSS_STACK) as *const () as usize);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//let mut executor = Executor::new();
|
||||||
|
//executor.spawn(Task::new(usermode_code()));
|
||||||
|
//executor.run();
|
||||||
|
|
||||||
|
//let mut a = Vec::new();
|
||||||
|
|
||||||
|
|
||||||
|
//a.push(6);
|
||||||
|
//a.push(9);
|
||||||
|
//a.push(4);
|
||||||
|
//a.push(2);
|
||||||
|
//a.push(0);
|
||||||
|
|
||||||
|
//log::error!("{:?}", a);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// EVENTMAN.lock().add_listener(events::Event::Ps2KeyPress(None), |k| {
|
||||||
|
// let Event::Ps2KeyPress(v) = k else {panic!()};
|
||||||
|
//
|
||||||
|
// log::debug!("Keypress event received! ({:?})", v.unwrap());
|
||||||
|
// Ok(())
|
||||||
|
// });
|
||||||
|
|
||||||
|
// let (level_4_page_table, _) = Cr3::read();
|
||||||
|
// println!("Level 4 page table at: {:?}", level_4_page_table.start_address());
|
||||||
log::info!("end of work");
|
log::info!("end of work");
|
||||||
loop {
|
loop {
|
||||||
if std::input::is_key_down(KeyCode::A) {
|
if std::input::is_key_down(KeyCode::A) {
|
||||||
|
@ -61,3 +88,6 @@ fn panic(pi: &core::panic::PanicInfo) -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn usermode_code() {
|
||||||
|
log::info!("Hello from usermode!");
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
use core::fmt::Write;
|
|
||||||
use log::{Level, LevelFilter, Metadata, Record, SetLoggerError};
|
use log::{Level, LevelFilter, Metadata, Record, SetLoggerError};
|
||||||
|
|
||||||
use crate::logger::serial::{write_com, ANSI_COLORS, COM0};
|
use crate::logger::serial::{write_com, ANSI_COLORS, COM0};
|
||||||
use crate::std::vga::text::{Color, ColorCode, WRITER};
|
|
||||||
|
|
||||||
|
use self::vga::{Color, ColorCode, WRITER};
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
pub mod vga;
|
||||||
pub mod serial;
|
pub mod serial;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
|
@ -13,6 +16,7 @@ pub static LOGGER: KLogger = KLogger;
|
||||||
pub struct KLogger;
|
pub struct KLogger;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const C_TRACE: ColorCode = ColorCode::new(Color::Cyan, Color::Black);
|
const C_TRACE: ColorCode = ColorCode::new(Color::Cyan, Color::Black);
|
||||||
const C_DEBUG: ColorCode = ColorCode::new(Color::Blue, Color::Black);
|
const C_DEBUG: ColorCode = ColorCode::new(Color::Blue, Color::Black);
|
||||||
const C_INFO: ColorCode = ColorCode::new(Color::Green, Color::Black);
|
const C_INFO: ColorCode = ColorCode::new(Color::Green, Color::Black);
|
||||||
|
@ -28,77 +32,51 @@ impl log::Log for KLogger {
|
||||||
|
|
||||||
fn log(&self, record: &Record) {
|
fn log(&self, record: &Record) {
|
||||||
if self.enabled(record.metadata()) {
|
if self.enabled(record.metadata()) {
|
||||||
if !crate::std::vga::video::is_video_mode_enabled() {
|
{WRITER.lock().set_color(Color::Magenta, Color::Black); }
|
||||||
self.log_vga(record).unwrap();
|
print!("[");
|
||||||
|
write_com(&COM0, format_args!("{}[", ANSI_COLORS::MAGENTA));
|
||||||
|
match record.level() {
|
||||||
|
Level::Trace => {
|
||||||
|
{WRITER.lock().set_color_code(C_TRACE); }
|
||||||
|
print!("TRACE");
|
||||||
|
write_com(&COM0, format_args!("{}TRACE", ANSI_COLORS::BLUE2));
|
||||||
|
}
|
||||||
|
Level::Debug => {
|
||||||
|
{WRITER.lock().set_color_code(C_DEBUG); }
|
||||||
|
print!("DEBUG");
|
||||||
|
write_com(&COM0, format_args!("{}DEBUG", ANSI_COLORS::BLUE));
|
||||||
|
}
|
||||||
|
Level::Info => {
|
||||||
|
{WRITER.lock().set_color_code(C_INFO); }
|
||||||
|
print!("INFO");
|
||||||
|
write_com(&COM0, format_args!("{}INFO", ANSI_COLORS::GREEN));
|
||||||
|
}
|
||||||
|
Level::Warn => {
|
||||||
|
{WRITER.lock().set_color_code(C_WARN); }
|
||||||
|
print!("WARN");
|
||||||
|
write_com(&COM0, format_args!("{}WARN", ANSI_COLORS::YELLOW));
|
||||||
|
}
|
||||||
|
Level::Error => {
|
||||||
|
{WRITER.lock().set_color_code(C_ERROR); }
|
||||||
|
print!("ERROR");
|
||||||
|
write_com(&COM0, format_args!("{}ERROR", ANSI_COLORS::RED));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.log_serial(record)
|
{WRITER.lock().set_color(Color::Magenta, Color::Black); }
|
||||||
|
print!("]");
|
||||||
|
{WRITER.lock().set_color_code(C_NORMAL); }
|
||||||
|
|
||||||
|
write_com(&COM0, format_args!("{}]", ANSI_COLORS::MAGENTA));
|
||||||
|
|
||||||
|
println!(" {}: {}", record.module_path().unwrap_or(""), record.args());
|
||||||
|
|
||||||
|
write_com(&COM0, format_args!(" {}{}: {}\n", ANSI_COLORS::RESET, record.module_path().unwrap_or(""), record.args()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&self) {}
|
fn flush(&self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KLogger {
|
|
||||||
fn log_vga(&self, record: &Record) -> core::fmt::Result {
|
|
||||||
let mut f = WRITER.lock();
|
|
||||||
f.set_color(Color::Magenta, Color::Black);
|
|
||||||
write!(f, "[")?;
|
|
||||||
match record.level() {
|
|
||||||
Level::Trace => {
|
|
||||||
f.set_color_code(C_TRACE);
|
|
||||||
write!(f, "TRACE")?;
|
|
||||||
}
|
|
||||||
Level::Debug => {
|
|
||||||
f.set_color_code(C_DEBUG);
|
|
||||||
write!(f, "DEBUG")?;
|
|
||||||
}
|
|
||||||
Level::Info => {
|
|
||||||
f.set_color_code(C_INFO);
|
|
||||||
write!(f, "INFO")?;
|
|
||||||
}
|
|
||||||
Level::Warn => {
|
|
||||||
f.set_color_code(C_WARN);
|
|
||||||
write!(f, "WARN")?;
|
|
||||||
}
|
|
||||||
Level::Error => {
|
|
||||||
f.set_color_code(C_ERROR);
|
|
||||||
write!(f, "ERROR")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.set_color(Color::Magenta, Color::Black);
|
|
||||||
write!(f, "]")?;
|
|
||||||
f.set_color_code(C_NORMAL);
|
|
||||||
|
|
||||||
writeln!(f, " {}: {}", record.module_path().unwrap_or(""), record.args())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn log_serial(&self, record: &Record) {
|
|
||||||
{WRITER.lock().set_color(Color::Magenta, Color::Black); }
|
|
||||||
write_com(&COM0, format_args!("{}[", ANSI_COLORS::MAGENTA));
|
|
||||||
match record.level() {
|
|
||||||
Level::Trace => {
|
|
||||||
write_com(&COM0, format_args!("{}TRACE", ANSI_COLORS::BLUE2));
|
|
||||||
}
|
|
||||||
Level::Debug => {
|
|
||||||
write_com(&COM0, format_args!("{}DEBUG", ANSI_COLORS::BLUE));
|
|
||||||
}
|
|
||||||
Level::Info => {
|
|
||||||
write_com(&COM0, format_args!("{}INFO", ANSI_COLORS::GREEN));
|
|
||||||
}
|
|
||||||
Level::Warn => {
|
|
||||||
write_com(&COM0, format_args!("{}WARN", ANSI_COLORS::YELLOW));
|
|
||||||
}
|
|
||||||
Level::Error => {
|
|
||||||
write_com(&COM0, format_args!("{}ERROR", ANSI_COLORS::RED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
write_com(&COM0, format_args!("{}]", ANSI_COLORS::MAGENTA));
|
|
||||||
write_com(&COM0, format_args!(" {}{}: {}\n", ANSI_COLORS::RESET, record.module_path().unwrap_or(""), record.args()));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init(lvl: LevelFilter) -> Result<(), SetLoggerError> {
|
pub fn init(lvl: LevelFilter) -> Result<(), SetLoggerError> {
|
||||||
log::set_logger(&LOGGER)?;
|
log::set_logger(&LOGGER)?;
|
||||||
log::set_max_level(lvl);
|
log::set_max_level(lvl);
|
||||||
|
|
30
kernel/src/logger/vga/macros.rs
Normal file
30
kernel/src/logger/vga/macros.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
use core::fmt;
|
||||||
|
use x86_64::instructions::interrupts;
|
||||||
|
|
||||||
|
use crate::logger::vga::Writer;
|
||||||
|
|
||||||
|
impl fmt::Write for Writer {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
self.write_string(s);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! print {
|
||||||
|
($($arg:tt)*) => ($crate::logger::vga::macros::_print(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;
|
||||||
|
interrupts::without_interrupts(|| {
|
||||||
|
crate::logger::vga::WRITER.lock().write_fmt(args).unwrap();
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
use x86::io::{outb, inb};
|
use x86::io::{outb, inb};
|
||||||
|
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use x86_64::instructions::interrupts;
|
|
||||||
|
#[macro_use]
|
||||||
|
pub mod macros;
|
||||||
|
|
||||||
lazy_static::lazy_static!{
|
lazy_static::lazy_static!{
|
||||||
pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer::new());
|
pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer::new());
|
||||||
|
@ -91,7 +93,7 @@ impl Writer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_string(&mut self, s: &str) {
|
pub fn write_string(&mut self, s: &str) {
|
||||||
for c in s.as_bytes() {
|
for c in s.as_bytes() {
|
||||||
match c {
|
match c {
|
||||||
// printable ASCII byte or newline
|
// printable ASCII byte or newline
|
||||||
|
@ -195,12 +197,3 @@ pub fn get_cursor_position() -> (u16, u16) {
|
||||||
}
|
}
|
||||||
(pos / (BUFFER_WIDTH as u16), pos % (BUFFER_WIDTH as u16))
|
(pos / (BUFFER_WIDTH as u16), pos % (BUFFER_WIDTH as u16))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Write for Writer {
|
|
||||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
|
||||||
interrupts::without_interrupts(|| {
|
|
||||||
self.write_string(s);
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
//use x86_64::align_up;
|
//use x86_64::align_up;
|
||||||
|
|
||||||
pub const HEAP_START: usize = 0x40000000; // 0x40000000 - 0x40019000
|
pub const HEAP_START: usize = 0o_000_001_000_000_0000; // 0x40000000 - 0x40019000
|
||||||
pub const HEAP_SIZE: usize = 100 * 1024; // 100 KiB
|
pub const HEAP_SIZE: usize = 100 * 1024; // 100 KiB
|
||||||
|
|
||||||
// A simple allocator that allocates memory linearly and ignores freed memory.
|
// A simple allocator that allocates memory linearly and ignores freed memory.
|
||||||
|
|
|
@ -20,9 +20,7 @@ static GLOBAL_ALLOCATOR: Talck<spin::Mutex<()>, ErrOnOom> = Talc::new(ErrOnOom).
|
||||||
|
|
||||||
pub struct DummyAlloc;
|
pub struct DummyAlloc;
|
||||||
unsafe impl GlobalAlloc for DummyAlloc {
|
unsafe impl GlobalAlloc for DummyAlloc {
|
||||||
unsafe fn alloc(&self, _: Layout) -> *mut u8 {
|
unsafe fn alloc(&self, _: Layout) -> *mut u8 { 0 as *mut u8 }
|
||||||
core::ptr::null_mut::<u8>()
|
|
||||||
}
|
|
||||||
unsafe fn dealloc(&self, _ptr: *mut u8, _: Layout) {}
|
unsafe fn dealloc(&self, _ptr: *mut u8, _: Layout) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,14 +122,12 @@ pub struct MemInfo<'a>{
|
||||||
pub kernel_end: usize,
|
pub kernel_end: usize,
|
||||||
pub mb_start: usize,
|
pub mb_start: usize,
|
||||||
pub mb_end: usize,
|
pub mb_end: usize,
|
||||||
pub vga_vide_start: usize,
|
|
||||||
pub vga_vide_size: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemInfo<'_> {
|
impl MemInfo<'_> {
|
||||||
pub fn load(mb_ptr: *const BootInformationHeader) -> Self {
|
pub fn load(mb_ptr: usize) -> Self {
|
||||||
let boot_info = unsafe {
|
let boot_info = unsafe {
|
||||||
multiboot2::BootInformation::load(mb_ptr).unwrap()
|
multiboot2::BootInformation::load(mb_ptr as *const BootInformationHeader).unwrap()
|
||||||
};
|
};
|
||||||
let mmap_tag = boot_info.memory_map_tag().unwrap();
|
let mmap_tag = boot_info.memory_map_tag().unwrap();
|
||||||
|
|
||||||
|
@ -150,27 +146,22 @@ impl MemInfo<'_> {
|
||||||
let kernel_end = elf_secs.clone().filter(|s| s.is_allocated()).map(|s| s.end_address()).min().unwrap() as usize;
|
let kernel_end = elf_secs.clone().filter(|s| s.is_allocated()).map(|s| s.end_address()).min().unwrap() as usize;
|
||||||
let mb_start = boot_info.start_address();
|
let mb_start = boot_info.start_address();
|
||||||
let mb_end = boot_info.end_address();
|
let mb_end = boot_info.end_address();
|
||||||
let vv_info = boot_info.framebuffer_tag().unwrap().unwrap();
|
|
||||||
let vv_start = vv_info.address();
|
|
||||||
let vv_size = vv_info.width() * vv_info.height();
|
|
||||||
|
|
||||||
//log::debug!("Kernel: start: 0x{:x} sz: 0x{:x}", mi.kernel_start, mi.kernel_end - mi.kernel_start);
|
//log::debug!("Kernel: start: 0x{:x} sz: 0x{:x}", mi.kernel_start, mi.kernel_end - mi.kernel_start);
|
||||||
//log::debug!("Multiboot: start: 0x{:x} sz: 0x{:x}", mi.mb_start, mi.mb_end - mi.mb_start);
|
//log::debug!("Multiboot: start: 0x{:x} sz: 0x{:x}", mi.mb_start, mi.mb_end - mi.mb_start);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
boot_info: unsafe { multiboot2::BootInformation::load(mb_ptr).unwrap()},
|
boot_info:unsafe { multiboot2::BootInformation::load(mb_ptr as *const BootInformationHeader).unwrap()},
|
||||||
mem_area_iter: MemoryAreaIter::new(mmap_tag),
|
mem_area_iter: MemoryAreaIter::new(mmap_tag),
|
||||||
kernel_start,
|
kernel_start,
|
||||||
kernel_end,
|
kernel_end,
|
||||||
mb_start,
|
mb_start,
|
||||||
mb_end,
|
mb_end,
|
||||||
vga_vide_start: vv_start as usize,
|
|
||||||
vga_vide_size: vv_size as usize
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(mb_ptr: *const BootInformationHeader) -> paging::ActivePageTable {
|
pub fn init(mb_ptr: usize) -> paging::ActivePageTable {
|
||||||
once::assert_has_not_been_called!("mem::init must be called only once");
|
once::assert_has_not_been_called!("mem::init must be called only once");
|
||||||
let mem_info = MemInfo::load(mb_ptr);
|
let mem_info = MemInfo::load(mb_ptr);
|
||||||
let mut frame_alloc = area_frame_alloc::AreaFrameAllocator::new(&mem_info);
|
let mut frame_alloc = area_frame_alloc::AreaFrameAllocator::new(&mem_info);
|
||||||
|
|
|
@ -28,13 +28,13 @@ impl EntryFlags {
|
||||||
|
|
||||||
if section.flags().contains(ElfSectionFlags::ALLOCATED) {
|
if section.flags().contains(ElfSectionFlags::ALLOCATED) {
|
||||||
// section is loaded to memory
|
// section is loaded to memory
|
||||||
flags |= EntryFlags::PRESENT;
|
flags = flags | EntryFlags::PRESENT;
|
||||||
}
|
}
|
||||||
if section.flags().contains(ElfSectionFlags::WRITABLE) {
|
if section.flags().contains(ElfSectionFlags::WRITABLE) {
|
||||||
flags |= EntryFlags::WRITABLE;
|
flags = flags | EntryFlags::WRITABLE;
|
||||||
}
|
}
|
||||||
if !section.flags().contains(ElfSectionFlags::EXECUTABLE) {
|
if !section.flags().contains(ElfSectionFlags::EXECUTABLE) {
|
||||||
flags |= EntryFlags::NO_EXECUTE;
|
flags = flags | EntryFlags::NO_EXECUTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags
|
flags
|
||||||
|
|
|
@ -7,7 +7,7 @@ use super::{
|
||||||
Frame, FrameAllocator,
|
Frame, FrameAllocator,
|
||||||
PAGE_SIZE, PhysicalAddress,
|
PAGE_SIZE, PhysicalAddress,
|
||||||
VirtualAddress, Page,
|
VirtualAddress, Page,
|
||||||
ENTRY_COUNT,
|
ENTRY_COUNT, InactivePageTable
|
||||||
};
|
};
|
||||||
use core::ptr::Unique;
|
use core::ptr::Unique;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![allow(unexpected_cfgs)]
|
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
use self::{entry::*, mapper::Mapper, temporary::TemporaryPage};
|
use self::{entry::*, mapper::Mapper, temporary::TemporaryPage};
|
||||||
use super::{Frame, FrameAllocator, MemInfo, PAGE_SIZE};
|
use super::{Frame, FrameAllocator, MemInfo, PAGE_SIZE};
|
||||||
|
@ -120,8 +119,8 @@ impl InactivePageTable {
|
||||||
|
|
||||||
impl Page {
|
impl Page {
|
||||||
pub fn containing_address(address: VirtualAddress) -> Page {
|
pub fn containing_address(address: VirtualAddress) -> Page {
|
||||||
assert!(
|
assert!(address < 0x0000_8000_0000_0000 ||
|
||||||
!(0x0000_8000_0000_0000..0xffff_8000_0000_0000).contains(&address),
|
address >= 0xffff_8000_0000_0000,
|
||||||
"invalid address: 0x{:x}", address);
|
"invalid address: 0x{:x}", address);
|
||||||
Page { number: address / PAGE_SIZE }
|
Page { number: address / PAGE_SIZE }
|
||||||
}
|
}
|
||||||
|
@ -138,7 +137,7 @@ impl Page {
|
||||||
(self.number >> 9) & 0o777
|
(self.number >> 9) & 0o777
|
||||||
}
|
}
|
||||||
fn p1_index(&self) -> usize {
|
fn p1_index(&self) -> usize {
|
||||||
self.number & 0o777
|
(self.number >> 0) & 0o777
|
||||||
}
|
}
|
||||||
pub fn range_inclusive(start: Page, end: Page) -> PageIter {
|
pub fn range_inclusive(start: Page, end: Page) -> PageIter {
|
||||||
PageIter {
|
PageIter {
|
||||||
|
@ -205,13 +204,8 @@ pub fn remap_the_kernel<A>(allocator: &mut A, mem_info: &MemInfo) -> ActivePageT
|
||||||
mapper.identity_map(frame, flags, allocator);
|
mapper.identity_map(frame, flags, allocator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let vga_text_buffer_frame = Frame::containing_address(0xb8000);
|
let vga_buffer_frame = Frame::containing_address(0xb8000);
|
||||||
let vga_video_buffer_frame_start = Frame::containing_address(mem_info.vga_vide_start);
|
mapper.identity_map(vga_buffer_frame, EntryFlags::WRITABLE, allocator);
|
||||||
let vga_video_buffer_frame_end = Frame::containing_address((mem_info.vga_vide_start + mem_info.vga_vide_size*3));
|
|
||||||
for frame in Frame::range_inclusive(vga_video_buffer_frame_start, vga_video_buffer_frame_end) {
|
|
||||||
mapper.identity_map(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE, allocator);
|
|
||||||
}
|
|
||||||
mapper.identity_map(vga_text_buffer_frame, EntryFlags::WRITABLE, allocator);
|
|
||||||
let multiboot_start = Frame::containing_address(mem_info.boot_info.start_address());
|
let multiboot_start = Frame::containing_address(mem_info.boot_info.start_address());
|
||||||
let multiboot_end = Frame::containing_address(mem_info.boot_info.end_address() - 1);
|
let multiboot_end = Frame::containing_address(mem_info.boot_info.end_address() - 1);
|
||||||
for frame in Frame::range_inclusive(multiboot_start, multiboot_end) {
|
for frame in Frame::range_inclusive(multiboot_start, multiboot_end) {
|
||||||
|
@ -231,7 +225,8 @@ pub fn remap_the_kernel<A>(allocator: &mut A, mem_info: &MemInfo) -> ActivePageT
|
||||||
active_table
|
active_table
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(disabled)]
|
|
||||||
|
|
||||||
pub fn test_paging<A>(allocator: &mut A)
|
pub fn test_paging<A>(allocator: &mut A)
|
||||||
where A: FrameAllocator
|
where A: FrameAllocator
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,12 +44,12 @@ impl<L> Table<L> where L: HierarchicalLevel {
|
||||||
self.next_table_mut(index).unwrap()
|
self.next_table_mut(index).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
|
pub fn next_table<'a>(&'a self, index: usize) -> Option<&'a Table<L::NextLevel>> {
|
||||||
self.next_table_address(index)
|
self.next_table_address(index)
|
||||||
.map(|address| unsafe { &*(address as *const _) })
|
.map(|address| unsafe { &*(address as *const _) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
|
pub fn next_table_mut<'a>(&'a mut self, index: usize) -> Option<&'a mut Table<L::NextLevel>> {
|
||||||
self.next_table_address(index)
|
self.next_table_address(index)
|
||||||
.map(|address| unsafe { &mut *(address as *mut _) })
|
.map(|address| unsafe { &mut *(address as *mut _) })
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ impl TemporaryPage {
|
||||||
where A: FrameAllocator
|
where A: FrameAllocator
|
||||||
{
|
{
|
||||||
TemporaryPage {
|
TemporaryPage {
|
||||||
page,
|
page: page,
|
||||||
allocator: TinyAllocator::new(allocator),
|
allocator: TinyAllocator::new(allocator),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![allow(dead_code)]
|
|
||||||
use core::task::{Context, Poll, Waker};
|
use core::task::{Context, Poll, Waker};
|
||||||
|
|
||||||
use super::{Task, TaskId};
|
use super::{Task, TaskId};
|
||||||
|
@ -54,7 +53,7 @@ impl Executor {
|
||||||
};
|
};
|
||||||
let waker = waker_cache
|
let waker = waker_cache
|
||||||
.entry(task_id)
|
.entry(task_id)
|
||||||
.or_insert_with(|| TaskWaker::new_waker(task_id, task_queue.clone()));
|
.or_insert_with(|| TaskWaker::new(task_id, task_queue.clone()));
|
||||||
let mut context = Context::from_waker(waker);
|
let mut context = Context::from_waker(waker);
|
||||||
match task.poll(&mut context) {
|
match task.poll(&mut context) {
|
||||||
Poll::Ready(()) => {
|
Poll::Ready(()) => {
|
||||||
|
@ -78,7 +77,7 @@ impl TaskWaker {
|
||||||
fn wake_task(&self) {
|
fn wake_task(&self) {
|
||||||
self.task_queue.push(self.task_id).expect("task_queue full");
|
self.task_queue.push(self.task_id).expect("task_queue full");
|
||||||
}
|
}
|
||||||
fn new_waker(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker {
|
fn new(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker {
|
||||||
Waker::from(Arc::new(TaskWaker {
|
Waker::from(Arc::new(TaskWaker {
|
||||||
task_id,
|
task_id,
|
||||||
task_queue,
|
task_queue,
|
||||||
|
@ -97,4 +96,3 @@ impl Wake for TaskWaker {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![allow(dead_code)]
|
|
||||||
use core::{future::Future, pin::Pin, sync::atomic::{AtomicU64, Ordering}, task::{Context, Poll}};
|
use core::{future::Future, pin::Pin, sync::atomic::{AtomicU64, Ordering}, task::{Context, Poll}};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use alloc::collections::{btree_set::BTreeSet, vec_deque::VecDeque};
|
use alloc::{boxed::Box, collections::{btree_set::BTreeSet, vec_deque::VecDeque}, sync::Arc, vec::Vec};
|
||||||
use pc_keyboard::{KeyCode, KeyEvent, KeyState};
|
use hashbrown::HashSet;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use pc_keyboard::{DecodedKey, KeyCode, KeyEvent, KeyState};
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
use x86_64::instructions::nop;
|
||||||
|
|
||||||
use crate::events::{Event, EVENTMAN};
|
use crate::events::{Event, EVENTMAN};
|
||||||
static mut KEYS_PRESSED: Mutex<BTreeSet<KeyCode>> = Mutex::new(BTreeSet::new());
|
static mut KEYS_PRESSED: Mutex<BTreeSet<KeyCode>> = Mutex::new(BTreeSet::new());
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod vga;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
pub mod text;
|
|
||||||
pub mod video;
|
|
|
@ -1,72 +0,0 @@
|
||||||
mod util;
|
|
||||||
use core::{borrow::BorrowMut, ops::Deref};
|
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use multiboot2::{BootInformation, BootInformationHeader, FramebufferTag, FramebufferType, TagTrait};
|
|
||||||
use nalgebra::Vector2;
|
|
||||||
use spin::{Mutex, MutexGuard};
|
|
||||||
pub use util::is_video_mode_enabled;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct Color {
|
|
||||||
r: u8,
|
|
||||||
g: u8,
|
|
||||||
b: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Color {
|
|
||||||
pub fn new(r: u8, g: u8, b: u8) -> Self {
|
|
||||||
Self {r, g, b}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VideoControler{
|
|
||||||
component_size: u8,
|
|
||||||
r_ofs: u8,
|
|
||||||
g_ofs: u8,
|
|
||||||
b_ofs: u8,
|
|
||||||
buf_addr: u64,
|
|
||||||
size: Vector2<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VideoControler {
|
|
||||||
pub fn new(mb2p: *const BootInformationHeader) -> Self {
|
|
||||||
let boot_info = unsafe { BootInformation::load(mb2p).unwrap() };
|
|
||||||
let fbt = boot_info.framebuffer_tag().unwrap().unwrap();
|
|
||||||
let FramebufferType::RGB { red, green, blue } = fbt.buffer_type().unwrap() else {
|
|
||||||
panic!();
|
|
||||||
};
|
|
||||||
assert!(red.size == green.size && green.size == blue.size);
|
|
||||||
log::info!("VGA VIDEO adddr: {:x}", fbt.address());
|
|
||||||
log::info!("VGA VIDEO FB TYPE: {:?}", fbt.buffer_type());
|
|
||||||
Self {
|
|
||||||
component_size: red.size,
|
|
||||||
r_ofs: red.position,
|
|
||||||
g_ofs: green.position,
|
|
||||||
b_ofs: blue.position,
|
|
||||||
buf_addr: fbt.address(),
|
|
||||||
size: Vector2::new(fbt.width() as usize, fbt.height() as usize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_px(&self, x: usize, y: usize, c: Color) {
|
|
||||||
let ptr = self.buf_addr as *mut () as *mut u8;
|
|
||||||
let px = ptr.wrapping_add(x * self.size.x + y);
|
|
||||||
unsafe {
|
|
||||||
*px.wrapping_add((self.r_ofs % 8) as usize) = c.r;
|
|
||||||
*px.wrapping_add((self.g_ofs % 8) as usize) = c.g;
|
|
||||||
*px.wrapping_add((self.b_ofs % 8) as usize) = c.b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fill_screen(&self, c: Color) {
|
|
||||||
for x in 0..100 {
|
|
||||||
for y in 0..100 {
|
|
||||||
self.set_px(x, y, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
extern "C" {
|
|
||||||
static __VIDEO_MODE: u8;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_video_mode_enabled() -> bool {
|
|
||||||
unsafe {
|
|
||||||
__VIDEO_MODE == 1
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user