Compare commits

...

5 Commits

Author SHA1 Message Date
adec09d9b0 added driver framework 2024-09-11 02:30:48 +03:00
62bbebf693 :3 2024-09-03 16:07:38 +03:00
4349fe9c6e Color video works!!!!!!!!!!!!!!!!!!! 2024-09-03 16:03:07 +03:00
08b2d22662 This will be the end of me 2024-09-02 20:55:25 +03:00
12e9a068e9 clippy stuff 2024-09-02 17:51:10 +03:00
34 changed files with 850 additions and 265 deletions

163
Cargo.lock generated
View File

@@ -2,6 +2,16 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "acpi"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e248409195304021f61b39ba2628f62a45a3abf6119669d44b3399d60eabe4c3"
dependencies = [
"bit_field",
"log",
]
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.8.11" version = "0.8.11"
@@ -20,12 +30,24 @@ 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 = "anyhow"
version = "1.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.3.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "az"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
[[package]] [[package]]
name = "bit_field" name = "bit_field"
version = "0.10.2" version = "0.10.2"
@@ -40,9 +62,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.5.0" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@@ -87,13 +115,45 @@ checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]] [[package]]
name = "derive_more" name = "derive_more"
version = "0.99.17" version = "0.99.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn 2.0.77",
]
[[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]]
@@ -110,31 +170,43 @@ dependencies = [
name = "kernel" name = "kernel"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bitflags 2.5.0", "acpi",
"anyhow",
"bitflags 2.6.0",
"cfg-if",
"crossbeam", "crossbeam",
"embedded-graphics",
"hashbrown", "hashbrown",
"lazy_static", "lazy_static",
"libm",
"log", "log",
"multiboot2", "multiboot2",
"once", "once",
"pc-keyboard", "pc-keyboard",
"pic8259", "pic8259",
"spin 0.9.8", "ps2",
"spin",
"talc", "talc",
"uart_16550", "uart_16550",
"x86", "x86",
"x86_64", "x86_64 0.15.1",
] ]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
dependencies = [ dependencies = [
"spin 0.5.2", "spin",
] ]
[[package]]
name = "libm"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.12" version = "0.4.12"
@@ -147,9 +219,15 @@ dependencies = [
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.21" version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "micromath"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815"
[[package]] [[package]]
name = "multiboot2" name = "multiboot2"
@@ -157,13 +235,22 @@ version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad7ef048d4783355163fd0c874aac3db54b919dc6a86dc29bb13f67308b114b0" checksum = "ad7ef048d4783355163fd0c874aac3db54b919dc6a86dc29bb13f67308b114b0"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.6.0",
"derive_more", "derive_more",
"log", "log",
"ptr_meta", "ptr_meta",
"uefi-raw", "uefi-raw",
] ]
[[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"
@@ -188,18 +275,28 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62d9a86c292b165f757e47e7fd66855def189b2564609bc4203727b27c33db22" checksum = "62d9a86c292b165f757e47e7fd66855def189b2564609bc4203727b27c33db22"
dependencies = [ dependencies = [
"x86_64", "x86_64 0.15.1",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.85" version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "ps2"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfef03bb1362e6a23a211efe8c72e2eeb6888f51fb329cdfa07bb470986ea7d0"
dependencies = [
"bitflags 1.3.2",
"x86_64 0.14.12",
]
[[package]] [[package]]
name = "ptr_meta" name = "ptr_meta"
version = "0.2.0" version = "0.2.0"
@@ -222,9 +319,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.36" version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -250,12 +347,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 = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.9.8" version = "0.9.8"
@@ -298,11 +389,11 @@ dependencies = [
[[package]] [[package]]
name = "uart_16550" name = "uart_16550"
version = "0.3.0" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dc00444796f6c71f47c85397a35e9c4dbf9901902ac02386940d178e2b78687" checksum = "4922792855b1bce30997fbaa5418597902c278a92d20dfe348e6f062c3bd861d"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 2.6.0",
"rustversion", "rustversion",
"x86", "x86",
] ]
@@ -313,7 +404,7 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efa8716f52e8cab8bcedfd5052388a0f263b69fe5cc2561548dc6a530678333c" checksum = "efa8716f52e8cab8bcedfd5052388a0f263b69fe5cc2561548dc6a530678333c"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.6.0",
"ptr_meta", "ptr_meta",
"uguid", "uguid",
] ]
@@ -353,6 +444,18 @@ dependencies = [
"raw-cpuid", "raw-cpuid",
] ]
[[package]]
name = "x86_64"
version = "0.14.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96cb6fd45bfeab6a5055c5bffdb08768bd0c069f1d946debe585bbb380a7c062"
dependencies = [
"bit_field",
"bitflags 2.6.0",
"rustversion",
"volatile",
]
[[package]] [[package]]
name = "x86_64" name = "x86_64"
version = "0.15.1" version = "0.15.1"
@@ -360,7 +463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df" checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df"
dependencies = [ dependencies = [
"bit_field", "bit_field",
"bitflags 2.5.0", "bitflags 2.6.0",
"rustversion", "rustversion",
"volatile", "volatile",
] ]

