forked from LowLevelDevs/FoundryOS
Bump edition to now stable 2024 edition (shiny!).
This commit is contained in:
+5
-2
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
unsafe {
|
||||||
let l4_table = active_l4_table(physical_memory_offset);
|
let l4_table = active_l4_table(physical_memory_offset);
|
||||||
OffsetPageTable::new(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
@@ -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
@@ -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
@@ -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);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+50
-34
@@ -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 {
|
impl FramebufferWriter {
|
||||||
Self { framebuffer }
|
pub fn new(framebuffer: Framebuffer) -> Self {
|
||||||
|
Self {
|
||||||
|
pitch: framebuffer.pitch(),
|
||||||
|
bpp: framebuffer.bpp(),
|
||||||
|
addr: framebuffer.addr(),
|
||||||
|
width: framebuffer.width(),
|
||||||
|
height: framebuffer.height(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_pixel(&self, x: usize, y: usize, color: Color) {
|
pub fn write_pixel(&self, x: usize, y: usize, color: Colour) {
|
||||||
let pitch = self.framebuffer.pitch() as usize;
|
let pitch = self.pitch as usize;
|
||||||
let bpp = (self.framebuffer.bpp() / 8) as usize;
|
let bpp = (self.bpp / 8) as usize;
|
||||||
let pixel_offset = y * pitch + x * bpp;
|
let pixel_offset = y * pitch + x * bpp;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
*(self.framebuffer.addr().add(pixel_offset) as *mut u32) = color.into();
|
*(self.addr.add(pixel_offset) as *mut u32) = color.into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_frame(&self, buffer: &[Color; 1280 * 800]) {
|
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()))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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) {
|
||||||
|
|||||||
+6
-2
@@ -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;
|
||||||
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
"in al, dx",
|
"in al, dx",
|
||||||
out("al") value,
|
out("al") value,
|
||||||
in("dx") port,
|
in("dx") port,
|
||||||
options(nomem, nostack, preserves_flags)
|
options(nomem, nostack, preserves_flags)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn outb(port: u16, value: u8) {
|
pub fn outb(port: u16, value: u8) {
|
||||||
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
"out dx, al",
|
"out dx, al",
|
||||||
in("dx") port,
|
in("dx") port,
|
||||||
in("al") value,
|
in("al") value,
|
||||||
options(nomem, nostack, preserves_flags)
|
options(nomem, nostack, preserves_flags)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-12
@@ -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,23 +103,21 @@ 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 + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
outb(PORT, 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 + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
outb(PORT, 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
@@ -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};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user