libk now replaces the plethora of lib crates #5

Merged
zxq5 merged 9 commits from nullndvoid/FoundryOS:dev into dev 2025-02-23 17:07:26 +00:00
14 changed files with 214 additions and 171 deletions
Showing only changes of commit b8aa203c05 - Show all commits
+5 -2
View File
@@ -4,12 +4,15 @@ resolver = "2"
[workspace.package] [workspace.package]
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2024"
authors = ["The Foundry OS contributors"] authors = ["The FoundryOS Contributors"]
[profile.dev] [profile.dev]
opt-level = "z" opt-level = "z"
debug = true debug = true
# Leave this on to force Cargo to use the debug runner,
# which adds the necessary flags for GDB debugging if you
# set $USE_GDB (to any value) e.g. USE_GDB=1 cargo run
debug-assertions = true debug-assertions = true
overflow-checks = true overflow-checks = true
lto = false lto = false
+4 -2
View File
@@ -1,7 +1,8 @@
[package] [package]
name = "foundry_os" name = "foundry_os"
version = "0.1.0" edition.workspace = true
edition = "2021" version.workspace = true
authors.workspace = true
[dependencies] [dependencies]
limine = "0.3.1" limine = "0.3.1"
@@ -20,3 +21,4 @@ default = []
[[bin]] [[bin]]
name = "kernel" name = "kernel"
path = "src/main.rs" path = "src/main.rs"
test = false
+3 -3
View File
@@ -7,11 +7,11 @@ use limine::{
use spin::Lazy; use spin::Lazy;
#[used] #[used]
#[link_section = ".requests"] #[unsafe(link_section = ".requests")]
static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new(); static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new();
#[used] #[used]
#[link_section = ".requests"] #[unsafe(link_section = ".requests")]
static HIGHER_HALF_DIRECT_MAP_REQUEST: HhdmRequest = HhdmRequest::new(); static HIGHER_HALF_DIRECT_MAP_REQUEST: HhdmRequest = HhdmRequest::new();
/// ```rs /// ```rs
@@ -26,7 +26,7 @@ pub static PHYSICAL_MEMORY_OFFSET: Lazy<u64> = Lazy::new(|| {
}); });
#[used] #[used]
#[link_section = ".requests"] #[unsafe(link_section = ".requests")]
static KERNEL_ADDRESS_REQUEST: KernelAddressRequest = KernelAddressRequest::new(); static KERNEL_ADDRESS_REQUEST: KernelAddressRequest = KernelAddressRequest::new();
/// Converts virtual addresses in the kernel to a physical address like this: /// Converts virtual addresses in the kernel to a physical address like this:
+8 -6
View File
@@ -1,6 +1,8 @@
// use lib_alloc::allocator::FoundryAllocator; // use lib_alloc::allocator::FoundryAllocator;
use limine::{memory_map::EntryType, response::MemoryMapResponse}; use limine::{memory_map::EntryType, response::MemoryMapResponse};
use x86_64::{ use x86_64::{
PhysAddr,
VirtAddr,
// addr, // addr,
registers::control::Cr3, registers::control::Cr3,
structures::paging::{ structures::paging::{
@@ -11,8 +13,6 @@ use x86_64::{
PhysFrame, PhysFrame,
Size4KiB, Size4KiB,
}, },
PhysAddr,
VirtAddr,
}; };
/// Returns a mutable reference to the current level 4 page table. /// Returns a mutable reference to the current level 4 page table.
@@ -27,7 +27,7 @@ unsafe fn active_l4_table(physical_memory_offset: VirtAddr) -> &'static mut Page
let phys_addr = level_4_frame.start_address(); let phys_addr = level_4_frame.start_address();
let virt = phys_addr.as_u64() + physical_memory_offset.as_u64(); let virt = phys_addr.as_u64() + physical_memory_offset.as_u64();
&mut *(virt as *mut PageTable) unsafe { &mut *(virt as *mut PageTable) }
} }
/// Initializes the `OffsetPageTable` for the current CPU architecture. /// Initializes the `OffsetPageTable` for the current CPU architecture.
@@ -49,8 +49,10 @@ unsafe fn active_l4_table(physical_memory_offset: VirtAddr) -> &'static mut Page
/// Returns an `OffsetPageTable` that allows for manipulation of the page /// Returns an `OffsetPageTable` that allows for manipulation of the page
/// tables for the current CPU architecture. /// tables for the current CPU architecture.
pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> { pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> {
let l4_table = active_l4_table(physical_memory_offset); unsafe {
OffsetPageTable::new(l4_table, physical_memory_offset) let l4_table = active_l4_table(physical_memory_offset);
OffsetPageTable::new(l4_table, physical_memory_offset)
}
} }
pub(crate) struct FoundryOSFrameAllocator { pub(crate) struct FoundryOSFrameAllocator {
@@ -76,7 +78,7 @@ impl FoundryOSFrameAllocator {
/// Yields one `PhysFrame` for each available 4KiB frame in the memory map. /// Yields one `PhysFrame` for each available 4KiB frame in the memory map.
/// ///
/// This function is used to allocate frames for the pagemap. /// This function is used to allocate frames for the pagemap.
fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> { fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> + use<> {
let regions = self.memory_map.entries().iter(); let regions = self.memory_map.entries().iter();
let usable_regions = regions.filter(|region| region.entry_type == EntryType::USABLE); let usable_regions = regions.filter(|region| region.entry_type == EntryType::USABLE);
+1 -1
View File
@@ -18,7 +18,7 @@ mod arch;
/// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler. /// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
#[used] #[used]
// The .requests section allows limine to find the requests faster and more safely. // The .requests section allows limine to find the requests faster and more safely.
#[link_section = ".requests"] #[unsafe(link_section = ".requests")]
static BASE_REVISION: BaseRevision = BaseRevision::new(); static BASE_REVISION: BaseRevision = BaseRevision::new();
#[panic_handler] #[panic_handler]
+1 -1
View File
@@ -9,7 +9,7 @@ use libk::{
scheduling::task::{Executor, Task}, scheduling::task::{Executor, Task},
}; };
#[no_mangle] #[unsafe(no_mangle)]
extern "C" fn kmain() -> ! { extern "C" fn kmain() -> ! {
println_log!(" [ Initialising Kernel Systems ] "); println_log!(" [ Initialising Kernel Systems ] ");
if let Err(err) = foundry_os::boot() { if let Err(err) = foundry_os::boot() {
+35 -29
View File
@@ -3,7 +3,7 @@ use spin::{Lazy, Mutex};
use x86_64::instructions::interrupts; use x86_64::instructions::interrupts;
pub use super::framebuffer::screensize_px; pub use super::framebuffer::screensize_px;
use super::framebuffer::{Color, FRAMEBUFFER_WRITER}; use super::framebuffer::{Colour, FRAMEBUFFER_WRITER};
mod font; mod font;
use font::FONT; use font::FONT;
@@ -28,32 +28,39 @@ pub struct Writer {
/// 8 pixels wide. /// 8 pixels wide.
text_col: u32, text_col: u32,
fg_color: Color, fg_color: Colour,
bg_color: Color, bg_color: Colour,
offset1: usize, offset1: usize,
offset2: usize, offset2: usize,
} }
impl Default for Writer {
fn default() -> Self {
Self::new()
}
}
impl Writer { impl Writer {
pub fn new() -> Self { pub fn new() -> Self {
if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() { FRAMEBUFFER_WRITER.lock().as_mut().map_or_else(
Self { || {
screen_width: writer.width() as u32 / 8, panic!("Framebuffer writer not initialized.");
screen_height: writer.height() as u32 / 16, },
|writer| Self {
screen_width: writer.width() / 8,
screen_height: writer.height() / 16,
text_line: 0, text_line: 0,
text_col: 0, text_col: 0,
fg_color: Color::White, fg_color: Colour::White,
bg_color: Color::Black, bg_color: Colour::Black,
offset1: 16, offset1: 16,
offset2: 0, offset2: 0,
} },
} else { )
panic!("Framebuffer writer not initialized");
}
} }
pub fn write_char(&mut self, c: u16) { pub fn write_glyph(&mut self, c: u16) {
if c as u8 == b'\n' { if c as u8 == b'\n' {
self.newline(); self.newline();
return; return;
@@ -63,8 +70,7 @@ impl Writer {
let data: &[u8] = &FONT[c as usize * 16..(c as usize + 1) * 16]; let data: &[u8] = &FONT[c as usize * 16..(c as usize + 1) * 16];
if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() { if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() {
for row in 0..16 { for (row, line) in data.iter().enumerate().take(16) {
let line: u8 = data[row];
for col in 0..8 { for col in 0..8 {
let pixel_x: u32 = self.text_col * FONT_WIDTH + col; let pixel_x: u32 = self.text_col * FONT_WIDTH + col;
let pixel_y: u32 = self.text_line * FONT_HEIGHT + row as u32; let pixel_y: u32 = self.text_line * FONT_HEIGHT + row as u32;
@@ -88,20 +94,20 @@ impl Writer {
} }
} }
pub fn set_offset(&mut self, offset1: usize, offset2: usize) { pub const fn set_offset(&mut self, offset1: usize, offset2: usize) {
self.offset1 = offset1; self.offset1 = offset1;
self.offset2 = offset2; self.offset2 = offset2;
} }
pub fn dimensions(&self) -> (u32, u32) { pub const fn dimensions(&self) -> (u32, u32) {
(self.screen_width, self.screen_height) (self.screen_width, self.screen_height)
} }
pub fn next_char(&mut self) { pub const fn next_char(&mut self) {
self.text_col += 1; self.text_col += 1;
} }
pub fn newline(&mut self) { pub const fn newline(&mut self) {
self.text_col = 0; self.text_col = 0;
if self.text_line + 1 >= self.screen_height { if self.text_line + 1 >= self.screen_height {
@@ -113,18 +119,18 @@ impl Writer {
pub fn write_string(&mut self, s: &str) { pub fn write_string(&mut self, s: &str) {
for c in s.chars() { for c in s.chars() {
self.write_char(c as u16); self.write_glyph(c as u16);
} }
} }
pub fn set_colour(&mut self, fg: Color, bg: Color) { pub const fn set_colour(&mut self, fg: Colour, bg: Colour) {
self.fg_color = fg; self.fg_color = fg;
self.bg_color = bg; self.bg_color = bg;
} }
pub fn reset_colour(&mut self) { pub const fn reset_colour(&mut self) {
self.fg_color = Color::White; self.fg_color = Colour::White;
self.bg_color = Color::Black; self.bg_color = Colour::Black;
} }
} }
@@ -135,7 +141,7 @@ impl core::fmt::Write for Writer {
} }
} }
fn write(args: fmt::Arguments, fg: Color, bg: Color) { fn write(args: fmt::Arguments, fg: Colour, bg: Colour) {
use core::fmt::Write; use core::fmt::Write;
interrupts::without_interrupts(|| { interrupts::without_interrupts(|| {
@@ -148,19 +154,19 @@ fn write(args: fmt::Arguments, fg: Color, bg: Color) {
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
x86_64::instructions::interrupts::without_interrupts(|| { x86_64::instructions::interrupts::without_interrupts(|| {
write(args, Color::White, Color::Black); write(args, Colour::White, Colour::Black);
}) })
} }
pub fn _print_err(args: fmt::Arguments) { pub fn _print_err(args: fmt::Arguments) {
x86_64::instructions::interrupts::without_interrupts(|| { x86_64::instructions::interrupts::without_interrupts(|| {
write(args, Color::Red, Color::Black); write(args, Colour::Red, Colour::Black);
}) })
} }
pub fn _print_log(args: fmt::Arguments) { pub fn _print_log(args: fmt::Arguments) {
x86_64::instructions::interrupts::without_interrupts(|| { x86_64::instructions::interrupts::without_interrupts(|| {
write(args, Color::Yellow, Color::Black); write(args, Colour::Yellow, Colour::Black);
}) })
} }
+54 -38
View File
@@ -1,52 +1,69 @@
use limine::request::FramebufferRequest; use limine::request::FramebufferRequest;
#[used] #[used]
#[link_section = ".requests"] #[unsafe(link_section = ".requests")]
static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new(); static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
mod colour; mod colour;
pub use colour::Color; pub use colour::Colour;
use core::panic; use core::panic;
use limine::framebuffer::Framebuffer; use limine::framebuffer::Framebuffer;
use spin::{Lazy, Mutex}; use spin::{Lazy, Mutex};
// use crate::{colour::Color, FRAMEBUFFER_REQUEST};
pub static FRAMEBUFFER_WRITER: Lazy<Mutex<Option<FramebufferWriter>>> = Lazy::new(|| { pub static FRAMEBUFFER_WRITER: Lazy<Mutex<Option<FramebufferWriter>>> = Lazy::new(|| {
Mutex::new( Mutex::new(FRAMEBUFFER_REQUEST.get_response().map_or_else(
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.get_response() { || {
let framebuffer = framebuffer_response.framebuffers().next().unwrap();
Some(FramebufferWriter::new(framebuffer))
} else {
panic!("Framebuffer request failed"); panic!("Framebuffer request failed");
}, },
) |framebuffer_response| {
let framebuffer = framebuffer_response.framebuffers().next().unwrap();
Some(FramebufferWriter::new(framebuffer))
},
))
}); });
pub struct FramebufferWriter<'a> { /// The updated writer stores necessary fields from the [Framebuffer].
framebuffer: Framebuffer<'a>, /// This ensures that the contained types are Send, as Framebuffer was
/// not marked as Send.
///
/// It also avoids the requirement for lifetimes.
///
/// Note this does not implement Writer as these functions only handle drawing pixels.
pub struct FramebufferWriter {
pitch: u64,
bpp: u16,
addr: *mut u8,
width: u64,
height: u64,
} }
unsafe impl<'a> Send for FramebufferWriter<'a> {} unsafe impl Send for FramebufferWriter {}
unsafe impl<'a> Sync for FramebufferWriter<'a> {} unsafe impl Sync for FramebufferWriter {}
impl<'a> FramebufferWriter<'a> {
pub fn new(framebuffer: Framebuffer<'a>) -> Self {
Self { framebuffer }
}
pub fn write_pixel(&self, x: usize, y: usize, color: Color) { impl FramebufferWriter {
let pitch = self.framebuffer.pitch() as usize; pub fn new(framebuffer: Framebuffer) -> Self {
let bpp = (self.framebuffer.bpp() / 8) as usize; Self {
let pixel_offset = y * pitch + x * bpp; pitch: framebuffer.pitch(),
bpp: framebuffer.bpp(),
unsafe { addr: framebuffer.addr(),
*(self.framebuffer.addr().add(pixel_offset) as *mut u32) = color.into(); width: framebuffer.width(),
height: framebuffer.height(),
} }
} }
pub fn render_frame(&self, buffer: &[Color; 1280 * 800]) { pub fn write_pixel(&self, x: usize, y: usize, color: Colour) {
let pitch = self.pitch as usize;
let bpp = (self.bpp / 8) as usize;
let pixel_offset = y * pitch + x * bpp;
unsafe {
*(self.addr.add(pixel_offset) as *mut u32) = color.into();
}
}
pub fn render_frame(&self, buffer: &[Colour; 1280 * 800]) {
for (y, row) in buffer.chunks(1280).enumerate() { for (y, row) in buffer.chunks(1280).enumerate() {
for (x, pixel) in row.iter().enumerate() { for (x, pixel) in row.iter().enumerate() {
self.write_pixel(x, y, *pixel); self.write_pixel(x, y, *pixel);
@@ -54,30 +71,29 @@ impl<'a> FramebufferWriter<'a> {
} }
} }
pub fn width(&self) -> u32 { pub const fn width(&self) -> u32 {
self.framebuffer.width() as u32 self.width as u32
} }
pub fn height(&self) -> u32 { pub const fn height(&self) -> u32 {
self.framebuffer.height() as u32 self.height as u32
} }
pub fn clear(&self) { pub fn clear(&self) {
let width = self.framebuffer.width() as usize; let width = self.width as usize;
let height = self.framebuffer.height() as usize; let height = self.height as usize;
for y in 0..height { for y in 0..height {
for x in 0..width { for x in 0..width {
self.write_pixel(x, y, Color::Black); self.write_pixel(x, y, Colour::Black);
} }
} }
} }
} }
pub fn screensize_px() -> (u32, u32) { pub fn screensize_px() -> (u32, u32) {
if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() { FRAMEBUFFER_WRITER
(writer.width(), writer.height()) .lock()
} else { .as_mut()
(0, 0) .map_or_else(|| (0, 0), |writer| (writer.width(), writer.height()))
}
} }
+27 -27
View File
@@ -1,6 +1,6 @@
#[repr(u32)] #[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Color { pub enum Colour {
ARGB(u8, u8, u8, u8), ARGB(u8, u8, u8, u8),
RGB(u8, u8, u8), RGB(u8, u8, u8),
HexARGB(u32), HexARGB(u32),
@@ -14,40 +14,40 @@ pub enum Color {
White = 0xFFFFFFFF, White = 0xFFFFFFFF,
} }
impl Into<u32> for Color { impl From<Colour> for u32 {
fn into(self) -> u32 { fn from(val: Colour) -> Self {
match self { match val {
Color::ARGB(a, r, g, b) => { Colour::ARGB(a, r, g, b) => {
(a as u32) << 24 | (r as u32) << 16 | (g as u32) << 8 | (b as u32) (a as u32) << 24 | (r as u32) << 16 | (g as u32) << 8 | (b as u32)
} }
Color::RGB(r, g, b) => (0u32) << 24 | (r as u32) << 16 | (g as u32) << 8 | (b as u32), Colour::RGB(r, g, b) => ((r as u32) << 16) | (g as u32) << 8 | (b as u32),
Color::HexARGB(hex) => hex, Colour::HexARGB(hex) => hex,
Color::Black => 0xFF000000, Colour::Black => 0xFF000000,
Color::Blue => 0xFF0000FF, Colour::Blue => 0xFF0000FF,
Color::Green => 0xFF00FF00, Colour::Green => 0xFF00FF00,
Color::Cyan => 0xFF00FFFF, Colour::Cyan => 0xFF00FFFF,
Color::Red => 0xFFFF0000, Colour::Red => 0xFFFF0000,
Color::Magenta => 0xFFFF00FF, Colour::Magenta => 0xFFFF00FF,
Color::Yellow => 0xFFFFFF00, Colour::Yellow => 0xFFFFFF00,
Color::White => 0xFFFFFFFF, Colour::White => 0xFFFFFFFF,
} }
} }
} }
impl core::fmt::Display for Color { impl core::fmt::Display for Colour {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self { match self {
Color::ARGB(r, g, b, a) => write!(f, "RGBA(#{:x}{:x}{:x}{:x})", r, g, b, a), Colour::ARGB(r, g, b, a) => write!(f, "RGBA(#{:x}{:x}{:x}{:x})", r, g, b, a),
Color::RGB(r, g, b) => write!(f, "RGB(#{:x}{:x}{:x})", r, g, b), Colour::RGB(r, g, b) => write!(f, "RGB(#{:x}{:x}{:x})", r, g, b),
Color::HexARGB(hex) => write!(f, "Hex(#{:x})", hex), Colour::HexARGB(hex) => write!(f, "Hex(#{:x})", hex),
Color::Black => write!(f, "Black"), Colour::Black => write!(f, "Black"),
Color::Blue => write!(f, "Blue"), Colour::Blue => write!(f, "Blue"),
Color::Green => write!(f, "Green"), Colour::Green => write!(f, "Green"),
Color::Cyan => write!(f, "Cyan"), Colour::Cyan => write!(f, "Cyan"),
Color::Red => write!(f, "Red"), Colour::Red => write!(f, "Red"),
Color::Magenta => write!(f, "Magenta"), Colour::Magenta => write!(f, "Magenta"),
Color::Yellow => write!(f, "Yellow"), Colour::Yellow => write!(f, "Yellow"),
Color::White => write!(f, "White"), Colour::White => write!(f, "White"),
} }
} }
} }
+24 -17
View File
@@ -5,9 +5,9 @@ use core::{
task::{Context, Poll}, task::{Context, Poll},
}; };
use super::{print, println}; use crate::prelude::*;
use crossbeam::queue::ArrayQueue; use crossbeam::queue::ArrayQueue;
use futures_util::{task::AtomicWaker, Stream}; use futures_util::{Stream, task::AtomicWaker};
use spin::Once; use spin::Once;
static KBD_QUEUE: Once<ArrayQueue<u8>> = Once::new(); static KBD_QUEUE: Once<ArrayQueue<u8>> = Once::new();
@@ -15,7 +15,7 @@ static WAKER: AtomicWaker = AtomicWaker::new();
pub fn add_scancode(scancode: u8) { pub fn add_scancode(scancode: u8) {
if let Some(queue) = KBD_QUEUE.get() { if let Some(queue) = KBD_QUEUE.get() {
if let Err(_) = queue.push(scancode) { if queue.push(scancode).is_err() {
println!("WARNING: scancode queue full; dropping keyboard input"); println!("WARNING: scancode queue full; dropping keyboard input");
} else { } else {
println!("waking waker"); println!("waking waker");
@@ -33,7 +33,14 @@ pub struct ScanCodeStream {
impl ScanCodeStream { impl ScanCodeStream {
pub fn new() -> Self { pub fn new() -> Self {
KBD_QUEUE.call_once(|| ArrayQueue::new(5)); KBD_QUEUE.call_once(|| ArrayQueue::new(5));
ScanCodeStream { _private: () }
Self { _private: () }
}
}
impl Default for ScanCodeStream {
fn default() -> Self {
Self::new()
} }
} }
@@ -42,30 +49,30 @@ impl Stream for ScanCodeStream {
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let queue = KBD_QUEUE.get().expect("scancode queue not initialized"); let queue = KBD_QUEUE.get().expect("scancode queue not initialized");
print!("polling or smth"); serial_println!("This is called once.");
WAKER.register(cx.waker());
// fast path // fast path
if let Some(scancode) = queue.pop() { if let Some(scancode) = queue.pop() {
return Poll::Ready(Some(scancode)); return Poll::Ready(Some(scancode));
} }
WAKER.register(&cx.waker()); queue.pop().map_or_else(
match queue.pop() { || {
Some(scancode) => { print!("Returning");
print!("scancode found"); Poll::Pending
},
|scancode| {
print!("Scancode found");
WAKER.take(); WAKER.take();
Poll::Ready(Some(scancode)) Poll::Ready(Some(scancode))
} },
None => { )
print!("returning");
Poll::Pending
}
}
} }
} }
use futures_util::stream::StreamExt; use futures_util::stream::StreamExt;
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1}; use pc_keyboard::{DecodedKey, HandleControl, Keyboard, ScancodeSet1, layouts};
pub async fn print_keypresses() { pub async fn print_keypresses() {
let mut scancodes = ScanCodeStream::new(); let mut scancodes = ScanCodeStream::new();
@@ -75,7 +82,7 @@ pub async fn print_keypresses() {
HandleControl::Ignore, HandleControl::Ignore,
); );
println!("OK!!!"); serial_println!("Printing keypresses.");
while let Some(scancode) = scancodes.next().await { while let Some(scancode) = scancodes.next().await {
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
+18 -14
View File
@@ -3,23 +3,27 @@
use core::arch::asm; use core::arch::asm;
#[inline] #[inline]
pub unsafe fn inb(port: u16) -> u8 { pub fn inb(port: u16) -> u8 {
let value: u8; let value: u8;
asm!( unsafe {
"in al, dx", asm!(
out("al") value, "in al, dx",
in("dx") port, out("al") value,
options(nomem, nostack, preserves_flags) in("dx") port,
); options(nomem, nostack, preserves_flags)
);
}
value value
} }
#[inline] #[inline]
pub unsafe fn outb(port: u16, value: u8) { pub fn outb(port: u16, value: u8) {
asm!( unsafe {
"out dx, al", asm!(
in("dx") port, "out dx, al",
in("al") value, in("dx") port,
options(nomem, nostack, preserves_flags) in("al") value,
); options(nomem, nostack, preserves_flags)
);
}
} }
+18 -22
View File
@@ -45,14 +45,14 @@ pub fn serial_read() -> &'static str {
let i = BUFFER_LEN.load(Ordering::SeqCst); let i = BUFFER_LEN.load(Ordering::SeqCst);
return unsafe { unsafe {
if i != 0 { if i != 0 {
core::str::from_utf8(&BUFFER[..i - 1]).unwrap() core::str::from_utf8(&BUFFER[..i - 1]).unwrap()
} else { } else {
serial_println!("empty string"); serial_println!("empty string");
"" ""
} }
}; }
} }
static PORT: u16 = 0x3f8; static PORT: u16 = 0x3f8;
@@ -83,15 +83,13 @@ impl Writer {
pub fn write_byte(&self, data: u8) { pub fn write_byte(&self, data: u8) {
unsafe { unsafe {
while !self.write_success() {} while !self.write_success() {}
outb(PORT + 0, data); outb(PORT, data);
} }
} }
} }
pub fn init() -> Result<(), &'static str> { pub fn init() -> Result<(), &'static str> {
if let Err(e) = test() { test()?;
return Err(e);
}
if READER.lock().is_none() { if READER.lock().is_none() {
*READER.lock() = Some(Reader); *READER.lock() = Some(Reader);
@@ -105,24 +103,22 @@ pub fn init() -> Result<(), &'static str> {
} }
pub fn test() -> Result<(), &'static str> { pub fn test() -> Result<(), &'static str> {
unsafe { outb(PORT + 1, 0x00); // Disable all interrupts
outb(PORT + 1, 0x00); // Disable all interrupts outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) outb(PORT, 0x03); // Set divisor to 3 (lo byte) 38400 baud
outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud outb(PORT + 1, 0x00); // (hi byte)
outb(PORT + 1, 0x00); // (hi byte) outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-bytethreshold
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-bytethreshold outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip outb(PORT, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
if inb(PORT + 0) != 0xAE { if inb(PORT) != 0xAE {
return Err("serial test failed"); return Err("serial test failed");
}
outb(PORT + 4, 0x0F);
} }
outb(PORT + 4, 0x0F);
Ok(()) Ok(())
} }
@@ -153,7 +149,7 @@ impl Reader {
pub fn read(&self) -> u8 { pub fn read(&self) -> u8 {
unsafe { unsafe {
while !self.read_ready() {} while !self.read_ready() {}
return inb(PORT + 0); inb(PORT)
} }
} }
} }
+3 -2
View File
@@ -1,5 +1,6 @@
#![no_std] #![no_std]
#![warn(tail_expr_drop_order)]
#![warn(clippy::correctness, clippy::perf, clippy::nursery)]
// alloc // alloc
// io : serial, framebuffer, ascii(?), keyboard // io : serial, framebuffer, ascii(?), keyboard
// ????? // ?????
@@ -11,5 +12,5 @@ pub mod scheduling;
/// Re-exports most of the IO macros. /// Re-exports most of the IO macros.
pub mod prelude { pub mod prelude {
pub use crate::{print_log, println, println_log, serial_print, serial_println}; pub use crate::{print, print_log, println, println_log, serial_print, serial_println};
} }
+13 -7
View File
@@ -14,8 +14,8 @@ pub struct Task {
} }
impl Task { impl Task {
pub fn new(future: impl Future<Output = ()> + 'static) -> Task { pub fn new(future: impl Future<Output = ()> + 'static) -> Self {
Task { Self {
id: TaskId::new(), id: TaskId::new(),
future: Box::pin(future), future: Box::pin(future),
} }
@@ -32,9 +32,15 @@ pub struct Executor {
waker_cache: BTreeMap<TaskId, Waker>, waker_cache: BTreeMap<TaskId, Waker>,
} }
impl Default for Executor {
fn default() -> Self {
Self::new()
}
}
impl Executor { impl Executor {
pub fn new() -> Self { pub fn new() -> Self {
Executor { Self {
tasks: BTreeMap::new(), tasks: BTreeMap::new(),
task_queue: Arc::new(ArrayQueue::new(100)), task_queue: Arc::new(ArrayQueue::new(100)),
waker_cache: BTreeMap::new(), waker_cache: BTreeMap::new(),
@@ -63,7 +69,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::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(()) => {
@@ -98,8 +104,8 @@ struct TaskWaker {
} }
impl TaskWaker { impl TaskWaker {
fn new(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker { fn waker(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker {
Waker::from(Arc::new(TaskWaker { Waker::from(Arc::new(Self {
task_id, task_id,
task_queue, task_queue,
})) }))
@@ -128,6 +134,6 @@ struct TaskId(u64);
impl TaskId { impl TaskId {
fn new() -> Self { fn new() -> Self {
static NEXT: AtomicU64 = AtomicU64::new(0); static NEXT: AtomicU64 = AtomicU64::new(0);
TaskId(NEXT.fetch_add(1, Ordering::Relaxed)) Self(NEXT.fetch_add(1, Ordering::Relaxed))
} }
} }