View File

@@ -5,3 +5,8 @@ members = [
exclude = ["boot"] exclude = ["boot"]
resolver = "2" resolver = "2"
[profile.release]
strip = false

View File

@@ -1,3 +1,10 @@
%define VIDEO_MODE 0
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)
@@ -8,7 +15,17 @@ header_start:
; insert optional multiboot tags here ; insert optional multiboot tags here
; required end tag %if VIDEO_MODE
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

View File

@@ -2,6 +2,9 @@ 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() {
@@ -77,7 +80,7 @@ function run_qemu() {
qemu-system-x86_64 \ qemu-system-x86_64 \
-cdrom $ISO \ -cdrom $ISO \
-serial stdio \ -serial stdio \
-device VGA -device VGA --enable-kvm
# -d int \ # -d int \
} }
@@ -128,7 +131,7 @@ case $1 in
build_dev build_dev
;; ;;
run-qemu-gdb) run-qemu-gdb)
build build_dev
run_qemu_gdb run_qemu_gdb
;; ;;
*) *)

View File

@@ -2,7 +2,6 @@
name = "kernel" name = "kernel"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
test=false
[lib] [lib]
name="kernel" name="kernel"
@@ -10,19 +9,22 @@ 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]
acpi = "5.0.0"
anyhow = { version = "1.0.87", default-features = false }
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"] }
embedded-graphics = "0.8.1"
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"] }
libm = "0.2.8"
log = "0.4.21" log = "0.4.21"
multiboot2 = "0.20.2" multiboot2 = "0.20.2"
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"
ps2 = "0.2.0"
spin = "0.9.8" spin = "0.9.8"
talc = "4.4.1" talc = "4.4.1"
uart_16550 = "0.3.0" uart_16550 = "0.3.0"

22
kernel/src/acpi/mod.rs Normal file
View File

@@ -0,0 +1,22 @@
use core::{cell::RefCell, ops::DerefMut};
use acpi::AcpiHandler;
use alloc::boxed::Box;
use crate::mem::{paging::ActivePageTable, Frame};
#[derive(Debug, Clone)]
struct AcpiMapper {
apt: RefCell<ActivePageTable>
}
impl AcpiMapper {
pub fn new(apt: ActivePageTable) -> Self {
Self {
apt: RefCell::new(apt)
}
}
}

View File

@@ -0,0 +1,105 @@
use core::fmt::Debug;
use alloc::{boxed::Box, string::{String, ToString}, vec::Vec, vec};
use hashbrown::HashMap;
use spin::{Mutex, MutexGuard};
use crate::utils::as_any_mut;
pub mod ps2;
lazy_static::lazy_static!(
pub static ref DRIVER_MGR: Mutex<DriverHandler> = Mutex::new(DriverHandler::new());
);
type RegisterFn = fn(
name: &mut String,
author: &mut String,
license: &mut String,
) -> Box<dyn Driver>;
pub trait Driver: Debug + Send{
fn new() -> impl Driver where Self: Sized;
fn register(
name: &mut String,
author: &mut String,
license: &mut String,
) -> Box<dyn Driver> where Self: Sized {
*name = alloc::format!("YOUR_DRIVER_NAME");
*author = alloc::format!("Your Name <your@email.tld>");
*license = alloc::format!("GPLv3");
// Box::new(Self::new())
todo!()
}
fn startup(&mut self) -> anyhow::Result<()> {
Ok(())
}
fn shutdown(&mut self) -> anyhow::Result<()> {
Ok(())
}
}
#[derive(Debug)]
pub struct DriverHandler {
drivers: HashMap<String, Box<dyn Driver>>,
}
impl DriverHandler {
pub fn new() -> Self {
Self {
drivers: HashMap::new(),
}
}
#[inline]
pub fn get_instance<'i>() -> MutexGuard<'i, Self> {
DRIVER_MGR.lock()
}
pub fn load_drivers(&mut self) {
for driver_reg_fn in Self::get_all_driver_entries() {
let mut name = String::new();
let mut author = String::new();
let mut license = String::new();
let driver = (driver_reg_fn)(&mut name, &mut author, &mut license);
log::info!("Loaded driver '{name}' ({license})");
self.drivers.insert(name, driver);
}
}
pub fn get_driver<T: Driver + 'static>(&mut self, name: &str) -> Option<&mut T> {
if let Some(d) = self.drivers.get_mut(&name.to_string()) {
unsafe {
// Lets hope for the best
Some(as_any_mut(d).downcast_mut_unchecked::<T>())
}
} else {
None
}
}
pub fn start_drivers(&mut self) {
for (name, driver) in &mut self.drivers {
if let Err(e) = driver.startup() {
log::error!("Driver '{name}' had an error on startup: {e}");
}
}
}
pub fn stop_drivers(&mut self) {
for (name, driver) in &mut self.drivers {
if let Err(e) = driver.shutdown() {
log::error!("Driver '{name}' had an error on shutdown: {e}");
}
}
}
#[inline]
fn get_all_driver_entries() -> Vec<RegisterFn> {
vec![
ps2::Ps2Driver::register,
]
}
}

