Compare commits
2 Commits
745b8efb8f
...
daca502ce0
Author | SHA1 | Date | |
---|---|---|---|
daca502ce0 | |||
b5ebe0d4ad |
@ -0,0 +1,52 @@
|
|||||||
|
const CD_SECTOR_SIZE: usize = 2048;
|
||||||
|
|
||||||
|
|
||||||
|
const ATA_BUS_PRIMARY: u16= 0x1f0;
|
||||||
|
const ATA_BUS_SECONDARY: u16 = 0x170;
|
||||||
|
|
||||||
|
const ATA_DRIVE_MASTER: u16 = 0xa0;
|
||||||
|
const ATA_DRIVE_SLAVE: u16 = 0xb0;
|
||||||
|
|
||||||
|
macro_rules! ATA_DATA {
|
||||||
|
($reg:expr) => (reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ATA_ERROR {
|
||||||
|
($reg:expr) => (reg + 1); // read
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ATA_FEATURES {
|
||||||
|
($reg:expr) => (reg + 1); // write
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ATA_SECTOR_COUNT {
|
||||||
|
($reg:expr) => (reg + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ATA_ADDRESS1 {
|
||||||
|
($reg:expr) => (reg + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ATA_ADDRESS2 {
|
||||||
|
($reg:expr) => (reg + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ATA_ADDRESS3 {
|
||||||
|
($reg:expr) => (reg + 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ATA_DRIVE_SELECT {
|
||||||
|
($reg:expr) => (reg + 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ATA_STATUS {
|
||||||
|
($reg:expr) => (reg + 7); // read
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ATA_COMMAND {
|
||||||
|
($reg:expr) => (reg + 7); // write
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ATA_DCR {
|
||||||
|
($reg:expr) => (reg + 0x206);
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
pub mod serial;
|
pub mod serial;
|
||||||
pub mod vga;
|
pub mod vga;
|
||||||
|
pub mod atapi;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::memory::gdt;
|
|
||||||
use crate::hlt_loop;
|
|
||||||
use crate::drivers::vga::{self, Color, ColorCode};
|
use crate::drivers::vga::{self, Color, ColorCode};
|
||||||
use crate::{println};
|
use crate::hlt_loop;
|
||||||
|
use crate::memory::gdt;
|
||||||
|
use crate::println;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
use pic::{init_pic, keyboard_interrupt_handler, timer_interrupt_handler, InterruptIndex};
|
||||||
use x86_64::structures::idt::PageFaultErrorCode;
|
use x86_64::structures::idt::PageFaultErrorCode;
|
||||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
||||||
use pic::{InterruptIndex, init_pic, keyboard_interrupt_handler, timer_interrupt_handler};
|
|
||||||
|
|
||||||
pub mod pic;
|
pub mod pic;
|
||||||
|
|
||||||
@ -64,5 +64,3 @@ extern "x86-interrupt" fn double_fault_handler(
|
|||||||
) -> ! {
|
) -> ! {
|
||||||
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
|
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::{PICS, InterruptIndex};
|
use super::{InterruptIndex, PICS};
|
||||||
|
|
||||||
use x86_64::instructions::port::Port;
|
use x86_64::instructions::port::Port;
|
||||||
use x86_64::structures::idt::{InterruptStackFrame};
|
use x86_64::structures::idt::InterruptStackFrame;
|
||||||
|
|
||||||
pub const PS2_CONTROLLER_PORT: u16 = 0x60;
|
pub const PS2_CONTROLLER_PORT: u16 = 0x60;
|
||||||
|
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
use pic8259::ChainedPics;
|
use crate::println;
|
||||||
use crate::{println};
|
|
||||||
pub use pit::{timer_interrupt_handler};
|
|
||||||
pub use keyboard::keyboard_interrupt_handler;
|
pub use keyboard::keyboard_interrupt_handler;
|
||||||
|
use pic8259::ChainedPics;
|
||||||
|
pub use pit::timer_interrupt_handler;
|
||||||
|
|
||||||
pub mod pit;
|
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
|
pub mod pit;
|
||||||
|
|
||||||
pub const PIC_1_OFFSET: u8 = 32;
|
pub const PIC_1_OFFSET: u8 = 32;
|
||||||
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum InterruptIndex {
|
pub enum InterruptIndex {
|
||||||
@ -34,5 +33,3 @@ pub fn init_pic() {
|
|||||||
println!("Initializing PIC");
|
println!("Initializing PIC");
|
||||||
unsafe { PICS.lock().initialize() };
|
unsafe { PICS.lock().initialize() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
use super::{PICS, InterruptIndex};
|
use super::{InterruptIndex, PICS};
|
||||||
use x86_64::structures::idt::InterruptStackFrame;
|
use x86_64::structures::idt::InterruptStackFrame;
|
||||||
|
|
||||||
static mut TICKS: u64 = 0;
|
static mut TICKS: u64 = 0;
|
||||||
|
|
||||||
pub fn gettick() -> u64 {
|
pub fn gettick() -> u64 {
|
||||||
unsafe { return TICKS }
|
unsafe { return TICKS }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
pub extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
#![feature(abi_x86_interrupt)]
|
#![feature(abi_x86_interrupt)]
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
|
|
||||||
|
mod drivers;
|
||||||
mod interrupts;
|
mod interrupts;
|
||||||
mod memory;
|
mod memory;
|
||||||
mod drivers;
|
|
||||||
mod task;
|
mod task;
|
||||||
|
|
||||||
//#[macro_use]
|
//#[macro_use]
|
||||||
@ -13,9 +13,9 @@ extern crate alloc;
|
|||||||
extern crate multiboot2;
|
extern crate multiboot2;
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use multiboot2::BootInformation;
|
|
||||||
use drivers::vga::{self, Color, ColorCode};
|
use drivers::vga::{self, Color, ColorCode};
|
||||||
use task::{executor::Executor, Task, keyboard};
|
use multiboot2::BootInformation;
|
||||||
|
use task::{executor::Executor, keyboard, Task};
|
||||||
|
|
||||||
#[alloc_error_handler]
|
#[alloc_error_handler]
|
||||||
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
|
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
|
||||||
@ -35,8 +35,7 @@ pub fn hlt_loop() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(boot_info: &BootInformation)
|
pub fn init(boot_info: &BootInformation) {
|
||||||
{
|
|
||||||
vga::change_color(ColorCode::new(Color::LightCyan, Color::Black));
|
vga::change_color(ColorCode::new(Color::LightCyan, Color::Black));
|
||||||
println!("Starting init");
|
println!("Starting init");
|
||||||
memory::init(boot_info);
|
memory::init(boot_info);
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
pub use self::frame_allocator::AreaFrameAllocator;
|
pub use self::frame_allocator::AreaFrameAllocator;
|
||||||
pub use paging::kernel_remap;
|
|
||||||
use crate::println;
|
use crate::println;
|
||||||
|
use heap_alloc::{ALLOCATOR, HEAP_SIZE, HEAP_START};
|
||||||
use multiboot2::BootInformation;
|
use multiboot2::BootInformation;
|
||||||
use paging::{Size4KiB, RecursivePageTable, FrameAllocator, Page, Flags, Mapper};
|
pub use paging::kernel_remap;
|
||||||
use heap_alloc::{HEAP_START, HEAP_SIZE, ALLOCATOR};
|
use paging::{Flags, FrameAllocator, Mapper, Page, RecursivePageTable, Size4KiB};
|
||||||
use x86_64::VirtAddr;
|
|
||||||
use x86_64::structures::paging::{mapper::MapToError, page::PageRangeInclusive};
|
use x86_64::structures::paging::{mapper::MapToError, page::PageRangeInclusive};
|
||||||
|
use x86_64::VirtAddr;
|
||||||
|
|
||||||
pub mod frame_allocator;
|
pub mod frame_allocator;
|
||||||
pub mod paging;
|
|
||||||
pub mod heap_alloc;
|
|
||||||
pub mod gdt;
|
pub mod gdt;
|
||||||
|
pub mod heap_alloc;
|
||||||
|
pub mod paging;
|
||||||
|
|
||||||
pub const PAGE_SIZE: usize = 4096;
|
pub const PAGE_SIZE: usize = 4096;
|
||||||
|
|
||||||
@ -19,13 +19,15 @@ pub fn init(boot_info: &BootInformation) {
|
|||||||
enable_write_protect_bit();
|
enable_write_protect_bit();
|
||||||
let mut frame_allocator = get_frame_allocator(boot_info.start_address());
|
let mut frame_allocator = get_frame_allocator(boot_info.start_address());
|
||||||
let mut active_table = kernel_remap(&mut frame_allocator, boot_info);
|
let mut active_table = kernel_remap(&mut frame_allocator, boot_info);
|
||||||
init_heap(&mut active_table, &mut frame_allocator)
|
init_heap(&mut active_table, &mut frame_allocator).expect("Heap initialization failed");
|
||||||
.expect("Heap initialization failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_heap<A>(active_table: &mut RecursivePageTable, frame_allocator: &mut A)
|
fn init_heap<A>(
|
||||||
-> Result<(), MapToError<Size4KiB>>
|
active_table: &mut RecursivePageTable,
|
||||||
where A: FrameAllocator<Size4KiB>
|
frame_allocator: &mut A,
|
||||||
|
) -> Result<(), MapToError<Size4KiB>>
|
||||||
|
where
|
||||||
|
A: FrameAllocator<Size4KiB>,
|
||||||
{
|
{
|
||||||
let page_range: PageRangeInclusive<Size4KiB> = {
|
let page_range: PageRangeInclusive<Size4KiB> = {
|
||||||
let heap_start = VirtAddr::new(HEAP_START);
|
let heap_start = VirtAddr::new(HEAP_START);
|
||||||
@ -41,12 +43,16 @@ fn init_heap<A>(active_table: &mut RecursivePageTable, frame_allocator: &mut A)
|
|||||||
.ok_or(MapToError::FrameAllocationFailed)?;
|
.ok_or(MapToError::FrameAllocationFailed)?;
|
||||||
let flags = Flags::PRESENT | Flags::WRITABLE;
|
let flags = Flags::PRESENT | Flags::WRITABLE;
|
||||||
unsafe {
|
unsafe {
|
||||||
active_table.map_to(page, frame, flags, frame_allocator)?.flush();
|
active_table
|
||||||
|
.map_to(page, frame, flags, frame_allocator)?
|
||||||
|
.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ALLOCATOR.lock().init(HEAP_START as usize, HEAP_SIZE as usize);
|
ALLOCATOR
|
||||||
|
.lock()
|
||||||
|
.init(HEAP_START as usize, HEAP_SIZE as usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -13,7 +13,6 @@ mod temporary_page;
|
|||||||
|
|
||||||
pub const P4: *mut PageTable = 0o177777_777_777_777_777_0000 as *mut _;
|
pub const P4: *mut PageTable = 0o177777_777_777_777_777_0000 as *mut _;
|
||||||
|
|
||||||
|
|
||||||
fn get_flags_from_elf_section(section: &ElfSection) -> Flags {
|
fn get_flags_from_elf_section(section: &ElfSection) -> Flags {
|
||||||
use multiboot2::{ELF_SECTION_ALLOCATED, ELF_SECTION_EXECUTABLE, ELF_SECTION_WRITABLE};
|
use multiboot2::{ELF_SECTION_ALLOCATED, ELF_SECTION_EXECUTABLE, ELF_SECTION_WRITABLE};
|
||||||
|
|
||||||
@ -32,8 +31,9 @@ fn get_flags_from_elf_section(section: &ElfSection) -> Flags {
|
|||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kernel_remap<'a, A>(allocator: &mut A, boot_info: & BootInformation) -> RecursivePageTable<'a>
|
pub fn kernel_remap<'a, A>(allocator: &mut A, boot_info: &BootInformation) -> RecursivePageTable<'a>
|
||||||
where A: FrameAllocator<Size4KiB>,
|
where
|
||||||
|
A: FrameAllocator<Size4KiB>,
|
||||||
{
|
{
|
||||||
println!("Remapping kernel");
|
println!("Remapping kernel");
|
||||||
let mut temporary_page = TemporaryPage::new(
|
let mut temporary_page = TemporaryPage::new(
|
||||||
@ -107,7 +107,11 @@ pub fn kernel_remap<'a, A>(allocator: &mut A, boot_info: & BootInformation) -> R
|
|||||||
let old_p4_page = Page::<Size4KiB>::containing_address(VirtAddr::new(
|
let old_p4_page = Page::<Size4KiB>::containing_address(VirtAddr::new(
|
||||||
old_table.p4_frame.start_address().as_u64(),
|
old_table.p4_frame.start_address().as_u64(),
|
||||||
));
|
));
|
||||||
active_table.unmap(old_p4_page).expect("Failed to unmap old P4").1.flush();
|
active_table
|
||||||
|
.unmap(old_p4_page)
|
||||||
|
.expect("Failed to unmap old P4")
|
||||||
|
.1
|
||||||
|
.flush();
|
||||||
println!("Stack guard page at {:#x}", old_p4_page.start_address());
|
println!("Stack guard page at {:#x}", old_p4_page.start_address());
|
||||||
active_table
|
active_table
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use crossbeam_queue::ArrayQueue;
|
|||||||
pub struct Executor {
|
pub struct Executor {
|
||||||
tasks: BTreeMap<TaskId, Task>,
|
tasks: BTreeMap<TaskId, Task>,
|
||||||
task_queue: Arc<ArrayQueue<TaskId>>,
|
task_queue: Arc<ArrayQueue<TaskId>>,
|
||||||
waker_cache: BTreeMap<TaskId, Waker>
|
waker_cache: BTreeMap<TaskId, Waker>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Executor {
|
impl Executor {
|
||||||
@ -14,7 +14,7 @@ impl Executor {
|
|||||||
Executor {
|
Executor {
|
||||||
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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ impl Executor {
|
|||||||
let Self {
|
let Self {
|
||||||
tasks,
|
tasks,
|
||||||
task_queue,
|
task_queue,
|
||||||
waker_cache
|
waker_cache,
|
||||||
} = self; // Executor destructuring
|
} = self; // Executor destructuring
|
||||||
|
|
||||||
while let Ok(task_id) = task_queue.pop() {
|
while let Ok(task_id) = task_queue.pop() {
|
||||||
@ -74,14 +74,14 @@ impl Executor {
|
|||||||
|
|
||||||
struct TaskWaker {
|
struct TaskWaker {
|
||||||
task_id: TaskId,
|
task_id: TaskId,
|
||||||
task_queue: Arc<ArrayQueue<TaskId>>
|
task_queue: Arc<ArrayQueue<TaskId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskWaker {
|
impl TaskWaker {
|
||||||
fn new(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker {
|
fn new(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker {
|
||||||
Waker::from(Arc::new(TaskWaker {
|
Waker::from(Arc::new(TaskWaker {
|
||||||
task_id,
|
task_id,
|
||||||
task_queue
|
task_queue,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
use crate::{println, print};
|
use crate::{print, println};
|
||||||
|
|
||||||
use conquer_once::spin::OnceCell;
|
use conquer_once::spin::OnceCell;
|
||||||
use core::{pin::Pin, task::{Context, Poll}};
|
use core::{
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
use crossbeam_queue::ArrayQueue;
|
use crossbeam_queue::ArrayQueue;
|
||||||
use futures_util::task::AtomicWaker;
|
|
||||||
use futures_util::stream::{Stream, StreamExt};
|
use futures_util::stream::{Stream, StreamExt};
|
||||||
|
use futures_util::task::AtomicWaker;
|
||||||
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
|
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
|
||||||
|
|
||||||
static SCANCODE_QUEUE: OnceCell<ArrayQueue<u8>> = OnceCell::uninit();
|
static SCANCODE_QUEUE: OnceCell<ArrayQueue<u8>> = OnceCell::uninit();
|
||||||
@ -18,7 +21,8 @@ pub struct ScancodeStream {
|
|||||||
|
|
||||||
impl ScancodeStream {
|
impl ScancodeStream {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
SCANCODE_QUEUE.try_init_once(|| ArrayQueue::new(100))
|
SCANCODE_QUEUE
|
||||||
|
.try_init_once(|| ArrayQueue::new(100))
|
||||||
.expect("ScancodeStream::new should only be called once");
|
.expect("ScancodeStream::new should only be called once");
|
||||||
ScancodeStream { _private: () }
|
ScancodeStream { _private: () }
|
||||||
}
|
}
|
||||||
@ -42,8 +46,8 @@ impl Stream for ScancodeStream {
|
|||||||
Ok(scancode) => {
|
Ok(scancode) => {
|
||||||
WAKER.take();
|
WAKER.take();
|
||||||
Poll::Ready(Some(scancode))
|
Poll::Ready(Some(scancode))
|
||||||
},
|
}
|
||||||
Err(crossbeam_queue::PopError) => Poll::Pending
|
Err(crossbeam_queue::PopError) => Poll::Pending,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,12 +56,10 @@ pub(crate) fn add_scancode(scancode: u8) {
|
|||||||
if let Ok(queue) = SCANCODE_QUEUE.try_get() {
|
if let Ok(queue) = SCANCODE_QUEUE.try_get() {
|
||||||
if let Err(_) = queue.push(scancode) {
|
if let Err(_) = queue.push(scancode) {
|
||||||
println!("Keyboard scancode queue full, dropping input {}", scancode);
|
println!("Keyboard scancode queue full, dropping input {}", scancode);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
WAKER.wake();
|
WAKER.wake();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
println!("Keyboard scancode queue uninitialized");
|
println!("Keyboard scancode queue uninitialized");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
use alloc::boxed::Box;
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::sync::atomic::{AtomicU64, Ordering};
|
use core::sync::atomic::{AtomicU64, Ordering};
|
||||||
use core::task::{Context, Poll};
|
use core::task::{Context, Poll};
|
||||||
use alloc::boxed::Box;
|
|
||||||
|
|
||||||
pub mod executor;
|
pub mod executor;
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
@ -19,14 +19,14 @@ impl TaskId {
|
|||||||
|
|
||||||
pub struct Task {
|
pub struct Task {
|
||||||
id: TaskId,
|
id: TaskId,
|
||||||
future: Pin<Box<dyn Future<Output = ()>>>
|
future: Pin<Box<dyn Future<Output = ()>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Task {
|
impl Task {
|
||||||
pub fn new(future: impl Future<Output = ()> + 'static) -> Task {
|
pub fn new(future: impl Future<Output = ()> + 'static) -> Task {
|
||||||
Task {
|
Task {
|
||||||
id: TaskId::new(),
|
id: TaskId::new(),
|
||||||
future: Box::pin(future)
|
future: Box::pin(future),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user