View File

@@ -0,0 +1,43 @@
use alloc::{boxed::Box, format, string::String};
use anyhow::bail;
use super::Driver;
#[derive(Debug)]
pub struct Ps2Driver{
}
impl Ps2Driver {
pub fn test(&self) -> String {
String::from("hewo")
}
}
impl Driver for Ps2Driver {
fn new() -> impl Driver where Self: Sized {
Self {
}
}
fn register(
name: &mut alloc::string::String,
author: &mut alloc::string::String,
license: &mut alloc::string::String,
) -> Box<dyn Driver> where Self: Sized {
*name = format!("PS/2");
*author = format!("MCorange <mcorange@mcorangehq.xyz>");
*license = format!("GPLv3");
Box::new(Self::new())
}
fn startup(&mut self) -> anyhow::Result<()> {
Ok(())
}
fn shutdown(&mut self) -> anyhow::Result<()> {
Ok(())
}
}

View File

@@ -37,12 +37,10 @@ impl EventManager {
} }
pub fn dispatch(&self, ev: &Event){ pub fn dispatch(&self, ev: &Event){
for listener in &self.listeners { for listener in self.listeners.iter().flatten() {
if let Some(l) = listener { if discriminant(ev) == discriminant(&listener.typ) {
if discriminant(ev) == discriminant(&l.typ) { // TODO: Do something with the result
// TODO: Do something with the result let _ = (listener.func)(ev);
let _ = (l.func)(ev);
}
} }
} }
} }

View File

@@ -21,14 +21,12 @@ 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) });
let stack_end = stack_start + STACK_SIZE as u64; 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) });
let stack_end = stack_start + STACK_SIZE as u64; stack_start + STACK_SIZE as u64
stack_end
}; };
tss tss
}; };

View File

@@ -1,23 +1,13 @@
use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode}; use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode};
use crate::{events::EVENTMAN, interrupts::InterruptIndex}; use crate::interrupts::InterruptIndex;
mod ps2_keyboard; pub mod ps2;
pub mod timer;
pub use ps2_keyboard::ps2_kb_int;
pub extern "x86-interrupt" fn breakpoint(sf: InterruptStackFrame){ pub extern "x86-interrupt" fn breakpoint(sf: InterruptStackFrame){
log::error!("EXCEPT: BREAKPOINT\n{:#?}", sf); log::error!("EXCEPT: BREAKPOINT\n{:#?}", sf);
} }
pub extern "x86-interrupt" fn timer_interrupt(_: InterruptStackFrame){
//log::debug!("INT: TIMER\n{:#?}", sf);
// print!(".");
// EVENTMAN.lock().dispatch(&crate::events::Event::TimerInterrupt(None));
unsafe {
super::PICS.lock()
.notify_end_of_interrupt(InterruptIndex::Timer as u8);
}
}
pub extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, _: u64) -> ! { pub extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, _: u64) -> ! {
panic!("EXCEPT: DOUBLE FAULT \n{:#?}", stack_frame); panic!("EXCEPT: DOUBLE FAULT \n{:#?}", stack_frame);
} }

View File

@@ -1,16 +1,13 @@
use hashbrown::HashSet; use x86_64::{instructions::port::Port, structures::idt::InterruptStackFrame};
use pc_keyboard::{DecodedKey, KeyState};
use spin::Mutex;
use x86_64::structures::idt::InterruptStackFrame;
use crate::{events::EVENTMAN, interrupts::PICS}; use crate::{events::EVENTMAN, interrupts::PICS};
pub struct Ps2KbPressEvent(DecodedKey); const PS2_PORT: u16 = 0x60;
// https://wiki.osdev.org/PS/2_Keyboard
pub extern "x86-interrupt" fn ps2_kb_int(_sf: InterruptStackFrame){ pub extern "x86-interrupt" fn ps2_kb_int(_sf: InterruptStackFrame){
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1}; use pc_keyboard::{layouts, HandleControl, Keyboard, ScancodeSet1};
use spin::Mutex; use spin::Mutex;
use x86_64::instructions::port::Port;
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> = static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> =
@@ -20,7 +17,7 @@ pub extern "x86-interrupt" fn ps2_kb_int(_sf: InterruptStackFrame){
} }
let mut keyboard = KEYBOARD.lock(); let mut keyboard = KEYBOARD.lock();
let mut port = Port::new(0x60); let mut port = Port::new(PS2_PORT);
let scancode: u8 = unsafe { port.read() }; let scancode: u8 = unsafe { port.read() };
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
@@ -28,6 +25,6 @@ pub extern "x86-interrupt" fn ps2_kb_int(_sf: InterruptStackFrame){
} }
unsafe { unsafe {
PICS.lock() PICS.lock()
.notify_end_of_interrupt(super::InterruptIndex::Keyboard as u8); .notify_end_of_interrupt(super::InterruptIndex::Ps2Keyboard.get());
} }
} }

View File

@@ -0,0 +1,14 @@
use x86_64::structures::idt::InterruptStackFrame;
use crate::interrupts::{InterruptIndex, PICS};
pub extern "x86-interrupt" fn timer_interrupt(_: InterruptStackFrame){
//log::debug!("INT: TIMER\n{:#?}", sf);
// print!(".");
// EVENTMAN.lock().dispatch(&crate::events::Event::TimerInterrupt(None));
unsafe {
PICS.lock()
.notify_end_of_interrupt(InterruptIndex::Timer.get());
}
}

View File

@@ -14,10 +14,11 @@ lazy_static::lazy_static! {
idt.breakpoint.set_handler_fn(handlers::breakpoint); idt.breakpoint.set_handler_fn(handlers::breakpoint);
idt.page_fault.set_handler_fn(handlers::page_fault); idt.page_fault.set_handler_fn(handlers::page_fault);
idt[InterruptIndex::Timer as u8] idt[InterruptIndex::Timer.get()]
.set_handler_fn(handlers::timer_interrupt); .set_handler_fn(handlers::timer::timer_interrupt);
idt[InterruptIndex::Keyboard as u8]
.set_handler_fn(handlers::ps2_kb_int); idt[InterruptIndex::Ps2Keyboard.get()]
.set_handler_fn(handlers::ps2::ps2_kb_int);
unsafe { unsafe {
@@ -31,11 +32,52 @@ lazy_static::lazy_static! {
pub static PICS: spin::Mutex<ChainedPics> = pub static PICS: spin::Mutex<ChainedPics> =
spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) }); spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
/// https://wiki.osdev.org/Interrupts
/// | IRQ | Description |
/// |------|----------------------------------------------------------|
/// | 0 | Programmable Interrupt Timer Interrupt |
/// | 1 | Keyboard Interrupt |
/// | 2 | Cascade (used internally by the two PICs. never raised) |
/// | 3 | COM2 (if enabled) |
/// | 4 | COM1 (if enabled) |
/// | 5 | LPT2 (if enabled) |
/// | 6 | Floppy Disk |
/// | 7 | LPT1 / Unreliable "spurious" interrupt (usually) |
/// | 8 | CMOS real-time clock (if enabled) |
/// | 9 | Free for peripherals / legacy SCSI / NIC |
/// | 10 | Free for peripherals / SCSI / NIC |
/// | 11 | Free for peripherals / SCSI / NIC |
/// | 12 | PS2 Mouse |
/// | 13 | FPU / Coprocessor / Inter-processor |
/// | 14 | Primary ATA Hard Disk |
/// | 15 | Secondary ATA Hard Disk |
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(u8)] #[repr(u8)]
pub enum InterruptIndex { pub enum InterruptIndex {
Timer = PIC_1_OFFSET, Timer = 0,
Keyboard, // PS/2 Ps2Keyboard,
Cascade,
Com2,
Com1,
Lpt2,
FloppyDisk,
Lpt1,
Cmos,
Ffp0,
Ffp1,
Ffp2,
Ps2Mouse,
Fpu,
PrimAtaHdd,
SecAtaHdd,
}
impl InterruptIndex {
pub fn get(self) -> u8 {
(self as u8) + PIC_1_OFFSET
}
} }
pub fn init_idt() { pub fn init_idt() {

View File

@@ -5,14 +5,16 @@
#![allow(internal_features)] #![allow(internal_features)]
#![feature(ptr_internals)] #![feature(ptr_internals)]
#![feature(allocator_api)] #![feature(allocator_api)]
#![feature(downcast_unchecked)]
use core::ptr::addr_of; use std::{input::Keyboard, vga::video::Color};
use alloc::vec::Vec; use mem::paging::ActivePageTable;
use pc_keyboard::{DecodedKey, KeyCode}; use multiboot2::{BootInformation, BootInformationHeader};
use x86_64::instructions::nop; use pc_keyboard::KeyCode;
use embedded_graphics::prelude::*;
use crate::{gdt::PRIV_TSS_STACK, scheduler::{executor::Executor, Task}, utils::jmp_to_usermode}; use scheduler::{executor::Executor, Task};
use utils::acpi_shutdown;
extern crate alloc; extern crate alloc;
@@ -26,58 +28,61 @@ mod events;
mod mem; mod mem;
mod scheduler; mod scheduler;
mod std; mod std;
mod drivers;
mod acpi;
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();
let active_table = mem::init(mb2p);
{
let mut dm = drivers::DriverHandler::get_instance();
dm.load_drivers();
dm.start_drivers();
}
active_table
}
let active_table = mem::init(mb2_info_addr); fn shutdown() -> ! {
{
//unsafe { let mut dm = drivers::DriverHandler::get_instance();
// jmp_to_usermode(active_table, usermode_code as *const () as usize, addr_of!(PRIV_TSS_STACK) as *const () as usize); dm.stop_drivers();
//} }
//let mut executor = Executor::new();
//executor.spawn(Task::new(usermode_code()));
//executor.run();
//let mut a = Vec::new();
//a.push(6); acpi_shutdown()
//a.push(9); }
//a.push(4);
//a.push(2);
//a.push(0);
//log::error!("{:?}", a); #[no_mangle]
extern "C" fn kmain(mb2p: *const BootInformationHeader) -> ! {
// let sch = Executor::new();
let _ = init(mb2p);
{
// EVENTMAN.lock().add_listener(events::Event::Ps2KeyPress(None), |k| { let mut dm = drivers::DriverHandler::get_instance();
// let Event::Ps2KeyPress(v) = k else {panic!()}; let driver = dm.get_driver::<drivers::ps2::Ps2Driver>("PS/2");
// if let Some(driver) = driver {
// log::debug!("Keypress event received! ({:?})", v.unwrap()); log::debug!("{:?}", driver.test());
// 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");
loop {
if std::input::is_key_down(KeyCode::A) {
log::info!(":3");
} }
} }
// utils::hcf();
'mainloop: loop {
if Keyboard::is_key_down(KeyCode::A) {
// vc.fill_screen(Color::new(0xFF, 0, 0));
} else {
//vc.fill_screen(Color::new(0, 0xFF, 0));
}
if Keyboard::are_keys_down(&[KeyCode::LAlt, KeyCode::F4]) {
break 'mainloop;
}
}
shutdown()
} }
@@ -88,6 +93,3 @@ fn panic(pi: &core::panic::PanicInfo) -> ! {
} }
async fn usermode_code() {
log::info!("Hello from usermode!");
}

View File

@@ -1,12 +1,9 @@
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;
@@ -16,7 +13,6 @@ 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);
@@ -32,51 +28,77 @@ 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()) {
{WRITER.lock().set_color(Color::Magenta, Color::Black); } if !crate::std::vga::video::is_video_mode_enabled() {
print!("["); self.log_vga(record).unwrap();
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));
}
} }
{WRITER.lock().set_color(Color::Magenta, Color::Black); } self.log_serial(record)
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);

View File

@@ -1,30 +0,0 @@
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();
});
}

View File

@@ -2,7 +2,7 @@
//use x86_64::align_up; //use x86_64::align_up;
pub const HEAP_START: usize = 0o_000_001_000_000_0000; // 0x40000000 - 0x40019000 pub const HEAP_START: usize = 0x40000000; // 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.

View File

@@ -20,7 +20,9 @@ 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 { 0 as *mut u8 } unsafe fn alloc(&self, _: Layout) -> *mut u8 {
core::ptr::null_mut::<u8>()
}
unsafe fn dealloc(&self, _ptr: *mut u8, _: Layout) {} unsafe fn dealloc(&self, _ptr: *mut u8, _: Layout) {}
} }
@@ -33,7 +35,7 @@ pub struct Frame {
impl Frame { impl Frame {
fn containing_address(address: usize) -> Frame { pub fn containing_address(address: usize) -> Frame {
Frame{ number: address / PAGE_SIZE } Frame{ number: address / PAGE_SIZE }
} }
fn start_address(&self) -> paging::PhysicalAddress { fn start_address(&self) -> paging::PhysicalAddress {
@@ -122,12 +124,14 @@ 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: usize) -> Self { pub fn load(mb_ptr: *const BootInformationHeader) -> Self {
let boot_info = unsafe { let boot_info = unsafe {
multiboot2::BootInformation::load(mb_ptr as *const BootInformationHeader).unwrap() multiboot2::BootInformation::load(mb_ptr).unwrap()
}; };
let mmap_tag = boot_info.memory_map_tag().unwrap(); let mmap_tag = boot_info.memory_map_tag().unwrap();
@@ -146,22 +150,27 @@ 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.pitch() * 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 as *const BootInformationHeader).unwrap()}, boot_info: unsafe { multiboot2::BootInformation::load(mb_ptr).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: usize) -> paging::ActivePageTable { pub fn init(mb_ptr: *const BootInformationHeader) -> 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);

View File

@@ -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 = flags | EntryFlags::PRESENT; flags |= EntryFlags::PRESENT;
} }
if section.flags().contains(ElfSectionFlags::WRITABLE) { if section.flags().contains(ElfSectionFlags::WRITABLE) {
flags = flags | EntryFlags::WRITABLE; flags |= EntryFlags::WRITABLE;
} }
if !section.flags().contains(ElfSectionFlags::EXECUTABLE) { if !section.flags().contains(ElfSectionFlags::EXECUTABLE) {
flags = flags | EntryFlags::NO_EXECUTE; flags |= EntryFlags::NO_EXECUTE;
} }
flags flags

View File

@@ -7,10 +7,11 @@ use super::{
Frame, FrameAllocator, Frame, FrameAllocator,
PAGE_SIZE, PhysicalAddress, PAGE_SIZE, PhysicalAddress,
VirtualAddress, Page, VirtualAddress, Page,
ENTRY_COUNT, InactivePageTable ENTRY_COUNT,
}; };
use core::ptr::Unique; use core::ptr::Unique;
#[derive(Debug, Clone)]
pub struct Mapper { pub struct Mapper {
p4: Unique<Table<Level4>>, p4: Unique<Table<Level4>>,
} }

View File

@@ -1,3 +1,4 @@
#![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};
@@ -19,7 +20,7 @@ pub struct Page {
number: usize, number: usize,
} }
#[derive(Debug, Clone)]
pub struct ActivePageTable { pub struct ActivePageTable {
mapper: Mapper mapper: Mapper
} }
@@ -38,7 +39,6 @@ impl DerefMut for ActivePageTable {
} }
impl ActivePageTable { impl ActivePageTable {
unsafe fn new() -> ActivePageTable { unsafe fn new() -> ActivePageTable {
ActivePageTable { ActivePageTable {
@@ -119,8 +119,8 @@ impl InactivePageTable {
impl Page { impl Page {
pub fn containing_address(address: VirtualAddress) -> Page { pub fn containing_address(address: VirtualAddress) -> Page {
assert!(address < 0x0000_8000_0000_0000 || assert!(
address >= 0xffff_8000_0000_0000, !(0x0000_8000_0000_0000..0xffff_8000_0000_0000).contains(&address),
"invalid address: 0x{:x}", address); "invalid address: 0x{:x}", address);
Page { number: address / PAGE_SIZE } Page { number: address / PAGE_SIZE }
} }
@@ -137,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 >> 0) & 0o777 self.number & 0o777
} }
pub fn range_inclusive(start: Page, end: Page) -> PageIter { pub fn range_inclusive(start: Page, end: Page) -> PageIter {
PageIter { PageIter {
@@ -204,8 +204,15 @@ 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_buffer_frame = Frame::containing_address(0xb8000); let vga_text_buffer_frame = Frame::containing_address(0xb8000);
mapper.identity_map(vga_buffer_frame, EntryFlags::WRITABLE, allocator); mapper.identity_map(vga_text_buffer_frame, EntryFlags::WRITABLE, allocator);
let vga_video_buffer_frame_start = Frame::containing_address(mem_info.vga_vide_start);
let vga_video_buffer_frame_end = Frame::containing_address(mem_info.vga_vide_start + mem_info.vga_vide_size);
for frame in Frame::range_inclusive(vga_video_buffer_frame_start, vga_video_buffer_frame_end) {
//mapper.identity_map(frame, EntryFlags::WRITABLE | EntryFlags::WRITE_THROUGH, 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) {
@@ -225,8 +232,7 @@ 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
{ {

View File

@@ -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<'a>(&'a self, index: usize) -> Option<&'a Table<L::NextLevel>> { pub fn next_table(&self, index: usize) -> Option<&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<'a>(&'a mut self, index: usize) -> Option<&'a mut Table<L::NextLevel>> { pub fn next_table_mut(&mut self, index: usize) -> Option<&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 _) })
} }

View File

@@ -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),
} }
} }

View File

@@ -1,3 +1,4 @@
#![allow(dead_code)]
use core::task::{Context, Poll, Waker}; use core::task::{Context, Poll, Waker};
use super::{Task, TaskId}; use super::{Task, TaskId};
@@ -53,7 +54,7 @@ impl Executor {
}; };
let waker = waker_cache let waker = waker_cache
.entry(task_id) .entry(task_id)
.or_insert_with(|| TaskWaker::new(task_id, task_queue.clone())); .or_insert_with(|| TaskWaker::new_waker(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(()) => {
@@ -77,7 +78,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(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker { fn new_waker(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,
@@ -96,3 +97,4 @@ impl Wake for TaskWaker {
} }

View File

@@ -1,3 +1,4 @@
#![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;

View File

@@ -1,50 +1,94 @@
use alloc::{boxed::Box, collections::{btree_set::BTreeSet, vec_deque::VecDeque}, sync::Arc, vec::Vec}; use core::{arch::asm, future::Future};
use hashbrown::HashSet;
use lazy_static::lazy_static;
use pc_keyboard::{DecodedKey, KeyCode, KeyEvent, KeyState};
use spin::Mutex;
use x86_64::instructions::nop;
use crate::events::{Event, EVENTMAN}; use alloc::{collections::{btree_set::BTreeSet, vec_deque::VecDeque}, vec::Vec};
use pc_keyboard::{KeyCode, KeyEvent, KeyState};
use spin::{Lazy, Mutex, MutexGuard};
use x86_64::instructions::port::{Port, PortGeneric, ReadWriteAccess};
use crate::{events::{Event, EVENTMAN}, scheduler::{executor::Executor, Task}};
static mut KEYS_PRESSED: Mutex<BTreeSet<KeyCode>> = Mutex::new(BTreeSet::new()); static mut KEYS_PRESSED: Mutex<BTreeSet<KeyCode>> = Mutex::new(BTreeSet::new());
static mut KEY_BUF: VecDeque<KeyEvent> = VecDeque::new(); static mut KEY_BUF: VecDeque<KeyEvent> = VecDeque::new();
const KEY_BUF_MAX_LEN: usize = 32; const KEY_BUF_MAX_LEN: usize = 32;
pub(super) unsafe fn init() { pub struct Keyboard;
EVENTMAN.lock().add_listener(crate::events::Event::Ps2KeyEvent(None), |e| { impl Keyboard {
let Event::Ps2KeyEvent(ke) = e else {panic!()}; pub(super) unsafe fn init() {
if let Some(ke) = ke { EVENTMAN.lock().add_listener(crate::events::Event::Ps2KeyEvent(None), |e| {
if KEY_BUF.len() > KEY_BUF_MAX_LEN { let Event::Ps2KeyEvent(ke) = e else {panic!()};
KEY_BUF.pop_front(); if let Some(ke) = ke {
if KEY_BUF.len() > KEY_BUF_MAX_LEN {
KEY_BUF.pop_front();
}
KEY_BUF.push_back(ke.clone());
} }
KEY_BUF.push_back(ke.clone());
}
Ok(()) Ok(())
}) });
} }
// TODO: It is possible for `KEY_BUF` to get overfilled and lose data and make keys stuck. pub fn keys_pressed<'a>() -> MutexGuard<'a, BTreeSet<KeyCode>> {
// Possibly run this every now an again somehow unsafe { KEYS_PRESSED.lock() }
unsafe fn process_events() { }
while !KEY_BUF.is_empty() { // TODO: It is possible for `KEY_BUF` to get overfilled and lose data and make keys stuck.
if let Some(ke) = KEY_BUF.pop_front() { // Possibly run this every now an again somehow
match ke.state { unsafe fn process_events() {
KeyState::Down => { while !KEY_BUF.is_empty() {
KEYS_PRESSED.lock().insert(ke.code); if let Some(ke) = KEY_BUF.pop_front() {
match ke.state {
KeyState::Down => {
Self::keys_pressed().insert(ke.code);
}
KeyState::Up => {
Self::keys_pressed().remove(&ke.code);
}
_ => ()
} }
KeyState::Up => {
KEYS_PRESSED.lock().remove(&ke.code);
}
_ => ()
} }
} }
} }
pub fn is_key_down(key: KeyCode) -> bool {
unsafe {
Self::process_events();
return Self::keys_pressed().contains(&key);
}
}
pub fn are_keys_down(keys: &[KeyCode]) -> bool {
for key in keys {
if !Self::keys_pressed().contains(key) {
return false;
}
}
true
}
} }
pub fn is_key_down(key: KeyCode) -> bool { pub static MOUSE: Lazy<Mutex<Mouse>> = Lazy::new(|| Mutex::new(Mouse::new()));
unsafe {
process_events(); pub struct Mouse {
return KEYS_PRESSED.lock().contains(&key);
}
} }
impl Mouse {
pub const fn new() -> Self {
Self {
}
}
fn get() {
let a = MOUSE.lock();
}
pub(super) fn init() {
}
fn on_move() {
}
}

View File

@@ -1,8 +1,11 @@
pub mod input; use crate::scheduler::executor::Executor;
pub mod input;
pub mod vga;
pub mod typemap;
pub fn init() { pub fn init() {
unsafe { input::init(); }; unsafe { input::Keyboard::init(); };
} }

37
kernel/src/std/typemap.rs Normal file
View File

@@ -0,0 +1,37 @@
use core::{any::{Any, TypeId}, marker::PhantomData, ops::Deref};
use alloc::{borrow::ToOwned, boxed::Box, vec};
use hashbrown::HashMap;
#[derive(Debug)]
pub struct TypeMap<'a> {
map: HashMap<TypeId, Box<dyn Any>>,
_phantom: PhantomData<&'a ()>
}
impl TypeMap<'_> {
pub fn new() -> Self {
Self {
map: HashMap::new(),
_phantom: PhantomData
}
}
pub fn insert<T: 'static>(&mut self, value: T) {
self.map.insert(TypeId::of::<T>(), Box::new(value));
}
pub fn get<T: 'static>(&self) -> Option<&T> {
self.map.get(&TypeId::of::<T>()).and_then(|boxed| boxed.downcast_ref::<T>())
}
}
impl<'a> IntoIterator for TypeMap<'a> {
type Item = (TypeId, Box<dyn Any>);
type IntoIter = hashbrown::hash_map::IntoIter<TypeId, Box<dyn Any>>;
fn into_iter(self) -> Self::IntoIter {
self.map.into_iter()
}
}

View File

@@ -0,0 +1,2 @@
pub mod text;
pub mod video;

View File

@@ -1,9 +1,7 @@
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());
@@ -93,7 +91,7 @@ impl Writer {
} }
} }
pub fn write_string(&mut self, s: &str) { 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
@@ -197,3 +195,12 @@ 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(())
}
}

View File

@@ -0,0 +1,120 @@
mod util;
use embedded_graphics::{pixelcolor::Rgb888, prelude::{DrawTarget, OriginDimensions, PixelColor, RgbColor, Size}};
use multiboot2::{BootInformation, BootInformationHeader, FramebufferTag, FramebufferType, TagTrait};
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}
}
}
#[derive(Clone, Copy)]
pub struct VideoControler{
component_size: u8,
r_ofs: u8,
g_ofs: u8,
b_ofs: u8,
buf_addr: u64,
pitch: usize,
size: [usize; 2],
bpp: u8
}
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 addr: {:x}", fbt.address());
log::info!("{fbt:#?}");
Self {
component_size: red.size,
r_ofs: red.position,
g_ofs: green.position,
b_ofs: blue.position,
buf_addr: fbt.address(),
size: [fbt.width() as usize, fbt.height() as usize],
pitch: fbt.pitch() as usize,
bpp: fbt.bpp(),
}
}
pub fn set_px(&self, x: usize, y: usize, c: Color) {
assert!(x <= self.size[0] && y <= self.size[1]);
let ptr = self.buf_addr as *mut () as *mut u8;
let px = ptr.wrapping_add((self.bpp / 8) as usize * x + self.pitch * 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..self.size[0] {
for y in 0..self.size[1] {
self.set_px(x, y, c);
}
}
}
pub fn fill_screen_grad(&self, start: Color, end: Color) {
let diag = libm::sqrt((self.size[0].pow(2) + self.size[1].pow(2)) as f64);
for x in 0..self.size[0] {
for y in 0..self.size[1] {
let dist = libm::sqrt((x.pow(2) + y.pow(2)) as f64);
let fact = dist / diag;
let color = Color::new(
start.r + (fact * (end.r - start.r) as f64) as u8,
start.g + (fact * (end.g - start.g) as f64) as u8,
start.b + (fact * (end.b - start.b) as f64) as u8,
);
self.set_px(x, y, color);
}
}
}
}
impl DrawTarget for VideoControler {
type Color = Rgb888;
type Error = &'static str;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>> {
for px in pixels {
self.set_px(
px.0.x as usize,
px.0.y as usize,
px.1.into()
)
}
Ok(())
}
}
impl OriginDimensions for VideoControler {
fn size(&self) -> embedded_graphics::prelude::Size {
Size::new(self.size[0] as u32, self.size[1] as u32)
}
}
impl From<Rgb888> for Color {
fn from(c: Rgb888) -> Self {
Color::new(c.r(), c.g(), c.b())
}
}

View File

@@ -0,0 +1,9 @@
extern "C" {
static __VIDEO_MODE: u8;
}
pub fn is_video_mode_enabled() -> bool {
unsafe {
__VIDEO_MODE == 1
}
}

View File

@@ -1,7 +1,7 @@
use core::arch::asm; use core::{any::Any, arch::asm};
use x86::msr::{rdmsr, wrmsr, IA32_EFER}; use x86::msr::{rdmsr, wrmsr, IA32_EFER};
use x86_64::{instructions, registers::{control::{Cr0, Cr0Flags}, segmentation::{Segment, DS}}, PrivilegeLevel}; use x86_64::{instructions::{self, port::PortWriteOnly}, registers::{control::{Cr0, Cr0Flags}, segmentation::{Segment, DS}}, PrivilegeLevel};
use crate::mem::paging::{ActivePageTable, VirtualAddress}; use crate::mem::paging::{ActivePageTable, VirtualAddress};
@@ -54,3 +54,14 @@ pub unsafe fn jmp_to_usermode(apt: ActivePageTable, code: VirtualAddress, stack_
code = in(reg) code_addr, sa = in(reg) sa_addr, cs = in(reg) cs_idx, ds = in(reg) ds_idx); code = in(reg) code_addr, sa = in(reg) sa_addr, cs = in(reg) cs_idx, ds = in(reg) ds_idx);
} }
pub fn acpi_shutdown() -> ! {
let mut port = x86_64::instructions::port::Port::new(0x0604);
unsafe {
port.write(0x2000_u16);
}
loop {hcf()}
}
pub fn as_any_mut<T: Any>(i: &mut T) -> &mut dyn Any {
i as &mut dyn Any
}